Implements albums page
This commit is contained in:
parent
2284a319c1
commit
4634c2758b
7 changed files with 231 additions and 37 deletions
2
index.js
2
index.js
|
@ -16,6 +16,8 @@ function CreateWindow() {
|
|||
* App Event Handlers
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||
|
||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=1024')
|
||||
|
||||
app.on('ready', () => {
|
||||
if (app.isQuiting) { app.quit(); return; }
|
||||
console.log('[Cider] Application is Ready. Creating Window.')
|
||||
|
|
|
@ -125,6 +125,8 @@ input[type=range].md-slider::-webkit-slider-runnable-track {
|
|||
border-radius: 4px;
|
||||
border: 1px solid rgb(100 100 100 / 35%);
|
||||
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3), 0px 1px 1px rgba(0, 0, 0, 0.4);
|
||||
background: #363636;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.md-select:focus {
|
||||
|
|
|
@ -82,15 +82,15 @@ const app = new Vue({
|
|||
topSongsExpanded: false
|
||||
},
|
||||
library: {
|
||||
sortingOptions: {
|
||||
"albumName": "Album",
|
||||
"artistName": "Artist",
|
||||
"name": "Name",
|
||||
"genre": "Genre",
|
||||
"releaseDate": "Release Date",
|
||||
"durationInMillis": "Duration"
|
||||
},
|
||||
songs: {
|
||||
sortingOptions: {
|
||||
"albumName": "Album",
|
||||
"artistName": "Artist",
|
||||
"name": "Name",
|
||||
"genre": "Genre",
|
||||
"releaseDate": "Release Date",
|
||||
"durationInMillis": "Duration"
|
||||
},
|
||||
sorting: "name",
|
||||
sortOrder: "asc",
|
||||
listing: [],
|
||||
|
@ -100,8 +100,20 @@ const app = new Vue({
|
|||
downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library
|
||||
},
|
||||
albums: {
|
||||
sortingOptions: {
|
||||
"artistName": "Artist",
|
||||
"name": "Name",
|
||||
"genre": "Genre",
|
||||
"releaseDate": "Release Date"
|
||||
},
|
||||
viewAs: 'covers',
|
||||
sorting: "name",
|
||||
sortOrder: "asc",
|
||||
listing: [],
|
||||
meta: {total: 0}
|
||||
meta: {total: 0, progress: 0},
|
||||
search: "",
|
||||
displayListing: [],
|
||||
downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library
|
||||
},
|
||||
},
|
||||
playlists: {
|
||||
|
@ -148,6 +160,10 @@ const app = new Vue({
|
|||
this.library.songs.listing = JSON.parse(localStorage.getItem("librarySongs"))
|
||||
this.library.songs.displayListing = this.library.songs.listing
|
||||
}
|
||||
if (localStorage.getItem("libraryAlbums") != null) {
|
||||
this.library.albums.listing = JSON.parse(localStorage.getItem("libraryAlbums"))
|
||||
this.library.albums.displayListing = this.library.albums.listing
|
||||
}
|
||||
|
||||
MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player")
|
||||
|
||||
|
@ -362,7 +378,6 @@ const app = new Vue({
|
|||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||
},
|
||||
async getTypeFromID(kind, id, isLibrary = false, params = {}) {
|
||||
|
||||
var a;
|
||||
try {
|
||||
a = await this.mkapi(kind.toString(), isLibrary, id.toString(), params);
|
||||
|
@ -448,6 +463,71 @@ const app = new Vue({
|
|||
sortSongs()
|
||||
}
|
||||
},
|
||||
// make a copy of searchLibrarySongs except use Albums instead of Songs
|
||||
searchLibraryAlbums() {
|
||||
let self = this
|
||||
function sortAlbums() {
|
||||
if (self.library.albums.sortOrder == "asc") {
|
||||
// sort this.library.albums.displayListing by album.attributes[self.library.albums.sorting] in ascending order based on alphabetical order and numeric order
|
||||
// check if album.attributes[self.library.albums.sorting] is a number and if so, sort by number if not, sort by alphabetical order ignoring case
|
||||
self.library.albums.displayListing.sort((a, b) => {
|
||||
let aa = null;
|
||||
let bb = null;
|
||||
if (self.library.albums.sorting == "genre") {
|
||||
aa = a.attributes.genreNames[0]
|
||||
bb = b.attributes.genreNames[0]
|
||||
}
|
||||
aa = a.attributes[self.library.albums.sorting]
|
||||
bb = b.attributes[self.library.albums.sorting]
|
||||
if (aa == null) {
|
||||
aa = ""
|
||||
}
|
||||
if (bb == null) {
|
||||
bb = ""
|
||||
}
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return aa - bb
|
||||
} else {
|
||||
return aa.toString().toLowerCase().localeCompare(bb.toString().toLowerCase())
|
||||
}
|
||||
})
|
||||
}
|
||||
if (self.library.albums.sortOrder == "desc") {
|
||||
// sort this.library.albums.displayListing by album.attributes[self.library.albums.sorting] in descending order based on alphabetical order and numeric order
|
||||
// check if album.attributes[self.library.albums.sorting] is a number and if so, sort by number if not, sort by alphabetical order ignoring case
|
||||
self.library.albums.displayListing.sort((a, b) => {
|
||||
if (self.library.albums.sorting == "genre") {
|
||||
aa = a.attributes.genreNames[0]
|
||||
bb = b.attributes.genreNames[0]
|
||||
}
|
||||
let aa = a.attributes[self.library.albums.sorting]
|
||||
let bb = b.attributes[self.library.albums.sorting]
|
||||
if (aa == null) {
|
||||
aa = ""
|
||||
}
|
||||
if (bb == null) {
|
||||
bb = ""
|
||||
}
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return bb - aa
|
||||
} else {
|
||||
return bb.toString().toLowerCase().localeCompare(aa.toString().toLowerCase())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if (this.library.albums.search == "") {
|
||||
this.library.albums.displayListing = this.library.albums.listing
|
||||
sortAlbums()
|
||||
} else {
|
||||
this.library.albums.displayListing = this.library.albums.listing.filter(item => {
|
||||
if (item.attributes.name.toLowerCase().includes(this.library.albums.search.toLowerCase())) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
sortAlbums()
|
||||
}
|
||||
},
|
||||
getSidebarItemClass(page) {
|
||||
if (this.page == page) {
|
||||
return ["active"]
|
||||
|
@ -499,6 +579,7 @@ const app = new Vue({
|
|||
this.library.songs.downloadState = 1
|
||||
|
||||
function downloadChunk() {
|
||||
self.library.songs.downloadState = 1
|
||||
if (downloaded == null) {
|
||||
app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
|
@ -540,6 +621,70 @@ const app = new Vue({
|
|||
|
||||
downloadChunk()
|
||||
},
|
||||
// copy the getLibrarySongsFull function except change Songs to Albums
|
||||
async getLibraryAlbumsFull(force = false) {
|
||||
let self = this
|
||||
let library = []
|
||||
let downloaded = null;
|
||||
if ((this.library.albums.downloadState == 2 || this.library.albums.downloadState == 1) && !force) {
|
||||
return
|
||||
}
|
||||
if (localStorage.getItem("libraryAlbums") != null) {
|
||||
this.library.albums.listing = JSON.parse(localStorage.getItem("libraryAlbums"))
|
||||
this.searchLibraryAlbums()
|
||||
}
|
||||
if (this.songstest) {
|
||||
return
|
||||
}
|
||||
this.library.albums.downloadState = 1
|
||||
this.library.songs.downloadState = 1
|
||||
|
||||
function downloadChunk() {
|
||||
self.library.songs.downloadState = 1
|
||||
if (downloaded == null) {
|
||||
app.mk.api.library.albums("", {limit: 100}, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
})
|
||||
} else {
|
||||
downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function processChunk(response) {
|
||||
downloaded = response
|
||||
library = library.concat(downloaded.data)
|
||||
self.library.songs.meta.total = downloaded.meta.total
|
||||
self.library.songs.meta.progress = library.length
|
||||
if (downloaded.meta.total == 0) {
|
||||
self.library.songs.downloadState = 3
|
||||
self.library.albums.downloadState = 3
|
||||
return
|
||||
}
|
||||
if (typeof downloaded.next == "undefined") {
|
||||
console.log("downloaded.next is undefined")
|
||||
self.library.albums.listing = library
|
||||
self.library.albums.downloadState = 2
|
||||
self.library.songs.downloadState = 2
|
||||
localStorage.setItem("libraryAlbums", JSON.stringify(library))
|
||||
self.searchLibraryAlbums()
|
||||
}
|
||||
if (downloaded.meta.total > library.length || typeof downloaded.meta.next != "undefined") {
|
||||
console.log(`downloading next chunk - ${library.length
|
||||
} albums so far`)
|
||||
downloadChunk()
|
||||
} else {
|
||||
self.library.albums.listing = library
|
||||
self.library.albums.downloadState = 2
|
||||
self.library.songs.downloadState = 2
|
||||
localStorage.setItem("libraryAlbums", JSON.stringify(library))
|
||||
self.searchLibraryAlbums()
|
||||
console.log(library)
|
||||
}
|
||||
}
|
||||
downloadChunk()
|
||||
},
|
||||
getTotalTime() {
|
||||
if (app.showingPlaylist.relationships.tracks.data.length > 0) {
|
||||
time = Math.round([].concat(...app.showingPlaylist.relationships.tracks.data).reduce((a, {attributes: {durationInMillis}}) => a + durationInMillis, 0) / 60000);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script type="text/x-template" id="mediaitem-list-item">
|
||||
<template>
|
||||
<div
|
||||
<div
|
||||
@click="app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)"
|
||||
v-observe-visibility="{callback: visibilityChanged}"
|
||||
class="cd-mediaitem-list-item">
|
||||
|
@ -39,7 +39,7 @@
|
|||
{{ item.attributes.genreNames[0] ?? "" }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="duration">
|
||||
<div class="duration" v-if="showDuration">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -59,7 +59,8 @@
|
|||
'item': {type: Object, required: true},
|
||||
'show-artwork': {type: Boolean, default: true},
|
||||
'show-library-status': {type: Boolean, default: true},
|
||||
'show-meta-data': {type: Boolean, default: false}
|
||||
'show-meta-data': {type: Boolean, default: false},
|
||||
'show-duration': {type: Boolean, default: true}
|
||||
},
|
||||
methods: {
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
|
|
|
@ -302,19 +302,8 @@
|
|||
<%- include('pages/library-songs') %>
|
||||
</transition>
|
||||
<!-- Library - Albums -->
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbums()">
|
||||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search" style="width:100%;" spellcheck="false" placeholder="Search..."
|
||||
class="search-input">
|
||||
</div>
|
||||
<mediaitem-square-large :item="item" v-for="item in library.albums.listing">
|
||||
</mediaitem-square-large>
|
||||
</div>
|
||||
</template>
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbumsFull()">
|
||||
<%- include('pages/library-albums') %>'); %>
|
||||
</transition>
|
||||
</div>
|
||||
<transition name="drawertransition">
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="searchLibraryAlbums"
|
||||
v-model="library.albums.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sorting" @change="searchLibraryAlbums()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.albums.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sortOrder" @change="searchLibraryAlbums()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.viewAs">
|
||||
<optgroup label="View As">
|
||||
<option value="covers">Cover Art</option>
|
||||
<option value="list">List</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-square-large v-if="library.albums.viewAs == 'covers'" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-square-large>
|
||||
<mediaitem-list-item v-if="library.albums.viewAs == 'list'" :show-duration="false" :show-meta-data="true" :show-library-status="false" :item="item" v-for="item in library.albums.displayListing">
|
||||
</mediaitem-list-item>
|
||||
</div>
|
||||
</template>
|
|
@ -14,17 +14,23 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<select class="md-select" v-model="library.songs.sorting" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<select class="md-select" v-model="library.songs.sortOrder" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sorting" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort By">
|
||||
<option v-for="(sort, index) in library.songs.sortingOptions" :value="index">{{ sort }}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.songs.sortOrder" @change="searchLibrarySongs()">
|
||||
<optgroup label="Sort Order">
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue