added new experiment: inline playlists and albums
This commit is contained in:
parent
f4159c35c8
commit
852ab56253
6 changed files with 970 additions and 350 deletions
|
@ -36,6 +36,7 @@ export class BrowserWindow {
|
||||||
"pages/home",
|
"pages/home",
|
||||||
"pages/artist-feed",
|
"pages/artist-feed",
|
||||||
"pages/cider-playlist",
|
"pages/cider-playlist",
|
||||||
|
"pages/playlist-inline",
|
||||||
"pages/recordLabel",
|
"pages/recordLabel",
|
||||||
"pages/collection-list",
|
"pages/collection-list",
|
||||||
"pages/apple-curator",
|
"pages/apple-curator",
|
||||||
|
|
|
@ -301,6 +301,7 @@ const app = new Vue({
|
||||||
qrcode: false,
|
qrcode: false,
|
||||||
equalizer: false,
|
equalizer: false,
|
||||||
audioSettings: false,
|
audioSettings: false,
|
||||||
|
showPlaylist: false,
|
||||||
},
|
},
|
||||||
socialBadges: {
|
socialBadges: {
|
||||||
badgeMap: {},
|
badgeMap: {},
|
||||||
|
@ -332,7 +333,7 @@ const app = new Vue({
|
||||||
},
|
},
|
||||||
showingPlaylist: () => {
|
showingPlaylist: () => {
|
||||||
document.getElementById("app-content").scrollTo(0, 0);
|
document.getElementById("app-content").scrollTo(0, 0);
|
||||||
app.resetState()
|
// app.resetState()
|
||||||
},
|
},
|
||||||
artistPage: () => {
|
artistPage: () => {
|
||||||
document.getElementById("app-content").scrollTo(0, 0);
|
document.getElementById("app-content").scrollTo(0, 0);
|
||||||
|
@ -344,7 +345,9 @@ const app = new Vue({
|
||||||
if (val) {
|
if (val) {
|
||||||
(this.chrome.userinfo.id) ? this.chrome.menuOpened = !this.chrome.menuOpened : false
|
(this.chrome.userinfo.id) ? this.chrome.menuOpened = !this.chrome.menuOpened : false
|
||||||
} else {
|
} else {
|
||||||
setTimeout(()=>{this.chrome.menuOpened = false}, 100)
|
setTimeout(() => {
|
||||||
|
this.chrome.menuOpened = false
|
||||||
|
}, 100)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stringTemplateParser(expression, valueObj) {
|
stringTemplateParser(expression, valueObj) {
|
||||||
|
@ -445,7 +448,8 @@ const app = new Vue({
|
||||||
let data = await response.text();
|
let data = await response.text();
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
getSocialBadges(cb = () => {}) {
|
getSocialBadges(cb = () => {
|
||||||
|
}) {
|
||||||
let self = this
|
let self = this
|
||||||
try {
|
try {
|
||||||
app.mk.api.v3.music("/v1/social/badging-map").then(data => {
|
app.mk.api.v3.music("/v1/social/badging-map").then(data => {
|
||||||
|
@ -617,7 +621,8 @@ const app = new Vue({
|
||||||
try {
|
try {
|
||||||
// Set profile name
|
// Set profile name
|
||||||
this.chrome.userinfo = (await app.mk.api.v3.music(`/v1/me/social-profile`)).data.data[0]
|
this.chrome.userinfo = (await app.mk.api.v3.music(`/v1/me/social-profile`)).data.data[0]
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
}
|
||||||
|
|
||||||
// API Fallback
|
// API Fallback
|
||||||
if (!this.chrome.userinfo) {
|
if (!this.chrome.userinfo) {
|
||||||
|
@ -634,8 +639,7 @@ const app = new Vue({
|
||||||
// Set the volume
|
// Set the volume
|
||||||
|
|
||||||
// Check the value of this.cfg.audio.muted
|
// Check the value of this.cfg.audio.muted
|
||||||
if( !this.cfg.audio.muted )
|
if (!this.cfg.audio.muted) {
|
||||||
{
|
|
||||||
// Set the mk.volume to the last stored volume data
|
// Set the mk.volume to the last stored volume data
|
||||||
this.mk.volume = this.cfg.audio.volume
|
this.mk.volume = this.cfg.audio.volume
|
||||||
} else if (this.cfg.audio.muted) {
|
} else if (this.cfg.audio.muted) {
|
||||||
|
@ -709,7 +713,8 @@ const app = new Vue({
|
||||||
if (!(i == 0 && ids[0] == lastItem.attributes.playParams.id)) {
|
if (!(i == 0 && ids[0] == lastItem.attributes.playParams.id)) {
|
||||||
try {
|
try {
|
||||||
app.mk.playLater({songs: [id]})
|
app.mk.playLater({songs: [id]})
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -774,7 +779,8 @@ const app = new Vue({
|
||||||
let previewURL = null
|
let previewURL = null
|
||||||
try {
|
try {
|
||||||
previewURL = app.mk.nowPlayingItem.previewURL
|
previewURL = app.mk.nowPlayingItem.previewURL
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
if (!previewURL) {
|
if (!previewURL) {
|
||||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/songs/${app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.relationships.catalog.data[0].id}`).then((response) => {
|
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/songs/${app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.relationships.catalog.data[0].id}`).then((response) => {
|
||||||
previewURL = response.data.data[0].attributes.previews[0].url
|
previewURL = response.data.data[0].attributes.previews[0].url
|
||||||
|
@ -786,12 +792,14 @@ const app = new Vue({
|
||||||
ipcRenderer.send('getPreviewURL', previewURL)
|
ipcRenderer.send('getPreviewURL', previewURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
a = a.item.attributes;
|
a = a.item.attributes;
|
||||||
} catch (_) {}
|
} catch (_) {
|
||||||
|
}
|
||||||
let type = (self.mk.nowPlayingItem != null) ? self.mk.nowPlayingItem["type"] ?? '' : '';
|
let type = (self.mk.nowPlayingItem != null) ? self.mk.nowPlayingItem["type"] ?? '' : '';
|
||||||
|
|
||||||
if (type.includes("musicVideo") || type.includes("uploadedVideo") || type.includes("music-movie")) {
|
if (type.includes("musicVideo") || type.includes("uploadedVideo") || type.includes("music-movie")) {
|
||||||
|
@ -852,7 +860,10 @@ const app = new Vue({
|
||||||
this.cfg.visual.theme = theme
|
this.cfg.visual.theme = theme
|
||||||
}
|
}
|
||||||
document.querySelector("#userTheme").href = `themes/${this.cfg.visual.theme}`
|
document.querySelector("#userTheme").href = `themes/${this.cfg.visual.theme}`
|
||||||
document.querySelectorAll(`[id*='less']`).forEach(el => { el.remove() });less.refresh()
|
document.querySelectorAll(`[id*='less']`).forEach(el => {
|
||||||
|
el.remove()
|
||||||
|
});
|
||||||
|
less.refresh()
|
||||||
},
|
},
|
||||||
unauthorize() {
|
unauthorize() {
|
||||||
this.mk.unauthorize()
|
this.mk.unauthorize()
|
||||||
|
@ -1276,11 +1287,10 @@ const app = new Vue({
|
||||||
},
|
},
|
||||||
routeView(item) {
|
routeView(item) {
|
||||||
let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? ''));
|
let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? ''));
|
||||||
let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));;
|
let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));
|
||||||
|
;
|
||||||
let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false;
|
let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false;
|
||||||
console.log(kind, id, isLibrary)
|
console.log(kind, id, isLibrary)
|
||||||
|
|
||||||
if (true) {
|
|
||||||
if (kind.includes("playlist") || kind.includes("album")) {
|
if (kind.includes("playlist") || kind.includes("album")) {
|
||||||
app.showingPlaylist = [];
|
app.showingPlaylist = [];
|
||||||
}
|
}
|
||||||
|
@ -1318,16 +1328,25 @@ const app = new Vue({
|
||||||
extend: "offers,editorialVideo",
|
extend: "offers,editorialVideo",
|
||||||
"views": "appears-on,more-by-artist,related-videos,other-versions,you-might-also-like,video-extras,audio-extras",
|
"views": "appears-on,more-by-artist,related-videos,other-versions,you-might-also-like,video-extras,audio-extras",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.cfg.advanced.experiments.includes('inline-playlists')) {
|
||||||
|
if (kind.toString().includes("album") || kind.toString().includes("playlist")) {
|
||||||
|
app.modals.showPlaylist = true
|
||||||
|
} else {
|
||||||
app.page = (kind) + "_" + (id);
|
app.page = (kind) + "_" + (id);
|
||||||
app.getTypeFromID((kind), (id), (isLibrary), params);
|
|
||||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
app.page = (kind) + "_" + (id);
|
||||||
|
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
app.getTypeFromID((kind), (id), (isLibrary), params);
|
||||||
document.querySelector("#app-content").scrollTop = 0
|
document.querySelector("#app-content").scrollTop = 0
|
||||||
} else {
|
} else {
|
||||||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
prevButton() {
|
prevButton() {
|
||||||
if (!app.prevButtonBackIndicator && app.mk.nowPlayingItem && app.mk.currentPlaybackTime > 2) {
|
if (!app.prevButtonBackIndicator && app.mk.nowPlayingItem && app.mk.currentPlaybackTime > 2) {
|
||||||
|
@ -1361,7 +1380,8 @@ const app = new Vue({
|
||||||
artistId = artistId.substring(artistId.lastIndexOf('ids=') + 4, artistId.lastIndexOf('-'))
|
artistId = artistId.substring(artistId.lastIndexOf('ids=') + 4, artistId.lastIndexOf('-'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {
|
||||||
|
}
|
||||||
|
|
||||||
if (artistId == "") {
|
if (artistId == "") {
|
||||||
let artistQuery = (await app.mk.api.v3.music(`v1/catalog/${app.mk.storefrontId}/search?term=${item.attributes.artistName}`, {
|
let artistQuery = (await app.mk.api.v3.music(`v1/catalog/${app.mk.storefrontId}/search?term=${item.attributes.artistName}`, {
|
||||||
|
@ -1373,7 +1393,8 @@ const app = new Vue({
|
||||||
artistId = artistQuery.artists.data[0].id;
|
artistId = artistQuery.artists.data[0].id;
|
||||||
console.log(artistId)
|
console.log(artistId)
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(artistId);
|
console.log(artistId);
|
||||||
if (artistId != "")
|
if (artistId != "")
|
||||||
|
@ -1396,7 +1417,8 @@ const app = new Vue({
|
||||||
albumId = albumId.substring(0, albumId.indexOf("?i="))
|
albumId = albumId.substring(0, albumId.indexOf("?i="))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {
|
||||||
|
}
|
||||||
|
|
||||||
if (albumId == "") {
|
if (albumId == "") {
|
||||||
try {
|
try {
|
||||||
|
@ -1408,7 +1430,8 @@ const app = new Vue({
|
||||||
albumId = albumQuery.albums.data[0].id;
|
albumId = albumQuery.albums.data[0].id;
|
||||||
console.log(albumId)
|
console.log(albumId)
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (albumId != "") {
|
if (albumId != "") {
|
||||||
self.appRoute(`album/${albumId}`)
|
self.appRoute(`album/${albumId}`)
|
||||||
|
@ -1418,7 +1441,8 @@ const app = new Vue({
|
||||||
let labelId = '';
|
let labelId = '';
|
||||||
try {
|
try {
|
||||||
labelId = item.relationships['record-labels'].data[0].id
|
labelId = item.relationships['record-labels'].data[0].id
|
||||||
} catch (_) {}
|
} catch (_) {
|
||||||
|
}
|
||||||
|
|
||||||
if (labelId == "") {
|
if (labelId == "") {
|
||||||
try {
|
try {
|
||||||
|
@ -1430,7 +1454,8 @@ const app = new Vue({
|
||||||
labelId = labelQuery["record-labels"].data[0].id;
|
labelId = labelQuery["record-labels"].data[0].id;
|
||||||
console.log(labelId)
|
console.log(labelId)
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (labelId != "") {
|
if (labelId != "") {
|
||||||
app.showingPlaylist = []
|
app.showingPlaylist = []
|
||||||
|
@ -1451,7 +1476,8 @@ const app = new Vue({
|
||||||
},
|
},
|
||||||
playMediaItem(item) {
|
playMediaItem(item) {
|
||||||
let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? ''));
|
let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? ''));
|
||||||
let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));;
|
let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));
|
||||||
|
;
|
||||||
let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false;
|
let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false;
|
||||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
console.log(kind, id, isLibrary)
|
console.log(kind, id, isLibrary)
|
||||||
|
@ -1559,7 +1585,8 @@ const app = new Vue({
|
||||||
} else {
|
} else {
|
||||||
this.getPlaylistContinuous(a)
|
this.getPlaylistContinuous(a)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
;
|
||||||
},
|
},
|
||||||
searchLibrarySongs() {
|
searchLibrarySongs() {
|
||||||
let self = this
|
let self = this
|
||||||
|
@ -1763,8 +1790,12 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mkapi(method, library = false, term, params = {}, params2 = {}, attempts = 0) {
|
async mkapi(method, library = false, term, params = {}, params2 = {}, attempts = 0) {
|
||||||
if (method.includes(`recordLabel`)) { method = `record-labels` }
|
if (method.includes(`recordLabel`)) {
|
||||||
if (method.includes(`appleCurator`)) { method = `apple-curators` }
|
method = `record-labels`
|
||||||
|
}
|
||||||
|
if (method.includes(`appleCurator`)) {
|
||||||
|
method = `apple-curators`
|
||||||
|
}
|
||||||
if (attempts > 3) {
|
if (attempts > 3) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1835,9 +1866,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(`/v1/me/library/songs/`, safeparams).then((response) => {
|
app.mk.api.v3.music(`/v1/me/library/songs/`, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error)
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error)
|
||||||
app.library.songs.downloadState = 2
|
app.library.songs.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (downloaded.next != null) {
|
if (downloaded.next != null) {
|
||||||
|
@ -1847,9 +1880,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error)
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error)
|
||||||
app.library.songs.downloadState = 2
|
app.library.songs.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log("Download next", downloaded.next)
|
console.log("Download next", downloaded.next)
|
||||||
|
@ -1939,9 +1974,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(`/v1/me/library/albums/`, safeparams).then((response) => {
|
app.mk.api.v3.music(`/v1/me/library/albums/`, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error)
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error)
|
||||||
app.library.albums.downloadState = 2
|
app.library.albums.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (downloaded.next != null) {
|
if (downloaded.next != null) {
|
||||||
|
@ -1951,9 +1988,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error);
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error);
|
||||||
app.library.albums.downloadState = 2
|
app.library.albums.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log("Download next", downloaded.next)
|
console.log("Download next", downloaded.next)
|
||||||
|
@ -2039,9 +2078,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(`/v1/me/library/artists/`, safeparams).then((response) => {
|
app.mk.api.v3.music(`/v1/me/library/artists/`, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error)
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error)
|
||||||
app.library.artists.downloadState = 2
|
app.library.artists.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2052,9 +2093,11 @@ const app = new Vue({
|
||||||
console.log('safe loading');
|
console.log('safe loading');
|
||||||
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
app.mk.api.v3.music(downloaded.next, safeparams).then((response) => {
|
||||||
processChunk(response.data)
|
processChunk(response.data)
|
||||||
}).catch((error) => {console.log('safe loading failed', error)
|
}).catch((error) => {
|
||||||
|
console.log('safe loading failed', error)
|
||||||
app.library.artists.downloadState = 2
|
app.library.artists.downloadState = 2
|
||||||
app.library.backgroundNotification.show = false})
|
app.library.backgroundNotification.show = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log("Download next", downloaded.next)
|
console.log("Download next", downloaded.next)
|
||||||
|
@ -2436,7 +2479,8 @@ const app = new Vue({
|
||||||
lrcrich = jsonResponse["message"]["body"]["macro_calls"]["track.richsync.get"]["message"]["body"]["richsync"]["richsync_body"];
|
lrcrich = jsonResponse["message"]["body"]["macro_calls"]["track.richsync.get"]["message"]["body"]["richsync"]["richsync_body"];
|
||||||
richsync = JSON.parse(lrcrich);
|
richsync = JSON.parse(lrcrich);
|
||||||
app.richlyrics = richsync;
|
app.richlyrics = richsync;
|
||||||
} catch (_) {}
|
} catch (_) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lrcfile == "") {
|
if (lrcfile == "") {
|
||||||
|
@ -2713,8 +2757,10 @@ const app = new Vue({
|
||||||
shuffleArray(query)
|
shuffleArray(query)
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < query.length; i++) {
|
for (let i = 0; i < query.length; i++) {
|
||||||
if (query[i].id == item.id) {query.splice(0, i+1);
|
if (query[i].id == item.id) {
|
||||||
break;}
|
query.splice(0, i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.mk.queue.append(query)
|
app.mk.queue.append(query)
|
||||||
|
@ -2748,7 +2794,10 @@ const app = new Vue({
|
||||||
shuffleArray(u)
|
shuffleArray(u)
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) {
|
for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) {
|
||||||
if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {u.splice(0, i+1); break;}
|
if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {
|
||||||
|
u.splice(0, i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.mk.queue.append(u)
|
app.mk.queue.append(u)
|
||||||
|
@ -2760,7 +2809,10 @@ const app = new Vue({
|
||||||
shuffleArray(u)
|
shuffleArray(u)
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) {
|
for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) {
|
||||||
if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {u.splice(0, i+1); break;}
|
if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {
|
||||||
|
u.splice(0, i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.mk.queue.append(u)
|
app.mk.queue.append(u)
|
||||||
|
@ -2796,7 +2848,8 @@ const app = new Vue({
|
||||||
console.log(err)
|
console.log(err)
|
||||||
try {
|
try {
|
||||||
app.mk.stop()
|
app.mk.stop()
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
this.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
this.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2916,7 +2969,8 @@ const app = new Vue({
|
||||||
result[key] = item[key];
|
result[key] = item[key];
|
||||||
return result;
|
return result;
|
||||||
}, {});
|
}, {});
|
||||||
return (await this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}`, {... {
|
return (await this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}`, {
|
||||||
|
...{
|
||||||
"omit[resource]": "autos",
|
"omit[resource]": "autos",
|
||||||
relate: "library",
|
relate: "library",
|
||||||
fields: "inLibrary"
|
fields: "inLibrary"
|
||||||
|
@ -3014,21 +3068,24 @@ const app = new Vue({
|
||||||
|
|
||||||
try {
|
try {
|
||||||
clearInterval(bginterval);
|
clearInterval(bginterval);
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setLibraryArtBG()
|
this.setLibraryArtBG()
|
||||||
}
|
}
|
||||||
} else if (this.mk.nowPlayingItem["id"] == this.currentTrackID) {
|
} else if (this.mk.nowPlayingItem["id"] == this.currentTrackID) {
|
||||||
try {
|
try {
|
||||||
clearInterval(bginterval);
|
clearInterval(bginterval);
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] && document.querySelector('.bg-artwork')) {
|
if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] && document.querySelector('.bg-artwork')) {
|
||||||
this.setLibraryArtBG()
|
this.setLibraryArtBG()
|
||||||
try {
|
try {
|
||||||
clearInterval(bginterval);
|
clearInterval(bginterval);
|
||||||
} catch (err) {}
|
} catch (err) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 200)
|
}, 200)
|
||||||
|
@ -3081,7 +3138,8 @@ const app = new Vue({
|
||||||
this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50);
|
this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50);
|
||||||
try {
|
try {
|
||||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`);
|
let data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`);
|
||||||
data = data.data.data[0];
|
data = data.data.data[0];
|
||||||
|
@ -3094,12 +3152,14 @@ const app = new Vue({
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.currentArtUrl = '';
|
this.currentArtUrl = '';
|
||||||
try {
|
try {
|
||||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -3117,7 +3177,8 @@ const app = new Vue({
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("")`);
|
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("")`);
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async setLibraryArtBG() {
|
async setLibraryArtBG() {
|
||||||
if (typeof this.mk.nowPlayingItem === "undefined") return;
|
if (typeof this.mk.nowPlayingItem === "undefined") return;
|
||||||
|
@ -3133,7 +3194,8 @@ const app = new Vue({
|
||||||
self.$store.commit("setLCDArtwork", img)
|
self.$store.commit("setLCDArtwork", img)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
quickPlay(query) {
|
quickPlay(query) {
|
||||||
|
@ -3401,7 +3463,9 @@ const app = new Vue({
|
||||||
"icon": "./assets/feather/share.svg",
|
"icon": "./assets/feather/share.svg",
|
||||||
"name": app.getLz('action.share'),
|
"name": app.getLz('action.share'),
|
||||||
"action": function () {
|
"action": function () {
|
||||||
app.mkapi( app.mk.nowPlayingItem.attributes?.playParams?.kind ?? app.mk.nowPlayingItem.type ?? 'songs', false, app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.id ?? '').then(u => {app.copyToClipboard((u.data.data.length && u.data.data.length > 0)? u.data.data[0].attributes.url : u.data.data.attributes.url)})
|
app.mkapi(app.mk.nowPlayingItem.attributes?.playParams?.kind ?? app.mk.nowPlayingItem.type ?? 'songs', false, app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.id ?? '').then(u => {
|
||||||
|
app.copyToClipboard((u.data.data.length && u.data.data.length > 0) ? u.data.data[0].attributes.url : u.data.data.attributes.url)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -3561,7 +3625,10 @@ const app = new Vue({
|
||||||
overflowY = element.offsetHeight < element.scrollHeight;
|
overflowY = element.offsetHeight < element.scrollHeight;
|
||||||
element.setAttribute('data-value', '\xa0\xa0\xa0\xa0' + element.textContent);
|
element.setAttribute('data-value', '\xa0\xa0\xa0\xa0' + element.textContent);
|
||||||
|
|
||||||
return (overflowX || overflowY); } catch (e) { return false}
|
return (overflowX || overflowY);
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async showWebRemoteQR() {
|
async showWebRemoteQR() {
|
||||||
//this.webremoteqr = await ipcRenderer.invoke('setRemoteQR','')
|
//this.webremoteqr = await ipcRenderer.invoke('setRemoteQR','')
|
||||||
|
@ -3839,7 +3906,8 @@ var checkIfScrollIsStatic = setInterval(() => {
|
||||||
// do something
|
// do something
|
||||||
}
|
}
|
||||||
position = document.getElementsByClassName('lyric-body')[0].scrollTop
|
position = document.getElementsByClassName('lyric-body')[0].scrollTop
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
|
@ -3863,10 +3931,12 @@ document.addEventListener('keydown', function(event) {
|
||||||
if (event.ctrlKey && event.keyCode == 121) {
|
if (event.ctrlKey && event.keyCode == 121) {
|
||||||
try {
|
try {
|
||||||
app.mk._services.mediaItemPlayback._currentPlayer.stop()
|
app.mk._services.mediaItemPlayback._currentPlayer.stop()
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
app.mk._services.mediaItemPlayback._currentPlayer.destroy()
|
app.mk._services.mediaItemPlayback._currentPlayer.destroy()
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3874,6 +3944,7 @@ document.addEventListener('keydown', function(event) {
|
||||||
if (event.ctrlKey && event.keyCode == 122) {
|
if (event.ctrlKey && event.keyCode == 122) {
|
||||||
try {
|
try {
|
||||||
ipcRenderer.send('detachDT', '')
|
ipcRenderer.send('detachDT', '')
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2947,7 +2947,6 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Album / Playlist Page */
|
/* Album / Playlist Page */
|
||||||
.playlist-page {
|
.playlist-page {
|
||||||
--bgColor: transparent;
|
--bgColor: transparent;
|
||||||
|
@ -3157,6 +3156,34 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
||||||
margin: 6px;
|
margin: 6px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.inline-playlist {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgb(0 0 0 / 50%);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: calc(var(--navigationBarHeight) + 32px) 0px 0px 0px;
|
||||||
|
z-index:2;
|
||||||
|
.playlist-inner {
|
||||||
|
background: black;
|
||||||
|
width: 80%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: overlay;
|
||||||
|
box-shadow: var(--ciderShadow-Generic);
|
||||||
|
border-radius: var(--mediaItemRadius) var(--mediaItemRadius) 0px 0px;
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
position: sticky;
|
||||||
|
top: 16px;
|
||||||
|
left: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes playlistArtworkFadeIn {
|
@keyframes playlistArtworkFadeIn {
|
||||||
|
|
|
@ -65,6 +65,11 @@
|
||||||
</template>
|
</template>
|
||||||
</transition>
|
</transition>
|
||||||
<!-- Playlist / Album page-->
|
<!-- Playlist / Album page-->
|
||||||
|
<transition name="wpfade">
|
||||||
|
<template v-if="modals.showPlaylist">
|
||||||
|
<playlist-inline :data="showingPlaylist"></playlist-inline>
|
||||||
|
</template>
|
||||||
|
</transition>
|
||||||
<transition name="wpfade">
|
<transition name="wpfade">
|
||||||
<template v-if="page.includes('playlist_')">
|
<template v-if="page.includes('playlist_')">
|
||||||
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
<cider-playlist :data="showingPlaylist"></cider-playlist>
|
||||||
|
|
507
src/renderer/views/pages/playlist-inline.ejs
Normal file
507
src/renderer/views/pages/playlist-inline.ejs
Normal file
|
@ -0,0 +1,507 @@
|
||||||
|
<script type="text/x-template" id="playlist-inline">
|
||||||
|
<div class="content-inner playlist-page inline-playlist" @click.self="$root.modals.showPlaylist = false">
|
||||||
|
<div class="playlist-inner" v-if="data != [] && data.attributes != null">
|
||||||
|
<div class="close-btn" title="Close" @click="$root.modals.showPlaylist = false">
|
||||||
|
<svg fill="white" xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"
|
||||||
|
aria-role="presentation" focusable="false">
|
||||||
|
<path
|
||||||
|
d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
||||||
|
fill-rule="nonzero"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<template v-if="app.playlists.loadingState == 0">
|
||||||
|
<div class="content-inner centered">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="app.playlists.loadingState == 1">
|
||||||
|
<div class="playlist-display"
|
||||||
|
:style="{
|
||||||
|
'--bgColor': (data.attributes.artwork != null && data.attributes.artwork['bgColor'] != null) ? ('#' + data.attributes.artwork.bgColor) : '',
|
||||||
|
'--textColor': (data.attributes.artwork != null && data.attributes.artwork['textColor1'] != null) ? ('#' + data.attributes.artwork.textColor1) : ''
|
||||||
|
}">
|
||||||
|
<div class="playlistInfo">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto flex-center">
|
||||||
|
<div style="width: 260px;height:260px;">
|
||||||
|
<mediaitem-artwork
|
||||||
|
shadow="large"
|
||||||
|
:video-priority="true"
|
||||||
|
:url="(data.attributes != null && data.attributes.artwork != null) ? data.attributes.artwork.url : ((data.relationships != null && data.relationships.tracks.data.length > 0 && data.relationships.tracks.data[0].attributes != null) ? ((data.relationships.tracks.data[0].attributes.artwork != null)? data.relationships.tracks.data[0].attributes.artwork.url : ''):'')"
|
||||||
|
:video="(data.attributes != null && data.attributes.editorialVideo != null) ? (data.attributes.editorialVideo.motionDetailSquare ? data.attributes.editorialVideo.motionDetailSquare.video : (data.attributes.editorialVideo.motionSquareVideo1x1 ? data.attributes.editorialVideo.motionSquareVideo1x1.video : '')) : '' "
|
||||||
|
size="260"
|
||||||
|
></mediaitem-artwork>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col playlist-info">
|
||||||
|
<template v-if="!editorialNotesExpanded">
|
||||||
|
<div>
|
||||||
|
<div class="playlist-name" @click="editPlaylistName()" v-show="!nameEditing">
|
||||||
|
{{data.attributes ? (data.attributes.name ??
|
||||||
|
(data.attributes.title ?? '') ?? '') : ''}}
|
||||||
|
</div>
|
||||||
|
<div class="playlist-name" v-show="nameEditing"><input type="text" spellcheck="false"
|
||||||
|
class="nameEdit"
|
||||||
|
v-model="data.attributes.name"
|
||||||
|
@blur="editPlaylist"
|
||||||
|
@change="editPlaylist"
|
||||||
|
@keydown.enter="editPlaylist"/></div>
|
||||||
|
<div class="playlist-artist item-navigate"
|
||||||
|
v-if="getArtistName(data) != ''"
|
||||||
|
@click="data.attributes && data.attributes.artistName ? app.searchAndNavigate(data,'artist') : ''">
|
||||||
|
{{getArtistName(data)}}
|
||||||
|
</div>
|
||||||
|
<div class="playlist-desc" v-if="data.attributes.description && (data.attributes.description.standard || data.attributes.description.short)">
|
||||||
|
<div v-if="data.attributes.description.short" class="content" v-html="data.attributes.description.short"></div>
|
||||||
|
<div v-else-if="data.attributes.description.standard" class="content" v-html="data.attributes.description.standard"></div>
|
||||||
|
<button v-if="data.attributes.description.short" class="more-btn"
|
||||||
|
@click="editorialNotesExpanded = !editorialNotesExpanded">
|
||||||
|
{{app.getLz('term.showMore')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="editorialNotesExpanded">
|
||||||
|
<div class="playlist-desc-expanded">
|
||||||
|
<div class="content"
|
||||||
|
v-html="((data.attributes.editorialNotes) ? (data.attributes.editorialNotes.standard ?? (data.attributes.editorialNotes.short ?? '') ) : (data.attributes.description ? (data.attributes.description.standard ?? (data.attributes.description.short ?? '')) : ''))"></div>
|
||||||
|
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">{{app.getLz('term.showLess')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="playlist-controls" v-observe-visibility="{callback: isHeaderVisible}">
|
||||||
|
<button class="md-btn md-btn-primary md-btn-icon" style="min-width: 100px;"
|
||||||
|
@click="app.mk.shuffleMode = 0; play()"> <img class="md-ico-play">
|
||||||
|
{{app.getLz('term.play')}}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-primary md-btn-icon" style="min-width: 100px;"
|
||||||
|
@click="app.mk.shuffleMode = 1;play()"> <img class="md-ico-shuffle">
|
||||||
|
{{app.getLz('term.shuffle')}}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-icon" style="min-width: 180px;" v-if="inLibrary!=null && confirm!=true"
|
||||||
|
@click="confirmButton()"> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
|
||||||
|
{{ (!inLibrary) ? app.getLz('action.addToLibrary') : app.getLz("action.removeFromLibrary") }}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-icon" style="min-width: 180px;" v-if="confirm==true"
|
||||||
|
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) "> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
|
||||||
|
{{app.getLz('term.confirm')}}
|
||||||
|
</button>
|
||||||
|
<button class="more-btn-round" style="float:right;" @click="menu">
|
||||||
|
<div class="svg-icon"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="artworkContainer" v-if="data.attributes.artwork != null">
|
||||||
|
<artwork-material :url="data.attributes.artwork.url" size="260" images="1"></artwork-material>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="floating-header" :style="{opacity: (headerVisible ? 0 : 1),'pointer-events': (headerVisible ? 'none' : '')}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{data.attributes ? (data.attributes.name ??
|
||||||
|
(data.attributes.title ?? '') ?? '') : ''}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto flex-center">
|
||||||
|
<div>
|
||||||
|
<button class="md-btn md-btn-primary md-btn-icon" style="min-width: 100px;"
|
||||||
|
@click="app.mk.shuffleMode = 0; play()"> <img class="md-ico-play">
|
||||||
|
{{app.getLz('term.play')}}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-primary md-btn-icon" style="min-width: 100px;"
|
||||||
|
@click="app.mk.shuffleMode = 1;play()"> <img class="md-ico-shuffle">
|
||||||
|
{{app.getLz('term.shuffle')}}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-icon" style="min-width: 180px;" v-if="inLibrary!=null && confirm!=true"
|
||||||
|
@click="confirmButton()"> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
|
||||||
|
{{ (!inLibrary) ? app.getLz('action.addToLibrary') : app.getLz("action.removeFromLibrary") }}
|
||||||
|
</button>
|
||||||
|
<button class="md-btn md-btn-icon" style="min-width: 180px;" v-if="confirm==true"
|
||||||
|
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) "> <img :class="(!inLibrary) ? 'md-ico-add' : 'md-ico-remove'">
|
||||||
|
{{app.getLz('term.confirm')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto flex-center">
|
||||||
|
<button class="more-btn-round" style="float:right;" @click="menu">
|
||||||
|
<div class="svg-icon"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="playlist-body">
|
||||||
|
<div class="well">
|
||||||
|
<div style="width:100%">
|
||||||
|
<draggable :sort="data.attributes.canEdit && data.type == 'library-playlists'"
|
||||||
|
v-model="data.relationships.tracks.data" @start="drag=true" @end="drag=false;put()">
|
||||||
|
<mediaitem-list-item :item="item" :parent="getItemParent(data)" :index="index" :showIndex="true" :showIndexPlaylist="(data.attributes.playParams.kind ?? data.type ?? '').includes('playlist')"
|
||||||
|
:context-ext="buildContextMenu()"
|
||||||
|
v-for="(item,index) in data.relationships.tracks.data"></mediaitem-list-item>
|
||||||
|
</draggable>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="friends-info" v-if="itemBadges.length != 0">
|
||||||
|
<div class="well">
|
||||||
|
<div class="badge-container">
|
||||||
|
<div class="socialBadge" :title="`${badge.attributes.name} - @${badge.attributes.handle}`"
|
||||||
|
v-for="badge in itemBadges">
|
||||||
|
<mediaitem-artwork
|
||||||
|
:url="badge.attributes.artwork.url"
|
||||||
|
:size="60"></mediaitem-artwork>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="playlist-time">
|
||||||
|
{{getFormattedDate()}}
|
||||||
|
</div>
|
||||||
|
<div class="playlist-time total">{{app.getTotalTime()}}</div>
|
||||||
|
<div class="playlist-time item-navigate" @click="app.searchAndNavigate(data,'recordLabel') "
|
||||||
|
style="width: 50%;">
|
||||||
|
{{data.attributes.copyright}}
|
||||||
|
</div>
|
||||||
|
<template v-if="(data.attributes?.playParams?.kind ?? data.type ?? '').includes('album') && data.relationships.catalog != null && data.relationships.catalog != null && data.relationships.catalog.data.length > 0">
|
||||||
|
<div class="playlist-time showExtended item-navigate" style="color:#fa586a; font-weight: bold" @click="app.routeView(data.relationships.catalog.data[0])">
|
||||||
|
{{$root.getLz("action.showAlbum")}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<hr>
|
||||||
|
<template v-if="typeof data.meta != 'undefined'">
|
||||||
|
<div v-for="view in data.meta.views.order" v-if="data.views[view].data.length != 0">
|
||||||
|
<div class="row" >
|
||||||
|
<div class="col">
|
||||||
|
<h3>{{ data.views[view].attributes.title }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mediaitem-scroller-horizontal :items="data.views[view].data"></mediaitem-scroller-horizontal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Vue.component('playlist-inline', {
|
||||||
|
template: "#playlist-inline",
|
||||||
|
props: ["data"],
|
||||||
|
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
editorialNotesExpanded: false,
|
||||||
|
drag: false,
|
||||||
|
nameEditing: false,
|
||||||
|
inLibrary: null,
|
||||||
|
confirm: false,
|
||||||
|
app: this.$root,
|
||||||
|
itemBadges: [],
|
||||||
|
badgesRequested: false,
|
||||||
|
headerVisible: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
this.$nextTick(function () {
|
||||||
|
this.isInLibrary()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
data: function () {
|
||||||
|
this.isInLibrary()
|
||||||
|
this.getBadges()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isHeaderVisible(visible) {
|
||||||
|
this.headerVisible = visible
|
||||||
|
},
|
||||||
|
getBadges() {
|
||||||
|
return
|
||||||
|
if (this.badgesRequested) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.badgesRequested = true
|
||||||
|
this.itemBadges = []
|
||||||
|
let self = this
|
||||||
|
var id = 0
|
||||||
|
try {
|
||||||
|
id = this.data.attributes.playParams.id
|
||||||
|
} catch (e) {
|
||||||
|
id = this.data.id
|
||||||
|
}
|
||||||
|
this.$root.getSocialBadges((badges) => {
|
||||||
|
let friends = badges[id]
|
||||||
|
if (friends) {
|
||||||
|
friends.forEach(function (friend) {
|
||||||
|
self.app.mk.api.v3.music(`/v1/social/${app.mk.storefrontId}/social-profiles/${friend}`).then(data => {
|
||||||
|
self.itemBadges.push(data.data.data[0])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
confirmButton() {
|
||||||
|
// Return button to normal state after 3 seconds
|
||||||
|
|
||||||
|
this.confirm = true
|
||||||
|
setTimeout(() => this.confirm = false, 3000);
|
||||||
|
},
|
||||||
|
getArtistName(data) {
|
||||||
|
console.log(data.attributes)
|
||||||
|
if (data.attributes.artistName) {
|
||||||
|
return data.attributes.artistName
|
||||||
|
} else if (data.attributes.artist) {
|
||||||
|
return data.attributes.artist.attributes.name
|
||||||
|
} else if (data.attributes.curatorName) {
|
||||||
|
return data.attributes.curatorName
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async isInLibrary() {
|
||||||
|
if (this.data.type && !this.data.type.includes("library")) {
|
||||||
|
// please keep using vars here
|
||||||
|
const params = {
|
||||||
|
"fields[playlists]": "inLibrary",
|
||||||
|
"fields[albums]": "inLibrary",
|
||||||
|
"relate": "library"
|
||||||
|
};
|
||||||
|
const res = await app.mkapi(this.data.attributes.playParams.kind ?? this.data.type, this.data.attributes.playParams.isLibrary ?? false, this.data.attributes.playParams.id ?? this.data.id, params);
|
||||||
|
this.inLibrary = (res.data.data[0] && res.data.data[0].attributes && res.data.data[0].attributes.inLibrary) ? res.data.data[0].attributes.inLibrary : false
|
||||||
|
console.log(res)
|
||||||
|
} else {
|
||||||
|
this.inLibrary = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editPlaylist() {
|
||||||
|
this.app.editPlaylist(this.data.id, this.data.attributes.name);
|
||||||
|
this.app.playlists.listing.forEach(playlist => {
|
||||||
|
if (playlist.id === this.data.id) {
|
||||||
|
playlist.attributes.name = this.data.attributes.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.nameEditing = false
|
||||||
|
},
|
||||||
|
addToLibrary(id) {
|
||||||
|
app.mk.addToLibrary(id)
|
||||||
|
this.inLibrary = true
|
||||||
|
this.confirm = false
|
||||||
|
},
|
||||||
|
async removeFromLibrary(id) {
|
||||||
|
const params = {"fields[somgs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library"};
|
||||||
|
var id = this.data.id ?? this.data.attributes.playParams.id
|
||||||
|
const res = await app.mkapi(this.data.attributes.playParams.kind ?? this.data.type, this.data.attributes.playParams.isLibrary ?? false, this.data.attributes.playParams.id ?? this.data.id, params);
|
||||||
|
if (res.data.data[0] && res.data.data[0].relationships && res.data.data[0].relationships.library && res.data.data[0].relationships.library.data && res.data.data[0].relationships.library.data.length > 0) {
|
||||||
|
id = res.data.data[0].relationships.library.data[0].id
|
||||||
|
}
|
||||||
|
let kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
||||||
|
const truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
|
app.mk.api.v3.music(`v1/me/library/${truekind}/${id.toString()}`,{},
|
||||||
|
{
|
||||||
|
fetchOptions: {
|
||||||
|
method: "DELETE"
|
||||||
|
}})
|
||||||
|
this.inLibrary = false
|
||||||
|
this.confirm = false
|
||||||
|
},
|
||||||
|
editPlaylistName() {
|
||||||
|
if (this.data.attributes.canEdit && this.data.type === "library-playlists") {
|
||||||
|
this.nameEditing = true
|
||||||
|
setTimeout(() => {
|
||||||
|
document.querySelector(".nameEdit").focus()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buildContextMenu(index) {
|
||||||
|
let self = this
|
||||||
|
if (!this.data.attributes.canEdit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
normal: [
|
||||||
|
{
|
||||||
|
name: app.getLz('action.removeFromPlaylist'),
|
||||||
|
action: () => {
|
||||||
|
self.remove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
multiple: [
|
||||||
|
{
|
||||||
|
name: app.getLz('action.removeFromPlaylist'),
|
||||||
|
action: () => {
|
||||||
|
self.remove()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async put() {
|
||||||
|
if (!this.data.attributes.canEdit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('sds',this.convert())
|
||||||
|
await app.mk.api.v3.music(
|
||||||
|
`/v1/me/library/playlists/${this.data.attributes.playParams.id}/tracks`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
fetchOptions: {
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify({
|
||||||
|
data: this.convert()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
async remove() {
|
||||||
|
if (!this.data.attributes.canEdit) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// for each app.selectedMediaItems splice the items from the playlist
|
||||||
|
for (let i = 0; i < app.selectedMediaItems.length; i++) {
|
||||||
|
let item = app.selectedMediaItems[i]
|
||||||
|
let index = this.data.relationships.tracks.data.findIndex(x => x.id == item.id)
|
||||||
|
if (index > -1) {
|
||||||
|
this.data.relationships.tracks.data.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.put()
|
||||||
|
},
|
||||||
|
convert() {
|
||||||
|
let pl_tracks = []
|
||||||
|
for (let i = 0; i < this.data.relationships.tracks.data.length; i++) {
|
||||||
|
pl_tracks.push({
|
||||||
|
id: this.data.relationships.tracks.data[i].id,
|
||||||
|
type: this.data.relationships.tracks.data[i].type
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return pl_tracks
|
||||||
|
},
|
||||||
|
getRecursive(url) {
|
||||||
|
app.apiCall(app.musicBaseUrl + "/v1/me/library/playlists/p.V7VYlrDso6kkYY/tracks?offset=100", res => {
|
||||||
|
this.data.relationships.tracks.data = this.data.relationships.tracks.data.concat(res.data.data)
|
||||||
|
if (res.data.next) {
|
||||||
|
this.getRecursive(res.data.next)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
menu(event) {
|
||||||
|
app.showMenuPanel({
|
||||||
|
items: {
|
||||||
|
"share": {
|
||||||
|
name: app.getLz('term.share'),
|
||||||
|
icon: "./assets/feather/share.svg",
|
||||||
|
action: () => {
|
||||||
|
let route = ""
|
||||||
|
switch (this.data.type) {
|
||||||
|
case 'albums':
|
||||||
|
route = `/v1/catalog/${app.mk.storefrontId}/albums/${this.data.id}`
|
||||||
|
break;
|
||||||
|
case 'playlists':
|
||||||
|
route = `/v1/catalog/${app.mk.storefrontId}/playlists/${this.data.id}`
|
||||||
|
break;
|
||||||
|
case "library-playlists":
|
||||||
|
route = `/v1/me/library/playlists/${this.data.id}/catalog`
|
||||||
|
break
|
||||||
|
case "library-albums":
|
||||||
|
route = `/v1/me/library/albums/${this.data.id}/catalog`
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (route === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.mk.api.v3.music(route).then(res => {
|
||||||
|
console.log(res.data.data[0].attributes.url)
|
||||||
|
app.copyToClipboard(res.data.data[0].attributes.url)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, event)
|
||||||
|
},
|
||||||
|
getItemParent: function (data) {
|
||||||
|
kind = data.attributes.playParams.kind;
|
||||||
|
id = data.attributes.playParams.id;
|
||||||
|
return `${kind}:${id}`
|
||||||
|
},
|
||||||
|
getFormattedDate: function () {
|
||||||
|
let date = (this.data.attributes.releaseDate ?? (this.data.attributes.lastModifiedDate ?? (this.data.attributes.dateAdded ?? '')))
|
||||||
|
let prefix = '';
|
||||||
|
if (date == null || date === "") return "";
|
||||||
|
switch (date) {
|
||||||
|
case this.data.attributes.releaseDate:
|
||||||
|
prefix = this.app.getLz('term.time.released')+ ' '
|
||||||
|
break;
|
||||||
|
case this.data.attributes.lastModifiedDate:
|
||||||
|
prefix = this.app.getLz('term.time.updated')+ ' '
|
||||||
|
break;
|
||||||
|
case this.data.attributes.dateAdded:
|
||||||
|
prefix = this.app.getLz('term.time.added')+ ' '
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let month, year;
|
||||||
|
try {
|
||||||
|
const releaseDate = new Date(date);
|
||||||
|
// month = new Intl.DateTimeFormat(this.app.cfg.general.language.replace('_','-'), {month: 'long'}).format(releaseDate);
|
||||||
|
// date = releaseDate.getDate();
|
||||||
|
// year = releaseDate.getFullYear();
|
||||||
|
let formatted = ''
|
||||||
|
try {formatted = new Intl.DateTimeFormat(this.app.cfg.general.language?.replace('_','-') ?? 'en-US', {day:'numeric',month: 'long', year: 'numeric'}).format(releaseDate);}
|
||||||
|
catch(e){
|
||||||
|
// use the format in json instead
|
||||||
|
if (this.app.getLz('date.format') != null){
|
||||||
|
formatted = new this.app.getLz('date.format').replace("${d}", releaseDate.getDate()).replace("${m}", releaseDate.getMonth()).replace("${y}", releaseDate.getFullYear());
|
||||||
|
} else {
|
||||||
|
formatted = new Intl.DateTimeFormat('en-US', {day:'numeric',month: 'long', year: 'numeric'}).format(releaseDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prefix + formatted
|
||||||
|
} catch (e) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
play() {
|
||||||
|
function shuffleArray(array) {
|
||||||
|
for (var i = array.length - 1; i > 0; i--) {
|
||||||
|
var j = Math.floor(Math.random() * (i + 1));
|
||||||
|
var temp = array[i];
|
||||||
|
array[i] = array[j];
|
||||||
|
array[j] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = this.data.attributes.playParams.id ?? this.data.id;
|
||||||
|
//console.log("1")
|
||||||
|
const kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
||||||
|
//console.log("1")
|
||||||
|
const truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||||
|
|
||||||
|
let query = (this.data ?? app.showingPlaylist).relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||||
|
app.mk.stop().then(function () {
|
||||||
|
app.mk.setQueue({[truekind]: [id]}).then(function () {
|
||||||
|
app.mk.play().then(function () {
|
||||||
|
if (query.length > 100) {
|
||||||
|
let u = query.slice(100);
|
||||||
|
if (app.mk.shuffleMode == 1) {
|
||||||
|
shuffleArray(u)
|
||||||
|
}
|
||||||
|
app.mk.queue.append(u)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -596,6 +596,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="md-option-line">
|
||||||
|
<div class="md-option-segment">
|
||||||
|
Inline Playlists and Albums
|
||||||
|
</div>
|
||||||
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
|
<input type="checkbox" v-model="app.cfg.advanced.experiments.includes('inline-playlists')" @click="app.cfg.advanced.experiments.includes('inline-playlists') ? removeExperiment('inline-playlists') : addExperiment('inline-playlists')" switch/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('term.language')}}
|
{{$root.getLz('term.language')}}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue