Merge branch 'main' into main-ts
|
@ -26,7 +26,6 @@
|
|||
"@sentry/electron": "^2.5.4",
|
||||
"discord-rpc": "^4.0.1",
|
||||
"ejs": "^3.1.6",
|
||||
"electron-acrylic-window": "^0.5.11",
|
||||
"electron-fetch": "^1.7.4",
|
||||
"electron-log": "^4.4.4",
|
||||
"electron-store": "^8.0.1",
|
||||
|
@ -37,6 +36,7 @@
|
|||
"lastfmapi": "^0.1.1",
|
||||
"mpris-service": "^2.1.2",
|
||||
"music-metadata": "^7.11.4",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
|
|
|
@ -23260,9 +23260,36 @@
|
|||
}
|
||||
if (null != (l = "string" != typeof (h = g.pathwayID) ? im("invalid steering manifest PATHWAY-PRIORITY list item data type") : /^[\w\-\.]+$/.test(h) ? void 0 : im("steering manifest contains invalid pathway ID: " + h)))
|
||||
break;
|
||||
if (g.hdcpLevel === "NONE"){
|
||||
n.push(g)}
|
||||
let cpc = g.allowedCPCMap ? JSON.stringify(g.allowedCPCMap) : "null";
|
||||
if (!cpc.includes("WIDEVINE_HARDWARE") && !g.url.includes('trickPlay') && !g.videoCodec.includes("hvc1"))
|
||||
n.push(g)
|
||||
}
|
||||
|
||||
|
||||
|
||||
try{
|
||||
// console.log(n, window.screen.width)
|
||||
let ok = (n.map( function(item){return{height : item.height, content: item}}));
|
||||
let screenHeight = (app.cfg.visual.videoRes ?? window.screen.height) ;
|
||||
ok.sort(function (a, b) {
|
||||
return a.height - b.height;
|
||||
});
|
||||
for (var i = 0; i < ok.length; i++){
|
||||
if (ok[i].height > screenHeight){
|
||||
if (i == 0){n.splice(0,n.length);n.push(ok[i].content)}
|
||||
else{n.splice(0,n.length);n.push(ok[i-1].content)}
|
||||
console.log('selected' , n[0].height)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (n.length > 1){
|
||||
n.splice(0,n.length - 1);
|
||||
}
|
||||
// console.log(n)
|
||||
// console.log(ok)
|
||||
} catch (e){ console.log(e)}
|
||||
return {
|
||||
variantMediaOptions: n,
|
||||
contentSteeringOption: u,
|
||||
|
|
26
src/renderer/assets/arrow-bend-down.svg
Normal file
|
@ -0,0 +1,26 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="256px" height="256px" viewBox="0 0 256 256" id="Flat">
|
||||
<path d="M236,56A108.12186,108.12186,0,0,1,128,164H60.9707l27.51465,27.51465a12.0001,12.0001,0,0,1-16.9707,16.9707l-48-48c-.02954-.02978-.054-.0625-.08325-.09228-.24683-.252-.48536-.51172-.70948-.78467-.12378-.15039-.23169-.30908-.34692-.46387-.118-.15869-.24109-.31348-.35132-.478-.1206-.18017-.22534-.3667-.33508-.55127-.09021-.15185-.18567-.2998-.26917-.45605-.10009-.18652-.18493-.37842-.27429-.56885-.07727-.16455-.15954-.32617-.22961-.49463-.07678-.18554-.139-.375-.20618-.56347-.06482-.18164-.1344-.35987-.19067-.54541-.05725-.189-.09961-.38135-.14734-.57325-.04712-.188-.10022-.374-.13819-.56543-.04406-.22168-.07055-.44482-.102-.668-.02307-.165-.05468-.32666-.07116-.49366a12.08048,12.08048,0,0,1,0-2.373c.01648-.167.04809-.32862.07116-.49366.0315-.22314.058-.44628.102-.668.038-.19141.09107-.37745.13819-.56543.04773-.1919.09009-.38428.14734-.57373.05627-.18506.12585-.36329.19055-.54493.06714-.18847.12939-.37793.2063-.56347.07007-.16846.15234-.33008.22973-.49463.08936-.19043.1742-.38233.27417-.56885.0835-.15625.179-.3042.26917-.45605.10974-.18457.21448-.3711.33508-.55127.11023-.16455.23328-.31934.35132-.478.11523-.15479.22314-.31348.34692-.46387.22412-.273.46265-.53271.70948-.78467.02929-.02978.05371-.0625.08325-.09228l48-48a12.0001,12.0001,0,0,1,16.9707,16.9707L60.9707,140H128a84.09562,84.09562,0,0,0,84-84,12,12,0,0,1,24,0Z"/>
|
||||
</svg>
|
||||
|
||||
|
||||
<!-- MIT License
|
||||
|
||||
Copyright (c) 2020-2021 Phosphor Icons
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE. -->
|
After Width: | Height: | Size: 2.5 KiB |
25
src/renderer/assets/arrow-bend-up.svg
Normal file
|
@ -0,0 +1,25 @@
|
|||
<svg width="256px" height="256px" viewBox="0 0 256 256" id="Flat" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M236,200a12,12,0,0,1-24,0,84.09562,84.09562,0,0,0-84-84H60.9707l27.51465,27.51465a12.0001,12.0001,0,0,1-16.9707,16.9707l-48-48c-.02954-.02954-.054-.06225-.08325-.092-.24683-.25195-.48536-.51221-.70948-.78491-.12378-.15064-.23169-.30908-.34692-.46411-.118-.15869-.24109-.31324-.35132-.47779-.1206-.17993-.22534-.3667-.33508-.55151-.09021-.15161-.18567-.29956-.26917-.45557-.10009-.18676-.18493-.37866-.27429-.56933-.07727-.16455-.15954-.32593-.22961-.49463-.07678-.1853-.139-.37476-.20618-.56323-.06482-.1814-.1344-.35987-.19067-.54517-.05725-.18945-.09961-.38184-.14734-.57324-.04712-.18848-.10022-.374-.13819-.56592-.04406-.22144-.07055-.44482-.102-.66772-.02307-.165-.05468-.32691-.07116-.49366a12.08048,12.08048,0,0,1,0-2.373c.01648-.16675.04809-.32862.07116-.49366.0315-.2229.058-.44628.102-.66772.038-.1919.09107-.37744.13819-.56592.04773-.1914.09009-.38379.14734-.57324.05627-.1853.12585-.36377.19055-.54492.06714-.18848.12939-.37818.2063-.56372.07007-.16846.15234-.33008.22973-.49463.08936-.19068.1742-.38233.27417-.56909.0835-.156.179-.304.26917-.45557.10974-.18481.21448-.37158.33508-.55151.11023-.16455.23328-.3191.35132-.47779.11523-.155.22314-.31347.34692-.46411.22412-.2727.46265-.533.70948-.78491.02929-.02979.05371-.0625.08325-.092l48-48a12.0001,12.0001,0,0,1,16.9707,16.9707L60.9707,92H128A108.12186,108.12186,0,0,1,236,200Z"/>
|
||||
</svg>
|
||||
|
||||
<!-- MIT License
|
||||
|
||||
Copyright (c) 2020-2021 Phosphor Icons
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE. -->
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/renderer/assets/banner.png
Normal file
After Width: | Height: | Size: 35 KiB |
1
src/renderer/assets/ko_fi.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg fill="none" height="391" viewBox="0 0 391 391" width="391" xmlns="http://www.w3.org/2000/svg"><path d="m52 102h296v199h-296z" fill="#fff"/><path d="m174 1.09995c-79.2999 8.9-145.5999 65.29995-166.59995 141.70005-15.2 55.6-5.8 114 26.10005 161.7 61.7 92.3 189.4999 114.2 278.7999 47.8 74.8-55.8 99.8-156.6 59.7-241-9.7-20.3001-20.4-35.6001-36.4-52.2001-27.2-27.9-61.3-46.7-99.6-54.99995-18.3-3.900005-43.3-5.1-62-3zm117.8 102.90005c25.2 7 43.6 24.6 50.2 48 7.8 28.1-.1 55.6-21.5 73.9-11.5 9.8-32.5 17.1-49.6 17.1h-7.6l-.8 7.2c-1.9 19.4-11.4 32.5-27 37-2.9.9-25.2 1.2-80 1.2l-75.9999.1-6-2.8c-9.6-4.5-16.9-12.7-19.7-22.2-.4-1.6-.8-36.6-.8-77.8 0-80.7 0-80.6 5.2-82.7 1.4-.5 48.5999-.9 114.2999-.9 109.5-.1 112.2-.1 119.3 1.9z" fill="#579fbf"/><path d="m264 173v34h8.8c15.5 0 25-5.3 31.2-17.4 3.3-6.6 3.5-7.4 3.5-17.5 0-9.6-.3-11.1-2.8-16.3-3-6.2-8.6-11.6-15.2-14.8-3.3-1.6-6.2-2-14.8-2h-10.7z" fill="#579fbf"/><path d="m177.885 147.41c-7.3 2.4-9.6 3.7-15.3 8.4l-4.7 3.9-4.3-3.5c-14.2-11.6-35-12.9-46.7-2.9-5.8 5-8.1996 10.3-8.7996 19.4-.5 8.1 1.2 15.8 4.9996 23.2 1.1 2.2 5.9 8 10.6 13 14.7 15.3 42.4 40.7 44.4 40.7 1.2 0 12.1-10.1 27.3-25.3 22.9-22.8 25.7-25.9 28.6-32.1 4.1-8.7 5-18.8 2.5-26.4-4.9-14.6-23.4-23.4-38.6-18.4z" fill="#ff5f5f"/></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/renderer/assets/open_collective.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg height="38" viewBox="0 0 38 38" width="38" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="m34.6194245 8.17880011c2.1314244 3.07072649 3.3805755 6.80008579 3.3805755 10.82119989s-1.2491511 7.7504734-3.3805755 10.8211999l-4.9217466-4.9217466c.9664963-1.748848 1.5166078-3.7599079 1.5166078-5.8994533s-.5501115-4.1506053-1.5166078-5.8994533zm-4.7982246-4.79822459-4.9217466 4.92174663c-1.748848-.96649637-3.7599079-1.51660786-5.8994533-1.51660786-6.7457637 0-12.21428571 5.46852201-12.21428571 12.21428571s5.46852201 12.2142857 12.21428571 12.2142857c2.1395454 0 4.1506053-.5501115 5.8994533-1.5166078l4.9217466 4.9217466c-3.0707265 2.1314244-6.8000858 3.3805755-10.8211999 3.3805755-10.49341025 0-19-8.5065898-19-19 0-10.49341025 8.50658975-19 19-19 4.0211141 0 7.7504734 1.24915112 10.8211999 3.38057552z" fill="#7fadf2"/><path d="m34.6194245 8.17880011c2.1314244 3.07072649 3.3805755 6.80008579 3.3805755 10.82119989s-1.2491511 7.7504734-3.3805755 10.8211999l-4.9217466-4.9217466c.9664963-1.748848 1.5166078-3.7599079 1.5166078-5.8994533s-.5501115-4.1506053-1.5166078-5.8994533z" fill="#b8d3f4"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -52,7 +52,7 @@ var CiderContextMenu = {
|
|||
}
|
||||
item.tabIndex = 0
|
||||
item.classList.add("context-menu-item")
|
||||
if(menudata.items[i]["icon"]) {
|
||||
if (menudata.items[i]["icon"]) {
|
||||
item.innerHTML += `<div class="sidebar-icon">${await app.getSvgIcon(menudata.items[i]["icon"])}</div>`
|
||||
}
|
||||
item.innerHTML += menudata.items[i].name
|
||||
|
@ -290,7 +290,18 @@ const app = new Vue({
|
|||
},
|
||||
socialBadges: {
|
||||
badgeMap: {},
|
||||
version: ""
|
||||
version: "",
|
||||
mediaItems: [],
|
||||
mediaItemDLState: 0 // 0 = not started, 1 = in progress, 2 = complete
|
||||
},
|
||||
menuPanel: {
|
||||
visible: false,
|
||||
event: null,
|
||||
content: {
|
||||
name: "",
|
||||
items: {},
|
||||
headerItems: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -315,6 +326,53 @@ const app = new Vue({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
async showSocialListeningTo() {
|
||||
let contentIds = Object.keys(app.socialBadges.badgeMap)
|
||||
app.showCollection({data: this.socialBadges.mediaItems}, "Friends Listening To", "albums")
|
||||
if(this.socialBadges.mediaItemDLState == 1 || this.socialBadges.mediaItemDLState == 2) {
|
||||
return
|
||||
}
|
||||
this.socialBadges.mediaItemDLState = 2
|
||||
await asyncForEach(contentIds, async (item)=>{
|
||||
try {
|
||||
let type = "albums"
|
||||
if(item.includes("pl.")) {
|
||||
type = "playlists"
|
||||
}
|
||||
if(item.includes("ra.")) {
|
||||
type = "stations"
|
||||
}
|
||||
let found = await app.mk.api.v3.music(`/v1/catalog/us/${type}/${item}`)
|
||||
this.socialBadges.mediaItems.push(found.data.data[0])
|
||||
}catch(e){
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
async openAppleMusicURL(url) {
|
||||
let properties = MusicKit.formattedMediaURL(url)
|
||||
let item = {
|
||||
id: properties.contentId,
|
||||
attributes: {
|
||||
playParams: {
|
||||
id: properties.contentId,
|
||||
kind: properties.kind,
|
||||
}
|
||||
},
|
||||
type: properties.kind,
|
||||
kind: properties.kind
|
||||
}
|
||||
app.routeView(item)
|
||||
},
|
||||
async showMenuPanel(data, event) {
|
||||
app.menuPanel.visible = true;
|
||||
app.menuPanel.content.name = data.name ?? "";
|
||||
app.menuPanel.content.items = data.items ?? {};
|
||||
app.menuPanel.content.headerItems = data.headerItems ?? {};
|
||||
if(event) {
|
||||
app.menuPanel.event = event;
|
||||
}
|
||||
},
|
||||
async getSvgIcon(url) {
|
||||
let response = await fetch(url);
|
||||
let data = await response.text();
|
||||
|
@ -353,22 +411,11 @@ const app = new Vue({
|
|||
history.forward()
|
||||
},
|
||||
getHTMLStyle() {
|
||||
switch (this.cfg.visual.window_transparency) {
|
||||
case "acrylic":
|
||||
default:
|
||||
document.querySelector("html").style.background = "";
|
||||
document.querySelector("body").style.background = "";
|
||||
document.querySelector("body").classList.remove("notransparency")
|
||||
break;
|
||||
case "disabled":
|
||||
document.querySelector("html").style.background = "#222";
|
||||
document.querySelector("body").classList.add("notransparency")
|
||||
|
||||
// document.querySelector("body").style.background = "#222";
|
||||
break;
|
||||
}
|
||||
document.querySelector("html").style.background = "#222";
|
||||
document.querySelector("body").classList.add("notransparency")
|
||||
},
|
||||
resetState() {
|
||||
this.menuPanel.visible = false;
|
||||
app.selectedMediaItems = [];
|
||||
for (let key in app.modals) {
|
||||
app.modals[key] = false;
|
||||
|
@ -387,10 +434,12 @@ const app = new Vue({
|
|||
id: self.selectedMediaItems[i].id,
|
||||
type: self.selectedMediaItems[i].kind
|
||||
})
|
||||
} else if ((self.selectedMediaItems[i].kind == "album" || self.selectedMediaItems[i].kind == "albums") && self.selectedMediaItems[i].isLibrary != true ) {
|
||||
} else if ((self.selectedMediaItems[i].kind == "album" || self.selectedMediaItems[i].kind == "albums") && self.selectedMediaItems[i].isLibrary != true) {
|
||||
self.selectedMediaItems[i].kind = "albums"
|
||||
let res = await self.mk.api.albumRelationship(self.selectedMediaItems[i].id,"tracks");
|
||||
let ids = res.map(function(i) {return {id:i.id, type: i.type}})
|
||||
let res = await self.mk.api.albumRelationship(self.selectedMediaItems[i].id, "tracks");
|
||||
let ids = res.map(function (i) {
|
||||
return {id: i.id, type: i.type}
|
||||
})
|
||||
pl_items = pl_items.concat(ids)
|
||||
} else if (self.selectedMediaItems[i].kind == "library-song" || self.selectedMediaItems[i].kind == "library-songs") {
|
||||
self.selectedMediaItems[i].kind = "library-songs"
|
||||
|
@ -398,10 +447,12 @@ const app = new Vue({
|
|||
id: self.selectedMediaItems[i].id,
|
||||
type: self.selectedMediaItems[i].kind
|
||||
})
|
||||
} else if ((self.selectedMediaItems[i].kind == "library-album" || self.selectedMediaItems[i].kind == "library-albums") || (self.selectedMediaItems[i].kind == "album" && self.selectedMediaItems[i].isLibrary == true )) {
|
||||
} else if ((self.selectedMediaItems[i].kind == "library-album" || self.selectedMediaItems[i].kind == "library-albums") || (self.selectedMediaItems[i].kind == "album" && self.selectedMediaItems[i].isLibrary == true)) {
|
||||
self.selectedMediaItems[i].kind = "library-albums"
|
||||
let res = await self.mk.api.library.albumRelationship(self.selectedMediaItems[i].id,"tracks");
|
||||
let ids = res.map(function(i) {return {id:i.id, type: i.type}})
|
||||
let res = await self.mk.api.library.albumRelationship(self.selectedMediaItems[i].id, "tracks");
|
||||
let ids = res.map(function (i) {
|
||||
return {id: i.id, type: i.type}
|
||||
})
|
||||
pl_items = pl_items.concat(ids)
|
||||
} else {
|
||||
pl_items.push({
|
||||
|
@ -635,6 +686,11 @@ const app = new Vue({
|
|||
this.$forceUpdate()
|
||||
}, 500)
|
||||
},
|
||||
getAppClasses() {
|
||||
if (this.cfg.advanced.experiments.includes('compactui')) {
|
||||
return {compact: true}
|
||||
}
|
||||
},
|
||||
invokeDrawer(panel) {
|
||||
if (this.drawer.panel == panel && this.drawer.open) {
|
||||
if (panel == "lyrics") {
|
||||
|
@ -721,7 +777,7 @@ const app = new Vue({
|
|||
}
|
||||
]
|
||||
}
|
||||
CiderContextMenu.Create(event, menu)
|
||||
this.showMenuPanel(menu, event)
|
||||
},
|
||||
async editPlaylistFolder(id, name = "New Playlist") {
|
||||
let self = this
|
||||
|
@ -754,8 +810,8 @@ const app = new Vue({
|
|||
}
|
||||
}
|
||||
).then(res => {
|
||||
self.refreshPlaylists()
|
||||
})
|
||||
self.refreshPlaylists()
|
||||
})
|
||||
},
|
||||
copyToClipboard(str) {
|
||||
navigator.clipboard.writeText(str)
|
||||
|
@ -886,7 +942,9 @@ const app = new Vue({
|
|||
"fields[catalog]": "artistUrl,albumUrl",
|
||||
"fields[songs]": "artistUrl,albumUrl"
|
||||
}
|
||||
if (!transient) {this.playlists.loadingState = 0;}
|
||||
if (!transient) {
|
||||
this.playlists.loadingState = 0;
|
||||
}
|
||||
let playlistId = ''
|
||||
|
||||
try {
|
||||
|
@ -991,6 +1049,7 @@ const app = new Vue({
|
|||
return hash;
|
||||
},
|
||||
appRoute(route) {
|
||||
console.log(route)
|
||||
if (route == "" || route == "#" || route == "/") {
|
||||
return;
|
||||
}
|
||||
|
@ -1004,12 +1063,13 @@ const app = new Vue({
|
|||
let hash = route.split("/")
|
||||
let page = hash[0]
|
||||
let id = hash[1]
|
||||
console.log(`page: ${page} id: ${id}`)
|
||||
let isLibrary = hash[2] ?? false
|
||||
console.log(`page: ${page} id: ${id} isLibrary: ${isLibrary}`)
|
||||
this.routeView({
|
||||
kind: page,
|
||||
id: id,
|
||||
attributes: {
|
||||
playParams: {kind: page, id: id}
|
||||
playParams: {kind: page, id: id, isLibrary: isLibrary}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -1036,7 +1096,7 @@ const app = new Vue({
|
|||
document.querySelector("#app-content").scrollTop = 0
|
||||
} else if (kind.toString().includes("artist")) {
|
||||
app.getArtistInfo(id, isLibrary)
|
||||
window.location.hash = `${kind}/${id}`
|
||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||
document.querySelector("#app-content").scrollTop = 0
|
||||
|
||||
} else if (kind.toString().includes("record-label") || kind.toString().includes("curator")) {
|
||||
|
@ -1057,7 +1117,7 @@ const app = new Vue({
|
|||
let params = {extend: "editorialVideo"}
|
||||
app.page = (kind) + "_" + (id);
|
||||
app.getTypeFromID((kind), (id), (isLibrary), params);
|
||||
window.location.hash = `${kind}/${id}`
|
||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||
document.querySelector("#app-content").scrollTop = 0
|
||||
} else {
|
||||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||
|
@ -1198,81 +1258,81 @@ const app = new Vue({
|
|||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
console.log(kind, id, isLibrary)
|
||||
app.mk.stop().then(() => {
|
||||
if (kind.includes("artist")) {
|
||||
app.mk.setStationQueue({artist: 'a-' + id}).then(() => {
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
// else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))){
|
||||
// /* Randomize array in-place using Durstenfeld shuffle algorithm */
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// app.mk.clearQueue().then(function () { {
|
||||
// app.mk.setQueue({[truekind]: [item.attributes.playParams.id ?? item.id]}).then(function () {
|
||||
// app.mk.play().then(function (){
|
||||
// app.mk.clearQueue().then(function (){
|
||||
// var playlistId = id
|
||||
// const params = {
|
||||
// include: "tracks",
|
||||
// platform: "web",
|
||||
// "include[library-playlists]": "catalog,tracks",
|
||||
// "fields[playlists]": "curatorName,playlistType,name,artwork,url",
|
||||
// "include[library-songs]": "catalog,artists,albums",
|
||||
// "fields[catalog]": "artistUrl,albumUrl",
|
||||
// "fields[songs]": "artistUrl,albumUrl"
|
||||
// }
|
||||
// var playlistId = ''
|
||||
if (kind.includes("artist")) {
|
||||
app.mk.setStationQueue({artist: 'a-' + id}).then(() => {
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
// else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))){
|
||||
// /* Randomize array in-place using Durstenfeld shuffle algorithm */
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// app.mk.clearQueue().then(function () { {
|
||||
// app.mk.setQueue({[truekind]: [item.attributes.playParams.id ?? item.id]}).then(function () {
|
||||
// app.mk.play().then(function (){
|
||||
// app.mk.clearQueue().then(function (){
|
||||
// var playlistId = id
|
||||
// const params = {
|
||||
// include: "tracks",
|
||||
// platform: "web",
|
||||
// "include[library-playlists]": "catalog,tracks",
|
||||
// "fields[playlists]": "curatorName,playlistType,name,artwork,url",
|
||||
// "include[library-songs]": "catalog,artists,albums",
|
||||
// "fields[catalog]": "artistUrl,albumUrl",
|
||||
// "fields[songs]": "artistUrl,albumUrl"
|
||||
// }
|
||||
// var playlistId = ''
|
||||
|
||||
// try {
|
||||
// function getPlaylist(id, params, isLibrary){
|
||||
// if (isLibrary){
|
||||
// return app.mk.api.library.playlist(id, params)
|
||||
// } else { return app.mk.api.playlist(id, params)}
|
||||
// }
|
||||
// getPlaylist(id, params, isLibrary).then(res => {
|
||||
// let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
// if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')}
|
||||
// app.mk.queue.append(query)
|
||||
// if (!res.relationships.tracks.next) {
|
||||
// return
|
||||
// } else {
|
||||
// getPlaylistTracks(res.relationships.tracks.next)
|
||||
// }
|
||||
// try {
|
||||
// function getPlaylist(id, params, isLibrary){
|
||||
// if (isLibrary){
|
||||
// return app.mk.api.library.playlist(id, params)
|
||||
// } else { return app.mk.api.playlist(id, params)}
|
||||
// }
|
||||
// getPlaylist(id, params, isLibrary).then(res => {
|
||||
// let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
// if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')}
|
||||
// app.mk.queue.append(query)
|
||||
// if (!res.relationships.tracks.next) {
|
||||
// return
|
||||
// } else {
|
||||
// getPlaylistTracks(res.relationships.tracks.next)
|
||||
// }
|
||||
|
||||
// function getPlaylistTracks(next) {
|
||||
// app.apiCall(app.musicBaseUrl + next, res => {
|
||||
// if (res.id != playlistId) {
|
||||
// return
|
||||
// }
|
||||
// let query = res.data.map(item => new MusicKit.MediaItem(item))
|
||||
// if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')}
|
||||
// app.mk.queue.append(query)
|
||||
// function getPlaylistTracks(next) {
|
||||
// app.apiCall(app.musicBaseUrl + next, res => {
|
||||
// if (res.id != playlistId) {
|
||||
// return
|
||||
// }
|
||||
// let query = res.data.map(item => new MusicKit.MediaItem(item))
|
||||
// if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')}
|
||||
// app.mk.queue.append(query)
|
||||
|
||||
// if (res.next) {
|
||||
// getPlaylistTracks(res.next)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// } catch (e) {}
|
||||
// if (res.next) {
|
||||
// getPlaylistTracks(res.next)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// } catch (e) {}
|
||||
|
||||
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
else {
|
||||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||
}
|
||||
})
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
else {
|
||||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||
}
|
||||
})
|
||||
},
|
||||
async getTypeFromID(kind, id, isLibrary = false, params = {}, params2 = {}) {
|
||||
let a;
|
||||
|
@ -1306,13 +1366,14 @@ const app = new Vue({
|
|||
},
|
||||
searchLibrarySongs() {
|
||||
let self = this
|
||||
let prefs = this.cfg.libraryPrefs.songs
|
||||
|
||||
function sortSongs() {
|
||||
// sort this.library.songs.displayListing by song.attributes[self.library.songs.sorting] in descending or ascending order based on alphabetical order and numeric order
|
||||
// check if song.attributes[self.library.songs.sorting] is a number and if so, sort by number if not, sort by alphabetical order ignoring case
|
||||
self.library.songs.displayListing.sort((a, b) => {
|
||||
let aa = a.attributes[self.library.songs.sorting]
|
||||
let bb = b.attributes[self.library.songs.sorting]
|
||||
let aa = a.attributes[prefs.sort]
|
||||
let bb = b.attributes[prefs.sort]
|
||||
if (self.library.songs.sorting == "genre") {
|
||||
aa = a.attributes.genreNames[0]
|
||||
bb = b.attributes.genreNames[0]
|
||||
|
@ -1323,13 +1384,13 @@ const app = new Vue({
|
|||
if (bb == null) {
|
||||
bb = ""
|
||||
}
|
||||
if (self.library.songs.sortOrder == "asc") {
|
||||
if (prefs.sortOrder == "asc") {
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return aa - bb
|
||||
} else {
|
||||
return aa.toString().toLowerCase().localeCompare(bb.toString().toLowerCase())
|
||||
}
|
||||
} else if (self.library.songs.sortOrder == "desc") {
|
||||
} else if (prefs.sortOrder == "desc") {
|
||||
if (aa.toString().match(/^\d+$/) && bb.toString().match(/^\d+$/)) {
|
||||
return bb - aa
|
||||
} else {
|
||||
|
@ -1570,9 +1631,10 @@ const app = new Vue({
|
|||
} else {
|
||||
|
||||
if (downloaded.next != null && typeof downloaded.next === "function") {
|
||||
downloaded.next("", params, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
}) } else {
|
||||
downloaded.next("", params, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
})
|
||||
} else {
|
||||
console.log("Download next", downloaded.next)
|
||||
}
|
||||
}
|
||||
|
@ -1648,10 +1710,11 @@ const app = new Vue({
|
|||
processChunk(response)
|
||||
})
|
||||
} else {
|
||||
if (downloaded.next != null && typeof downloaded.next === "function") {
|
||||
downloaded.next("", params, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
}) } else {
|
||||
if (downloaded.next != null && typeof downloaded.next === "function") {
|
||||
downloaded.next("", params, {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
})
|
||||
} else {
|
||||
console.log("Download next", downloaded.next)
|
||||
}
|
||||
}
|
||||
|
@ -1729,12 +1792,13 @@ const app = new Vue({
|
|||
})
|
||||
} else {
|
||||
if (downloaded.next != null && typeof downloaded.next === "function") {
|
||||
downloaded.next("", "artists", {includeResponseMeta: !0}).then((response) => {
|
||||
downloaded.next("", "artists", {includeResponseMeta: !0}).then((response) => {
|
||||
processChunk(response)
|
||||
}) } else {
|
||||
console.log("Download next", downloaded.next)
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
console.log("Download next", downloaded.next)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1780,7 +1844,7 @@ const app = new Vue({
|
|||
let hours = Math.floor(time / 3600)
|
||||
let mins = Math.floor(time / 60) % 60
|
||||
let secs = time % 60
|
||||
return app.showingPlaylist.relationships.tracks.data.length + " tracks, " + ((hours > 0) ? (hours + (" hour" + ((hours > 1) ? "s, " : ", "))) : "") + ((mins > 0) ? (mins + (" minute" + ((mins > 1) ? "s, " : ", "))) : "") + secs + (" second" + ((secs > 1) ? "s." : "."));
|
||||
return app.showingPlaylist.relationships.tracks.data.length + " track" + (app.showingPlaylist.relationships.tracks.data.length > 1 ? "s" : "") + ", " + ((hours > 0) ? (hours + (" hour" + ((hours > 1) ? "s, " : ", "))) : "") + ((mins > 0) ? (mins + (" minute" + ((mins > 1) ? "s, " : ", "))) : "") + secs + (" second" + ((secs > 1) ? "s." : "."));
|
||||
} else return ""
|
||||
} catch (err) {
|
||||
return ""
|
||||
|
@ -2354,76 +2418,84 @@ const app = new Vue({
|
|||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
let kind = parent.substring(0, parent.indexOf(":"))
|
||||
let id = parent.substring(parent.indexOf(":") + 1, parent.length)
|
||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
console.log(truekind, id)
|
||||
|
||||
try {
|
||||
if (app.library.songs.listing.length > childIndex && parent == "librarysongs") {
|
||||
if (app.library.songs.displayListing.length > childIndex && parent == "librarysongs") {
|
||||
console.log(item)
|
||||
if (item && ((app.library.songs.listing[childIndex].id != item.id))) {
|
||||
childIndex = app.library.songs.listing.indexOf(item)
|
||||
if (item && ((app.library.songs.displayListing[childIndex].id != item.id))) {
|
||||
childIndex = app.library.songs.displayListing.indexOf(item)
|
||||
}
|
||||
|
||||
let query = app.library.songs.listing.map(item => new MusicKit.MediaItem(item));
|
||||
try {
|
||||
app.mk.stop()
|
||||
} catch (e) {
|
||||
}
|
||||
this.mk.clearQueue().then(function (_) {
|
||||
if (app.mk.shuffleMode == 1){ shuffleArray(query)}
|
||||
app.mk.queue.append(query)
|
||||
if (childIndex != -1) {
|
||||
app.mk.changeToMediaAtIndex(childIndex)
|
||||
} else if (item) {
|
||||
app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1)
|
||||
let query = app.library.songs.displayListing.map(item => new MusicKit.MediaItem(item));
|
||||
|
||||
|
||||
app.mk.stop().then(() => {
|
||||
this.mk.clearQueue().then(function (_) {
|
||||
if (app.mk.shuffleMode == 1) {
|
||||
shuffleArray(query)
|
||||
}
|
||||
app.mk.queue.append(query)
|
||||
if (childIndex != -1) {
|
||||
app.mk.changeToMediaAtIndex(childIndex)
|
||||
} else if (item) {
|
||||
app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1)
|
||||
app.mk.play()
|
||||
})
|
||||
} else {
|
||||
app.mk.play()
|
||||
})
|
||||
} else {
|
||||
app.mk.play()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
app.mk.stop().then(() => {
|
||||
if (truekind == "playlists" && (id.startsWith("p.") || id.startsWith("pl.u"))){
|
||||
app.mk.setQueue({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1).then(function(){
|
||||
if ((app.showingPlaylist && app.showingPlaylist.id == id)) {
|
||||
let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
if (query.length > 100) {
|
||||
let u = query.slice(100); if (app.mk.shuffleMode == 1) { shuffleArray(u) }
|
||||
app.mk.queue.append(u)}
|
||||
} else {
|
||||
app.getPlaylistFromID(id, true).then(function () {
|
||||
if (truekind == "playlists" && (id.startsWith("p.") || id.startsWith("pl.u"))) {
|
||||
app.mk.setQueue({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1).then(function () {
|
||||
if ((app.showingPlaylist && app.showingPlaylist.id == id)) {
|
||||
let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
if (query.length > 100) {
|
||||
let u = query.slice(100); if (app.mk.shuffleMode == 1) { shuffleArray(u) }
|
||||
app.mk.queue.append(u)}
|
||||
})
|
||||
}
|
||||
})
|
||||
let u = query;
|
||||
if (app.mk.shuffleMode == 1) {
|
||||
shuffleArray(u)
|
||||
}
|
||||
app.mk.queue.append(u)
|
||||
} else {
|
||||
app.getPlaylistFromID(id, true).then(function () {
|
||||
let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item));
|
||||
let u = query;
|
||||
if (app.mk.shuffleMode == 1) {
|
||||
shuffleArray(u)
|
||||
}
|
||||
app.mk.queue.append(u)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.mk.setQueue({[truekind]: [id]}).then(function (queue) {
|
||||
if (item && ((queue._itemIDs[childIndex] != item.id))) {
|
||||
childIndex = queue._itemIDs.indexOf(item.id)
|
||||
}
|
||||
if (childIndex != -1) {
|
||||
app.mk.changeToMediaAtIndex(childIndex)
|
||||
} else if (item) {
|
||||
app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1)
|
||||
app.mk.play()
|
||||
})
|
||||
} else {
|
||||
app.mk.play()
|
||||
this.mk.setQueue({[truekind]: [id]}).then(function (queue) {
|
||||
if (item && ((queue._itemIDs[childIndex] != item.id))) {
|
||||
childIndex = queue._itemIDs.indexOf(item.id)
|
||||
}
|
||||
if (childIndex != -1) {
|
||||
app.mk.changeToMediaAtIndex(childIndex)
|
||||
} else if (item) {
|
||||
app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () {
|
||||
app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1)
|
||||
app.mk.play()
|
||||
})
|
||||
} else {
|
||||
app.mk.play()
|
||||
}
|
||||
})
|
||||
}
|
||||
})}
|
||||
})}
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
try {
|
||||
|
@ -2524,7 +2596,8 @@ const app = new Vue({
|
|||
if (type.slice(-1) != "s") {
|
||||
type += "s"
|
||||
}
|
||||
let id = item.playParams.catalogId ? item.playParams.catalogId : item.id
|
||||
type = type.replace("library-", "")
|
||||
let id = item.attributes.playParams.catalogId ?? item.id
|
||||
|
||||
let index = types.findIndex(function (type) {
|
||||
return type.type == this
|
||||
|
@ -2535,7 +2608,11 @@ const app = new Vue({
|
|||
types[index].id.push(id)
|
||||
}
|
||||
}
|
||||
return await this.mk.api.catalogResources(types, {"omit[resource]": "autos", relate: "library", fields: "inLibrary"})
|
||||
return await this.mk.api.catalogResources(types, {
|
||||
"omit[resource]": "autos",
|
||||
relate: "library",
|
||||
fields: "inLibrary"
|
||||
})
|
||||
},
|
||||
isInLibrary(playParams) {
|
||||
let self = this
|
||||
|
@ -2572,7 +2649,7 @@ const app = new Vue({
|
|||
}
|
||||
},
|
||||
getMediaItemArtwork(url, height = 64, width) {
|
||||
if(typeof url == "undefined" || url == "") {
|
||||
if (typeof url == "undefined" || url == "") {
|
||||
return "https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg"
|
||||
}
|
||||
let newurl = `${url.replace('{w}', width ?? height).replace('{h}', height).replace('{f}', "webp").replace('{c}', ((width === 900) ? "sr" : "cc"))}`;
|
||||
|
@ -2582,7 +2659,7 @@ const app = new Vue({
|
|||
}
|
||||
return newurl
|
||||
},
|
||||
_rgbToRgb(rgb = [0,0,0]) {
|
||||
_rgbToRgb(rgb = [0, 0, 0]) {
|
||||
// if rgb
|
||||
return `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
|
||||
},
|
||||
|
@ -2602,7 +2679,7 @@ const app = new Vue({
|
|||
this.currentTrackID = this.mk.nowPlayingItem["id"];
|
||||
document.querySelector('.bg-artwork').src = "";
|
||||
if (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"]) {
|
||||
getBase64FromUrl(this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"].replace('{w}', size).replace('{h}', size)).then(img =>{
|
||||
getBase64FromUrl(this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"].replace('{w}', size).replace('{h}', size)).then(img => {
|
||||
document.querySelectorAll('.bg-artwork').forEach(artwork => {
|
||||
artwork.src = img;
|
||||
})
|
||||
|
@ -2690,29 +2767,32 @@ const app = new Vue({
|
|||
|
||||
|
||||
// },
|
||||
async getCurrentArtURL(){
|
||||
try{
|
||||
async getCurrentArtURL() {
|
||||
try {
|
||||
this.currentArtUrl = '';
|
||||
if (app.mk.nowPlayingItem != null && app.mk.nowPlayingItem.attributes != null && app.mk.nowPlayingItem.attributes.artwork != null && app.mk.nowPlayingItem.attributes.artwork.url != null && app.mk.nowPlayingItem.attributes.artwork.url!= '' )
|
||||
{
|
||||
if (app.mk.nowPlayingItem != null && app.mk.nowPlayingItem.attributes != null && app.mk.nowPlayingItem.attributes.artwork != null && app.mk.nowPlayingItem.attributes.artwork.url != null && app.mk.nowPlayingItem.attributes.artwork.url != '') {
|
||||
this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50);
|
||||
try{
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);}
|
||||
catch (e) {}
|
||||
try {
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
let data = await this.mk.api.library.song(this.mk.nowPlayingItem.id);
|
||||
if (data != null && data !== "" && data.attributes != null && data.attributes.artwork != null) {
|
||||
this.currentArtUrl = (data["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50);
|
||||
try{
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);}
|
||||
catch (e) {}
|
||||
} else {this.currentArtUrl = '';
|
||||
try{
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);}
|
||||
catch (e) {}
|
||||
try {
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
this.currentArtUrl = '';
|
||||
try {
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
},
|
||||
|
@ -2737,7 +2817,7 @@ const app = new Vue({
|
|||
const data = await this.mk.api.library.song(this.mk.nowPlayingItem.id)
|
||||
|
||||
if (data != null && data !== "") {
|
||||
getBase64FromUrl((data["attributes"]["artwork"]["url"]).toString()).then(img =>{
|
||||
getBase64FromUrl((data["attributes"]["artwork"]["url"]).toString()).then(img => {
|
||||
document.querySelector('.bg-artwork').forEach(artwork => {
|
||||
artwork.src = img;
|
||||
})
|
||||
|
@ -2763,16 +2843,16 @@ const app = new Vue({
|
|||
let type = item.type.slice(-1) === "s" ? item.type : item.type + "s"
|
||||
let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id
|
||||
if (item.id.startsWith("i.")) {
|
||||
if(!type.startsWith("library-")) {
|
||||
if (!type.startsWith("library-")) {
|
||||
type = "library-" + type
|
||||
}
|
||||
id = item.id
|
||||
}
|
||||
let response = await this.mk.api.v3.music(`/v1/me/ratings/${type}?platform=web&ids=${id}`)
|
||||
if(response.data.data.length != 0) {
|
||||
if (response.data.data.length != 0) {
|
||||
let value = response.data.data[0].attributes.value
|
||||
return value
|
||||
}else{
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
|
@ -2780,7 +2860,7 @@ const app = new Vue({
|
|||
let type = item.type.slice(-1) === "s" ? item.type : item.type + "s"
|
||||
let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id
|
||||
if (item.id.startsWith("i.")) {
|
||||
if(!type.startsWith("library-")) {
|
||||
if (!type.startsWith("library-")) {
|
||||
type = "library-" + type
|
||||
}
|
||||
id = item.id
|
||||
|
@ -2804,7 +2884,7 @@ const app = new Vue({
|
|||
let type = item.type.slice(-1) === "s" ? item.type : item.type + "s"
|
||||
let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id
|
||||
if (item.id.startsWith("i.")) {
|
||||
if(!type.startsWith("library-")) {
|
||||
if (!type.startsWith("library-")) {
|
||||
type = "library-" + type
|
||||
}
|
||||
id = item.id
|
||||
|
@ -2828,7 +2908,7 @@ const app = new Vue({
|
|||
let type = item.type.slice(-1) === "s" ? item.type : item.type + "s"
|
||||
let id = item.attributes.playParams.catalogId ? item.attributes.playParams.catalogId : item.id
|
||||
if (item.id.startsWith("i.")) {
|
||||
if(!type.startsWith("library-")) {
|
||||
if (!type.startsWith("library-")) {
|
||||
type = "library-" + type
|
||||
}
|
||||
id = item.id
|
||||
|
@ -2842,16 +2922,20 @@ const app = new Vue({
|
|||
},
|
||||
volumeWheel(event) {
|
||||
if (event.deltaY < 0) {
|
||||
if(this.mk.volume < 1){
|
||||
if (this.mk.volume < 1) {
|
||||
if (this.mk.volume <= 0.9) {
|
||||
this.mk.volume += 0.1
|
||||
} else { this.mk.volume = 1 }
|
||||
} else {
|
||||
this.mk.volume = 1
|
||||
}
|
||||
}
|
||||
} else if (event.deltaY > 0) {
|
||||
if(this.mk.volume > 0){
|
||||
if (this.mk.volume >= 0.1){
|
||||
this.mk.volume -= 0.1
|
||||
} else {this.mk.volume = 0}
|
||||
if (this.mk.volume > 0) {
|
||||
if (this.mk.volume >= 0.1) {
|
||||
this.mk.volume -= 0.1
|
||||
} else {
|
||||
this.mk.volume = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2921,10 +3005,53 @@ const app = new Vue({
|
|||
items: []
|
||||
},
|
||||
normal: {
|
||||
headerItems: [
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "unlove",
|
||||
"active": true,
|
||||
"name": "Unlove",
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"active": true,
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
],
|
||||
items: [
|
||||
{
|
||||
"icon": "./assets/feather/list.svg",
|
||||
"name": "Add to Playlist...",
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.promptAddToPlaylist()
|
||||
}
|
||||
|
@ -2935,51 +3062,15 @@ const app = new Vue({
|
|||
"name": "Add to Library...",
|
||||
"disabled": false,
|
||||
"action": function () {
|
||||
app.addToLibrary(item_id);
|
||||
app.addToLibrary(app.mk.nowPlayingItem.id);
|
||||
// if (!isLibrary) {app.addToLibrary(item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = true} else { app.removeFromLibrary(data_type,item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = false};
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/unheart.svg",
|
||||
"id": "unlove",
|
||||
"name": "Unlove",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/x-circle.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(app.mk.nowPlayingItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/radio.svg",
|
||||
"name": "Start Radio",
|
||||
"action": function () {
|
||||
app.mk.setStationQueue({song: item_id}).then(() => {
|
||||
app.mk.setStationQueue({song: app.mk.nowPlayingItem.id}).then(() => {
|
||||
app.mk.play()
|
||||
app.selectedMediaItems = []
|
||||
})
|
||||
|
@ -3004,17 +3095,23 @@ const app = new Vue({
|
|||
// }else{
|
||||
// menus.normal.items.find(x => x.id == "addToLibrary").disabled = true
|
||||
// }
|
||||
this.showMenuPanel(menus[useMenu], event)
|
||||
|
||||
try{
|
||||
let rating = await app.getRating(app.mk.nowPlayingItem)
|
||||
if (rating == 0) {
|
||||
menus.normal.headerItems.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').disabled = false
|
||||
} else if (rating == 1) {
|
||||
menus.normal.headerItems.find(x => x.id == 'unlove').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'love').hidden = true
|
||||
} else if (rating == -1) {
|
||||
menus.normal.headerItems.find(x => x.id == 'undo_dislike').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').hidden = true
|
||||
}
|
||||
} catch(err) {
|
||||
|
||||
let rating = await app.getRating(app.mk.nowPlayingItem)
|
||||
if(rating == 0) {
|
||||
menus.normal.items.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.items.find(x => x.id == 'dislike').disabled = false
|
||||
}else if(rating == 1) {
|
||||
menus.normal.items.find(x => x.id == 'unlove').disabled = false
|
||||
}else if(rating == -1) {
|
||||
menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
LastFMDeauthorize() {
|
||||
ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e));
|
||||
|
@ -3061,10 +3158,14 @@ const app = new Vue({
|
|||
peak: peak
|
||||
}
|
||||
},
|
||||
fullscreen(flag){
|
||||
fullscreen(flag) {
|
||||
if (flag) {
|
||||
ipcRenderer.send('setFullScreen', true);
|
||||
app.appMode = 'fullscreen';
|
||||
if (app.mk.nowPlayingItem.type && app.mk.nowPlayingItem.type.toLowerCase().includes("video")) {
|
||||
document.querySelector('video#apple-music-video-player').requestFullscreen()
|
||||
} else {
|
||||
app.appMode = 'fullscreen';
|
||||
}
|
||||
document.addEventListener('keydown', event => {
|
||||
if (event.key === 'Escape' && app.appMode === 'fullscreen') {
|
||||
this.fullscreen(false);
|
||||
|
@ -3079,6 +3180,41 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
|
||||
Vue.component('animated-number', {
|
||||
|
||||
template: "<div style='display: inline-block;'>{{ displayNumber }}</div>",
|
||||
props: {'number': {default: 0}},
|
||||
|
||||
data() {
|
||||
return {
|
||||
displayNumber: 0,
|
||||
interval: false
|
||||
}
|
||||
},
|
||||
|
||||
ready() {
|
||||
this.displayNumber = this.number ? this.number : 0;
|
||||
},
|
||||
|
||||
watch: {
|
||||
number() {
|
||||
clearInterval(this.interval);
|
||||
|
||||
if (this.number == this.displayNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.interval = window.setInterval(() => {
|
||||
if (this.displayNumber != this.number) {
|
||||
var change = (this.number - this.displayNumber) / 10;
|
||||
change = change >= 0 ? Math.ceil(change) : Math.floor(change);
|
||||
this.displayNumber = this.displayNumber + change;
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('sidebar-library-item', {
|
||||
template: '#sidebar-library-item',
|
||||
props: {
|
||||
|
@ -3189,14 +3325,19 @@ document.addEventListener('musickitloaded', function () {
|
|||
};
|
||||
request.open("GET", "https://api.cider.sh/");
|
||||
request.send();
|
||||
|
||||
// check for widevine failure and reconfigure the instance.
|
||||
window.addEventListener("drmUnsupported", function () {
|
||||
initMusicKit()
|
||||
});
|
||||
});
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
// Use the window load event to keep the page load performant
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('sw.js?v=1');
|
||||
navigator.serviceWorker.register('sw.js?v=1');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const getBase64FromUrl = async (url) => {
|
||||
const data = await fetch(url);
|
||||
|
@ -3269,6 +3410,12 @@ function xmlToJson(xml) {
|
|||
return obj;
|
||||
};
|
||||
|
||||
async function asyncForEach(array, callback) {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
}
|
||||
|
||||
var checkIfScrollIsStatic = setInterval(() => {
|
||||
try {
|
||||
if (position === document.getElementsByClassName('lyric-body')[0].scrollTop) {
|
||||
|
|
59
src/renderer/less/compact.less
Normal file
|
@ -0,0 +1,59 @@
|
|||
#app.compact {
|
||||
.content-inner {
|
||||
zoom: 0.95;
|
||||
}
|
||||
.app-sidebar-content {
|
||||
padding:0px;
|
||||
|
||||
.app-sidebar-header-text {
|
||||
padding: 6px 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
.app-sidebar-item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
margin: 0px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0px;
|
||||
transition: unset;
|
||||
transform: unset;
|
||||
|
||||
&:active {
|
||||
background: var(--selected-click);
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--keyColor-disabled);
|
||||
}
|
||||
}
|
||||
.sidebar-icon {
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.folder-body {
|
||||
border-radius: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 951px) {
|
||||
.content-inner {
|
||||
zoom: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if page width is less than 951px
|
||||
@media (max-width: 951px) {
|
||||
.content-inner {
|
||||
zoom: 0.8;
|
||||
}
|
||||
}
|
|
@ -45,6 +45,17 @@ body {
|
|||
transition: opacity .10s var(--appleEase);
|
||||
}
|
||||
|
||||
a:-webkit-any-link {
|
||||
color: var(--keyColor);
|
||||
}
|
||||
|
||||
hr {
|
||||
appearance: none;
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: rgb(255 255 255 / 20%);
|
||||
}
|
||||
|
||||
body[loading] {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
|
@ -57,10 +68,10 @@ body[platform='linux'] {
|
|||
body.notransparency::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0.5;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
@ -134,7 +145,7 @@ body.notransparency::before {
|
|||
}
|
||||
|
||||
.bgGradientMaterial-base {
|
||||
position:relative;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.bgGradientMaterial-base::before {
|
||||
|
@ -224,13 +235,14 @@ input[type="text"], input[type="number"] {
|
|||
z-index: -1;
|
||||
|
||||
.bg-artwork.a {
|
||||
top:0;
|
||||
left:0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
//mix-blend-mode: luminosity;
|
||||
}
|
||||
|
||||
.bg-artwork.b {
|
||||
bottom:0;
|
||||
right:0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
animation-direction: reverse;
|
||||
animation-delay: 10s;
|
||||
}
|
||||
|
@ -332,6 +344,8 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
left: 0;
|
||||
padding: 32px;
|
||||
width: 100%;
|
||||
transition: zoom 1s;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.content-inner.centered {
|
||||
|
@ -423,6 +437,18 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
|
||||
.app-sidebar-footer {
|
||||
padding: 11px;
|
||||
|
||||
.app-playback-controls {
|
||||
.control-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.volume {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-sidebar-button {
|
||||
|
@ -496,6 +522,21 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
background: rgb(0 0 0 / 15%);
|
||||
flex-direction: column;
|
||||
padding: 20px 0px;
|
||||
|
||||
&.libraryNotification {
|
||||
flex-direction: row;
|
||||
padding: 0px;
|
||||
|
||||
.message {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 46px;
|
||||
height: 30px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-sidebar-content {
|
||||
|
@ -1558,7 +1599,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
font-family: 'Inter', 'Noto Sans JP','Source Han Sans SC', 'Source Han Sans HK','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
font-family: 'Inter', 'Noto Sans JP', 'Source Han Sans SC', 'Source Han Sans HK', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
}
|
||||
|
||||
.lyric-body .no-lyrics {
|
||||
|
@ -1568,7 +1609,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
font-weight: bold;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
|
||||
.lyric-line {
|
||||
--bgSpeed: 1s;
|
||||
appearance: none;
|
||||
|
@ -1653,7 +1694,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
.lyrics-translation {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 450;
|
||||
font-family: 'Inter', 'Noto Sans JP','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
font-family: 'Inter', 'Noto Sans JP', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
filter: contrast(0.5);
|
||||
}
|
||||
|
||||
|
@ -1672,7 +1713,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
.lyric-body:hover + .lyric-footer, .lyric-footer:hover {
|
||||
display: flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modular-fs .app-drawer .lyric-footer {
|
||||
|
@ -1802,6 +1843,38 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
/* Cider */
|
||||
|
||||
.about-page {
|
||||
.teamBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
padding: 6px 16px;
|
||||
margin: 4px;
|
||||
|
||||
> img {
|
||||
width: 30px;
|
||||
margin: 0px 16px 0px 0px;
|
||||
pointer-events: none;
|
||||
border-radius: 100%;
|
||||
box-shadow: var(--mediaItemShadow);
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
}
|
||||
|
||||
.sponsorBtn {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> img {
|
||||
width: 26px;
|
||||
margin: 0px 16px 0px 0px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.md-close-btn {
|
||||
-webkit-mask-image: url("ameres://icons/webui/close.svg");
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
|
@ -1838,35 +1911,43 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
&:active {
|
||||
filter: brightness(75%);
|
||||
transform: translateY(2px);
|
||||
transform: scale(0.98);
|
||||
transition: transform 0s var(--appleEase), box-shadow 0.2s var(--appleEase);
|
||||
}
|
||||
}
|
||||
|
||||
.md-select {
|
||||
padding: 5px 10px;
|
||||
font-size: 1em;
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(200, 200, 200, 0.1);
|
||||
font-family: inherit;
|
||||
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;
|
||||
}
|
||||
font-size: 14px;
|
||||
background: rgba(100, 100, 100, 0.25);
|
||||
color: #c8c8c8;
|
||||
font-weight: 500;
|
||||
|
||||
.md-select:focus {
|
||||
outline: none;
|
||||
}
|
||||
option {
|
||||
font-size: 1em;
|
||||
font-family: inherit;
|
||||
padding: 8px 16px;
|
||||
background: #404040;
|
||||
}
|
||||
|
||||
.md-select > option {
|
||||
font-size: 1em;
|
||||
font-family: inherit;
|
||||
padding: 8px 16px;
|
||||
optgroup {
|
||||
background: #2c2c2c;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: solid 1px var(--selected);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-playlist {
|
||||
.folder-button-active {
|
||||
background: rgb(255 255 255 / 12%);
|
||||
}
|
||||
|
||||
.folder-body {
|
||||
background: #ffffff0a;
|
||||
border-radius: 10px;
|
||||
|
@ -2238,6 +2319,28 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
}
|
||||
|
||||
// Library - Songs page
|
||||
.library-page {
|
||||
padding: 0px;
|
||||
|
||||
.library-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-bottom: 1px solid rgba(200, 200, 200, 0.05);
|
||||
z-index: 6;
|
||||
background: black;
|
||||
padding: 0px 2em;
|
||||
backdrop-filter: blur(32px);
|
||||
background: rgba(24, 24, 24, 0.15);
|
||||
top: var(--navigationBarHeight);
|
||||
}
|
||||
|
||||
.well {
|
||||
margin: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Album / Playlist Page */
|
||||
.playlist-page {
|
||||
--bgColor: transparent;
|
||||
|
@ -2383,6 +2486,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
}
|
||||
|
||||
.playlist-more {
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
box-shadow: var(--ciderShadow-Generic);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
float: right;
|
||||
border: 0px;
|
||||
cursor: pointer;
|
||||
z-index: 5;
|
||||
|
||||
&:hover {
|
||||
background: var(--keyColor-rollover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--keyColor-pressed);
|
||||
}
|
||||
}
|
||||
|
||||
.playlist-time {
|
||||
font-size: 0.9em;
|
||||
|
@ -2677,6 +2799,114 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
}
|
||||
|
||||
.menu-panel {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.menu-header-body {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
background: rgb(200 200 200 / 10%);
|
||||
.menu-option-header {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: var(--mediaItemRadius);
|
||||
appearance: none;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
|
||||
&.active {
|
||||
.sidebar-icon>.svg-icon {
|
||||
--color: var(--keyColor);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--selected);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--selected-click);
|
||||
}
|
||||
}
|
||||
}
|
||||
.menu-panel-body {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background: rgb(38 38 38);
|
||||
position: relative;
|
||||
min-width: 200px;
|
||||
box-shadow: var(--ciderShadow-Generic);
|
||||
border-radius: var(--mediaItemRadius);
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
|
||||
.menu-option {
|
||||
text-align: left;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
appearance: none;
|
||||
border: 0px;
|
||||
font: inherit;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
background: var(--selected);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: var(--selected-click);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.menu-header-text {
|
||||
margin: 18px 6px;
|
||||
|
||||
.close-btn {
|
||||
width: 50px;
|
||||
height: 42px;
|
||||
background-image: var(--gfx-closeBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
appearance: none;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(196, 43, 28)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-body {
|
||||
overflow: overlay;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.menu-footer {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.queue-panel {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
@ -2774,6 +3004,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
&.hmedia-scroller-card {
|
||||
height: 370px;
|
||||
|
||||
.mediaitem-card {
|
||||
margin: 12px;
|
||||
}
|
||||
|
@ -2835,11 +3066,11 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
.info-rect {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
|
@ -2848,7 +3079,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
.subtitle {
|
||||
width: 90%;
|
||||
font-size: 12px;
|
||||
font-size: .8em;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
@ -2870,21 +3101,19 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.content-rating {
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
border-radius: 3px;
|
||||
background: rgb(200 200 200 / 15%);
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
margin-right: 12px;
|
||||
flex: 0 0 auto;
|
||||
font-weight: 500;
|
||||
color: #ccc;
|
||||
.explicit-icon {
|
||||
background-image: url("./assets/explicit.svg");
|
||||
height: 12px;
|
||||
width: 36px;
|
||||
filter: contrast(0);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.isLibrary {
|
||||
flex: 0 0 auto;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
border: 0px;
|
||||
|
@ -2897,6 +3126,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
&:hover {
|
||||
background: rgb(200 200 200 / 10%);
|
||||
box-shadow: var(--mediaItemShadow);
|
||||
|
||||
.overlay-play {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -2913,6 +3143,20 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
box-shadow: var(--mediaItemShadow);
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
// list item compact
|
||||
&.compact {
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
|
||||
.artwork {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-rect {
|
||||
padding-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mediaitem-hrect */
|
||||
|
@ -3261,9 +3505,10 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
background: rgba(50, 50, 50, 0.7);
|
||||
cursor: pointer;
|
||||
transition: opacity 0.1s var(--appleEase);
|
||||
:hover{
|
||||
|
||||
:hover {
|
||||
border-radius: 50%;
|
||||
background: rgba(250, 0, 0, 0.7);
|
||||
background: rgba(250, 0, 0, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3365,6 +3610,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
overflow: hidden;
|
||||
border-radius: 0px;
|
||||
margin: 0;
|
||||
|
||||
.mediaitem-artwork {
|
||||
border-radius: 0px;
|
||||
|
||||
|
@ -3382,15 +3628,15 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
&::before {
|
||||
background: var(--bgartwork);
|
||||
content: "";
|
||||
top:0;
|
||||
left:0;
|
||||
bottom:0;
|
||||
right:0;
|
||||
position:absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
background-size: cover;
|
||||
background-position: bottom;
|
||||
z-index: 0;
|
||||
opacity:1;
|
||||
opacity: 1;
|
||||
filter: brightness(0.5) blur(50px) saturate(180%);
|
||||
}
|
||||
}
|
||||
|
@ -3578,19 +3824,20 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
background-color: rgba(200, 200, 200, 0.7);
|
||||
}
|
||||
|
||||
.playback-button--small{
|
||||
.playback-button--small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.right-col{
|
||||
.right-col {
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1023px) {
|
||||
.display--large {
|
||||
display: flex !important;
|
||||
display: flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
.display--large {
|
||||
display: flex;
|
||||
|
||||
|
@ -3612,7 +3859,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
height: 4px;
|
||||
background-color: rgb(200 200 200 / 10%);
|
||||
border-radius: 2px;
|
||||
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
opacity: 1;
|
||||
transform: scale(0.5);
|
||||
|
@ -3625,14 +3872,14 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
cursor: default;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
.background{
|
||||
|
||||
.background {
|
||||
position: absolute;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
|
@ -3642,30 +3889,29 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.bg-artwork-container{
|
||||
|
||||
.bg-artwork-container {
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
|
||||
.bg-artwork-container .bg-artwork {
|
||||
filter: brightness(80%) saturate(69%) blur(180px) contrast(0.8) opacity(0.8);
|
||||
filter: brightness(85%) saturate(95%) blur(180px) contrast(0.9) opacity(0.9);
|
||||
}
|
||||
|
||||
.no-animation{
|
||||
animation : unset;
|
||||
.no-animation {
|
||||
animation: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.lyrics-col {
|
||||
|
||||
.lyrics-col{
|
||||
|
||||
height: 62vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
width: 80%;
|
||||
height: 62vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
width: 80%;
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
box-shadow: unset;
|
||||
|
@ -3675,25 +3921,25 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
box-shadow: inset 0px 0px 10px 10px rgb(200 200 200 / 50%);
|
||||
}
|
||||
|
||||
.no-lyrics{
|
||||
.no-lyrics {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lyric-line{
|
||||
.lyric-line {
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.queue-col{
|
||||
.queue-col {
|
||||
|
||||
width: 60vh;
|
||||
height: 50vh;
|
||||
|
||||
.queue-title{
|
||||
.queue-title {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
|
@ -3708,9 +3954,9 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
&:hover ::-webkit-scrollbar-thumb {
|
||||
box-shadow: inset 0px 0px 10px 10px rgb(200 200 200 / 50%);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-toggles{
|
||||
}
|
||||
|
||||
.tab-toggles {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
@ -3718,18 +3964,18 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 15vh;
|
||||
height: 5vh;
|
||||
justify-content: space-evenly;
|
||||
|
||||
|
||||
.queue {
|
||||
background-image: url("./assets/list.svg") ;
|
||||
background-image: url("./assets/list.svg");
|
||||
padding: 0.5vh;
|
||||
width: 2.5vh;
|
||||
height: 2.5vh;
|
||||
background-origin: content-box;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
||||
.lyrics {
|
||||
background-image: url("./assets/quote-right.svg") ;
|
||||
background-image: url("./assets/quote-right.svg");
|
||||
padding: 0.5vh;
|
||||
width: 2.5vh;
|
||||
height: 2.5vh;
|
||||
|
@ -3754,12 +4000,12 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
height: 50vh;
|
||||
}
|
||||
|
||||
.controls-parents{
|
||||
.controls-parents {
|
||||
width: 50vh;
|
||||
}
|
||||
|
||||
.app-playback-controls {
|
||||
.song-artist , .song-name {
|
||||
.app-playback-controls {
|
||||
.song-artist, .song-name {
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
|
@ -3772,16 +4018,18 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
.song-name-normal {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
|
||||
&.song-artist-marquee {
|
||||
> marquee {
|
||||
//margin-bottom: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.song-artist {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.song-name {
|
||||
width: unset !important;
|
||||
margin-top: 0.15vh;
|
||||
|
@ -3804,7 +4052,8 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
input[type="range"] {
|
||||
width: 100%;
|
||||
}
|
||||
>div {
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -3828,7 +4077,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
overflow: hidden;
|
||||
margin: 0 0 0.5em;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
> input[type=range] {
|
||||
&::-webkit-slider-thumb {
|
||||
|
@ -3838,14 +4087,14 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
|
||||
input[type=range] {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: rgb(200 200 200 / 10%);
|
||||
border-radius: 2px;
|
||||
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
opacity: 0;
|
||||
transform: scale(0.5);
|
||||
|
@ -3858,7 +4107,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
cursor: default;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
|
@ -3875,19 +4124,35 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Cider */
|
||||
|
||||
// sidebar icon
|
||||
.svg-icon {
|
||||
--color: #aaa;
|
||||
--url: url("./assets/feather/share.svg");
|
||||
-webkit-mask-image: var(--url);
|
||||
-webkit-mask-size: cover;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
background: var(--color);
|
||||
}
|
||||
|
||||
.sidebar-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 8px;
|
||||
|
||||
>svg {
|
||||
> .svg-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
--color: #aaa;
|
||||
}
|
||||
|
||||
> svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #aaa;
|
||||
|
@ -3917,6 +4182,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
.bgArtworkMaterial {
|
||||
display: block;
|
||||
|
||||
&::before {
|
||||
top: -50%;
|
||||
left: -20%;
|
||||
|
@ -3939,15 +4205,14 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
transform-origin: center;
|
||||
animation: fsLyricIn var(--appleEase) .2s;
|
||||
opacity: 0.9;
|
||||
text-shadow:
|
||||
-1px -1px 0 #000,
|
||||
0 -1px 0 #000,
|
||||
1px -1px 0 #000,
|
||||
1px 0 0 #000,
|
||||
1px 1px 0 #000,
|
||||
0 1px 0 #000,
|
||||
-1px 1px 0 #000,
|
||||
-1px 0 0 #000;
|
||||
text-shadow: -1px -1px 0 #000,
|
||||
0 -1px 0 #000,
|
||||
1px -1px 0 #000,
|
||||
1px 0 0 #000,
|
||||
1px 1px 0 #000,
|
||||
0 1px 0 #000,
|
||||
-1px 1px 0 #000,
|
||||
-1px 0 0 #000;
|
||||
|
||||
&:not(.active) {
|
||||
display: none;
|
||||
|
@ -3966,12 +4231,12 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
@keyframes fsLyricIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.98)
|
||||
opacity: 0;
|
||||
transform: scale(0.98)
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4162,7 +4427,7 @@ div#captions {
|
|||
background: rgba(0, 0, 0, 0.6);
|
||||
color: yellow;
|
||||
white-space: pre-line;
|
||||
font-family: 'Inter', 'Noto Sans JP','Source Han Sans SC', 'Source Han Sans HK','Source Han Sans SC', 'Source Han Sans HK','Noto Sans SC','Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
font-family: 'Inter', 'Noto Sans JP', 'Source Han Sans SC', 'Source Han Sans HK', 'Source Han Sans SC', 'Source Han Sans HK', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans HK', 'Noto Sans KR', sans-serif;
|
||||
}
|
||||
|
||||
[v-cloak] {
|
||||
|
@ -4276,6 +4541,7 @@ body.no-gpu {
|
|||
.bg-artwork-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#navigation-bar {
|
||||
backdrop-filter: unset;
|
||||
mix-blend-mode: unset;
|
||||
|
@ -4314,4 +4580,6 @@ body.no-gpu {
|
|||
.drawertransition-leave-to {
|
||||
right: -300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import url("less/compact.less");
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="modal-search">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
ref="searchInput"
|
||||
|
|
|
@ -7,14 +7,19 @@
|
|||
:data-index="index"
|
||||
:data-guid="guid"
|
||||
:data-islibrary="this.item.attributes.playParams.isLibrary ?? false"
|
||||
:key="item.attributes.playParams.id ?? item.id"
|
||||
class="cd-mediaitem-list-item"
|
||||
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}">
|
||||
@mouseenter="checkLibrary"
|
||||
@mouseover="showInLibrary = true"
|
||||
@mouseleave="showInLibrary = false"
|
||||
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
|
||||
<template v-if="isVisible">
|
||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||
<div class="isLibrary" :style="{opacity: (showInLibrary ? 1 : 0)}" v-if="showLibraryStatus == true">
|
||||
<button @click="addToLibrary()"
|
||||
v-if="!app.isInLibrary(item.attributes.playParams) && !addedToLibrary">🖤
|
||||
v-if="!addedToLibrary">
|
||||
<div class="svg-icon" :style="{'--color': 'var(--keyColor)', '--url': 'url(./assets/feather/plus.svg)'}"></div>
|
||||
</button>
|
||||
<button v-else @click="removeFromLibrary()">❤️</button>
|
||||
<button v-else style="opacity:0;">❤️</button>
|
||||
</div>
|
||||
<div class="artwork" v-if="showArtwork == true">
|
||||
<mediaitem-artwork
|
||||
|
@ -24,7 +29,7 @@
|
|||
<button class="overlay-play" @click="playTrack()"><%- include("../svg/play.svg") %></button>
|
||||
</div>
|
||||
<div class="info-rect" :style="{'padding-left': (showArtwork ? '' : '16px')}"
|
||||
@dblclick="app.routeView(item)">
|
||||
@dblclick="route()">
|
||||
<div class="title text-overflow-elipsis">
|
||||
{{ item.attributes.name }}
|
||||
</div>
|
||||
|
@ -44,10 +49,8 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-rating" v-if="item.attributes.contentRating" @dblclick="app.routeView(item)">
|
||||
{{ item.attributes.contentRating }}
|
||||
</div>
|
||||
<template v-if="showMetaData == true" @dblclick="app.routeView(item)">
|
||||
<div class="explicit-icon" v-if="item.attributes && item.attributes.contentRating == 'explicit'"></div>
|
||||
<template v-if="showMetaData == true" @dblclick="route()">
|
||||
<div class="metainfo">
|
||||
{{ item.attributes.releaseDate ? new Date(item.attributes.releaseDate).toLocaleDateString()
|
||||
: "" }}
|
||||
|
@ -56,7 +59,7 @@
|
|||
{{ item.attributes.genreNames[0] ?? "" }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="duration" v-if="displayDuration" @dblclick="app.routeView(item)">
|
||||
<div class="duration" v-if="displayDuration" @dblclick="route()">
|
||||
{{ msToMinSec(item.attributes.durationInMillis ?? 0) }}
|
||||
</div>
|
||||
</template>
|
||||
|
@ -68,11 +71,13 @@
|
|||
template: '#mediaitem-list-item',
|
||||
data: function () {
|
||||
return {
|
||||
showInLibrary: false,
|
||||
isVisible: false,
|
||||
addedToLibrary: false,
|
||||
guid: this.uuidv4(),
|
||||
app: this.$root,
|
||||
displayDuration: true
|
||||
displayDuration: true,
|
||||
addClasses: {}
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
@ -84,14 +89,36 @@
|
|||
'show-meta-data': {type: Boolean, default: false},
|
||||
'show-duration': {type: Boolean, default: true},
|
||||
'contextExt': {type: Object, required: false},
|
||||
'class-list': {type: String, required: false, default: ""},
|
||||
},
|
||||
mounted() {
|
||||
let duration = this.item.attributes.durationInMillis ?? 0
|
||||
if (duration == 0 || !this.showDuration) {
|
||||
this.displayDuration = false
|
||||
}
|
||||
this.getClasses()
|
||||
},
|
||||
methods: {
|
||||
async checkLibrary() {
|
||||
if(this.addedToLibrary) {return this.addedToLibrary}
|
||||
if(this.item.type.includes("library-playlists") || this.item.type.includes("station")) {
|
||||
this.addedToLibrary = true
|
||||
return
|
||||
}
|
||||
this.$root.inLibrary([this.item]).then(res => {
|
||||
this.addedToLibrary = res[0].attributes.inLibrary
|
||||
})
|
||||
return this.addedToLibrary
|
||||
},
|
||||
getClasses() {
|
||||
if(this.classList) {
|
||||
this.addClasses = {}
|
||||
let classList = this.classList.split(' ')
|
||||
for(let i = 0; i < classList.length; i++) {
|
||||
this.addClasses[classList[i]] = true
|
||||
}
|
||||
}
|
||||
},
|
||||
dragStart(evt) {
|
||||
evt.dataTransfer.setData('text/plain', JSON.stringify({
|
||||
type: this.item.attributes.playParams.kind ?? this.item.type,
|
||||
|
@ -197,12 +224,14 @@
|
|||
items: [
|
||||
{
|
||||
"name": "Add to Playlist...",
|
||||
"icon": "./assets/feather/plus.svg",
|
||||
"action": function () {
|
||||
app.promptAddToPlaylist()
|
||||
}
|
||||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks next`,
|
||||
"icon": "./assets/arrow-bend-up.svg",
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
|
@ -224,6 +253,7 @@
|
|||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks later`,
|
||||
"icon": "./assets/arrow-bend-down.svg",
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
|
@ -245,7 +275,68 @@
|
|||
]
|
||||
},
|
||||
normal: {
|
||||
headerItems: [
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "unlove",
|
||||
"active": true,
|
||||
"name": "Unlove",
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"active": true,
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
],
|
||||
items: [
|
||||
{
|
||||
"id": "addToLibrary",
|
||||
"icon": "./assets/feather/plus.svg",
|
||||
"name": "Add to library",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
self.addToLibrary()
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "removeFromLibrary",
|
||||
"icon": "./assets/feather/x-circle.svg",
|
||||
"name": "Remove from library",
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
self.removeFromLibrary()
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/list.svg",
|
||||
"name": "Add to Playlist...",
|
||||
|
@ -255,6 +346,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Play Next",
|
||||
"icon": "./assets/arrow-bend-up.svg",
|
||||
"action": function () {
|
||||
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
|
@ -263,6 +355,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Play Later",
|
||||
"icon": "./assets/arrow-bend-down.svg",
|
||||
"action": function () {
|
||||
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
|
@ -279,42 +372,6 @@
|
|||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/unheart.svg",
|
||||
"id": "unlove",
|
||||
"name": "Unlove",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/x-circle.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/user.svg",
|
||||
"name": "Go to Artist",
|
||||
|
@ -352,21 +409,38 @@
|
|||
if (this.contextExt.multiple) {
|
||||
menus.multiple.items = menus.multiple.items.concat(this.contextExt.multiple)
|
||||
}
|
||||
}
|
||||
app.showMenuPanel(menus[useMenu], event)
|
||||
|
||||
try {
|
||||
await this.checkLibrary().then(res => {
|
||||
console.log(res)
|
||||
if(res) {
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||
}else{
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
||||
}
|
||||
})
|
||||
|
||||
}catch(e) {
|
||||
|
||||
}
|
||||
try{
|
||||
let rating = await app.getRating(self.item)
|
||||
if (rating == 0) {
|
||||
menus.normal.items.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.items.find(x => x.id == 'dislike').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').disabled = false
|
||||
} else if (rating == 1) {
|
||||
menus.normal.items.find(x => x.id == 'unlove').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'unlove').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'love').hidden = true
|
||||
} else if (rating == -1) {
|
||||
menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'undo_dislike').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').hidden = true
|
||||
}
|
||||
} catch(err) {
|
||||
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
this.isVisible = isVisible
|
||||
|
@ -474,6 +548,14 @@
|
|||
else {
|
||||
app.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url)
|
||||
}})
|
||||
},
|
||||
route(){
|
||||
let kind = (this.item.attributes.playParams ? (this.item.attributes.playParams.kind ?? (this.item.type ?? '')) : (this.item.type ?? ''));
|
||||
if (kind.toLowerCase().includes('album') || kind.toLowerCase().includes('playlist')){
|
||||
app.routeView(this.item)
|
||||
} else {
|
||||
this.playTrack()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
},
|
||||
methods: {
|
||||
getBgColor() {
|
||||
let color = `#${(this.item.attributes.artwork.bgColor != null) ? (this.item.attributes.artwork.bgColor) : `333333`}`
|
||||
let color = `#${(this.item.attributes.artwork != null && this.item.attributes.artwork.bgColor != null) ? (this.item.attributes.artwork.bgColor) : `333333`}`
|
||||
let c = color.substring(1); // strip #
|
||||
var rgb = parseInt(c, 16); // convert rrggbb to decimal
|
||||
var r = (rgb >> 16) & 0xff; // extract red
|
||||
|
@ -85,8 +85,6 @@
|
|||
|
||||
var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709
|
||||
|
||||
console.log(color)
|
||||
console.log(luma)
|
||||
if (luma > 140) {
|
||||
return "#aaaaaa"
|
||||
}else{
|
||||
|
@ -142,9 +140,10 @@
|
|||
}
|
||||
},
|
||||
async getBadges() {
|
||||
let self = this
|
||||
if (this.badges[this.item.attributes.playParams.id ?? this.item.id]) {
|
||||
let friends = this.badges[this.item.attributes.playParams.id ?? this.item.id]
|
||||
const self = this
|
||||
const id = (this.item.attributes.playParams ? this.item.attributes.playParams.id : null) || this.item.id
|
||||
if (id && this.badges[id]) {
|
||||
let friends = this.badges[id]
|
||||
if (friends) {
|
||||
friends.forEach(function (friend) {
|
||||
self.app.mk.api.socialProfile(friend).then(data => {
|
||||
|
@ -247,7 +246,6 @@
|
|||
} else {
|
||||
console.log(event)
|
||||
}
|
||||
await this.isInLibrary();
|
||||
let self = this
|
||||
let useMenu = "normal"
|
||||
if (app.selectedMediaItems.length <= 1) {
|
||||
|
@ -261,6 +259,7 @@
|
|||
items: [
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks next`,
|
||||
"icon": "./assets/arrow-bend-up.svg",
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
|
@ -282,6 +281,7 @@
|
|||
},
|
||||
{
|
||||
name: `Play ${app.selectedMediaItems.length} tracks later`,
|
||||
"icon": "./assets/arrow-bend-down.svg",
|
||||
action: () => {
|
||||
let itemsToPlay = {}
|
||||
app.selectedMediaItems.forEach(item => {
|
||||
|
@ -303,6 +303,48 @@
|
|||
]
|
||||
},
|
||||
normal: {
|
||||
headerItems: [
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "unlove",
|
||||
"active": true,
|
||||
"name": "Unlove",
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"active": true,
|
||||
"hidden": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
],
|
||||
items: [
|
||||
{
|
||||
"icon": "./assets/feather/list.svg",
|
||||
|
@ -312,8 +354,35 @@
|
|||
app.promptAddToPlaylist()
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "addToLibrary",
|
||||
"icon": "./assets/feather/plus.svg",
|
||||
"name": "Add to library",
|
||||
"hidden": false,
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
let item_id = self.item.attributes.playParams.id ?? self.item.id;
|
||||
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
|
||||
app.addToLibrary(item_id);
|
||||
self.addedToLibrary = true;
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "removeFromLibrary",
|
||||
"icon": "./assets/feather/x-circle.svg",
|
||||
"name": "Remove from library",
|
||||
"hidden": true,
|
||||
"action": async function () {
|
||||
console.log("remove");
|
||||
let item_id = self.item.attributes.playParams.id ?? self.item.id;
|
||||
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
|
||||
await self.removeFromLibrary(item_id);
|
||||
self.addedToLibrary = false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Play Next",
|
||||
"icon": "./assets/arrow-bend-up.svg",
|
||||
"action": function () {
|
||||
app.mk.playNext({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
|
@ -322,66 +391,13 @@
|
|||
},
|
||||
{
|
||||
"name": "Play Later",
|
||||
"icon": "./assets/arrow-bend-down.svg",
|
||||
"action": function () {
|
||||
app.mk.playLater({[self.item.attributes.playParams.kind ?? self.item.type]: self.item.attributes.playParams.id ?? self.item.id})
|
||||
app.mk.queue._reindex()
|
||||
app.selectedMediaItems = []
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/plus.svg",
|
||||
"name": (this.addedToLibrary) ? "Remove from Library..." : "Add to Library...",
|
||||
"action": async function () {
|
||||
let item_id = self.item.attributes.playParams.id ?? self.item.id;
|
||||
let data_type = self.item.attributes.playParams.kind ?? self.item.type;
|
||||
if (self.addedToLibrary != true) {
|
||||
console.log("add");
|
||||
app.addToLibrary(item_id);
|
||||
self.addedToLibrary = true
|
||||
} else {
|
||||
console.log("remove");
|
||||
await self.removeFromLibrary(item_id);
|
||||
self.addedToLibrary = false
|
||||
}
|
||||
;
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/heart.svg",
|
||||
"id": "love",
|
||||
"name": "Love",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.love(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/unheart.svg",
|
||||
"id": "unlove",
|
||||
"name": "Unlove",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/thumbs-down.svg",
|
||||
"id": "dislike",
|
||||
"name": "Dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.dislike(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/x-circle.svg",
|
||||
"id": "undo_dislike",
|
||||
"name": "Undo dislike",
|
||||
"disabled": true,
|
||||
"action": function () {
|
||||
app.unlove(self.item)
|
||||
}
|
||||
},
|
||||
{
|
||||
"icon": "./assets/feather/share.svg",
|
||||
"name": "Share",
|
||||
|
@ -398,14 +414,35 @@
|
|||
return item.id != "addToPlaylist"
|
||||
})
|
||||
}
|
||||
let rating = await app.getRating(self.item)
|
||||
if (rating == 0) {
|
||||
menus.normal.items.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.items.find(x => x.id == 'dislike').disabled = false
|
||||
} else if (rating == 1) {
|
||||
menus.normal.items.find(x => x.id == 'unlove').disabled = false
|
||||
} else if (rating == -1) {
|
||||
menus.normal.items.find(x => x.id == 'undo_dislike').disabled = false
|
||||
app.showMenuPanel(menus[useMenu], event)
|
||||
|
||||
try {
|
||||
await this.isInLibrary().then((_) => {
|
||||
if(self.addedToLibrary) {
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||
}else{
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').disabled = false
|
||||
}
|
||||
})
|
||||
|
||||
}catch(e) {
|
||||
|
||||
}
|
||||
try{
|
||||
let rating = await app.getRating(self.item)
|
||||
if (rating == 0) {
|
||||
menus.normal.headerItems.find(x => x.id == 'love').disabled = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').disabled = false
|
||||
} else if (rating == 1) {
|
||||
menus.normal.headerItems.find(x => x.id == 'unlove').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'love').hidden = true
|
||||
} else if (rating == -1) {
|
||||
menus.normal.headerItems.find(x => x.id == 'undo_dislike').hidden = false
|
||||
menus.normal.headerItems.find(x => x.id == 'dislike').hidden = true
|
||||
}
|
||||
} catch(err) {
|
||||
|
||||
}
|
||||
|
||||
if (this.contextExt) {
|
||||
|
@ -416,7 +453,6 @@
|
|||
menus.multiple.items = menus.multiple.items.concat(this.contextExt.multiple)
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu])
|
||||
},
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
|
|
111
src/renderer/views/components/menu-panel.ejs
Normal file
|
@ -0,0 +1,111 @@
|
|||
<script type="text/x-template" id="cider-menu-panel">
|
||||
<div class="menu-panel" @click.self="menuPanel.visible = false" @contextmenu.self="menuPanel.visible = false">
|
||||
|
||||
<div class="menu-panel-body" :style="getStyle()">
|
||||
<div class="menu-header-text" v-if="content.name != ''">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3 class="queue-header-text">{{ content.name }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-header-body" v-if="Object.keys(content.headerItems).length != 0">
|
||||
<template v-for="item in content.headerItems">
|
||||
<button class="menu-option-header" :class="getClasses(item)" :title="item.name"
|
||||
v-if="canDisplay(item)" :style="getItemStyle(item)" @click="action(item)">
|
||||
<div class="sidebar-icon" style="margin: 0;" v-if="item.icon">
|
||||
<div class="svg-icon" :style="{'--url': 'url(' + item.icon + ')'}"></div>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="menu-body">
|
||||
<template v-for="item in content.items">
|
||||
<button class="menu-option" v-if="canDisplay(item)" :style="getItemStyle(item)"
|
||||
@click="action(item)">
|
||||
<div class="sidebar-icon" v-if="item.icon">
|
||||
<div class="svg-icon" :style="{'--url': 'url(' + item.icon + ')'}"></div>
|
||||
</div>
|
||||
{{ item.name }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
Vue.component('cider-menu-panel', {
|
||||
template: '#cider-menu-panel',
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
menuPanel: this.$root.menuPanel,
|
||||
content: this.$root.menuPanel.content,
|
||||
getSvgIcon: this.$root.getSvgIcon,
|
||||
position: [0, 0],
|
||||
size: [0, 0],
|
||||
event: this.$root.menuPanel.event
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.event) {
|
||||
this.position = [this.event.clientX, this.event.clientY];
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.size = [document.querySelector(".menu-panel-body").offsetWidth, document.querySelector(".menu-panel-body").offsetHeight];
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
getClasses(item) {
|
||||
if (item["active"]) {
|
||||
return "active";
|
||||
}
|
||||
},
|
||||
getStyle() {
|
||||
let style = {}
|
||||
|
||||
if (this.event) {
|
||||
style["position"] = "absolute";
|
||||
style["left"] = this.event.clientX + "px";
|
||||
style["top"] = this.event.clientY + "px";
|
||||
// make sure the menu panel isnt off the screen
|
||||
if (this.event.clientX + this.size[0] > window.innerWidth) {
|
||||
style["left"] = (window.innerWidth - this.size[0]) + "px";
|
||||
}
|
||||
if (this.event.clientY + this.size[1] > window.innerHeight) {
|
||||
style["top"] = (window.innerHeight - this.size[1]) + "px";
|
||||
}
|
||||
}
|
||||
return style
|
||||
},
|
||||
getItemStyle(item) {
|
||||
let style = {}
|
||||
if (item["disabled"]) {
|
||||
style = Object.assign(style, {
|
||||
"pointer-events": "none",
|
||||
"opacity": "0.5",
|
||||
});
|
||||
}
|
||||
return style
|
||||
},
|
||||
canDisplay(item) {
|
||||
if (!item["hidden"]) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
async getActions() {
|
||||
return this.content.items;
|
||||
},
|
||||
action(item) {
|
||||
item.action()
|
||||
if (!item["keepOpen"]) {
|
||||
this.menuPanel.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -113,7 +113,7 @@
|
|||
}]
|
||||
}
|
||||
}
|
||||
CiderContextMenu.Create(event, menus[useMenu]);
|
||||
app.showMenuPanel(menus[useMenu], event);
|
||||
},
|
||||
playQueueItem(index) {
|
||||
app.mk.changeToMediaAtIndex(index)
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
"addToFavorites": {
|
||||
name: "Add to favorites",
|
||||
disabled: true,
|
||||
hidden: true,
|
||||
action: () => {
|
||||
this.addFavorite(playlist_id, "library-playlists")
|
||||
}
|
||||
|
@ -143,7 +144,7 @@
|
|||
if(this.item.type === "library-playlist-folders") {
|
||||
menu.items.addToFavorites.disabled = true
|
||||
}
|
||||
CiderContextMenu.Create(event, menu)
|
||||
app.showMenuPanel(menu, event)
|
||||
},
|
||||
dragOver(evt) {
|
||||
evt.preventDefault();
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</head>
|
||||
|
||||
<body oncontextmenu="return false;" loading="1" platform="<%= env.platform %>">
|
||||
<div id="app">
|
||||
<div id="app" :class="getAppClasses()">
|
||||
<transition name="fsModeSwitch">
|
||||
<div id="app-main" v-show="appMode == 'player'">
|
||||
<div class="mv-chrome" v-if="chrome.topChromeVisible == false"></div>
|
||||
|
@ -48,23 +48,23 @@
|
|||
<div class="app-chrome-item full-height" v-else>
|
||||
<div class="app-title"></div>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||
@click="mk.shuffleMode = 1"></button>
|
||||
<button class="playback-button--small shuffle active" v-else
|
||||
@click="mk.shuffleMode = 0"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button previous" @click="prevButton()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button pause" @click="mk.pause()" v-if="mk.isPlaying"></button>
|
||||
<button class="playback-button play" @click="mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||
@click="mk.repeatMode = 1"></button>
|
||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 2"
|
||||
|
@ -92,9 +92,10 @@
|
|||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||
</div>
|
||||
<div class="song-artist item-navigate" style="display: inline-block;"
|
||||
@click="getNowPlayingItemDetailed('album')">
|
||||
@click="getNowPlayingItemDetailed('album')">
|
||||
<div class="separator" style="display: inline-block;">{{"-"}}</div>
|
||||
{{(mk.nowPlayingItem["attributes"]["albumName"]) ? (mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
|
||||
{{(mk.nowPlayingItem["attributes"]["albumName"]) ?
|
||||
(mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -127,7 +128,8 @@
|
|||
<div class="app-chrome--right">
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<div class="app-chrome-item volume-icon"></div>
|
||||
<input type="range" class="" @wheel="volumeWheel" step="0.01" min="0" max="1" v-model="mk.volume"
|
||||
<input type="range" class="" @wheel="volumeWheel" step="0.01" min="0" max="1"
|
||||
v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
</div>
|
||||
<div class="app-chrome-item generic" v-if="false">
|
||||
|
@ -181,21 +183,30 @@
|
|||
<div class="app-sidebar-header-text">
|
||||
Apple Music
|
||||
</div>
|
||||
<sidebar-library-item name="Home" svg-icon="./assets/feather/home.svg" page="home"></sidebar-library-item>
|
||||
<sidebar-library-item name="Listen Now" svg-icon="./assets/feather/play-circle.svg" page="listen_now"></sidebar-library-item>
|
||||
<sidebar-library-item name="Browse" svg-icon="./assets/feather/globe.svg" page="browse"></sidebar-library-item>
|
||||
<sidebar-library-item name="Radio" svg-icon="./assets/feather/radio.svg" page="radio"></sidebar-library-item>
|
||||
<sidebar-library-item name="Home" svg-icon="./assets/feather/home.svg"
|
||||
page="home"></sidebar-library-item>
|
||||
<sidebar-library-item name="Listen Now" svg-icon="./assets/feather/play-circle.svg"
|
||||
page="listen_now"></sidebar-library-item>
|
||||
<sidebar-library-item name="Browse" svg-icon="./assets/feather/globe.svg"
|
||||
page="browse"></sidebar-library-item>
|
||||
<sidebar-library-item name="Radio" svg-icon="./assets/feather/radio.svg"
|
||||
page="radio"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text">
|
||||
Library
|
||||
</div>
|
||||
<sidebar-library-item name="Recently Added" svg-icon="./assets/feather/plus-circle.svg" page="library-recentlyadded"></sidebar-library-item>
|
||||
<sidebar-library-item name="Songs" svg-icon="./assets/feather/music.svg" page="library-songs"></sidebar-library-item>
|
||||
<sidebar-library-item name="Albums" svg-icon="./assets/feather/disc.svg" page="library-albums"></sidebar-library-item>
|
||||
<sidebar-library-item name="Artists" svg-icon="./assets/feather/user.svg" page="library-artists"></sidebar-library-item>
|
||||
<sidebar-library-item name="Recently Added" svg-icon="./assets/feather/plus-circle.svg"
|
||||
page="library-recentlyadded"></sidebar-library-item>
|
||||
<sidebar-library-item name="Songs" svg-icon="./assets/feather/music.svg"
|
||||
page="library-songs"></sidebar-library-item>
|
||||
<sidebar-library-item name="Albums" svg-icon="./assets/feather/disc.svg"
|
||||
page="library-albums"></sidebar-library-item>
|
||||
<sidebar-library-item name="Artists" svg-icon="./assets/feather/user.svg"
|
||||
page="library-artists"></sidebar-library-item>
|
||||
<div class="app-sidebar-header-text" @contextmenu="playlistHeaderContextMenu">
|
||||
Playlists
|
||||
</div>
|
||||
<sidebar-playlist v-for="item in getPlaylistFolderChildren('p.playlistsroot')" :item="item"></sidebar-playlist>
|
||||
<sidebar-playlist v-for="item in getPlaylistFolderChildren('p.playlistsroot')"
|
||||
:item="item"></sidebar-playlist>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<div class="usermenu-container" v-if="chrome.menuOpened">
|
||||
|
@ -220,10 +231,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button class="usermenu-item" v-if="cfg.advanced.AudioContext && cfg.audio.spatial" @click="modals.spatialProperties = true">
|
||||
<button class="usermenu-item" v-if="cfg.advanced.AudioContext && cfg.audio.spatial"
|
||||
@click="modals.spatialProperties = true">
|
||||
Spatialized Audio Settings
|
||||
</button>
|
||||
<button class="usermenu-item">
|
||||
<button class="usermenu-item" @click="appRoute('apple-account-settings')">
|
||||
Account Settings
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('about')">
|
||||
About
|
||||
</button>
|
||||
<button class="usermenu-item" @click="window.open('https://discord.gg/applemusic')">
|
||||
|
@ -239,9 +254,45 @@
|
|||
</div>
|
||||
</transition>
|
||||
<div class="app-sidebar-footer">
|
||||
<input type="range" class="web-slider display--small" step="0.01" min="0" max="1"
|
||||
v-model="mk.volume" @wheel="volumeWheel"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
|
||||
<div class="app-playback-controls display--small" v-if="mkReady()"
|
||||
@contextmenu="nowPlayingContextMenu">
|
||||
<div class="control-buttons">
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||
@click="mk.shuffleMode = 1"></button>
|
||||
<button class="playback-button--small shuffle active" v-else
|
||||
@click="mk.shuffleMode = 0"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button previous" @click="prevButton()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button pause" @click="mk.pause()"
|
||||
v-if="mk.isPlaying"></button>
|
||||
<button class="playback-button play" @click="mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="mk.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||
@click="mk.repeatMode = 1"></button>
|
||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 2"
|
||||
v-else-if="mk.repeatMode == 1"></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 0"
|
||||
v-else-if="mk.repeatMode == 2"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome-item volume">
|
||||
<div class="app-chrome-item volume-icon"></div>
|
||||
<div class="input-container">
|
||||
<input type="range" class="" @wheel="volumeWheel" step="0.01" min="0" max="1"
|
||||
v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="app-sidebar-button" style="width:100%"
|
||||
:class="{active: chrome.menuOpened}"
|
||||
@blur="setTimeout(()=>{chrome.menuOpened = false}, 100)"
|
||||
|
@ -269,13 +320,9 @@
|
|||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-sidebar-notification" v-if="library.downloadNotification.show">
|
||||
<div>{{ library.downloadNotification.message }}</div>
|
||||
<div>{{ library.downloadNotification.progress }} / {{ library.downloadNotification.total }}
|
||||
</div>
|
||||
<div style="width: 100%">
|
||||
<progress style="width: 80%;" :value="library.downloadNotification.progress"
|
||||
:max="library.downloadNotification.total"></progress>
|
||||
<div class="app-sidebar-notification libraryNotification" v-if="library.downloadNotification.show">
|
||||
<div class="message">{{ library.downloadNotification.message }} ({{
|
||||
library.downloadNotification.progress }} / {{ library.downloadNotification.total }})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -285,6 +332,18 @@
|
|||
<button class="nav-item"
|
||||
@click="navigateForward()"><%- include('svg/chevron-right.svg') %></button>
|
||||
</div>
|
||||
<!-- Apple Setings Page -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'apple-account-settings'">
|
||||
<apple-account-settings></apple-account-settings>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- About -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'about'">
|
||||
<about-page></about-page>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Artist Page -->
|
||||
<transition name="wpfade">
|
||||
<template v-if="page == 'artist-page' && artistPage.data.attributes">
|
||||
|
@ -427,7 +486,9 @@
|
|||
</transition>
|
||||
<!-- Library - Songs -->
|
||||
<transition name="wpfade" v-on:enter="getLibrarySongsFull()">
|
||||
<%- include('pages/library-songs') %>
|
||||
<template v-if="page == 'library-songs'">
|
||||
<cider-library-songs :data="library.songs"></cider-library-songs>
|
||||
</template>
|
||||
</transition>
|
||||
<!-- Library - Albums -->
|
||||
<transition name="wpfade" v-on:enter="getLibraryAlbumsFull(null, 1); searchLibraryAlbums(1);">
|
||||
|
@ -456,31 +517,42 @@
|
|||
|
||||
</div>
|
||||
<transition name="drawertransition">
|
||||
<div class="app-drawer" v-if="drawer.open">
|
||||
<div class="app-drawer" v-if="drawer.open && drawer.panel == 'lyrics'">
|
||||
<div class="bgArtworkMaterial">
|
||||
<div class="bg-artwork-container">
|
||||
<img class="bg-artwork a" :src="$store.state.artwork.playerLCD">
|
||||
<img class="bg-artwork b" :src="$store.state.artwork.playerLCD">
|
||||
</div>
|
||||
</div>
|
||||
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="lyriccurrenttime" :lyrics="lyrics"
|
||||
:richlyrics="richlyrics"></lyrics-view>
|
||||
<div v-if="drawer.panel == 'lyrics'" class="lyric-footer">
|
||||
<button class="md-btn" @click="modularUITest(!fullscreenLyrics)">{{fullscreenLyrics ? "Default View":'Fullscreen View'}}</button>
|
||||
</div>
|
||||
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="lyriccurrenttime" :lyrics="lyrics"
|
||||
:richlyrics="richlyrics"></lyrics-view>
|
||||
<div v-if="drawer.panel == 'lyrics'" class="lyric-footer">
|
||||
<button class="md-btn" @click="modularUITest(!fullscreenLyrics)">{{fullscreenLyrics ?
|
||||
"Default View":'Fullscreen View'}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="drawertransition">
|
||||
<div class="app-drawer" v-if="drawer.open && drawer.panel == 'queue'">
|
||||
<cider-queue ref="queue" v-if="drawer.panel == 'queue'"></cider-queue>
|
||||
</div>
|
||||
</transition>
|
||||
<cider-menu-panel v-if="menuPanel.visible">
|
||||
</cider-menu-panel>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="fsModeSwitch">
|
||||
<div class="fullscreen-view-container" v-if="appMode == 'fullscreen'">
|
||||
<fullscreen-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime" :lyrics="lyrics" :richlyrics="richlyrics"></fullscreen-view>
|
||||
<fullscreen-view :image="currentArtUrl.replace('50x50', '600x600')" :time="lyriccurrenttime"
|
||||
:lyrics="lyrics" :richlyrics="richlyrics"></fullscreen-view>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="wpfade">
|
||||
<div class="bg-artwork-container" :class="{noanimation: (!cfg.visual.bg_artwork_rotation || !animateBackground)}">
|
||||
<div class="bg-artwork-container"
|
||||
:class="{noanimation: (!cfg.visual.bg_artwork_rotation || !animateBackground)}">
|
||||
<img @load="chrome.artworkReady = true" class="bg-artwork a "
|
||||
>
|
||||
<img class="bg-artwork b"
|
||||
|
@ -528,6 +600,11 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Apple Settings Page -->
|
||||
<%- include('pages/apple-account-settings') %>
|
||||
<!-- Library - Songs -->
|
||||
<%- include('pages/library-songs') %>
|
||||
|
||||
<!-- Media Item Artwork-->
|
||||
<%- include("components/mediaitem-artwork"); %>
|
||||
<!-- Browse -->
|
||||
|
@ -563,6 +640,9 @@
|
|||
<!-- Search -->
|
||||
<%- include('pages/search') %>
|
||||
|
||||
<!-- About -->
|
||||
<%- include('pages/about') %>
|
||||
|
||||
<script type="text/x-template" id="am-musiccovershelf">
|
||||
<h1>{{ component.attributes.title.stringForDisplay }}</h1>
|
||||
</script>
|
||||
|
@ -576,6 +656,8 @@
|
|||
</button>
|
||||
</script>
|
||||
|
||||
<!-- Menu Panel -->
|
||||
<%- include('components/menu-panel') %>
|
||||
<!-- Playlist Listing -->
|
||||
<%- include('components/sidebar-playlist') %>
|
||||
<!-- Spatial Properties -->
|
||||
|
|
|
@ -1,19 +1,107 @@
|
|||
Major thanks to the Cider Development Team and all of our contributors.
|
||||
<script type="text/x-template" id="about-page">
|
||||
<div class="content-inner about-page">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<img src="assets/banner.png" alt="Cider Logo" style="display:block;margin:0 auto;width: 500px;">
|
||||
<p style="text-align: center">Major thanks to the Cider Collective Team and all of our contributors.</p>
|
||||
|
||||
<p>"Apple Music" - Copyright © 2021 <a href="https://www.apple.com/" class="dt-footer__link"
|
||||
target="_blank"
|
||||
rel="noopener" data-dt-link-to-exclude="">Apple Inc.</a>
|
||||
All Rights
|
||||
Reserved.</p>
|
||||
<p style="text-align: center">"Apple Music" - Copyright © 2021 <a href="https://www.apple.com/" class="dt-footer__link"
|
||||
target="_blank"
|
||||
rel="noopener" data-dt-link-to-exclude="">Apple Inc.</a>
|
||||
All Rights
|
||||
Reserved.</p>
|
||||
<hr>
|
||||
<h3>Sponsor this project</h3>
|
||||
<button onclick="window.open('https://ko-fi.com/cryptofyre')" class="md-btn sponsorBtn"><img src="./assets/ko_fi.svg"/>Ko-fi</button>
|
||||
<button onclick="window.open('https://opencollective.com/ciderapp')" class="md-btn sponsorBtn"><img src="./assets/open_collective.svg"/>Open Collective</button>
|
||||
|
||||
cryptofyre - Developer - https://github.com/cryptofyre
|
||||
Core - Developer - https://github.com/coredev-uk
|
||||
Quacksire - Developer - https://github.com/child-duckling
|
||||
booploops - Developer - https://github.com/booploops
|
||||
vapormusic - Developer - https://github.com/vapormusic
|
||||
Void - Social Communications Team - https://twitter.com/MoonyVoid
|
||||
NoseySG - Social Communications Team - https://twitter.com/noah_grose
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Cider Team</h3>
|
||||
<button class="md-btn teamBtn" @click="window.open(member.link)" v-for="member in team">
|
||||
<img :src="member.avatar"/>
|
||||
<div class="row" style="width:100%;">
|
||||
<div class="col" style="text-align: left">
|
||||
{{ member.name }}
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<b>{{ member.role }}</b>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3></h3>
|
||||
<h3>Contributors</h3>
|
||||
<img class="md-contributors"
|
||||
style="cursor:pointer;width:100%;"
|
||||
onclick="window.open('https://github.com/ciderapp/Cider/graphs/contributors')"
|
||||
src="https://contrib.rocks/image?repo=ciderapp/Cider"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img class="md-contributors"
|
||||
onclick="window.open('https://github.com/ciderapp/Cider/graphs/contributors')"
|
||||
src="https://contrib.rocks/image?repo=ciderapp/Cider"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('about-page', {
|
||||
template: '#about-page',
|
||||
data: function () {
|
||||
return {
|
||||
window: window,
|
||||
team: [
|
||||
{
|
||||
name: 'cryptofyre',
|
||||
link: 'https://github.com/cryptofyre',
|
||||
role: 'Developer',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/33162551?v=4'
|
||||
},
|
||||
{
|
||||
name: 'Core',
|
||||
link: 'https://github.com/coredev-uk',
|
||||
role: 'Developer',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/64542347?v=4'
|
||||
},
|
||||
{
|
||||
name: 'Quacksire',
|
||||
link: 'https://github.com/quacksire',
|
||||
role: 'Developer',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/19170969?v=4'
|
||||
},
|
||||
{
|
||||
name: 'booploops',
|
||||
link: 'https://github.com/booploops',
|
||||
role: 'Developer',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/49113086?v=4'
|
||||
},
|
||||
{
|
||||
name: 'vapormusic',
|
||||
link: 'https://github.com/vapormusic',
|
||||
role: 'Developer',
|
||||
avatar: 'https://avatars.githubusercontent.com/u/27716185?v=4'
|
||||
},
|
||||
{
|
||||
name: 'Void',
|
||||
link: 'https://twitter.com/MoonyVoid',
|
||||
role: 'Social Team',
|
||||
avatar: 'https://pbs.twimg.com/profile_images/1226463559472816129/8LScNYED_400x400.jpg'
|
||||
},
|
||||
{
|
||||
name: 'NoseySG',
|
||||
link: 'https://twitter.com/noah_grose',
|
||||
role: 'Social Team',
|
||||
avatar: 'https://pbs.twimg.com/profile_images/1422541289837535239/qg-aaoP9_400x400.jpg'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
18
src/renderer/views/pages/apple-account-settings.ejs
Normal file
|
@ -0,0 +1,18 @@
|
|||
<script type="text/x-template" id="apple-account-settings">
|
||||
<div style="display:flex;width:100%;height:100%;padding-top: var(--navigationBarHeight);position:absolute;top:0;left:0;">
|
||||
<webview id="foo" src="https://music.apple.com/includes/commerce/account/settings?product=music&isFullscreen=true&isModal=false" style="display:inline-flex; width:100%;"></webview>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('apple-account-settings', {
|
||||
template: '#apple-account-settings',
|
||||
mounted() {
|
||||
document.querySelector("#foo").addEventListener("dom-ready", ()=>{
|
||||
// document.querySelector("#foo").executeJavaScript(`document.body.innerHTML += ("<style>.header {display: none!important;} </style>")`)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -8,7 +8,7 @@
|
|||
<h3>Your Artists Feed</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well" style="margin-top:0px;">
|
||||
<div class="well" style="margin-top:0;">
|
||||
<template v-if="artistFeed.length > 0">
|
||||
<mediaitem-list-item v-for="item in artistFeed" :item="item"></mediaitem-list-item>
|
||||
</template>
|
||||
|
|
|
@ -52,10 +52,10 @@
|
|||
</div>
|
||||
<div class="col" v-if="data.views['top-songs']">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<h3>Top Songs</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 10" style="padding:0px;">
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 10" style="padding:0;">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - Top Songs', 'top-songs')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -138,12 +138,14 @@
|
|||
let followAction = "follow"
|
||||
let followActions = {
|
||||
follow: {
|
||||
icon: "./assets/feather/plus-circle.svg",
|
||||
name: "Follow Artist",
|
||||
action: ()=>{
|
||||
self.app.cfg.home.followedArtists.push(self.data.id)
|
||||
}
|
||||
},
|
||||
unfollow: {
|
||||
icon: "./assets/feather/x-circle.svg",
|
||||
name: "Unfollow Artist",
|
||||
action: ()=>{
|
||||
let index = self.app.cfg.home.followedArtists.indexOf(self.data.id)
|
||||
|
@ -156,9 +158,10 @@
|
|||
if(this.app.cfg.home.followedArtists.includes(self.data.id)) {
|
||||
followAction = "unfollow"
|
||||
}
|
||||
CiderContextMenu.Create(event, {
|
||||
app.showMenuPanel({
|
||||
items: [
|
||||
{
|
||||
icon: "./assets/feather/play.svg",
|
||||
name: "Play Artist Radio",
|
||||
action: ()=>{
|
||||
app.mk.setStationQueue({artist:self.data.id}).then(()=>{
|
||||
|
@ -168,13 +171,14 @@
|
|||
},
|
||||
followActions[followAction],
|
||||
{
|
||||
icon: "./assets/feather/share.svg",
|
||||
name: "Share",
|
||||
action: ()=>{
|
||||
self.app.copyToClipboard(self.data.attributes.url)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}, event)
|
||||
},
|
||||
getArtistPalette(artist) {
|
||||
if (artist["attributes"]["artwork"]) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<div style="width: 260px;height:260px;">
|
||||
<mediaitem-artwork
|
||||
:video-priority="true"
|
||||
:url="(data.attributes != null && data.attributes.artwork && data.attributes.artwork != null) ? data.attributes.artwork.url : ((data.relationships != null && data.relationships.tracks.data.length > 0) ? data.relationships.tracks.data[0].attributes.artwork.url ?? '':'')"
|
||||
: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>
|
||||
|
@ -40,10 +40,11 @@
|
|||
@click="data.attributes && data.attributes.artistName ? app.searchAndNavigate(data,'artist') : ''">
|
||||
{{getArtistName(data)}}
|
||||
</div>
|
||||
<div class="playlist-desc" v-if="getDescription(data) != ''">
|
||||
<div class="content"
|
||||
v-html="getDescription(data)"></div>
|
||||
<button class="more-btn" @click="editorialNotesExpanded = !editorialNotesExpanded">
|
||||
<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">
|
||||
More
|
||||
</button>
|
||||
</div>
|
||||
|
@ -58,18 +59,30 @@
|
|||
</div>
|
||||
</template>
|
||||
<div class="playlist-controls">
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
<button class="md-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 0; play()">
|
||||
Play
|
||||
</button>
|
||||
<button class="wr-btn" style="min-width: 120px;"
|
||||
<button class="md-btn" style="min-width: 120px;"
|
||||
@click="app.mk.shuffleMode = 1;play()">
|
||||
Shuffle
|
||||
</button>
|
||||
<button class="wr-btn" style="min-width: 120px;" v-if="inLibrary!=null"
|
||||
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString())">
|
||||
<button class="md-btn" style="min-width: 120px;" v-if="inLibrary!=null && confirm!=true"
|
||||
@click="confirmButton()">
|
||||
{{ (!inLibrary) ? "Add to Library" : "Remove from Library" }}
|
||||
</button>
|
||||
<button class="md-btn" style="min-width: 120px;" v-if="confirm==true"
|
||||
@click="(!inLibrary) ? addToLibrary(data.attributes.playParams.id.toString()) : removeFromLibrary(data.attributes.playParams.id.toString()) ">
|
||||
Confirm?
|
||||
</button>
|
||||
<button class="playlist-more" @click="menu">
|
||||
<div style=" margin-top: -1px;
|
||||
margin-left: -5px;
|
||||
width: 36px;
|
||||
height: 36px;">
|
||||
<%- include("../svg/more.svg") %>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -88,7 +101,8 @@
|
|||
<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">
|
||||
<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>
|
||||
|
@ -97,7 +111,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="playlist-time">
|
||||
{{getFormattedDate(data.attributes.releaseDate)}}
|
||||
{{getFormattedDate()}}
|
||||
</div>
|
||||
<div class="playlist-time total">{{app.getTotalTime()}}</div>
|
||||
<div class="playlist-time item-navigate" @click="app.searchAndNavigate(data,'recordLabel') "
|
||||
|
@ -109,16 +123,19 @@
|
|||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-playlist', {
|
||||
template: "#cider-playlist",
|
||||
props: ["data"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
editorialNotesExpanded: false,
|
||||
drag: false,
|
||||
nameEditing: false,
|
||||
inLibrary: null,
|
||||
confirm: false,
|
||||
app: this.$root,
|
||||
itemBadges: [],
|
||||
badgesRequested: false
|
||||
|
@ -161,24 +178,14 @@
|
|||
}
|
||||
})
|
||||
},
|
||||
getDescription(data) {
|
||||
console.log(data.attributes)
|
||||
if (data.attributes.editorialNotes) {
|
||||
if (data.attributes.editorialNotes.hasOwnProperty('short')) {
|
||||
return data.attributes.editorialNotes.short
|
||||
} else if (data.attributes.editorialNotes.hasOwnProperty('standard')) {
|
||||
return data.attributes.editorialNotes.standard
|
||||
}
|
||||
} else if (data.attributes.description) {
|
||||
if (data.attributes.description.hasOwnProperty('short')) {
|
||||
return data.attributes.description.short
|
||||
} else if (data.attributes.description.hasOwnProperty('standard')) {
|
||||
return data.attributes.description.standard
|
||||
}
|
||||
}
|
||||
return ''
|
||||
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) {
|
||||
|
@ -192,8 +199,12 @@
|
|||
async isInLibrary() {
|
||||
if (this.data.type && !this.data.type.includes("library")) {
|
||||
// please keep using vars here
|
||||
var params = { "fields[playlists]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library" }
|
||||
var 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);
|
||||
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 && res.attributes && res.attributes.inLibrary) ? res.attributes.inLibrary : false
|
||||
console.log(res)
|
||||
} else {
|
||||
|
@ -203,7 +214,7 @@
|
|||
editPlaylist() {
|
||||
this.app.editPlaylist(this.data.id, this.data.attributes.name);
|
||||
this.app.playlists.listing.forEach(playlist => {
|
||||
if (playlist.id == this.data.id) {
|
||||
if (playlist.id === this.data.id) {
|
||||
playlist.attributes.name = this.data.attributes.name
|
||||
}
|
||||
})
|
||||
|
@ -212,21 +223,23 @@
|
|||
addToLibrary(id) {
|
||||
app.mk.addToLibrary(id)
|
||||
this.inLibrary = true
|
||||
this.confirm = false
|
||||
},
|
||||
async removeFromLibrary(id) {
|
||||
var params = { "fields[somgs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library" }
|
||||
const params = {"fields[somgs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library"};
|
||||
var id = this.data.id ?? this.data.attributes.playParams.id
|
||||
var 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);
|
||||
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 && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) {
|
||||
id = res.relationships.library.data[0].id
|
||||
}
|
||||
let kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
||||
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
app.mk.api.library.remove({ [truekind]: id })
|
||||
const truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
app.mk.api.library.remove({[truekind]: id})
|
||||
this.inLibrary = false
|
||||
this.confirm = false
|
||||
},
|
||||
editPlaylistName() {
|
||||
if (this.data.attributes.canEdit && this.data.type == "library-playlists") {
|
||||
if (this.data.attributes.canEdit && this.data.type === "library-playlists") {
|
||||
this.nameEditing = true
|
||||
setTimeout(() => {
|
||||
document.querySelector(".nameEdit").focus()
|
||||
|
@ -295,20 +308,69 @@
|
|||
}
|
||||
})
|
||||
},
|
||||
menu(event) {
|
||||
app.showMenuPanel({
|
||||
items: {
|
||||
"share": {
|
||||
name: "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 (date) {
|
||||
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 = 'Released '
|
||||
break;
|
||||
case this.data.attributes.lastModifiedDate:
|
||||
prefix = 'Updated '
|
||||
break;
|
||||
case this.data.attributes.dateAdded:
|
||||
prefix = 'Added '
|
||||
break;
|
||||
}
|
||||
let month, year;
|
||||
try {
|
||||
var releaseDate = new Date(date);
|
||||
month = new Intl.DateTimeFormat('en-US', { month: 'long' }).format(releaseDate);
|
||||
const releaseDate = new Date(date);
|
||||
console.log(date, releaseDate)
|
||||
month = new Intl.DateTimeFormat('en-US', {month: 'long'}).format(releaseDate);
|
||||
date = releaseDate.getDate();
|
||||
year = releaseDate.getFullYear();
|
||||
|
||||
return date + " " + month + " " + year;
|
||||
return prefix + date + " " + month + " " + year;
|
||||
} catch (e) {
|
||||
return ""
|
||||
}
|
||||
|
@ -322,25 +384,27 @@
|
|||
array[j] = temp;
|
||||
}
|
||||
}
|
||||
var id = this.data.attributes.playParams.id ?? this.data.id;
|
||||
|
||||
const id = this.data.attributes.playParams.id ?? this.data.id;
|
||||
//console.log("1")
|
||||
var kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
||||
const kind = this.data.attributes.playParams.kind ?? this.data.type ?? '';
|
||||
//console.log("1")
|
||||
var truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
||||
|
||||
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.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)}
|
||||
})
|
||||
let u = query.slice(100);
|
||||
if (app.mk.shuffleMode == 1) {
|
||||
shuffleArray(u)
|
||||
}
|
||||
app.mk.queue.append(u)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<button class="cd-btn-seeall" @click="app.appRoute('artist-feed')">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well artistfeed-well" style="margin-top:0px;">
|
||||
<div class="well artistfeed-well" style="margin-top:0;">
|
||||
<template v-if="artistFeed.length > 0">
|
||||
<mediaitem-list-item v-for="item in artistFeed.limit(6)" :item="item"></mediaitem-list-item>
|
||||
</template>
|
||||
|
@ -55,7 +55,14 @@
|
|||
</div>
|
||||
<div class="row" v-if="friendsListeningTo && friendsListeningTo.length > 0">
|
||||
<div class="col">
|
||||
<h3>Friends Listening To</h3>
|
||||
<div class="row">
|
||||
<div class="col nopadding">
|
||||
<h3>Friends Listening To</h3>
|
||||
</div>
|
||||
<div class="col-auto nopadding flex-center">
|
||||
<button class="cd-btn-seeall" @click="app.showSocialListeningTo()">See All</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well">
|
||||
<template v-if="isSectionReady('friendsListeningTo')">
|
||||
<mediaitem-square kind="small" v-for="item in friendsListeningTo"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template v-if="page == 'library-albums'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<h1 class="header-text">Albums</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
|
@ -9,8 +9,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<h1 class="header-text">Artists</h1>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template v-if="page == 'library-recentlyadded'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<h1 class="header-text">Recently Added</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
|
@ -10,8 +10,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0px;">
|
||||
<div class="col" style="padding:0;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
|
|
|
@ -1,46 +1,80 @@
|
|||
<template v-if="page == 'library-songs'">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px;">
|
||||
<h1 class="header-text">Songs</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.songs.downloadState == 2" @click="getLibrarySongsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
</div>
|
||||
<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="searchLibrarySongs"
|
||||
v-model="library.songs.search" class="search-input">
|
||||
|
||||
|
||||
<script type="text/x-template" id="cider-library-songs">
|
||||
<div class="content-inner library-page">
|
||||
<div class="library-header">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0;">
|
||||
<div class="search-input-container" style="width:100%;margin: 16px 0;">
|
||||
<div class="search-input--icon"></div>
|
||||
<input type="search"
|
||||
style="width:100%;"
|
||||
spellcheck="false"
|
||||
placeholder="Search..."
|
||||
@input="$root.searchLibrarySongs"
|
||||
v-model="library.songs.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<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 class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="prefs.sort" @change="$root.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="prefs.sortOrder" @change="$root.searchLibrarySongs()">
|
||||
<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="prefs.size" @change="$root.searchLibrarySongs()">
|
||||
<optgroup label="Size">
|
||||
<option value="normal">Normal</option>
|
||||
<option value="compact">Compact</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<button v-if="library.songs.downloadState == 2" @click="$root.getLibrarySongsFull(true)" class="reload-btn"><%- include('../svg/redo.svg') %></button>
|
||||
<button v-else class="reload-btn" style="opacity: 0.8;pointer-events: none">
|
||||
<div class="spinner"></div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
|
||||
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
<div class="well" :key="1" v-if="prefs.size == 'compact'">
|
||||
<mediaitem-list-item class-list="compact" :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="well" :key="2" v-else>
|
||||
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-library-songs', {
|
||||
template: '#cider-library-songs',
|
||||
data: function () {
|
||||
return {
|
||||
library: this.$root.library,
|
||||
mediaItemSize: "compact",
|
||||
prefs: this.$root.cfg.libraryPrefs.songs
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sayHello: function () {
|
||||
alert('Hello world!');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -1,6 +1,6 @@
|
|||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0px">
|
||||
<div class="col" style="padding:0">
|
||||
<h1 class="header-text">Made For You</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -90,18 +90,6 @@
|
|||
<input type="checkbox" switch v-model="app.cfg.visual.bg_artwork_rotation"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Window Transparency
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select" style="width:180px;" v-model="app.cfg.visual.window_transparency" @change="app.getHTMLStyle()">
|
||||
<option value="default">Default</option>
|
||||
<option value="acrylic" v-if="app.platform == 'win32'">Acrylic</option>
|
||||
<option value="disabled">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Hardware Acceleration<br>
|
||||
|
@ -447,7 +435,7 @@
|
|||
<div class="md-option-segment">
|
||||
LastFM Scrobbling
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<div class="md-option-segment md-btn md-option-segment_auto">
|
||||
<label class="list-button list-element" id="lfmConnect" ref="lfmConnect"
|
||||
onclick="app.LastFMAuthenticate()">Connect</label>
|
||||
</div>
|
||||
|
@ -477,77 +465,92 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="md-option-header">
|
||||
<span>Unfinished / Non Functional</span>
|
||||
<span>Experimental</span>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme
|
||||
Compact UI
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Cider</option>
|
||||
</select>
|
||||
<div class="md-option-segment md-option-segment_auto" >
|
||||
<button class="md-btn" :class="{'md-btn-primary': app.cfg.advanced.experiments.includes('compactui')}" @click="app.cfg.advanced.experiments.includes('compactui') ? removeExperiment('compactui') : addExperiment('compactui')">
|
||||
{{app.cfg.advanced.experiments.includes('compactui') ? 'Enabled' : 'Disabled'}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme Options
|
||||
<div style="opacity: 0.5; pointer-events: none">
|
||||
<div class="md-option-header">
|
||||
<span>Unfinished / Non Functional</span>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="btn">Theme Options</button>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Scrollbars
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Theme Options
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="btn">Theme Options</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Show on hover</option>
|
||||
<option value="1">Always show</option>
|
||||
<option value="2">Hidden</option>
|
||||
</select>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Scrollbars
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value="0">Show on hover</option>
|
||||
<option value="1">Always show</option>
|
||||
<option value="2">Hidden</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Refresh Rate
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Refresh Rate
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Automatic</option>
|
||||
<option value='30'>30</option>
|
||||
<option value='60'>60</option>
|
||||
<option value='144'>144</option>
|
||||
<option value='175'>175</option>
|
||||
<option value='240'>240</option>
|
||||
<option value='360'>30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Automatic</option>
|
||||
<option value='30'>30</option>
|
||||
<option value='60'>60</option>
|
||||
<option value='144'>144</option>
|
||||
<option value='175'>175</option>
|
||||
<option value='240'>240</option>
|
||||
<option value='360'>30</option>
|
||||
</select>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Close Button Behavior
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Minimize to system tray</option>
|
||||
<option value='1'>Minimize to taskbar ? dock</option>
|
||||
<option value='2'>Quit Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Close Button Behavior
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Minimize to system tray</option>
|
||||
<option value='1'>Minimize to taskbar ? dock</option>
|
||||
<option value='2'>Quit Cider</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Open Cider on Startup
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Never</option>
|
||||
<option value='1'>Always</option>
|
||||
<option value='2'>Always, minimized</option>
|
||||
<option value='2'>Always, hidden in tray</option>
|
||||
</select>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Open Cider on Startup
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select">
|
||||
<option value='0'>Never</option>
|
||||
<option value='1'>Always</option>
|
||||
<option value='2'>Always, minimized</option>
|
||||
<option value='2'>Always, hidden in tray</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -573,6 +576,12 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
addExperiment(flag) {
|
||||
app.cfg.advanced.experiments.push(flag);
|
||||
},
|
||||
removeExperiment(flag) {
|
||||
app.cfg.advanced.experiments.splice(app.cfg.advanced.experiments.indexOf(flag), 1);
|
||||
},
|
||||
toggleAudioContext: function(){
|
||||
if (app.cfg.advanced.AudioContext){
|
||||
CiderAudio.init();
|
||||
|
|
13
src/renderer/views/svg/in-library.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 214 214" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-79.4309,9.53659)">
|
||||
<path d="M250.163,76.146C250.163,52.589 231.037,33.463 207.48,33.463L122.114,33.463C98.556,33.463 79.431,52.589 79.431,76.146L79.431,161.512C79.431,185.07 98.556,204.195 122.114,204.195L207.48,204.195C231.037,204.195 250.163,185.07 250.163,161.512L250.163,76.146ZM235.163,83.646C235.163,64.228 219.398,48.463 199.98,48.463L129.614,48.463C110.196,48.463 94.431,64.228 94.431,83.646L94.431,154.012C94.431,173.43 110.196,189.195 129.614,189.195L199.98,189.195C219.398,189.195 235.163,173.43 235.163,154.012L235.163,83.646Z" style="fill:currentColor;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.906286,0,0,0.906286,-20.9871,-22.3274)">
|
||||
<path d="M250.163,76.146C250.163,52.589 231.037,33.463 207.48,33.463L122.114,33.463C98.556,33.463 79.431,52.589 79.431,76.146L79.431,161.512C79.431,185.07 98.556,204.195 122.114,204.195L207.48,204.195C231.037,204.195 250.163,185.07 250.163,161.512L250.163,76.146Z" style="fill:white;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.333526,0,0,0.333526,43.0167,0)">
|
||||
<path d="M511.8,130.7C511.8,115 510.5,99.3 506.7,84C500,56 484,34.7 460.2,19C448,11 434.5,6.1 420.1,3.5C409.1,1.5 397.9,0.6 386.8,0.3L384.1,0L127.6,0C124.4,0.3 121.1,0.4 117.9,0.6C102,1.5 86.2,3.2 71.1,9.2C42.7,20.4 22.1,40.1 10.1,68.4C5.9,78 3.8,88.2 2.3,98.5C1.1,106.8 0.4,115.3 0.1,123.7L-0.1,125.7L-0.1,386.4C0.1,389.4 0.2,392.4 0.4,395.4C1.5,412.8 3.7,430.1 11.1,446.1C24.9,476.4 48.2,496.3 80.1,505.8C89,508.6 98.3,509.8 107.7,510.6C119.5,511.8 131.4,511.9 143.2,511.9L378.5,511.9C389.7,511.9 400.8,511.2 412,509.7C429.6,507.5 446.1,502.3 461,492.5C478.9,480.7 492.4,465 501.1,445.4C505.1,436.4 507.3,426.8 509,417.2C511.4,402.8 511.9,388.2 511.9,373.6C511.8,292.6 511.9,211.6 511.8,130.6L511.8,130.7ZM374.8,93.4L374.8,337.6C374.8,346.5 373.6,355.3 369.6,363.3C363.4,375.9 353.4,383.8 340,387.6C332.6,389.8 324.9,390.9 317.2,391.3C297,392.3 279.4,378.6 275.8,358.6C272.7,342.1 280.6,323.9 298,315.4C304.8,312.1 312.2,310.1 319.7,308.6C327.8,306.9 335.9,305.3 343.9,303.4C349.8,302.1 353.6,298.5 354.8,292.4L355.2,288.3L355.2,172.1L354.6,168.2C353.8,165 351.4,163 348.1,163.2C344.7,163.4 341.4,163.9 338,164.6C321.7,167.8 305.5,171 289.3,174.3L210.4,190.2L209.3,190.5C203.4,192.2 201.3,194.8 201,201L201,203.7C200.9,259.2 201,314.7 200.9,370.2C200.9,379.2 199.9,388 196.3,396.4C190.4,410.1 179.9,418.7 165.7,422.7C158.2,424.9 150.5,426.1 142.7,426.4C122.3,427.2 105.3,413.6 101.8,393.5C98.8,376.2 106.7,357.5 126.4,349.2C134.1,346 142,344.3 150.1,342.6C156.2,341.4 162.4,340.1 168.4,338.9C176.6,337.2 180.8,332 181.2,323.7L181.2,131C181.2,128.3 181.5,125.7 182.1,123.1C183.6,117 187.9,113.5 193.8,112.1C199.2,110.7 204.8,109.7 210.3,108.5C226,105.3 241.5,102.2 257.2,99.1L305.6,89.3C319.9,86.5 334.2,83.6 348.5,80.7C353.2,79.8 357.9,78.8 362.7,78.4C369.3,77.8 373.9,82 374.5,88.7C374.7,90.3 374.8,91.9 374.8,93.4Z" style="fill:currentColor;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -2,12 +2,7 @@
|
|||
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
fill="white" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#333333;}
|
||||
</style>
|
||||
<g id="XMLID_6_">
|
||||
<path id="XMLID_11_" class="st0" d="M418.5,139.4H232.4v139.8h186.1V139.4z M464.8,46.7H46.3C20.5,46.7,0,68.1,0,93.1v325.9
|
||||
<path id="XMLID_11_" d="M418.5,139.4H232.4v139.8h186.1V139.4z M464.8,46.7H46.3C20.5,46.7,0,68.1,0,93.1v325.9
|
||||
c0,25.8,21.4,46.3,46.3,46.3h419.4c25.8,0,46.3-20.5,46.3-46.3V93.1C512,67.2,490.6,46.7,464.8,46.7z M464.8,418.9H46.3V92.2h419.4
|
||||
v326.8H464.8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 716 B After Width: | Height: | Size: 627 B |