Merge branch 'main' of https://github.com/ciderapp/Cider into main
This commit is contained in:
commit
90dcde279a
137 changed files with 8653 additions and 4265 deletions
8
src/renderer/assets/MissingArtwork.svg
Normal file
8
src/renderer/assets/MissingArtwork.svg
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?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 1024 1024" 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;">
|
||||
<rect x="0" y="0" width="1024" height="1024" style="fill:rgb(110,110,110);"/>
|
||||
<g transform="matrix(6.05996,0,0,6.05996,189.003,209)">
|
||||
<path d="M93.161,0.071C59.66,-1.043 32.22,11.314 32.22,11.314L32.2,74.023C28.789,72.669 24.641,72.348 20.428,73.372C11.345,75.579 5.397,83.192 7.143,90.379C8.889,97.566 17.667,101.604 26.749,99.398C35.313,97.317 41.087,90.429 40.256,83.626L40.256,36.771C40.256,36.771 59.66,29.987 84.829,28.286L84.829,63.135C81.455,61.843 77.386,61.55 73.25,62.555C64.167,64.761 58.219,72.374 59.965,79.562C61.71,86.749 70.488,90.786 79.571,88.58C87.502,86.653 93.042,80.603 93.158,74.316L93.161,74.32L93.161,0.071Z" style="fill-opacity:0.16;fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/renderer/assets/oobe/maverick.png
Normal file
BIN
src/renderer/assets/oobe/maverick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 346 KiB |
BIN
src/renderer/assets/oobe/mojave.png
Normal file
BIN
src/renderer/assets/oobe/mojave.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 326 KiB |
File diff suppressed because it is too large
Load diff
BIN
src/renderer/audio/impulses/AtmosphereRealizer_BSCBM.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_BSCBM.wav
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Cuddle.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Cuddle.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E168_1.2.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E168_1.2.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E68_1.5.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E68_1.5.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E68_2.2.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_E68_2.2.wav
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z3600.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z3600.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_A.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_A.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_B.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_B.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_C.wav
Normal file
BIN
src/renderer/audio/impulses/AtmosphereRealizer_Z8500_C.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CAP_256_FINAL_48k.wav
Normal file
BIN
src/renderer/audio/impulses/CAP_256_FINAL_48k.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CAP_64.wav
Normal file
BIN
src/renderer/audio/impulses/CAP_64.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_BPLK.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_BPLK.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_Diffuse.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_Diffuse.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_HW2K.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_HW2K.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_LIVE.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_LIVE.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_LIVE_2.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_LIVE_2.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_Maikiwi.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_Maikiwi.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_MaikiwiPlus.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_MaikiwiPlus.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_Natural+.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_Natural+.wav
Normal file
Binary file not shown.
BIN
src/renderer/audio/impulses/CiderSpatial_Natural.wav
Normal file
BIN
src/renderer/audio/impulses/CiderSpatial_Natural.wav
Normal file
Binary file not shown.
Binary file not shown.
|
@ -1,294 +1,367 @@
|
|||
var notyf = new Notyf();
|
||||
|
||||
const MusicKitObjects = {
|
||||
LibraryPlaylist: function () {
|
||||
this.id = ""
|
||||
this.type = "library-playlist-folders"
|
||||
this.href = ""
|
||||
this.attributes = {
|
||||
dateAdded: "",
|
||||
name: ""
|
||||
}
|
||||
this.playlists = []
|
||||
}
|
||||
}
|
||||
LibraryPlaylist: function () {
|
||||
this.id = "";
|
||||
this.type = "library-playlist-folders";
|
||||
this.href = "";
|
||||
this.attributes = {
|
||||
dateAdded: "",
|
||||
name: "",
|
||||
};
|
||||
this.playlists = [];
|
||||
},
|
||||
};
|
||||
|
||||
// limit an array to a certain number of items
|
||||
Array.prototype.limit = function (n) {
|
||||
return this.slice(0, n);
|
||||
return this.slice(0, n);
|
||||
};
|
||||
|
||||
Vue.component('animated-number', {
|
||||
Vue.component("animated-number", {
|
||||
template: "<div style='display: inline-block;'>{{ displayNumber }}</div>",
|
||||
props: { number: { default: 0 } },
|
||||
|
||||
template: "<div style='display: inline-block;'>{{ displayNumber }}</div>",
|
||||
props: { 'number': { default: 0 } },
|
||||
data() {
|
||||
return {
|
||||
displayNumber: 0,
|
||||
interval: false,
|
||||
};
|
||||
},
|
||||
|
||||
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);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
ready() {
|
||||
this.displayNumber = this.number ? this.number : 0;
|
||||
Vue.component("sidebar-library-item", {
|
||||
template: "#sidebar-library-item",
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
|
||||
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);
|
||||
}
|
||||
page: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
svgIcon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
cdClick: {
|
||||
type: Function,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
app: app,
|
||||
svgIconData: "",
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
if (this.svgIcon) {
|
||||
this.svgIconData = await this.app.getSvgIcon(this.svgIcon);
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('sidebar-library-item', {
|
||||
template: '#sidebar-library-item',
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
page: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
svgIcon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
cdClick: {
|
||||
type: Function,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
app: app,
|
||||
svgIconData: ""
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (this.svgIcon) {
|
||||
this.svgIconData = await this.app.getSvgIcon(this.svgIcon)
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
|
||||
function fallbackinitMusicKit() {
|
||||
const request = new XMLHttpRequest();
|
||||
const request = new XMLHttpRequest();
|
||||
|
||||
function loadAlternateKey() {
|
||||
let parsedJson = JSON.parse(this.responseText)
|
||||
MusicKit.configure({
|
||||
developerToken: parsedJson.developerToken,
|
||||
app: {
|
||||
name: 'Apple Music',
|
||||
build: '1978.4.1',
|
||||
version: "1.0"
|
||||
},
|
||||
sourceType: 24,
|
||||
suppressErrorDialog: true
|
||||
})
|
||||
setTimeout(() => {
|
||||
app.init()
|
||||
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||
app.spawnMica()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
function loadAlternateKey() {
|
||||
let parsedJson = JSON.parse(this.responseText);
|
||||
MusicKit.configure({
|
||||
developerToken: parsedJson.developerToken,
|
||||
app: {
|
||||
name: "Apple Music",
|
||||
build: "1978.4.1",
|
||||
version: "1.0",
|
||||
},
|
||||
sourceType: 24,
|
||||
suppressErrorDialog: true,
|
||||
});
|
||||
setTimeout(() => {
|
||||
app.init();
|
||||
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||
app.spawnMica();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
request.addEventListener("load", loadAlternateKey);
|
||||
request.open("GET", "https://raw.githubusercontent.com/lujjjh/LitoMusic/main/token.json");
|
||||
request.send();
|
||||
request.addEventListener("load", loadAlternateKey);
|
||||
request.open(
|
||||
"GET",
|
||||
"https://raw.githubusercontent.com/lujjjh/LitoMusic/main/token.json"
|
||||
);
|
||||
request.send();
|
||||
}
|
||||
|
||||
document.addEventListener('musickitloaded', function () {
|
||||
console.log('MusicKit loaded')
|
||||
// MusicKit global is now defined
|
||||
function initMusicKit() {
|
||||
let parsedJson = JSON.parse(this.responseText)
|
||||
MusicKit.configure({
|
||||
developerToken: parsedJson.token,
|
||||
app: {
|
||||
name: 'Apple Music',
|
||||
build: '1978.4.1',
|
||||
version: "1.0"
|
||||
},
|
||||
sourceType: 24,
|
||||
suppressErrorDialog: true
|
||||
}).then(() => {
|
||||
function waitForApp() {
|
||||
if (typeof app.init !== "undefined") {
|
||||
app.init()
|
||||
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||
app.spawnMica()
|
||||
}
|
||||
}
|
||||
else {
|
||||
setTimeout(waitForApp, 250);
|
||||
}
|
||||
}
|
||||
waitForApp()
|
||||
})
|
||||
}
|
||||
function initMusicKit() {
|
||||
|
||||
|
||||
const request = new XMLHttpRequest();
|
||||
request.timeout = 5000;
|
||||
request.addEventListener("load", initMusicKit);
|
||||
request.onreadystatechange = function (aEvt) {
|
||||
if (request.readyState == 4) {
|
||||
if (request.status != 200)
|
||||
fallbackinitMusicKit()
|
||||
let parsedJson = JSON.parse(this.responseText);
|
||||
MusicKit.configure({
|
||||
developerToken: parsedJson.token,
|
||||
app: {
|
||||
name: "Apple Music",
|
||||
build: "1978.4.1",
|
||||
version: "1.0",
|
||||
},
|
||||
sourceType: 24,
|
||||
suppressErrorDialog: true,
|
||||
}).then(() => {
|
||||
function waitForApp() {
|
||||
if (typeof app.init !== "undefined") {
|
||||
app.init();
|
||||
if (app.cfg.visual.window_background_style == "mica" && !app.isDev) {
|
||||
app.spawnMica();
|
||||
}
|
||||
};
|
||||
request.open("GET", "https://api.cider.sh/v1/");
|
||||
request.send();
|
||||
} else {
|
||||
setTimeout(waitForApp, 250);
|
||||
}
|
||||
}
|
||||
waitForApp();
|
||||
});
|
||||
}
|
||||
|
||||
// check for widevine failure and reconfigure the instance.
|
||||
window.addEventListener("drmUnsupported", function () {
|
||||
initMusicKit()
|
||||
});
|
||||
function capiInit() {
|
||||
const request = new XMLHttpRequest();
|
||||
request.timeout = 5000;
|
||||
request.addEventListener("load", initMusicKit);
|
||||
request.onreadystatechange = function (aEvt) {
|
||||
if (request.readyState == 4) {
|
||||
if (request.status != 200) fallbackinitMusicKit();
|
||||
}
|
||||
};
|
||||
request.open("GET", "https://api.cider.sh/v1/");
|
||||
request.send();
|
||||
}
|
||||
|
||||
document.addEventListener("musickitloaded", function () {
|
||||
if (showOobe()) return;
|
||||
console.log("MusicKit loaded");
|
||||
// MusicKit global is now defined
|
||||
capiInit()
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
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');
|
||||
});
|
||||
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");
|
||||
});
|
||||
}
|
||||
|
||||
const getBase64FromUrl = async (url) => {
|
||||
const data = await fetch(url);
|
||||
const blob = await data.blob();
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(blob);
|
||||
reader.onloadend = () => {
|
||||
const base64data = reader.result;
|
||||
resolve(base64data);
|
||||
}
|
||||
});
|
||||
}
|
||||
const data = await fetch(url);
|
||||
const blob = await data.blob();
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(blob);
|
||||
reader.onloadend = () => {
|
||||
const base64data = reader.result;
|
||||
resolve(base64data);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
function Clone(obj) {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
function uuidv4() {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||
);
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(
|
||||
c ^
|
||||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
|
||||
).toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
function xmlToJson(xml) {
|
||||
// Create the return object
|
||||
let obj = {};
|
||||
|
||||
// Create the return object
|
||||
let obj = {};
|
||||
|
||||
if (xml.nodeType == 1) { // element
|
||||
// do attributes
|
||||
if (xml.attributes.length > 0) {
|
||||
obj["@attributes"] = {};
|
||||
for (var j = 0; j < xml.attributes.length; j++) {
|
||||
let attribute = xml.attributes.item(j);
|
||||
obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
|
||||
}
|
||||
}
|
||||
} else if (xml.nodeType == 3) { // text
|
||||
obj = xml.nodeValue;
|
||||
if (xml.nodeType == 1) {
|
||||
// element
|
||||
// do attributes
|
||||
if (xml.attributes.length > 0) {
|
||||
obj["@attributes"] = {};
|
||||
for (var j = 0; j < xml.attributes.length; j++) {
|
||||
let attribute = xml.attributes.item(j);
|
||||
obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
|
||||
}
|
||||
}
|
||||
} else if (xml.nodeType == 3) {
|
||||
// text
|
||||
obj = xml.nodeValue;
|
||||
}
|
||||
|
||||
// do children
|
||||
if (xml.hasChildNodes()) {
|
||||
for (var i = 0; i < xml.childNodes.length; i++) {
|
||||
var item = xml.childNodes.item(i);
|
||||
var nodeName = item.nodeName;
|
||||
if (typeof (obj[nodeName]) == "undefined") {
|
||||
obj[nodeName] = xmlToJson(item);
|
||||
} else {
|
||||
if (typeof (obj[nodeName].push) == "undefined") {
|
||||
var old = obj[nodeName];
|
||||
obj[nodeName] = [];
|
||||
obj[nodeName].push(old);
|
||||
}
|
||||
obj[nodeName].push(xmlToJson(item));
|
||||
}
|
||||
// do children
|
||||
if (xml.hasChildNodes()) {
|
||||
for (var i = 0; i < xml.childNodes.length; i++) {
|
||||
var item = xml.childNodes.item(i);
|
||||
var nodeName = item.nodeName;
|
||||
if (typeof obj[nodeName] == "undefined") {
|
||||
obj[nodeName] = xmlToJson(item);
|
||||
} else {
|
||||
if (typeof obj[nodeName].push == "undefined") {
|
||||
var old = obj[nodeName];
|
||||
obj[nodeName] = [];
|
||||
obj[nodeName].push(old);
|
||||
}
|
||||
obj[nodeName].push(xmlToJson(item));
|
||||
}
|
||||
}
|
||||
console.log(obj);
|
||||
return obj;
|
||||
};
|
||||
}
|
||||
console.log(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
async function asyncForEach(array, callback) {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
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) {
|
||||
clearInterval(checkIfScrollIsStatic)
|
||||
// do something
|
||||
}
|
||||
position = document.getElementsByClassName('lyric-body')[0].scrollTop
|
||||
} catch (e) {
|
||||
try {
|
||||
if (
|
||||
position === document.getElementsByClassName("lyric-body")[0].scrollTop
|
||||
) {
|
||||
clearInterval(checkIfScrollIsStatic);
|
||||
// do something
|
||||
}
|
||||
|
||||
position = document.getElementsByClassName("lyric-body")[0].scrollTop;
|
||||
} catch (e) { }
|
||||
}, 50);
|
||||
|
||||
// WebGPU Console Notification
|
||||
async function webGPU() {
|
||||
try {
|
||||
const currentGPU = await navigator.gpu.requestAdapter()
|
||||
console.log("WebGPU enabled on", currentGPU.name, "with feature ID", currentGPU.features.size)
|
||||
} catch (e) {
|
||||
console.log("WebGPU disabled / WebGPU initialization failed")
|
||||
}
|
||||
try {
|
||||
const currentGPU = await navigator.gpu.requestAdapter();
|
||||
console.log(
|
||||
"WebGPU enabled on",
|
||||
currentGPU.name,
|
||||
"with feature ID",
|
||||
currentGPU.features.size
|
||||
);
|
||||
} catch (e) {
|
||||
console.log("WebGPU disabled / WebGPU initialization failed");
|
||||
}
|
||||
}
|
||||
|
||||
function isJson(item) {
|
||||
item = typeof item !== "string"
|
||||
? JSON.stringify(item)
|
||||
: item;
|
||||
|
||||
try {
|
||||
item = JSON.parse(item);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof item === "object" && item !== null) {
|
||||
return true;
|
||||
}
|
||||
item = typeof item !== "string" ? JSON.stringify(item) : item;
|
||||
|
||||
try {
|
||||
item = JSON.parse(item);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof item === "object" && item !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
webGPU().then()
|
||||
webGPU().then();
|
||||
|
||||
function showOobe() {
|
||||
return false
|
||||
if (localStorage.getItem("music.ampwebplay.media-user-token") && localStorage.getItem("seenOOBE")) {
|
||||
return false
|
||||
} else {
|
||||
function waitForApp() {
|
||||
if (typeof app.init !== "undefined") {
|
||||
app.oobeInit();
|
||||
} else {
|
||||
setTimeout(waitForApp, 250);
|
||||
}
|
||||
}
|
||||
waitForApp();
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
let screenWidth = screen.width;
|
||||
let screenHeight = screen.height;
|
||||
|
||||
window.onerror = function (error) {
|
||||
console.log(error)
|
||||
bootbox.alert("Error occurred: " + error)
|
||||
};
|
||||
document.addEventListener("DOMContentLoaded", async function () {
|
||||
// app.oobeInit()
|
||||
});
|
||||
|
||||
document.addEventListener(
|
||||
"contextmenu",
|
||||
function (e) {
|
||||
if (
|
||||
e.target.tagName.toLowerCase() == "textarea" ||
|
||||
(e.target.tagName.toLowerCase() == "input" &&
|
||||
e.target.type != "checkbox" &&
|
||||
e.target.type != "radio" &&
|
||||
e.target.disabled == false)
|
||||
) {
|
||||
e.preventDefault();
|
||||
const menuPanel = {
|
||||
items: {
|
||||
cut: {
|
||||
name: app.getLz("action.cut"),
|
||||
action: function () {
|
||||
document.execCommand("cut");
|
||||
},
|
||||
},
|
||||
copy: {
|
||||
name: app.getLz("action.copy"),
|
||||
action: function () {
|
||||
document.execCommand("copy");
|
||||
},
|
||||
},
|
||||
paste: {
|
||||
name: app.getLz("action.paste"),
|
||||
action: function () {
|
||||
document.execCommand("paste");
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
name: app.getLz("action.delete"),
|
||||
action: function () {
|
||||
document.execCommand("delete");
|
||||
},
|
||||
},
|
||||
selectAll: {
|
||||
name: app.getLz("action.selectAll"),
|
||||
action: function () {
|
||||
document.execCommand("selectAll");
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
app.showMenuPanel(menuPanel, e);
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
padding: 14px;
|
||||
background: var(--opaquePageBGColor);
|
||||
font-size: 0.85em;
|
||||
|
||||
&.child {
|
||||
background: rgb(0 0 0 / 15%);
|
||||
}
|
||||
}
|
||||
|
||||
.md-option-segment.md-option-segment_auto {
|
||||
|
|
|
@ -17,4 +17,5 @@
|
|||
--ciderColor: @ciderColor;
|
||||
--appOpacity: @appOpacity;
|
||||
--transparencyRate: @transparencyRate;
|
||||
--macOSChromeColor: rgb(14 14 14 / 32%);
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
@font-face {
|
||||
font-family: "codicon";
|
||||
font-display: block;
|
||||
src: url("codicon.ttf") format("truetype");
|
||||
src: url("./codicon.ttf?f06865699f1720ee6ca6e0a4aa084d76") format("truetype");
|
||||
}
|
||||
|
||||
.codicon[class*='codicon-'] {
|
||||
|
@ -43,6 +43,10 @@
|
|||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.codicon-modifier-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* custom speed & easing for loading icon */
|
||||
.codicon-loading {
|
||||
animation-duration: 1s !important;
|
||||
|
@ -551,3 +555,7 @@
|
|||
.codicon-arrow-circle-left:before { content: "\ebfd" }
|
||||
.codicon-arrow-circle-right:before { content: "\ebfe" }
|
||||
.codicon-arrow-circle-up:before { content: "\ebff" }
|
||||
.codicon-layout-sidebar-right-off:before { content: "\ec00" }
|
||||
.codicon-layout-panel-off:before { content: "\ec01" }
|
||||
.codicon-layout-sidebar-left-off:before { content: "\ec02" }
|
||||
.codicon-blank:before { content: "\ec03" }
|
||||
|
|
Binary file not shown.
|
@ -274,7 +274,7 @@
|
|||
|
||||
.song-name {
|
||||
text-align : left;
|
||||
font-size : 0.98em;
|
||||
font-size : 0.8em;
|
||||
font-weight : 500;
|
||||
width : 100%;
|
||||
-webkit-mask-image: linear-gradient(-90deg, transparent 0%, transparent 10%, black 20%);
|
||||
|
@ -283,8 +283,12 @@
|
|||
.song-artist,
|
||||
.song-album {
|
||||
font-size: 0.75em;
|
||||
opacity : 0.8;
|
||||
cursor : pointer;
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
max-width: 360px;
|
||||
-webkit-mask-image: linear-gradient(-90deg, transparent 0%, transparent 10%, black 20%);
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
|
|
|
@ -211,7 +211,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Media Item Elements
|
||||
|
||||
.mediaitem-artwork {
|
||||
|
@ -221,9 +220,6 @@
|
|||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
.animatedartwork-view-box {
|
||||
position: absolute;
|
||||
|
@ -270,6 +266,9 @@
|
|||
object-fit: cover;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
pointer-events: none;
|
||||
background-image: url("./assets/MissingArtwork.svg");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
&.no-shadow {
|
||||
|
@ -289,6 +288,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#artworkLCD img {
|
||||
image-rendering: auto;
|
||||
}
|
||||
|
||||
/* queue item */
|
||||
.cd-queue-item {
|
||||
border-bottom: 0px solid rgb(200 200 200 / 10%);
|
||||
|
@ -393,11 +397,26 @@
|
|||
align-items: center;
|
||||
border-radius: var(--mediaItemRadius);
|
||||
position: relative;
|
||||
&:hover{
|
||||
.heart-icon{
|
||||
|
||||
.listitem-content {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
flex-direction: row;
|
||||
font-size: 14px;
|
||||
justify-content: center-between;
|
||||
align-items: center;
|
||||
border-radius: var(--mediaItemRadius);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.heart-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.popular {
|
||||
background-image: url(assets/star.svg);
|
||||
background-repeat: no-repeat;
|
||||
|
@ -411,7 +430,6 @@
|
|||
.artwork {
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
border-radius: var(--mediaItemRadius);
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
flex: 0 0 auto;
|
||||
|
@ -421,6 +439,11 @@
|
|||
outline: none;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: var(--mediaItemRadiusSmall);
|
||||
|
||||
.mediaitem-artwork {
|
||||
border-radius: var(--mediaItemRadiusSmall);
|
||||
}
|
||||
|
||||
.overlay-play {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
|
@ -522,27 +545,35 @@
|
|||
10% {
|
||||
box-shadow: inset 0 -4px 0
|
||||
}
|
||||
|
||||
20% {
|
||||
box-shadow: inset 0 -10px 0
|
||||
}
|
||||
|
||||
30% {
|
||||
box-shadow: inset 0 -12px 0
|
||||
}
|
||||
|
||||
40% {
|
||||
box-shadow: inset 0 -8px 0
|
||||
}
|
||||
|
||||
50% {
|
||||
box-shadow: inset 0 -4px 0
|
||||
}
|
||||
|
||||
60% {
|
||||
box-shadow: inset 0 -6px 0
|
||||
}
|
||||
|
||||
80% {
|
||||
box-shadow: inset 0 -12px 0
|
||||
}
|
||||
|
||||
90% {
|
||||
box-shadow: inset 0 -6px 0
|
||||
}
|
||||
|
||||
to {
|
||||
box-shadow: inset 0 -2px 0
|
||||
}
|
||||
|
@ -927,6 +958,7 @@
|
|||
|
||||
/* mediaitem-square */
|
||||
.cd-mediaitem-square {
|
||||
--transitionDuration: .25s;
|
||||
--scaleRate: 1.25;
|
||||
--scaleRateArtwork: 1;
|
||||
width: 200px;
|
||||
|
@ -938,6 +970,7 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
|
||||
|
||||
.artwork-container {
|
||||
position: relative;
|
||||
|
@ -952,6 +985,8 @@
|
|||
flex: 0 0 auto;
|
||||
margin: 6px;
|
||||
cursor: pointer;
|
||||
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear;
|
||||
|
||||
.mediaitem-artwork {
|
||||
box-shadow: unset;
|
||||
}
|
||||
|
@ -1024,15 +1059,33 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1600px) {
|
||||
width: calc(200px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
.artwork-container>.artwork {
|
||||
width: calc(190px * var(--scaleRateArtwork));
|
||||
height: calc(190px * var(--scaleRateArtwork));
|
||||
&:not(.mediaitem-card):not(.mediaitem-brick):not(.mediaitem-video):not(.noscale) {
|
||||
@media (min-width: 1460px) {
|
||||
--scaleRate: 1.1;
|
||||
--scaleRateArtwork: 0.9;
|
||||
width: calc(200px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(190px * var(--scaleRateArtwork));
|
||||
height: calc(190px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1550px) {
|
||||
--scaleRate: 1.25;
|
||||
--scaleRateArtwork: 1;
|
||||
width: calc(200px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(190px * var(--scaleRateArtwork));
|
||||
height: calc(190px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.info-rect {
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
|
@ -1072,7 +1125,7 @@
|
|||
margin: 2em;
|
||||
border-radius: 10px;
|
||||
|
||||
>.codicon {
|
||||
> .codicon {
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
opacity: 0.5;
|
||||
|
@ -1080,8 +1133,6 @@
|
|||
}
|
||||
|
||||
&.mediaitem-video {
|
||||
--scaleRate: 1.25;
|
||||
--scaleRateArtwork: 1.25;
|
||||
height: 200px;
|
||||
width: 240px;
|
||||
|
||||
|
@ -1090,12 +1141,29 @@
|
|||
width: 212px;
|
||||
}
|
||||
|
||||
@media (min-width: 1600px) {
|
||||
width: calc(240px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
.artwork-container>.artwork {
|
||||
width: calc(212px * var(--scaleRateArtwork));
|
||||
height: calc(120px * var(--scaleRateArtwork));
|
||||
&:not(.noscale) {
|
||||
@media (min-width: 1460px) {
|
||||
--scaleRate: 1.1;
|
||||
--scaleRateArtwork: 1.1;
|
||||
width: calc(240px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(220px * var(--scaleRateArtwork));
|
||||
height: calc(123px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1550px) {
|
||||
--scaleRate: 1.25;
|
||||
--scaleRateArtwork: 1.25;
|
||||
width: calc(240px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(220px * var(--scaleRateArtwork));
|
||||
height: calc(123px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1108,6 +1176,32 @@
|
|||
height: 123px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
&:not(.noscale) {
|
||||
@media (min-width: 1460px) {
|
||||
--scaleRate: 1.1;
|
||||
--scaleRateArtwork: 1.1;
|
||||
width: calc(240px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(220px * var(--scaleRateArtwork));
|
||||
height: calc(123px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1550px) {
|
||||
--scaleRate: 1.25;
|
||||
--scaleRateArtwork: 1.25;
|
||||
width: calc(240px * var(--scaleRate));
|
||||
height: calc(200px * var(--scaleRate));
|
||||
|
||||
.artwork-container > .artwork {
|
||||
width: calc(220px * var(--scaleRateArtwork));
|
||||
height: calc(123px * var(--scaleRateArtwork));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.mediaitem-small {
|
||||
|
@ -1123,7 +1217,7 @@
|
|||
&.mediaitem-card {
|
||||
background: #ccc;
|
||||
background: var(--spcolor);
|
||||
height: 298px;
|
||||
height: 302px;
|
||||
width: 230px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
@ -1136,7 +1230,7 @@
|
|||
overflow: hidden;
|
||||
border-radius: 0px;
|
||||
margin: 0;
|
||||
|
||||
transition: width var(--transitionDuration) linear, height var(--transitionDuration) linear, filter 0.2s ease-in-out;
|
||||
.mediaitem-artwork {
|
||||
border-radius: 0px;
|
||||
|
||||
|
@ -1150,6 +1244,8 @@
|
|||
padding: 10px 10px 14px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
|
||||
&::before {
|
||||
background: var(--bgartwork);
|
||||
|
@ -1164,6 +1260,7 @@
|
|||
z-index: 0;
|
||||
opacity: 1;
|
||||
filter: brightness(0.5) blur(50px) saturate(180%);
|
||||
transition: filter 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,9 +1272,10 @@
|
|||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
z-index: 1;
|
||||
&+ .subtitle {
|
||||
|
||||
& + .subtitle {
|
||||
max-height: none !important;
|
||||
margin-top: -0.5em;
|
||||
// margin-top: -0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1191,7 +1289,7 @@
|
|||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
overflow: hidden;
|
||||
max-height: 3.8em;
|
||||
max-height: 4.8em;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@ -1207,14 +1305,34 @@
|
|||
border-radius: inherit;
|
||||
}
|
||||
|
||||
//@media (min-width: 1600px) {
|
||||
// width: calc(230px * 1.25);
|
||||
// height: calc(298px * 1.25);
|
||||
// .artwork-container>.artwork {
|
||||
// width: calc(230px * 1.25);
|
||||
// height: calc(230px * 1.25);
|
||||
// }
|
||||
//}
|
||||
&:hover {
|
||||
.artwork{
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
.info-rect-card::before {
|
||||
filter: brightness(0.3) blur(50px) saturate(180%);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.noscale) {
|
||||
@media (min-width: 1460px) {
|
||||
width: calc(230px * 1.1);
|
||||
height: calc(298px * 1.1);
|
||||
.artwork-container > .artwork {
|
||||
width: calc(230px * 1.1);
|
||||
height: calc(230px * 1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1550px) {
|
||||
width: calc(230px * 1.25);
|
||||
height: calc(298px * 1.25);
|
||||
.artwork-container > .artwork {
|
||||
width: calc(230px * 1.25);
|
||||
height: calc(230px * 1.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1460,7 +1578,6 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
/* End Switch Checkbox */
|
||||
|
||||
|
||||
|
||||
.header-text {
|
||||
margin: 0px;
|
||||
}
|
||||
|
@ -1580,10 +1697,31 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
background-repeat: no-repeat;
|
||||
opacity: 0.70;
|
||||
border-radius: 6px;
|
||||
}
|
||||
position: relative;
|
||||
|
||||
.playback-button:active {
|
||||
transform: scale(0.95);
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: var(--selected);
|
||||
border-radius: inherit;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
transform: scale(0.5);
|
||||
pointer-events: none;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:before {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.playback-button--small {
|
||||
|
@ -1599,22 +1737,47 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
border: 0px;
|
||||
box-shadow: unset;
|
||||
opacity: 0.70;
|
||||
}
|
||||
position: relative;
|
||||
|
||||
.playback-button:hover,
|
||||
.playback-button--small:hover {
|
||||
background-color: rgb(200 200 200 / 10%);
|
||||
}
|
||||
&:before {
|
||||
content: "";
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: var(--selected);
|
||||
border-radius: inherit;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
transform: scale(0.5);
|
||||
pointer-events: none;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
||||
.playback-button:active,
|
||||
.playback-button--small:active {
|
||||
transform: scale(0.9);
|
||||
&:hover {
|
||||
&:before {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.playback-button--small.active {
|
||||
background-color: rgb(200 200 200 / 25%);
|
||||
}
|
||||
|
||||
.playback-button:hover,
|
||||
.playback-button--small:hover {
|
||||
// background-color: var(--selected);
|
||||
}
|
||||
|
||||
.playback-button:active,
|
||||
.playback-button--small:active {
|
||||
background-color: var(--selected-click);
|
||||
}
|
||||
|
||||
.playback-button--small.search {
|
||||
background-image: url("./assets/search.svg");
|
||||
}
|
||||
|
@ -1655,6 +1818,18 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
.playback-button.collapseLibrary {
|
||||
font-family: "codicon";
|
||||
font-size: 1em;
|
||||
color: var(--textColor);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.playback-button.pause {
|
||||
background-image: url('./assets/cider-icons/pause.svg');
|
||||
background-size: 38px;
|
||||
|
@ -1678,11 +1853,14 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
background-size: 60%;
|
||||
background-position: center;
|
||||
}
|
||||
.playback-button.disabled, .playback-button--small.disabled {
|
||||
|
||||
.playback-button.disabled,
|
||||
.playback-button--small.disabled {
|
||||
opacity: 0.25 !important;
|
||||
pointer-events: none;
|
||||
transform: none !important;
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
@ -1694,10 +1872,11 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
>svg {
|
||||
height:16px;
|
||||
width:16px;
|
||||
pointer-events: none;
|
||||
|
||||
> svg {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1907,6 +2086,7 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
border-radius: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.artist-chip__name {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -1989,36 +2169,37 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
|
||||
// fancy pills
|
||||
.nav-pills {
|
||||
position : relative;
|
||||
position: relative;
|
||||
|
||||
.nav-link {
|
||||
transition: transform .3s var(--appleEase);
|
||||
position : relative;
|
||||
position: relative;
|
||||
|
||||
|
||||
&:after {
|
||||
--dist: 1px;
|
||||
content : "";
|
||||
position : absolute;
|
||||
top : var(--dist);
|
||||
bottom : var(--dist);
|
||||
left : var(--dist);
|
||||
right : var(--dist);
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: var(--dist);
|
||||
bottom: var(--dist);
|
||||
left: var(--dist);
|
||||
right: var(--dist);
|
||||
// width : 100%;
|
||||
// height : 100%;
|
||||
background-color: transparent;
|
||||
border-radius : 50px;
|
||||
z-index : -1;
|
||||
opacity : 0;
|
||||
border-radius: 50px;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: background-color .5s var(--appleEase), opacity 0.25s var(--appleEase), border-radius .32s var(--appleEase);
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
outline : none;
|
||||
transform : scale(1.1);
|
||||
outline: none;
|
||||
transform: scale(1.1);
|
||||
// background: #eee;
|
||||
background : transparent;
|
||||
color : #333;
|
||||
background: transparent;
|
||||
color: #333;
|
||||
|
||||
&:after {
|
||||
opacity: 1;
|
||||
|
@ -2031,11 +2212,11 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
}
|
||||
|
||||
&.active {
|
||||
outline : none;
|
||||
transform : scale(1.1);
|
||||
outline: none;
|
||||
transform: scale(1.1);
|
||||
// background: #eee;
|
||||
background : transparent;
|
||||
color : #333;
|
||||
background: transparent;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
|
||||
&:after {
|
||||
|
@ -2049,24 +2230,24 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
|
||||
&:hover {
|
||||
.nav-link.active {
|
||||
outline : none;
|
||||
transform : scale(1.0);
|
||||
outline: none;
|
||||
transform: scale(1.0);
|
||||
background: transparent;
|
||||
color: #eee;
|
||||
transform : scale(1.0);
|
||||
transform: scale(1.0);
|
||||
|
||||
&:after {
|
||||
background : rgb(200 200 200 / 15%);
|
||||
opacity : 1;
|
||||
background: rgb(200 200 200 / 15%);
|
||||
opacity: 1;
|
||||
transition: color 0s;
|
||||
// border-radius: 5px;
|
||||
--dist: 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform : scale(1.1);
|
||||
z-index : 1;
|
||||
color : #333;
|
||||
transform: scale(1.1);
|
||||
z-index: 1;
|
||||
color: #333;
|
||||
|
||||
&:after {
|
||||
background: #eee;
|
||||
|
@ -2078,15 +2259,15 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
}
|
||||
|
||||
&:after {
|
||||
content : '';
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
bottom : 0;
|
||||
right : 0;
|
||||
background : rgb(200 200 200 / 10%);
|
||||
border-radius : 50px;
|
||||
z-index : 0;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgb(200 200 200 / 10%);
|
||||
border-radius: 50px;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
@ -2095,6 +2276,7 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
|
||||
.grouping-btn {
|
||||
padding: 16px;
|
||||
appearance: none;
|
||||
|
@ -2126,8 +2308,7 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
}
|
||||
}
|
||||
|
||||
.app-sidebar-header
|
||||
.search-input-container .search-hints-container {
|
||||
.app-sidebar-header .search-input-container .search-hints-container {
|
||||
top: 38px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
@ -2135,17 +2316,16 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
.content-inner {
|
||||
&.library-page {
|
||||
.heart-icon {
|
||||
left: 7px;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
.cd-mediaitem-list-item {
|
||||
padding-left: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.library-artists-page {
|
||||
.inner-container
|
||||
.list-container
|
||||
.podcasts-list {
|
||||
.inner-container .list-container .podcasts-list {
|
||||
background: rgba(27, 27, 27);
|
||||
padding-top: 14px;
|
||||
width: 272px;
|
||||
|
@ -2153,9 +2333,10 @@ input[type=checkbox][switch]:checked:active::before {
|
|||
.cd-mediaitem-list-item {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.cd-mediaitem-list-item:hover {
|
||||
width: 96%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -153,22 +153,8 @@
|
|||
}
|
||||
|
||||
.close-btn {
|
||||
width : 50px;
|
||||
height : 100%;
|
||||
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;
|
||||
.menu-panel.menu-header-text.close-btn
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(196, 43, 28)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,22 +177,7 @@
|
|||
}
|
||||
|
||||
.close-btn {
|
||||
width : 50px;
|
||||
height : 100%;
|
||||
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-panel.menu-header-text.close-btn
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,23 +342,31 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.menu-header-text {
|
||||
margin: 18px 6px;
|
||||
|
||||
.close-btn {
|
||||
width : 50px;
|
||||
height : 42px;
|
||||
background-image : var(--gfx-closeBtn);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
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;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
appearance: none;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
border-radius: 50px;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
font-family: "codicon";
|
||||
color: var(--textColor);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(196, 43, 28)
|
||||
|
@ -505,7 +484,8 @@
|
|||
.popover-artwork {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
margin: 0 0 20px 0;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.song-name {
|
||||
|
|
|
@ -3,4 +3,57 @@ body[platform="linux"] {
|
|||
#window-controls-container {
|
||||
//display: none;
|
||||
}
|
||||
|
||||
.window-controls {
|
||||
justify-content: flex-end;
|
||||
align-items : center;
|
||||
padding-right : 6px;
|
||||
|
||||
>div {
|
||||
--iconSize: 16px;
|
||||
|
||||
&.close,
|
||||
&.minmax,
|
||||
&.minimize,
|
||||
&.minmax.restore {
|
||||
background-image: unset!important;
|
||||
position : relative;
|
||||
display : grid;
|
||||
align-content : center;
|
||||
text-align : center;
|
||||
height : 36px!important;
|
||||
width : 36px!important;
|
||||
border-radius : 50px;
|
||||
transition: background-color .1s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background: rgb(200 200 200 / 10%)!important;
|
||||
}
|
||||
}
|
||||
|
||||
&.close::before {
|
||||
font-family: "codicon";
|
||||
font-size : var(--iconSize);
|
||||
content : "";
|
||||
}
|
||||
|
||||
&.minmax::before {
|
||||
font-family: "codicon";
|
||||
font-size : var(--iconSize);
|
||||
content : "";
|
||||
}
|
||||
|
||||
&.minimize::before {
|
||||
font-family: "codicon";
|
||||
font-size : var(--iconSize);
|
||||
content : "";
|
||||
}
|
||||
|
||||
&.restore::before {
|
||||
font-family: "codicon";
|
||||
font-size : var(--iconSize);
|
||||
content : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,5 +13,37 @@ body[platform="darwin"] {
|
|||
&::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app-chrome {
|
||||
background-color: var(--macOSChromeColor);
|
||||
}
|
||||
|
||||
&.twopanel {
|
||||
--chromeHeight1: 55px;
|
||||
--chromeHeight: calc(var(--chromeHeight1) + var(--chromeHeight2));
|
||||
|
||||
.app-chrome .app-chrome-item.search {
|
||||
margin-right: 12px;
|
||||
}
|
||||
.app-chrome .app-mainmenu {
|
||||
width: 46px;
|
||||
}
|
||||
|
||||
.app-chrome.chrome-bottom {
|
||||
background-color: var(--macOSChromeColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#app-main {
|
||||
background-color: transparent;
|
||||
|
||||
.app-navigation {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#app-content {
|
||||
background-color: var(--baseColor);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -114,23 +114,35 @@
|
|||
margin: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
// Search Page
|
||||
&.search-page {
|
||||
|
||||
.searchToggle {
|
||||
float: right;
|
||||
|
||||
>button {
|
||||
min-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.cd-mediaitem-square.mediaitem-brick {
|
||||
width: 530px !important;
|
||||
.artwork-container .artwork{
|
||||
height:168px !important;
|
||||
width:507px !important;
|
||||
z-index: 1;
|
||||
}
|
||||
.title{
|
||||
font-weight: bold;
|
||||
justify-content: left;
|
||||
font-size: 18px;
|
||||
margin-top: -40px;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
}
|
||||
width: 530px !important;
|
||||
|
||||
.artwork-container .artwork {
|
||||
height : 168px !important;
|
||||
width : 507px !important;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight : bold;
|
||||
justify-content: left;
|
||||
font-size : 18px;
|
||||
margin-top : -40px;
|
||||
z-index : 5;
|
||||
pointer-events : none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,7 +565,7 @@
|
|||
overflow-y : overlay;
|
||||
height : 100%;
|
||||
padding : 0px;
|
||||
background-color: var(--color1);
|
||||
background-color: var(--color3);
|
||||
|
||||
&.scrollbody {
|
||||
.tabs {
|
||||
|
@ -622,7 +634,7 @@
|
|||
opacity : .7;
|
||||
animation : playlistArtworkFadeIn 1s var(--appleEase);
|
||||
|
||||
.artworkMaterial>img {
|
||||
.artworkMaterial img {
|
||||
filter : brightness(100%) blur(80px) saturate(100%) contrast(1);
|
||||
object-position: center;
|
||||
object-fit : cover;
|
||||
|
@ -665,13 +677,23 @@
|
|||
}
|
||||
|
||||
.nameEdit {
|
||||
font-weight : 700;
|
||||
font-size : 1.6rem;
|
||||
flex-shrink : unset;
|
||||
background : transparent;
|
||||
border : 0px;
|
||||
color : inherit;
|
||||
font-family : inherit;
|
||||
font-weight: 700;
|
||||
font-size : 1.6rem;
|
||||
flex-shrink: unset;
|
||||
background : transparent;
|
||||
border : 0px;
|
||||
color : inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.descriptionEdit {
|
||||
font-size : 14px;
|
||||
flex-shrink: unset;
|
||||
background : transparent;
|
||||
border : 0px;
|
||||
color : inherit;
|
||||
font-family: inherit;
|
||||
width : 60vw;
|
||||
}
|
||||
|
||||
.descriptionEdit {
|
||||
|
@ -950,6 +972,10 @@
|
|||
right : 28px;
|
||||
}
|
||||
|
||||
&.animated .artist-header {
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.artist-header {
|
||||
//background: linear-gradient(45deg, var(--keyColor), #0e0e0e);
|
||||
color : white;
|
||||
|
@ -965,6 +991,19 @@
|
|||
// margin-top: -16px;
|
||||
}
|
||||
|
||||
.artist-hero {
|
||||
height:100%;
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
|
||||
.mediaitem-artwork {
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.artworkContainer {
|
||||
position : absolute;
|
||||
|
@ -978,7 +1017,7 @@
|
|||
opacity : .7;
|
||||
animation : playlistArtworkFadeIn 1s var(--appleEase);
|
||||
|
||||
.artworkMaterial>img {
|
||||
.artworkMaterial img {
|
||||
filter : brightness(100%) blur(80px) saturate(100%) contrast(1);
|
||||
object-position: center;
|
||||
object-fit : cover;
|
||||
|
@ -1001,6 +1040,7 @@
|
|||
position : absolute;
|
||||
overflow : hidden;
|
||||
box-shadow: rgb(0 0 0 / 50%) 0 0 0 1000000px inset;
|
||||
z-index: 1;
|
||||
|
||||
video {
|
||||
overflow : hidden;
|
||||
|
@ -1166,8 +1206,9 @@
|
|||
&.addon {
|
||||
background: rgb(86 86 86 / 20%);
|
||||
}
|
||||
|
||||
&.applied {
|
||||
background: var(--keyColor-disabled);
|
||||
background : var(--keyColor-disabled);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
@ -1218,10 +1259,10 @@
|
|||
}
|
||||
|
||||
.handle {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
height : 100%;
|
||||
display : flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-items : center;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
|
@ -1229,6 +1270,7 @@
|
|||
&:hover {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
@ -1645,26 +1687,223 @@
|
|||
}
|
||||
}
|
||||
|
||||
.content-inner.cider-multiroom{
|
||||
.content-inner.oobe {
|
||||
position : absolute;
|
||||
overflow : hidden;
|
||||
top : 0;
|
||||
left : 0;
|
||||
bottom : 0;
|
||||
right : 0;
|
||||
display : grid;
|
||||
place-items: center;
|
||||
width : 100%;
|
||||
background : #1e1e1e;
|
||||
|
||||
.oobe-view {
|
||||
display : flex;
|
||||
flex-direction : column;
|
||||
justify-content: center;
|
||||
align-items : center;
|
||||
gap : 32px;
|
||||
max-width : 1280px;
|
||||
max-height : 720px;
|
||||
align-self : center;
|
||||
justify-self : center;
|
||||
height : 100%;
|
||||
width : 100%;
|
||||
|
||||
|
||||
.oobe-header {
|
||||
font-size : 3em;
|
||||
text-shadow: var(--replayTextShadow);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.oobe-body {
|
||||
flex : 1;
|
||||
width : 100%;
|
||||
background : #ffffff0d;
|
||||
border-radius: 20px;
|
||||
padding : 3em;
|
||||
overflow-y : scroll;
|
||||
overflow-x : hidden;
|
||||
|
||||
@media screen and (max-width: 1161px) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&.text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.blurb {
|
||||
white-space: pre-wrap;
|
||||
margin : 16px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
&.visual {
|
||||
padding: 1em;
|
||||
|
||||
.stylePicker {
|
||||
border-radius: 10px;
|
||||
overflow : hidden;
|
||||
cursor : pointer;
|
||||
transition : 0.25s all;
|
||||
box-shadow : 0px 2px 6px rgba(0, 0, 0, 0.25);
|
||||
width : 450px;
|
||||
margin : 0 auto;
|
||||
|
||||
.visualPreview {
|
||||
pointer-events: none;
|
||||
transition : .25s all;
|
||||
width : 100%;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
padding : 0;
|
||||
display : flex;
|
||||
justify-content: center;
|
||||
align-items : center;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
font-size : 1.25em;
|
||||
font-weight: 500;
|
||||
position : absolute;
|
||||
bottom : 0;
|
||||
left : 0;
|
||||
width : 100%;
|
||||
border : 0px;
|
||||
text-shadow: 0px 2px 6px rgba(0, 0, 0, 0.25);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.style-active {
|
||||
outline: 4px solid var(--keyColor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
&:hover {
|
||||
transform : scale(1.10) translateZ(-1px) translateY(10px);
|
||||
z-index : 1;
|
||||
box-shadow: 0px 12px 16px rgb(0 0 0 / 25%);
|
||||
}
|
||||
|
||||
@media screen and (max-height: 688px) {
|
||||
width: 270px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oobe-footer {
|
||||
display : flex;
|
||||
flex-direction : row;
|
||||
justify-content: center;
|
||||
align-items : center;
|
||||
padding : 16px;
|
||||
|
||||
.md-btn {
|
||||
font-size : 18px;
|
||||
min-width : 128px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.oobe-titlebar {
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
height : 46px;
|
||||
width : 100%;
|
||||
align-items : center;
|
||||
justify-content : right;
|
||||
display : flex;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
.button-group {
|
||||
-webkit-app-region: no-drag;
|
||||
display : flex;
|
||||
flex-direction : row;
|
||||
width : 100px;
|
||||
height : 100%;
|
||||
justify-content : center;
|
||||
align-items : center;
|
||||
gap : 16px;
|
||||
|
||||
>button {
|
||||
height : 32px;
|
||||
width : 32px;
|
||||
font-size : 16px;
|
||||
border-radius : 0px;
|
||||
border : 0;
|
||||
appearance : none;
|
||||
position : relative;
|
||||
display : flex;
|
||||
justify-content: center;
|
||||
align-items : center;
|
||||
border-radius : 100%;
|
||||
|
||||
&.close {
|
||||
background-color: #fc3c44aa;
|
||||
&:hover {
|
||||
background-color: #fc3c44;
|
||||
}
|
||||
}
|
||||
|
||||
&.min {
|
||||
background-color: rgb(200 200 200 / 5%);
|
||||
&:hover {
|
||||
background-color: rgb(200 200 200 / 10%);
|
||||
}
|
||||
}
|
||||
|
||||
&.close::before {
|
||||
font-family: "codicon";
|
||||
content : "";
|
||||
color : white;
|
||||
}
|
||||
|
||||
&.min::before {
|
||||
font-family: "codicon";
|
||||
content : "";
|
||||
color : white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-inner.cider-multiroom {
|
||||
padding: 0px;
|
||||
.detail{
|
||||
|
||||
.detail {
|
||||
padding: 32px;
|
||||
}
|
||||
.header-desc{
|
||||
font-size: 1em;
|
||||
|
||||
.header-desc {
|
||||
font-size : 1em;
|
||||
font-weight: 400;
|
||||
}
|
||||
.artworkContainer{
|
||||
|
||||
.artworkContainer {
|
||||
height: 300px;
|
||||
width : 100%;
|
||||
img{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
height : 100%;
|
||||
width : 100%;
|
||||
overflow : hidden;
|
||||
object-fit: cover;
|
||||
filter: unset;
|
||||
&:last-child{
|
||||
transform: unset;
|
||||
filter : unset;
|
||||
|
||||
&:last-child {
|
||||
transform: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,107 +1,91 @@
|
|||
import { CiderCache } from "./cidercache.js"
|
||||
import { CiderCache } from "./cidercache.js";
|
||||
|
||||
async function spawnMica() {
|
||||
if (typeof window.micaSpawned !== "undefined") {
|
||||
return
|
||||
if (typeof window.micaSpawned !== "undefined") {
|
||||
return;
|
||||
} else {
|
||||
window.micaSpawned = true;
|
||||
}
|
||||
const micaDiv = document.createElement("div");
|
||||
const blurIterations = 6;
|
||||
micaDiv.id = "micaEffect";
|
||||
micaDiv.style.position = "fixed";
|
||||
micaDiv.style.top = "0";
|
||||
micaDiv.style.left = "0";
|
||||
micaDiv.style.right = "0";
|
||||
micaDiv.style.bottom = "0";
|
||||
micaDiv.style.zIndex = -1;
|
||||
|
||||
let lastScreenX;
|
||||
let lastScreenY;
|
||||
let lastScreenWidth;
|
||||
let lastScreenHeight;
|
||||
|
||||
let regen = true;
|
||||
let imgSrc = await ipcRenderer.sendSync("get-wallpaper", {
|
||||
blurAmount: 256
|
||||
});
|
||||
|
||||
// let micaCache = await CiderCache.getCache("mica-cache");
|
||||
// if (!micaCache) {
|
||||
// micaCache = {
|
||||
// path: "",
|
||||
// data: "",
|
||||
// };
|
||||
// }
|
||||
// if (micaCache.path == imgSrc.path) {
|
||||
// regen = false;
|
||||
// imgSrc = micaCache;
|
||||
// }
|
||||
let canvas = document.createElement("canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
let img = new Image();
|
||||
micaDiv.style.backgroundImage = `url(${imgSrc.data})`;
|
||||
document.body.appendChild(micaDiv);
|
||||
|
||||
function onScreenMove(cb) {
|
||||
function detectScreenMove() {
|
||||
if (lastScreenY !== window.screenY || lastScreenX !== window.screenX) {
|
||||
lastScreenY = window.screenY;
|
||||
lastScreenX = window.screenX;
|
||||
cb();
|
||||
}
|
||||
// window size change
|
||||
if (
|
||||
lastScreenWidth !== window.innerWidth ||
|
||||
lastScreenHeight !== window.innerHeight
|
||||
) {
|
||||
lastScreenWidth = window.innerWidth;
|
||||
lastScreenHeight = window.innerHeight;
|
||||
cb();
|
||||
}
|
||||
if (true) {
|
||||
requestAnimationFrame(detectScreenMove);
|
||||
}
|
||||
}
|
||||
|
||||
if (true) {
|
||||
requestAnimationFrame(detectScreenMove);
|
||||
}
|
||||
}
|
||||
|
||||
onScreenMove(function () {
|
||||
const screenHeight = window.screen.height;
|
||||
const screenWidth = window.screen.width;
|
||||
const windowHeight = window.innerHeight;
|
||||
const windowWidth = window.innerWidth;
|
||||
const ratio = windowWidth / windowHeight;
|
||||
const x = window.screenX;
|
||||
const y = window.screenY;
|
||||
micaDiv.style.backgroundSize = `${screenWidth}px ${screenHeight}px`;
|
||||
// micaDiv.style.backgroundPosition = `-${x}px -${y}px`;
|
||||
if (x < 0) {
|
||||
micaDiv.style.backgroundPosition = `${screenWidth + x}px -${y}px`;
|
||||
} else {
|
||||
window.micaSpawned = true
|
||||
micaDiv.style.backgroundPosition = `-${x}px -${y}px`;
|
||||
}
|
||||
const micaDiv = document.createElement('div');
|
||||
const blurIterations = 6
|
||||
micaDiv.id = 'micaEffect';
|
||||
micaDiv.style.position = "fixed"
|
||||
micaDiv.style.top = "0"
|
||||
micaDiv.style.left = "0"
|
||||
micaDiv.style.right = "0"
|
||||
micaDiv.style.bottom = "0"
|
||||
micaDiv.style.zIndex = -1
|
||||
|
||||
let lastScreenX;
|
||||
let lastScreenY;
|
||||
let lastScreenWidth;
|
||||
let lastScreenHeight;
|
||||
|
||||
let regen = true
|
||||
let imgSrc = await ipcRenderer.sendSync("get-wallpaper")
|
||||
|
||||
let micaCache = await CiderCache.getCache("mica-cache")
|
||||
if (!micaCache) {
|
||||
micaCache = {
|
||||
path: "",
|
||||
data: ""
|
||||
}
|
||||
}
|
||||
if (micaCache.path == imgSrc.path) {
|
||||
regen = false
|
||||
imgSrc = micaCache
|
||||
}
|
||||
let canvas = document.createElement('canvas');
|
||||
let ctx = canvas.getContext('2d');
|
||||
let img = new Image();
|
||||
img.src = imgSrc.data;
|
||||
img.onload = function () {
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
if (regen) {
|
||||
for (let i = 0; i < blurIterations; i++) {
|
||||
StackBlur.canvasRGB(canvas, 0, 0, img.width, img.height, 128);
|
||||
}
|
||||
micaCache.path = imgSrc.path
|
||||
micaCache.data = canvas.toDataURL()
|
||||
CiderCache.putCache("mica-cache", micaCache)
|
||||
}
|
||||
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
micaDiv.style.backgroundImage = `url(${micaCache.data})`;
|
||||
document.body.appendChild(micaDiv);
|
||||
// on animation finished set animation to unset
|
||||
micaDiv.addEventListener('animationend', function () {
|
||||
micaDiv.style.opacity = '1';
|
||||
micaDiv.style.animation = 'unset';
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function onScreenMove(cb) {
|
||||
function detectScreenMove() {
|
||||
if (lastScreenY !== window.screenY || lastScreenX !== window.screenX) {
|
||||
lastScreenY = window.screenY;
|
||||
lastScreenX = window.screenX;
|
||||
cb();
|
||||
}
|
||||
// window size change
|
||||
if (lastScreenWidth !== window.innerWidth || lastScreenHeight !== window.innerHeight) {
|
||||
lastScreenWidth = window.innerWidth;
|
||||
lastScreenHeight = window.innerHeight;
|
||||
cb();
|
||||
}
|
||||
if (true) {
|
||||
requestAnimationFrame(detectScreenMove);
|
||||
}
|
||||
}
|
||||
|
||||
if (true) {
|
||||
requestAnimationFrame(detectScreenMove);
|
||||
}
|
||||
}
|
||||
|
||||
onScreenMove(function () {
|
||||
const screenHeight = window.screen.height;
|
||||
const screenWidth = window.screen.width;
|
||||
const windowHeight = window.innerHeight;
|
||||
const windowWidth = window.innerWidth;
|
||||
const ratio = windowWidth / windowHeight;
|
||||
const x = window.screenX;
|
||||
const y = window.screenY;
|
||||
micaDiv.style.backgroundSize = `${screenWidth}px ${screenHeight}px`;
|
||||
// micaDiv.style.backgroundPosition = `-${x}px -${y}px`;
|
||||
if (x < 0) {
|
||||
micaDiv.style.backgroundPosition = `${screenWidth + x}px -${y}px`;
|
||||
} else {
|
||||
micaDiv.style.backgroundPosition = `-${x}px -${y}px`;
|
||||
}
|
||||
});
|
||||
return true
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
export { spawnMica }
|
||||
export { spawnMica };
|
||||
|
|
|
@ -26,6 +26,7 @@ const app = new Vue({
|
|||
showHints: false,
|
||||
results: {},
|
||||
resultsSocial: {},
|
||||
resultsLibrary: {},
|
||||
limit: 10
|
||||
},
|
||||
fullscreenLyrics: false,
|
||||
|
@ -116,6 +117,7 @@ const app = new Vue({
|
|||
displayListing: [],
|
||||
downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library
|
||||
},
|
||||
localsongs: []
|
||||
},
|
||||
playlists: {
|
||||
listing: [],
|
||||
|
@ -177,9 +179,7 @@ const app = new Vue({
|
|||
"artwork": { "url": "./assets/logocut.png" }
|
||||
}
|
||||
},
|
||||
forceDirectives: {
|
||||
|
||||
},
|
||||
forceDirectives: {},
|
||||
menuOpened: false,
|
||||
maximized: false,
|
||||
drawerOpened: false,
|
||||
|
@ -241,8 +241,8 @@ const app = new Vue({
|
|||
},
|
||||
moreinfodata: [],
|
||||
notyf: notyf,
|
||||
idleTimer : null,
|
||||
idleState : false,
|
||||
idleTimer: null,
|
||||
idleState: false,
|
||||
},
|
||||
watch: {
|
||||
cfg: {
|
||||
|
@ -274,6 +274,31 @@ const app = new Vue({
|
|||
}, false)
|
||||
},
|
||||
methods: {
|
||||
setWindowHash(route = "") {
|
||||
window.location.hash = `#${route}`;
|
||||
},
|
||||
async oobeInit() {
|
||||
this.appMode = "oobe"
|
||||
this.setLz(this.cfg.general.language)
|
||||
this.setLzManual()
|
||||
clearTimeout(this.hangtimer)
|
||||
document.body.removeAttribute("loading")
|
||||
ipcRenderer.invoke("renderer-ready", true)
|
||||
document.querySelector("#LOADER").remove()
|
||||
},
|
||||
getAppStyle() {
|
||||
let finalStyle = {}
|
||||
if (this.cfg.visual.window_background_style === "color") {
|
||||
finalStyle["background-color"] = this.cfg.visual.windowColor
|
||||
}
|
||||
if (this.cfg.visual.customAccentColor) {
|
||||
finalStyle["--keyColor"] = this.cfg.visual.accentColor
|
||||
finalStyle["--songProgressColor"] = this.cfg.visual.accentColor
|
||||
} else if (this.cfg.visual.purplePodcastPlaybackBar && MusicKit.getInstance().nowPlayingItem?.type == "podcast-episodes") {
|
||||
finalStyle["--songProgressColor"] = '#6929D0'
|
||||
}
|
||||
return finalStyle
|
||||
},
|
||||
setTimeout(func, time) {
|
||||
return setTimeout(func, time);
|
||||
},
|
||||
|
@ -297,10 +322,11 @@ const app = new Vue({
|
|||
}
|
||||
},
|
||||
formatVolumeTooltip() {
|
||||
return this.cfg.audio.dBSPL ? (Number(this.cfg.audio.dBSPLcalibration) + (Math.log10(this.mk.volume) * 20)).toFixed(2) + ' dB SPL' : (Math.log10(this.mk.volume) * 20).toFixed(2) + ' dBFS'
|
||||
let advancedTooltip = this.cfg.audio.dBSPL ? (Number(this.cfg.audio.dBSPLcalibration) + (Math.log10(this.mk.volume) * 20)).toFixed(2) + ' dB SPL' : (Math.log10(this.mk.volume) * 20).toFixed(2) + ' dBFS'
|
||||
return this.cfg.audio.advanced ? advancedTooltip : (this.mk.volume * 100).toFixed(0) + '%'
|
||||
},
|
||||
mainMenuVisibility(val) {
|
||||
if(this.chrome.sidebarCollapsed) {
|
||||
mainMenuVisibility(val, isContextMenu) {
|
||||
if (this.chrome.sidebarCollapsed && !isContextMenu) {
|
||||
this.chrome.sidebarCollapsed = false
|
||||
return
|
||||
}
|
||||
|
@ -334,7 +360,8 @@ const app = new Vue({
|
|||
this.listennow.timestamp = 0;
|
||||
this.browsepage.timestamp = 0;
|
||||
this.radio.timestamp = 0;
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Grabs translation for localization.
|
||||
|
@ -490,18 +517,20 @@ const app = new Vue({
|
|||
})
|
||||
},
|
||||
goToGrouping(url = "https://music.apple.com/WebObjects/MZStore.woa/wa/viewGrouping?cc=us&id=34") {
|
||||
const id = url.split("id=")[1];
|
||||
window.location.hash = `#groupings/${id}`
|
||||
if (url.includes('viewTop')) {
|
||||
window.location.hash = `#charts/top`
|
||||
} else {
|
||||
const id = url.split("id=")[1];
|
||||
window.location.hash = `#groupings/${id}`
|
||||
}
|
||||
},
|
||||
navigateForward() {
|
||||
history.forward()
|
||||
},
|
||||
getHTMLStyle() {
|
||||
if (app.cfg.visual.uiScale != 1) {
|
||||
document.querySelector("#app").style.zoom = app.cfg.visual.uiScale
|
||||
} else {
|
||||
document.querySelector("#app").style.zoom = ""
|
||||
}
|
||||
|
||||
ipcRenderer.send("setScreenScale", app.cfg.visual.uiScale);
|
||||
|
||||
},
|
||||
resetState() {
|
||||
this.menuPanel.visible = false;
|
||||
|
@ -617,7 +646,9 @@ const app = new Vue({
|
|||
},
|
||||
async init() {
|
||||
let self = this
|
||||
|
||||
if (!localStorage.getItem("seenOOBE")) {
|
||||
localStorage.setItem("seenOOBE", 1)
|
||||
}
|
||||
if (this.cfg.visual.styles.length != 0) {
|
||||
await this.reloadStyles()
|
||||
}
|
||||
|
@ -694,9 +725,6 @@ const app = new Vue({
|
|||
// Set mk.volume to -1 (setting to 0 wont work, so temp solution setting to -1)
|
||||
this.mk.volume = -1;
|
||||
}
|
||||
// ipcRenderer.invoke('getStoreValue', 'audio.volume').then((value) => {
|
||||
// self.mk.volume = value
|
||||
// })
|
||||
|
||||
// load cached library
|
||||
let librarySongs = await CiderCache.getCache("library-songs")
|
||||
|
@ -809,13 +837,30 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* DiscordRPC Reload Return Event
|
||||
* @author @coredev-uk
|
||||
*/
|
||||
ipcRenderer.on('rpcReloaded', (e, user) => {
|
||||
if (user.username) {
|
||||
app.notyf.success(app.stringTemplateParser(app.getLz("settings.option.connectivity.discordRPC.reconnectedToUser"), {
|
||||
user: `${user.username}#${user.discriminator}`,
|
||||
userid: user.id
|
||||
}));
|
||||
}
|
||||
})
|
||||
|
||||
ipcRenderer.on('getUpdatedLocalList', (event, data) => {
|
||||
console.log("cider-local", data);
|
||||
this.library.localsongs = data;
|
||||
})
|
||||
|
||||
ipcRenderer.on('SoundCheckTag', (event, tag) => {
|
||||
// let replaygain = self.parseSCTagToRG(tag)
|
||||
try {
|
||||
if (app.mk.nowPlayingItem.type !== 'song') {
|
||||
CiderAudio.audioNodes.gainNode.gain.value = 0.70794578438;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let soundcheck = tag.split(" ")
|
||||
let numbers = []
|
||||
for (let item of soundcheck) {
|
||||
|
@ -824,18 +869,23 @@ const app = new Vue({
|
|||
}
|
||||
numbers.shift()
|
||||
let peak = Math.max(numbers[6], numbers[7]) / 32768.0
|
||||
let gain = Math.pow(10, ((-1.3 - (Math.log10(peak) * 20)) / 20))// EBU R 128 Compliant
|
||||
let gain = Math.pow(10, ((-1.7 - (Math.log10(peak) * 20)) / 20))// EBU R 128 Compliant
|
||||
console.debug(`[Cider][MaikiwiSoundCheck] Peak Gain: '${(Math.log10(peak) * 20).toFixed(2)}' dB | Adjusting '${(Math.log10(gain) * 20).toFixed(2)}' dB`)
|
||||
try {
|
||||
//CiderAudio.audioNodes.gainNode.gain.value = (Math.min(Math.pow(10, (replaygain.gain / 20)), (1 / replaygain.peak)))
|
||||
CiderAudio.audioNodes.gainNode.gain.value = gain
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
try { ipcRenderer.send('SoundCheckTag', event, tag); }
|
||||
catch (e) {
|
||||
try {ipcRenderer.send('SoundCheckTag', event, tag);}
|
||||
catch (e) {console.log("[Cider][MaikiwiSoundCheck] Error [Gave up after 3 consecutive attempts]: " + e)}
|
||||
} catch (e) {
|
||||
try {
|
||||
ipcRenderer.send('SoundCheckTag', event, tag);
|
||||
} catch (e) {
|
||||
try {
|
||||
ipcRenderer.send('SoundCheckTag', event, tag);
|
||||
} catch (e) {
|
||||
console.log("[Cider][MaikiwiSoundCheck] Error [Gave up after 3 consecutive attempts]: " + e)
|
||||
}
|
||||
}
|
||||
} // brute force until it works
|
||||
})
|
||||
|
@ -864,42 +914,58 @@ const app = new Vue({
|
|||
ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes());
|
||||
})
|
||||
|
||||
this.mk.addEventListener(MusicKit.Events.queueItemsDidChange, ()=>{
|
||||
this.mk.addEventListener(MusicKit.Events.queueItemsDidChange, () => {
|
||||
if (self.$refs.queue) {
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
self.$refs.queue.updateQueue();
|
||||
}, 100)
|
||||
}
|
||||
})
|
||||
|
||||
// Used for Live Radio stations to set Metadata
|
||||
this.mk.addEventListener(MusicKit.Events.timedMetadataDidChange, (e) => {
|
||||
app.mk.nowPlayingItem.attributes.name = e.title
|
||||
app.mk.nowPlayingItem.attributes.artistName = e.performer
|
||||
app.mk.nowPlayingItem.attributes.albumName = e.album
|
||||
if(e.links[1]) {
|
||||
app.currentArtUrl = e.links[1].url
|
||||
app.currentArtUrlRaw = e.links[1].url
|
||||
}else{
|
||||
app.currentArtUrl = e.links[0].url
|
||||
app.currentArtUrlRaw = e.links[0].url
|
||||
}
|
||||
app.mk.nowPlayingItem._songId = e._adamId ? e._adamId : -1
|
||||
app.mk.nowPlayingItem.id = e._adamId ? e._adamId : -1
|
||||
})
|
||||
|
||||
this.mk.addEventListener(MusicKit.Events.nowPlayingItemDidChange, (a) => {
|
||||
if (self.$refs.queue) {
|
||||
self.$refs.queue.updateQueue();
|
||||
}
|
||||
this.currentSongInfo = a
|
||||
|
||||
try {
|
||||
if (app.mk.nowPlayingItem.flavor.includes("64")) {
|
||||
if (localStorage.getItem("playingBitrate") !== "64") {
|
||||
localStorage.setItem("playingBitrate", "64")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
}
|
||||
else if (app.mk.nowPlayingItem.flavor.includes("256")) {
|
||||
if (localStorage.getItem("playingBitrate") !== "256") {
|
||||
|
||||
if (app.cfg.advanced.AudioContext) {
|
||||
try {
|
||||
if (app.mk.nowPlayingItem.flavor.includes("64")) {
|
||||
if (localStorage.getItem("playingBitrate") !== "64") {
|
||||
localStorage.setItem("playingBitrate", "64")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
} else if (app.mk.nowPlayingItem.flavor.includes("256")) {
|
||||
if (localStorage.getItem("playingBitrate") !== "256") {
|
||||
localStorage.setItem("playingBitrate", "256")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
} else {
|
||||
localStorage.setItem("playingBitrate", "256")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} catch (e) {
|
||||
localStorage.setItem("playingBitrate", "256")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
} catch(e) {
|
||||
localStorage.setItem("playingBitrate", "256")
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
|
||||
|
||||
if (app.cfg.audio.normalization) {
|
||||
// get unencrypted audio previews to get SoundCheck's normalization tag
|
||||
try {
|
||||
|
@ -960,7 +1026,7 @@ const app = new Vue({
|
|||
}
|
||||
setTimeout(() => {
|
||||
let i = (document.querySelector('#apple-music-player')?.src ?? "")
|
||||
if (i.endsWith(".m3u8") || i.endsWith(".m3u")){
|
||||
if (i.endsWith(".m3u8") || i.endsWith(".m3u")) {
|
||||
this._playRadioStream(i)
|
||||
}
|
||||
}, 1500)
|
||||
|
@ -977,7 +1043,7 @@ const app = new Vue({
|
|||
this.appRoute(window.location.hash)
|
||||
}
|
||||
|
||||
if(this.page != "home") {
|
||||
if (this.page != "home") {
|
||||
this.resumeTabs()
|
||||
}
|
||||
this.mediaKeyFixes()
|
||||
|
@ -988,7 +1054,7 @@ const app = new Vue({
|
|||
this.$forceUpdate()
|
||||
}, 500)
|
||||
document.querySelector('#apple-music-video-player-controls').addEventListener('mousemove', () => {
|
||||
this.showFoo('.music-player-info',2000);
|
||||
this.showFoo('.music-player-info', 2000);
|
||||
})
|
||||
ipcRenderer.invoke("renderer-ready", true)
|
||||
document.querySelector("#LOADER").remove()
|
||||
|
@ -996,7 +1062,7 @@ const app = new Vue({
|
|||
this.checkForThemeUpdates()
|
||||
}
|
||||
},
|
||||
showFoo(querySelector,time) {
|
||||
showFoo(querySelector, time) {
|
||||
clearTimeout(this.idleTimer);
|
||||
if (this.idleState == true) {
|
||||
document.querySelector(querySelector).classList.remove("inactive");
|
||||
|
@ -1019,7 +1085,11 @@ const app = new Vue({
|
|||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (res[0].sha != theme.commit) {
|
||||
const notify = notyf.open({ className: "notyf-info", type: "info", message: `[Themes] ${theme.name} has an update available.` })
|
||||
const notify = notyf.open({
|
||||
className: "notyf-info",
|
||||
type: "info",
|
||||
message: `[Themes] ${theme.name} has an update available.`
|
||||
})
|
||||
notify.on("click", () => {
|
||||
app.appRoute("themes-github")
|
||||
notyf.dismiss(notify)
|
||||
|
@ -1118,9 +1188,20 @@ const app = new Vue({
|
|||
},
|
||||
getAppClasses() {
|
||||
let classes = {}
|
||||
if (this.cfg.advanced.experiments.includes('compactui')) {
|
||||
classes.compact = true
|
||||
switch (this.getThemeDirective('forceUI') ?? "none") {
|
||||
case "compact":
|
||||
classes.compact = true;
|
||||
break;
|
||||
case "standard":
|
||||
classes.compact = false;
|
||||
break;
|
||||
default:
|
||||
if (this.cfg.advanced.experiments.includes('compactui')) {
|
||||
classes.compact = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.cfg.visual.window_background_style == "none") {
|
||||
classes.simplebg = true
|
||||
}
|
||||
|
@ -1202,12 +1283,72 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
},
|
||||
async syncFavorites() {
|
||||
const notify = notyf.open({
|
||||
className: "notyf-info",
|
||||
type: "info",
|
||||
message: `[${app.getLz('home.syncFavorites')}] ${app.getLz('home.syncFavorites.gettingArtists')}`
|
||||
})
|
||||
const results = await MusicKitTools.v3Continuous({
|
||||
href: "/v1/me/library/artists", options: {
|
||||
"include": ["catalog"],
|
||||
"fields[artists]": ["inFavorites"]
|
||||
}
|
||||
})
|
||||
let favs = []
|
||||
// for each result
|
||||
results.forEach(result => {
|
||||
try {
|
||||
if (result.relationships?.catalog?.data[0]?.attributes?.inFavorites) {
|
||||
if(!favs.includes(result.relationships?.catalog?.data[0].id)) {
|
||||
favs.push(result.relationships?.catalog?.data[0].id)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
e = null
|
||||
}
|
||||
})
|
||||
notyf.success(`[${app.getLz('home.syncFavorites')}] ${app.getLz('action.done')}`)
|
||||
app.cfg.home.followedArtists = favs
|
||||
return favs
|
||||
},
|
||||
async setArtistFavorite(id, val = true) {
|
||||
if(val) {
|
||||
if(!app.cfg.home.followedArtists.includes(id)) {
|
||||
app.cfg.home.followedArtists.push(id)
|
||||
}
|
||||
await app.mk.api.v3.music(`/v1/me/favorites`, {
|
||||
"art[url]": "f",
|
||||
"ids[artists]": app.artistPage.data.id,
|
||||
"l": app.mklang,
|
||||
"platform": "web"
|
||||
}, {
|
||||
fetchOptions: {
|
||||
method: "POST"
|
||||
}
|
||||
})
|
||||
}else{
|
||||
if(app.cfg.home.followedArtists.includes(id)) {
|
||||
app.cfg.home.followedArtists.splice(app.cfg.home.followedArtists.indexOf(id), 1)
|
||||
}
|
||||
await app.mk.api.v3.music(`/v1/me/favorites`, {
|
||||
"art[url]": "f",
|
||||
"ids[artists]": app.artistPage.data.id,
|
||||
"l": app.mklang,
|
||||
"platform": "web"
|
||||
}, {
|
||||
fetchOptions: {
|
||||
method: "DELETE"
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
async refreshPlaylists(localOnly = false, useCachedPlaylists = true) {
|
||||
let self = this
|
||||
let trackMap = this.cfg.advanced.playlistTrackMapping
|
||||
let newListing = []
|
||||
let trackMapping = {}
|
||||
|
||||
|
||||
if (useCachedPlaylists) {
|
||||
const cachedPlaylist = await CiderCache.getCache("library-playlists")
|
||||
const cachedTrackMapping = await CiderCache.getCache("library-playlists-tracks")
|
||||
|
@ -1235,7 +1376,7 @@ const app = new Vue({
|
|||
async function deepScan(parent = "p.playlistsroot") {
|
||||
console.debug(`scanning ${parent}`)
|
||||
// const playlistData = await app.mk.api.v3.music(`/v1/me/library/playlist-folders/${parent}/children/`)
|
||||
const playlistData = await MusicKitTools.v3Continuous({href: `/v1/me/library/playlist-folders/${parent}/children/`})
|
||||
const playlistData = await MusicKitTools.v3Continuous({ href: `/v1/me/library/playlist-folders/${parent}/children/` })
|
||||
console.log(playlistData)
|
||||
await asyncForEach(playlistData, async (playlist) => {
|
||||
playlist.parent = parent
|
||||
|
@ -1267,10 +1408,12 @@ const app = new Vue({
|
|||
}
|
||||
})
|
||||
}
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
if (playlist.type == "library-playlist-folders") {
|
||||
try {
|
||||
await deepScan(playlist.id).catch(e => { })
|
||||
await deepScan(playlist.id).catch(e => {
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
@ -1428,10 +1571,10 @@ const app = new Vue({
|
|||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
/**
|
||||
* @param {string} url, href for the initial request
|
||||
* @memberof app
|
||||
*/
|
||||
*/
|
||||
async showRoom(url) {
|
||||
let self = this
|
||||
const response = await this.mk.api.v3.music(url)
|
||||
|
@ -1559,7 +1702,7 @@ const app = new Vue({
|
|||
this.page = ""
|
||||
const artistData = await this.mkapi("artists", false, id, {
|
||||
"views": "featured-release,full-albums,appears-on-albums,featured-albums,featured-on-albums,singles,compilation-albums,live-albums,latest-release,top-music-videos,similar-artists,top-songs,playlists,more-to-hear,more-to-see",
|
||||
"extend": "artistBio,bornOrFormed,editorialArtwork,editorialVideo,isGroup,origin,hero",
|
||||
"extend": "centeredFullscreenBackground,artistBio,bornOrFormed,editorialArtwork,editorialVideo,isGroup,origin,hero",
|
||||
"extend[playlists]": "trackCount",
|
||||
"include[songs]": "albums",
|
||||
"fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url,trackCount",
|
||||
|
@ -1654,8 +1797,7 @@ const app = new Vue({
|
|||
const mDisplay = m > 0 ? `${m} ${app.getLz("term.time.minute", { "count": m })}` : "";
|
||||
|
||||
return dDisplay + (dDisplay && hDisplay ? ", " : "") + hDisplay + (hDisplay && mDisplay ? ", " : "") + mDisplay;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let returnTime = datetime.toISOString().substring(11, 19);
|
||||
|
||||
const timeGates = {
|
||||
|
@ -1753,27 +1895,28 @@ const app = new Vue({
|
|||
if (item.attributes.link.url.includes("viewMultiRoom")) {
|
||||
const params = new Proxy(new URLSearchParams(item.attributes.link.url), {
|
||||
get: (searchParams, prop) => searchParams.get(prop),
|
||||
});
|
||||
});
|
||||
id = params.fcId
|
||||
app.getTypeFromID("multiroom", id, false, {
|
||||
platform: "web",
|
||||
extend: "editorialArtwork,uber,lockupStyle"
|
||||
}).then(()=> {
|
||||
}).then(() => {
|
||||
kind = "multiroom"
|
||||
window.location.hash = `${kind}/${id}`
|
||||
document.querySelector("#app-content").scrollTop = 0
|
||||
})
|
||||
|
||||
|
||||
return;
|
||||
} else {
|
||||
window.open(item.attributes.link.url)}
|
||||
window.open(item.attributes.link.url)
|
||||
}
|
||||
}
|
||||
|
||||
} else if (kind == "multirooms"){
|
||||
} else if (kind == "multirooms") {
|
||||
app.getTypeFromID("multiroom", id, false, {
|
||||
platform: "web",
|
||||
extend: "editorialArtwork,uber,lockupStyle"
|
||||
}).then(()=> {
|
||||
}).then(() => {
|
||||
kind = "multiroom"
|
||||
window.location.hash = `${kind}/${id}`
|
||||
document.querySelector("#app-content").scrollTop = 0
|
||||
|
@ -1812,7 +1955,7 @@ const app = new Vue({
|
|||
params["meta[albums:tracks]"] = 'popularity'
|
||||
params["fields[albums]"] = "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialNotes,editorialVideo,name,playParams,releaseDate,url,copyright"
|
||||
}
|
||||
if (kind.includes("playlist") || kind.includes("album")){
|
||||
if (kind.includes("playlist") || kind.includes("album")) {
|
||||
app.page = (kind) + "_" + (id);
|
||||
window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}`
|
||||
app.getTypeFromID((kind), (id), (isLibrary), params);
|
||||
|
@ -1847,33 +1990,40 @@ const app = new Vue({
|
|||
}
|
||||
},
|
||||
isDisabled() {
|
||||
if(!app.mk.nowPlayingItem || app.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation') {
|
||||
if (!app.mk.nowPlayingItem || app.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
isPrevDisabled() {
|
||||
if(this.isDisabled() || (app.mk.queue._position == 0 && app.mk.currentPlaybackTime <= 2)) {
|
||||
if (this.isDisabled() || (app.mk.queue._position == 0 && app.mk.currentPlaybackTime <= 2)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
isNextDisabled() {
|
||||
if(this.isDisabled() || app.mk.queue._position + 1 == app.mk.queue.length) {
|
||||
if (this.isDisabled() || app.mk.queue._position + 1 == app.mk.queue.length) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
async getNowPlayingItemDetailed(target) {
|
||||
let nowPlayingItem = JSON.parse(JSON.stringify(this.mk.nowPlayingItem))
|
||||
if(nowPlayingItem.type === "radioStation" && app.mk.nowPlayingItem.id !== -1) {
|
||||
nowPlayingItem.playParams = {kind: "songs"}
|
||||
nowPlayingItem.attributes.playParams.catalogId = app.mk.nowPlayingItem.id
|
||||
nowPlayingItem.attributes.playParams.id = app.mk.nowPlayingItem.id
|
||||
nowPlayingItem.id = app.mk.nowPlayingItem.id
|
||||
}
|
||||
try {
|
||||
let u = await app.mkapi(app.mk.nowPlayingItem.playParams.kind,
|
||||
(app.mk.nowPlayingItem.songId == -1),
|
||||
(app.mk.nowPlayingItem.songId != -1) ? app.mk.nowPlayingItem.songId : app.mk.nowPlayingItem["id"],
|
||||
let u = await app.mkapi(nowPlayingItem.playParams.kind,
|
||||
(nowPlayingItem.songId == -1),
|
||||
(nowPlayingItem.songId != -1) ? nowPlayingItem.songId : nowPlayingItem["id"],
|
||||
{ "include[songs]": "albums,artists", l: app.mklang });
|
||||
app.searchAndNavigate(u.data.data[0], target)
|
||||
} catch (e) {
|
||||
app.searchAndNavigate(app.mk.nowPlayingItem, target)
|
||||
app.searchAndNavigate(nowPlayingItem, target)
|
||||
}
|
||||
},
|
||||
async searchAndNavigate(item, target) {
|
||||
|
@ -1989,16 +2139,6 @@ const app = new Vue({
|
|||
this.getArtistFromID(id)
|
||||
//this.getTypeFromID("artist",id,isLibrary,query)
|
||||
},
|
||||
followArtistById(id, follow) {
|
||||
if (follow && !this.followingArtist(id)) {
|
||||
this.cfg.home.followedArtists.push(id)
|
||||
} else {
|
||||
let index = this.cfg.home.followedArtists.indexOf(id)
|
||||
if (index > -1) {
|
||||
this.cfg.home.followedArtists.splice(index, 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
followingArtist(id) {
|
||||
console.debug(`check for ${id}`)
|
||||
return this.cfg.home.followedArtists.includes(id)
|
||||
|
@ -2015,8 +2155,7 @@ const app = new Vue({
|
|||
app.mk.setStationQueue({ artist: 'a-' + id }).then(() => {
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '')
|
||||
}
|
||||
})
|
||||
|
@ -2039,7 +2178,7 @@ const app = new Vue({
|
|||
} finally {
|
||||
if (kind == "appleCurator") {
|
||||
app.appleCurator = a.data.data[0]
|
||||
} else if (kind == "multiroom"){
|
||||
} else if (kind == "multiroom") {
|
||||
app.multiroom = a.data.data[0]
|
||||
} else {
|
||||
this.getPlaylistContinuous(a, true)
|
||||
|
@ -2048,7 +2187,7 @@ const app = new Vue({
|
|||
} finally {
|
||||
if (kind == "appleCurator") {
|
||||
app.appleCurator = a.data.data[0]
|
||||
} else if (kind == "multiroom"){
|
||||
} else if (kind == "multiroom") {
|
||||
app.multiroom = a.data.data[0]
|
||||
} else {
|
||||
this.getPlaylistContinuous(a, true)
|
||||
|
@ -2292,8 +2431,7 @@ const app = new Vue({
|
|||
try {
|
||||
if (method.includes(`multiroom`)) {
|
||||
return await this.mk.api.v3.music(`v1/editorial/${app.mk.storefrontId}/${truemethod}/${term.toString()}`, params, params2)
|
||||
}
|
||||
else if (library) {
|
||||
} else if (library) {
|
||||
return await this.mk.api.v3.music(`v1/me/library/${truemethod}/${term.toString()}`, params, params2)
|
||||
} else {
|
||||
return await this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${truemethod}/${term.toString()}`, params, params2)
|
||||
|
@ -2320,6 +2458,7 @@ const app = new Vue({
|
|||
let library = []
|
||||
let cacheId = "library-songs"
|
||||
let downloaded = null;
|
||||
this.$store.commit("resetRecentlyAdded")
|
||||
if ((this.library.songs.downloadState == 2) && !force) {
|
||||
return
|
||||
}
|
||||
|
@ -2642,7 +2781,7 @@ const app = new Vue({
|
|||
"include[songs]": "artists",
|
||||
"include[music-videos]": "artists",
|
||||
"fields[albums]": ["artistName", "artistUrl", "artwork", "contentRating", "editorialArtwork", "editorialVideo", "name", "playParams", "releaseDate", "url"],
|
||||
"fields[artists]": ["name", "url"],
|
||||
"fields[artists]": ["name", "url", "artwork"],
|
||||
"extend[stations]": ["airDate", "supportsAirTimeUpdates"],
|
||||
"meta[stations]": "inflectionPoints",
|
||||
types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-upsells",
|
||||
|
@ -3042,7 +3181,8 @@ const app = new Vue({
|
|||
} else { //4xx rejected
|
||||
getToken(2, '', '', id, lang, '');
|
||||
}
|
||||
} catch (e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
req2.send();
|
||||
}
|
||||
|
@ -3100,8 +3240,7 @@ const app = new Vue({
|
|||
translation: ''
|
||||
});
|
||||
app.lyrics = preLrc.reverse();
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
app.lyrics = "";
|
||||
}
|
||||
};
|
||||
|
@ -3143,6 +3282,7 @@ const app = new Vue({
|
|||
function b64_to_utf8(str) {
|
||||
return decodeURIComponent(escape(window.atob(str)));
|
||||
}
|
||||
|
||||
const htmlDecode = (input) => {
|
||||
const doc = new DOMParser().parseFromString(input, "text/html");
|
||||
return doc.documentElement.textContent;
|
||||
|
@ -3173,8 +3313,7 @@ const app = new Vue({
|
|||
translation: ''
|
||||
});
|
||||
app.lyrics = preLrc.reverse();
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
app.loadNeteaseLyrics();
|
||||
app.lyrics = "";
|
||||
|
@ -3532,6 +3671,18 @@ const app = new Vue({
|
|||
friendlyTypes(type) {
|
||||
// use switch statement to return friendly name for media types "songs,artists,albums,playlists,music-videos,stations,apple-curators,curators"
|
||||
switch (type) {
|
||||
case "library-songs":
|
||||
return app.getLz('term.songs')
|
||||
break;
|
||||
case "library-artists":
|
||||
return app.getLz('term.artists')
|
||||
break;
|
||||
case "library-albums":
|
||||
return app.getLz('term.albums')
|
||||
break;
|
||||
case "library-playlists":
|
||||
return app.getLz('term.playlists')
|
||||
break;
|
||||
case "song":
|
||||
return app.getLz('term.songs')
|
||||
break;
|
||||
|
@ -3614,6 +3765,13 @@ const app = new Vue({
|
|||
results.data.results["meta"] = results.data.meta
|
||||
self.search.resultsSocial = results.data.results
|
||||
})
|
||||
|
||||
this.search.resultsLibrary = await app.mk.api.library.search(app.search.term, {
|
||||
types: 'library-songs,library-albums,library-playlists,library-artists',
|
||||
limit: 25,
|
||||
offset: 0
|
||||
})
|
||||
|
||||
},
|
||||
async inLibrary(items = []) {
|
||||
let types = []
|
||||
|
@ -3690,7 +3848,7 @@ const app = new Vue({
|
|||
},
|
||||
getMediaItemArtwork(url, height = 64, width) {
|
||||
if (typeof url == "undefined" || url == "") {
|
||||
return "https://beta.music.apple.com/assets/product/MissingArtworkMusic.svg"
|
||||
return "./assets/MissingArtwork.svg"
|
||||
}
|
||||
height = parseInt(height * window.devicePixelRatio)
|
||||
if (width) {
|
||||
|
@ -3766,6 +3924,9 @@ const app = new Vue({
|
|||
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.currentArtUrlRaw = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '')
|
||||
this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', artworkSize).replace('{h}', artworkSize);
|
||||
if (this.mk.nowPlayingItem._assets[0].artworkURL) {
|
||||
this.currentArtUrl = this.mk.nowPlayingItem._assets[0].artworkURL
|
||||
}
|
||||
try {
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||
} catch (e) {
|
||||
|
@ -3776,6 +3937,9 @@ const app = new Vue({
|
|||
if (data != null && data !== "" && data.attributes != null && data.attributes.artwork != null) {
|
||||
this.currentArtUrlRaw = (data["attributes"]["artwork"]["url"] ?? '')
|
||||
this.currentArtUrl = (data["attributes"]["artwork"]["url"] ?? '').replace('{w}', artworkSize).replace('{h}', artworkSize);
|
||||
if (this.mk.nowPlayingItem._assets[0].artworkURL) {
|
||||
this.currentArtUrl = this.mk.nowPlayingItem._assets[0].artworkURL
|
||||
}
|
||||
ipcRenderer.send('updateRPCImage', this.currentArtUrl ?? '');
|
||||
try {
|
||||
document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`);
|
||||
|
@ -3988,10 +4152,10 @@ const app = new Vue({
|
|||
setAirPlayCodeUI() {
|
||||
this.modals.airplayPW = true
|
||||
},
|
||||
sendAirPlaySuccess(){
|
||||
sendAirPlaySuccess() {
|
||||
notyf.success('Device paired successfully!');
|
||||
},
|
||||
sendAirPlayFailed(){
|
||||
sendAirPlayFailed() {
|
||||
notyf.error('Device paring failed!');
|
||||
},
|
||||
windowFocus(val) {
|
||||
|
@ -4183,7 +4347,15 @@ const app = new Vue({
|
|||
this.showMenuPanel(menus[useMenu], event)
|
||||
|
||||
try {
|
||||
let result = await this.inLibrary([this.mk.nowPlayingItem])
|
||||
// if its a radio station, then change the attributes to match a song
|
||||
const nowPlayingItem = JSON.parse(JSON.stringify(this.mk.nowPlayingItem))
|
||||
if(nowPlayingItem.type == "radioStation" && app.mk.nowPlayingItem.id != -1) {
|
||||
nowPlayingItem.type = "song"
|
||||
nowPlayingItem.attributes.playParams.catalogId = app.mk.nowPlayingItem.id
|
||||
nowPlayingItem.attributes.playParams.id = app.mk.nowPlayingItem.id
|
||||
nowPlayingItem.id = app.mk.nowPlayingItem.id
|
||||
}
|
||||
let result = await this.inLibrary([nowPlayingItem])
|
||||
if (result[0].attributes.inLibrary) {
|
||||
menus.normal.items.find(x => x.id == 'addToLibrary').hidden = true
|
||||
menus.normal.items.find(x => x.id == 'removeFromLibrary').hidden = false
|
||||
|
@ -4242,7 +4414,7 @@ const app = new Vue({
|
|||
});
|
||||
},
|
||||
fullscreen(flag) {
|
||||
this.fullscreenState = flag;
|
||||
this.fullscreenState = flag;
|
||||
if (flag) {
|
||||
ipcRenderer.send('setFullScreen', true);
|
||||
app.appMode = 'fullscreen';
|
||||
|
@ -4257,7 +4429,7 @@ const app = new Vue({
|
|||
app.appMode = 'player';
|
||||
}
|
||||
},
|
||||
pip(){
|
||||
pip() {
|
||||
document.querySelector('video#apple-music-video-player').requestPictureInPicture()
|
||||
// .then(pictureInPictureWindow => {
|
||||
// pictureInPictureWindow.addEventListener("resize", () => {
|
||||
|
@ -4438,16 +4610,19 @@ const app = new Vue({
|
|||
_playRadioStream(e) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = process;
|
||||
xhr.open("GET", e , true);
|
||||
xhr.open("GET", e, true);
|
||||
xhr.send();
|
||||
let self = this
|
||||
|
||||
function process() {
|
||||
if (xhr.readyState == 4) {
|
||||
let sources = xhr.responseText.match(/^(?!#)(?!\s).*$/mg).filter(function(element){return (element);});
|
||||
// Load first source
|
||||
let src = sources[0];
|
||||
app.mk._services.mediaItemPlayback._currentPlayer._playAssetURL(src, false)
|
||||
}
|
||||
if (xhr.readyState == 4) {
|
||||
let sources = xhr.responseText.match(/^(?!#)(?!\s).*$/mg).filter(function (element) {
|
||||
return (element);
|
||||
});
|
||||
// Load first source
|
||||
let src = sources[0];
|
||||
app.mk._services.mediaItemPlayback._currentPlayer._playAssetURL(src, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,24 @@ const store = new Vuex.Store({
|
|||
// recentlyAdded: ipcRenderer.sendSync("get-library-recentlyAdded"),
|
||||
// playlists: ipcRenderer.sendSync("get-library-playlists")
|
||||
},
|
||||
pageState: {
|
||||
recentlyAdded: {
|
||||
loaded: false,
|
||||
nextUrl: null,
|
||||
items: [],
|
||||
size: "normal"
|
||||
}
|
||||
},
|
||||
artwork: {
|
||||
playerLCD: ""
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
resetRecentlyAdded(state) {
|
||||
state.pageState.recentlyAdded.loaded = false;
|
||||
state.pageState.recentlyAdded.nextUrl = null;
|
||||
state.pageState.recentlyAdded.items = [];
|
||||
},
|
||||
setLCDArtwork(state, artwork) {
|
||||
state.artwork.playerLCD = artwork
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
@import url("assets/fonts/Pretendard/pretendardvariable.css");
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap');
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+HK:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100;300;400;500;700;900&display=swap");
|
||||
@import url("less/appvars.less");
|
||||
@import url("less/bootstrap-vue.min.less");
|
||||
@import url("less/ameframework.less");
|
||||
|
@ -20,7 +19,9 @@
|
|||
--mediaItemShadow-Shadow: 0 8px 40px rgb(0 0 0 / 0.55);
|
||||
--mediaItemShadow-ShadowSubtle: 0 4px 14px rgb(0 0 0 / 10%);
|
||||
--ciderShadow-Generic: var(--mediaItemShadow), 0 8px 40px rgb(0 0 0 / 0.55);
|
||||
--mediaItemRadius: 6px;
|
||||
--mediaItemRadius: 8px;
|
||||
--mediaItemRadiusSmall: 6px;
|
||||
--mediaItemRadiusMedium: 8px;
|
||||
--mediaItemRadiusRound: 100%;
|
||||
--panelRadius: 10px;
|
||||
--contentInnerPadding: 16px;
|
||||
|
@ -31,6 +32,7 @@
|
|||
--selected-click: rgb(80 80 80 / 30%);
|
||||
--hover: rgb(200 200 200 / 10%);
|
||||
// --keyColor: #fa586a;
|
||||
--keyColorDefault: @keyColor;
|
||||
--keyColor: @keyColor;
|
||||
--keyColor-rgb: 250, 88, 106;
|
||||
--keyColor-rollover: #ff8a9c;
|
||||
|
@ -66,7 +68,7 @@ body {
|
|||
background-size: cover;
|
||||
background-position: center;
|
||||
background: #0000;
|
||||
font-family: "Pretendard Variable", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
font-family: "Pretendard Variable", "Noto Sans JP", "Noto Sans KR", "Noto Sans TC", "Noto Sans SC", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
transition: opacity .10s var(--appleEase);
|
||||
}
|
||||
|
||||
|
@ -308,19 +310,19 @@ a.dropdown-item {
|
|||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
|
||||
> img {
|
||||
img {
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
opacity: 0.5;
|
||||
filter: brightness(200%) blur(180px) saturate(280%) contrast(2);
|
||||
}
|
||||
|
||||
> img:first-child {
|
||||
img:first-child {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
> img:last-child {
|
||||
img:last-child {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transform: rotate(180deg);
|
||||
|
@ -374,15 +376,14 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
}
|
||||
|
||||
#app-sidebar {
|
||||
/* background-color: var(--color1); */
|
||||
height: 100%;
|
||||
width: var(--sidebarWidth);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
background : var(--sidebarColorMix);
|
||||
max-width : var(--sidebarWidth);
|
||||
background: linear-gradient(180deg, var(--baseColorMix) calc(var(--chromeHeight1) + 1px), var(--sidebarColorMix) calc(var(--chromeHeight1) + 1px));
|
||||
max-width: var(--sidebarWidth);
|
||||
padding-top: var(--chromeHeight1);
|
||||
}
|
||||
|
||||
|
@ -449,13 +450,13 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
width: 100%;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
border : 1px solid rgba(100, 100, 100, 0.35);
|
||||
border-top : 1px solid rgba(100, 100, 100, 0.5);
|
||||
border-bottom: 1px solid rgb(60 60 60 / 12%);
|
||||
border: 1px solid rgba(100, 100, 100, 0.35);
|
||||
border-top: 1px solid rgba(100, 100, 100, 0.5);
|
||||
border-bottom: 1px solid rgb(60 60 60 / 62%);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
background: rgba(100, 100, 100, 0.25);;
|
||||
color: rgb(200 200 200);
|
||||
background: #1e1e1e99;
|
||||
color: #c8c8c8;
|
||||
font-weight: 500;
|
||||
padding-left: 32px;
|
||||
position: relative;
|
||||
|
@ -531,18 +532,15 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
|
||||
&.collapseTab {
|
||||
display:flex;
|
||||
padding:0px;
|
||||
padding:6px;
|
||||
border:0;
|
||||
>button {
|
||||
appearance: none;
|
||||
border:0px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 12px;
|
||||
padding-left: 32px;
|
||||
padding-left: 40px;
|
||||
text-align: left;
|
||||
font-family: inherit;
|
||||
background-color: var(--color2);
|
||||
color: var(--textColor);
|
||||
&:hover {
|
||||
background-color: var(--selected);
|
||||
}
|
||||
|
@ -550,17 +548,17 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
background-color: var(--selected-click);
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
content: '';
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 32px;
|
||||
width: 46px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
font-size: 1em;
|
||||
font-family: "codicon";
|
||||
}
|
||||
}
|
||||
|
@ -667,7 +665,9 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
#cmenu() {
|
||||
.container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
width: var(--sidebarWidth);
|
||||
max-width: var(--sidebarWidth);
|
||||
padding: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -1018,20 +1018,21 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
align-items: center;
|
||||
-webkit-app-region: no-drag;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item.generic {
|
||||
width: 50px;
|
||||
opacity: 0.70;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item.volume {
|
||||
width: 100px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
&.generic {
|
||||
width: 50px;
|
||||
opacity: 0.70;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item.search {
|
||||
margin-right: 6px;
|
||||
&.volume {
|
||||
width: 100px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
&.search {
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.volume-button {
|
||||
|
@ -1161,52 +1162,47 @@ input[type=range].web-slider::-webkit-slider-runnable-track {
|
|||
&-macos {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div {
|
||||
height: 100%;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div:hover {
|
||||
background: rgb(200 200 200 / 10%);
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div.close {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: var(--gfx-closeBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(196, 43, 28)
|
||||
> div {
|
||||
height: 100%;
|
||||
width: 32px;
|
||||
&:hover {
|
||||
background: rgb(200 200 200 / 10%);
|
||||
}
|
||||
&.close {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: var(--gfx-closeBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(196, 43, 28)
|
||||
}
|
||||
}
|
||||
&.minmax {
|
||||
background-image: var(--gfx-maxBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
&.minmax.restore {
|
||||
background-image: var(--gfx-restoreBtn);
|
||||
}
|
||||
&.minimize {
|
||||
background-image: var(--gfx-minBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div.minmax {
|
||||
background-image: var(--gfx-maxBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div.minmax.restore {
|
||||
background-image: var(--gfx-restoreBtn);
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .window-controls > div.minimize {
|
||||
background-image: var(--gfx-minBtn);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-app-region: no-drag;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body[platform="darwin"] .app-chrome .app-chrome-item > .window-controls > div.minimize {
|
||||
display: none;
|
||||
}
|
||||
|
@ -1242,6 +1238,15 @@ body[platform="darwin"] .app-chrome .app-chrome-item > .window-controls > div.cl
|
|||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .app-playback-controls {
|
||||
.info-rect{
|
||||
mask-image: linear-gradient(-90deg, transparent 0%, black 10%, black 90%, transparent 100%);
|
||||
-webkit-mask-image: linear-gradient(-90deg, transparent 3%, black 10%, black 90%, transparent 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width:100%;
|
||||
}
|
||||
.song-name {
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
|
@ -1409,7 +1414,7 @@ div[data-type="musicVideo"] .info-rect .title::before {
|
|||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
@ -1418,7 +1423,7 @@ div[data-type="musicVideo"] .info-rect .title::before {
|
|||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
@ -1441,10 +1446,13 @@ div[data-type="musicVideo"] .info-rect .title::before {
|
|||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 4px;
|
||||
border-radius: var(--mediaItemRadiusSmall);
|
||||
flex: 0 0 auto;
|
||||
margin: 6px;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
.mediaitem-artwork {
|
||||
border-radius: var(--mediaItemRadiusSmall);
|
||||
}
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .app-playback-controls .actions {
|
||||
|
@ -1515,7 +1523,7 @@ div[data-type="musicVideo"] .info-rect .title::before {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.app-chrome .app-chrome-item > .app-playback-controls > div > .song-artist-album {
|
||||
.app-chrome .app-chrome-item > .app-playback-controls .song-artist-album {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
|
@ -1603,12 +1611,12 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
&::-webkit-slider-thumb:hover {
|
||||
background-image: radial-gradient(var(--keyColor) 2px, transparent 3px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 2px, transparent 3px, transparent 10px);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb:active {
|
||||
background-image: radial-gradient(var(--keyColor) 3px, transparent 4px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 3px, transparent 4px, transparent 10px);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
|
@ -1645,7 +1653,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: "Pretendard Variable", "Noto Sans JP", "Noto Sans KR", "Noto Sans TC", "Noto Sans SC", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
.lyric-body .no-lyrics {
|
||||
|
@ -1679,6 +1687,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
|
||||
.lyric-line.active .verse.verse-active {
|
||||
opacity: 1;
|
||||
transition: opacity 0.35s var(--appleEase);
|
||||
}
|
||||
|
||||
.lyric-line:hover {
|
||||
|
@ -1704,7 +1713,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
opacity: 1;
|
||||
transform: scale(1);
|
||||
/*background: var(--keyColor);*/
|
||||
transition: transform 0.2s var(--appleEase);
|
||||
transition: transform 0.2s var(--appleEase), opacity 0.35s var(--appleEase);
|
||||
}
|
||||
|
||||
.lyric-line:not(.active) {
|
||||
|
@ -1749,7 +1758,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: "Pretendard Variable", "Noto Sans JP", "Noto Sans KR", "Noto Sans TC", "Noto Sans SC", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
filter: contrast(0.5);
|
||||
}
|
||||
|
||||
|
@ -2147,12 +2156,12 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
&::-webkit-slider-thumb:hover {
|
||||
background-image: radial-gradient(var(--keyColor) 2px, transparent 3px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 2px, transparent 3px, transparent 10px);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb:active {
|
||||
background-image: radial-gradient(var(--keyColor) 3px, transparent 4px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 3px, transparent 4px, transparent 10px);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
|
@ -2397,7 +2406,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
@ -2406,7 +2415,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
@ -2535,12 +2544,12 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
}
|
||||
|
||||
&::-webkit-slider-thumb:hover {
|
||||
background-image: radial-gradient(var(--keyColor) 2px, transparent 3px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 2px, transparent 3px, transparent 10px);
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb:active {
|
||||
background-image: radial-gradient(var(--keyColor) 3px, transparent 4px, transparent 10px);
|
||||
background-image: radial-gradient(var(--songProgressColor) 3px, transparent 4px, transparent 10px);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
|
@ -2808,7 +2817,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
||||
}
|
||||
|
@ -2817,7 +2826,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
background: var(--keyColor);
|
||||
background: var(--songProgressColor);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
@ -2955,6 +2964,16 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
|
|||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity .15s var(--appleEase);
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter-active,
|
||||
.modal-leave-active {
|
||||
transition: opacity .1s var(--appleEase), transform .1s var(--appleEase);
|
||||
|
@ -3453,22 +3472,7 @@ body.no-gpu {
|
|||
}
|
||||
|
||||
.close-btn {
|
||||
width: 50px;
|
||||
height: 100%;
|
||||
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-panel.menu-header-text.close-btn
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,32 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.app-chrome:not(.chrome-bottom) {
|
||||
backdrop-filter: unset;
|
||||
background-color: var(--baseColor);
|
||||
}
|
||||
|
||||
.menu-panel .menu-panel-body {
|
||||
background: rgb(30 30 30);
|
||||
}
|
||||
.menu-panel .menu-panel-body .menu-option::before {
|
||||
transition: unset!important;
|
||||
}
|
||||
|
||||
#app.twopanel .app-chrome:not(.chrome-bottom) .app-chrome--center .top-nav-group .app-sidebar-item:before {
|
||||
transition: unset!important;
|
||||
}
|
||||
|
||||
.playback-button:before, .playback-button--small:before {
|
||||
transition: unset!important;
|
||||
}
|
||||
|
||||
.floating-header {
|
||||
backdrop-filter: unset!important;
|
||||
background: rgb(0 0 0 / 80%)!important;
|
||||
}
|
||||
|
||||
.replaycard-enter-active,
|
||||
.replaycard-leave-active {
|
||||
transition: unset;
|
||||
|
|
|
@ -57,10 +57,6 @@
|
|||
.cd-mediaitem-square:not(.mediaitem-card) {
|
||||
transition : transform .2s var(--appleEase);
|
||||
transition-delay: .1s;
|
||||
padding : 12px;
|
||||
|
||||
// background-color: red;
|
||||
height: 220px;
|
||||
|
||||
|
||||
.artwork-container {}
|
||||
|
@ -73,9 +69,16 @@
|
|||
transition-delay: .05s;
|
||||
}
|
||||
|
||||
.artwork-container {
|
||||
transform : scale(0.962) translateZ(0);
|
||||
transition : transform .1s var(--appleEase);
|
||||
transition-delay: 0s;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.artwork-container {
|
||||
transform : scale(1.1);
|
||||
transform : scale(1.0);
|
||||
transition : transform .1s var(--appleEase);
|
||||
transition-delay: 0s;
|
||||
transform-origin: center;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="app-content" @scroll.passive="setContentScrollPos" :scrollpos="chrome.contentScrollPosY" scrollaxis="y" :style="{'overflow': (chrome.contentAreaScrolling ? '' : 'hidden')}">
|
||||
<div id="app-content" :scrollpos="chrome.contentScrollPosY" scrollaxis="y" :style="{'overflow': (chrome.contentAreaScrolling ? '' : 'hidden')}">
|
||||
<div id="navigation-bar" v-if="getThemeDirective('appNavigation') == 'seperate'">
|
||||
<button class="nav-item" @click="navigateBack()">
|
||||
<%- include('../svg/chevron-left.svg') %>
|
||||
|
@ -24,11 +24,6 @@
|
|||
</template>
|
||||
</transition>
|
||||
<% } %>
|
||||
|
||||
<!-- Library - Recently Added -->
|
||||
<transition :name="chrome.desiredPageTransition" v-on:enter="getLibraryAlbumsFull(null, 0); searchLibraryAlbums(0);">
|
||||
<%- include('../pages/library-recentlyadded') %>');
|
||||
</transition>
|
||||
<!-- Library - Made For You -->
|
||||
<transition :name="chrome.desiredPageTransition" v-on:enter="getMadeForYou()">
|
||||
<template v-if="page == 'library-madeforyou'">
|
||||
|
|
|
@ -1,4 +1,129 @@
|
|||
<div class="app-navigation" v-cloak>
|
||||
<transition name="wpfade">
|
||||
<div class="usermenu-container" v-if="chrome.menuOpened">
|
||||
<div class="usermenu-body">
|
||||
<button
|
||||
class="app-sidebar-button"
|
||||
style="width: 100%"
|
||||
@click="appRoute('apple-account-settings')"
|
||||
>
|
||||
<img
|
||||
class="sidebar-user-icon"
|
||||
loading="lazy"
|
||||
:src="getMediaItemArtwork(chrome.hideUserInfo ? './assets/logocut.png' : (chrome.userinfo.attributes['artwork'] ? chrome.userinfo.attributes['artwork']['url'] : ''), 26)"
|
||||
/>
|
||||
|
||||
<div class="sidebar-user-text" v-if="!chrome.hideUserInfo">
|
||||
<template v-if="chrome.userinfo.id || mk.isAuthorized">
|
||||
<div class="fullname text-overflow-elipsis">
|
||||
{{
|
||||
chrome.userinfo != null &&
|
||||
chrome.userinfo.attributes != null
|
||||
? chrome.userinfo.attributes.name ?? ""
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
<div class="handle-text text-overflow-elipsis">
|
||||
{{
|
||||
chrome.userinfo != null &&
|
||||
chrome.userinfo.attributes != null
|
||||
? chrome.userinfo.attributes.handle ?? ""
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div @click="mk.authorize()">
|
||||
{{ $root.getLz("term.login") }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="sidebar-user-text" v-else>
|
||||
{{ $root.getLz("app.name") }}
|
||||
</div>
|
||||
</button>
|
||||
<!-- Use 20px SVG for usermenu icon -->
|
||||
<button
|
||||
class="usermenu-item"
|
||||
v-if="cfg.general.privateEnabled"
|
||||
@click="cfg.general.privateEnabled = false"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/x.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.disablePrivateSession")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('remote-pair')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/smartphone.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("action.showWebRemoteQR")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
@click="cfg.advanced.AudioContext ? modals.castMenu = true : $root.notyf.error($root.getLz('settings.warn.enableAdvancedFunctionality'))"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/cast.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.cast")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
@click="cfg.advanced.AudioContext ? modals.audioSettings = true : $root.notyf.error($root.getLz('settings.warn.enableAdvancedFunctionality'))"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/headphones.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.audioSettings")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
v-if="pluginInstalled"
|
||||
@click="modals.pluginMenu = true"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/grid.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.plugin")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('about')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/info.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.about")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('settings')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/settings.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.settings")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="unauthorize()">
|
||||
<span class="usermenu-item-icon" style="right: 2.5px">
|
||||
<%- include("../svg/log-out.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.logout")
|
||||
}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="sidebartransition">
|
||||
<%- include("sidebar") %>
|
||||
</transition>
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
<b-popover custom-class="mediainfo-popover" target="artworkLCD" triggers="hover" placement="right">
|
||||
<div class="content">
|
||||
<div class="shadow-artwork">
|
||||
<mediaitem-artwork :url="currentArtUrl" :url="currentArtUrlRaw"></mediaitem-artwork>
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="popover-artwork">
|
||||
<mediaitem-artwork :size="210" :url="currentArtUrlRaw"></mediaitem-artwork>
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="song-name">{{ mk.nowPlayingItem["attributes"]["name"] }}</div>
|
||||
<div class="song-artist" @click="getNowPlayingItemDetailed(`artist`)">{{ mk.nowPlayingItem["attributes"]["artistName"] }}</div>
|
||||
|
@ -60,13 +60,27 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="app-playback-controls">
|
||||
<div class="artwork" id="artworkLCD" style="pointer-events: none;">
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="playback-info">
|
||||
<div class="song-name">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="app-chrome--center">
|
||||
<div class="app-chrome-playback-duration-bottom">
|
||||
<b-row>
|
||||
<b-col sm="auto">{{ convertTime(getSongProgress()) }}</b-col>
|
||||
<b-row v-if="mkReady()">
|
||||
<b-col sm="auto" v-if="!mk.nowPlayingItem?.isLiveRadioStation">{{ convertTime(getSongProgress()) }}</b-col>
|
||||
<b-col sm="auto" v-else>--:--</b-col>
|
||||
<b-col>
|
||||
<input type="range" step="0.01" min="0" :style="progressBarStyle()"
|
||||
@input="playerLCD.desiredDuration = $event.target.value;playerLCD.userInteraction = true"
|
||||
|
@ -74,7 +88,8 @@
|
|||
@touchend="mk.seekToTime($event.target.value);setTimeout(()=>{playerLCD.desiredDuration = 0;playerLCD.userInteraction = false}, 1000);"
|
||||
:max="mk.currentPlaybackDuration" :value="getSongProgress()">
|
||||
</b-col>
|
||||
<b-col sm="auto">{{ convertTime(mk.currentPlaybackDuration) }}</b-col>
|
||||
<b-col sm="auto" v-if="!mk.nowPlayingItem?.isLiveRadioStation">{{ convertTime(mk.currentPlaybackDuration) }}</b-col>
|
||||
<b-col sm="auto" v-else>{{ getLz("term.live") }}</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
<div class="app-chrome-playback-controls">
|
||||
|
|
|
@ -1,217 +1,118 @@
|
|||
<div
|
||||
class="app-chrome"
|
||||
:style="{'display': chrome.topChromeVisible ? '' : 'none'}"
|
||||
>
|
||||
<div class="app-chrome" :style="{'display': chrome.topChromeVisible ? '' : 'none'}">
|
||||
<div class="app-chrome--left">
|
||||
<div
|
||||
class="app-chrome-item full-height"
|
||||
v-if="chrome.windowControlPosition == 'left' && !chrome.nativeControls"
|
||||
>
|
||||
<div class="app-chrome-item full-height" v-if="chrome.windowControlPosition == 'left' && !chrome.nativeControls">
|
||||
<div class="window-controls-macos">
|
||||
<div class="close" @click="ipcRenderer.send('close')"></div>
|
||||
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
||||
<div
|
||||
class="minmax restore"
|
||||
v-if="chrome.maximized"
|
||||
@click="ipcRenderer.send('maximize')"
|
||||
></div>
|
||||
<div class="minmax restore" v-if="chrome.maximized" @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="minmax" v-else @click="ipcRenderer.send('maximize')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome-item full-height" v-else>
|
||||
<button
|
||||
class="app-mainmenu"
|
||||
@blur="mainMenuVisibility(false)"
|
||||
@click="mainMenuVisibility(true)"
|
||||
:class="{active: chrome.menuOpened}"
|
||||
:aria-label="$root.getLz('term.quickNav')"
|
||||
></button>
|
||||
<button class="app-mainmenu" @blur="mainMenuVisibility(false, true)" @click="mainMenuVisibility(true, false)"
|
||||
@contextmenu="mainMenuVisibility(true, true)" :class="{active: chrome.menuOpened}"
|
||||
:aria-label="$root.getLz('term.quickNav')"></button>
|
||||
</div>
|
||||
<template v-if="getThemeDirective('appNavigation') != 'seperate'">
|
||||
<div
|
||||
class="vdiv"
|
||||
v-if="getThemeDirective('windowLayout') == 'twopanel'"
|
||||
></div>
|
||||
<div class="vdiv" v-if="getThemeDirective('windowLayout') == 'twopanel'"></div>
|
||||
<div class="app-chrome-item">
|
||||
<button
|
||||
class="playback-button navigation"
|
||||
@click="navigateBack()"
|
||||
:title="$root.getLz('term.navigateBack')"
|
||||
v-b-tooltip.hover
|
||||
>
|
||||
<button class="playback-button navigation" @click="navigateBack()" :title="$root.getLz('term.navigateBack')"
|
||||
v-b-tooltip.hover>
|
||||
<%- include('../svg/chevron-left.svg') %>
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button
|
||||
class="playback-button navigation"
|
||||
@click="navigateForward()"
|
||||
:title="$root.getLz('term.navigateForward')"
|
||||
v-b-tooltip.hover
|
||||
>
|
||||
<button class="playback-button navigation" @click="navigateForward()"
|
||||
:title="$root.getLz('term.navigateForward')" v-b-tooltip.hover>
|
||||
<%- include('../svg/chevron-right.svg') %>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="vdiv display--large"
|
||||
v-if="getThemeDirective('windowLayout') != 'twopanel'"
|
||||
></div>
|
||||
<div class="app-chrome-item" v-if="getThemeDirective('windowLayout') == 'twopanel'">
|
||||
<button class="playback-button collapseLibrary" v-b-tooltip.hover
|
||||
:title="chrome.sidebarCollapsed ? getLz('action.showLibrary') : getLz('action.hideLibrary')"
|
||||
@click="chrome.sidebarCollapsed = !chrome.sidebarCollapsed">
|
||||
<transition name="fade">
|
||||
<span v-if="chrome.sidebarCollapsed"></span>
|
||||
</transition>
|
||||
<transition name="fade">
|
||||
<span v-if="!chrome.sidebarCollapsed"></span>
|
||||
</transition>
|
||||
|
||||
</button>
|
||||
</div>
|
||||
<div class="vdiv display--large" v-if="getThemeDirective('windowLayout') != 'twopanel'"></div>
|
||||
</template>
|
||||
<template v-if="getThemeDirective('windowLayout') != 'twopanel'">
|
||||
<div class="app-chrome-item display--large">
|
||||
<button
|
||||
class="playback-button--small shuffle"
|
||||
v-if="mk.shuffleMode == 0"
|
||||
:class="isDisabled() && 'disabled'"
|
||||
@click="mk.shuffleMode = 1"
|
||||
:title="$root.getLz('term.enableShuffle')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button--small shuffle active"
|
||||
v-else
|
||||
:class="isDisabled() && 'disabled'"
|
||||
@click="mk.shuffleMode = 0"
|
||||
:title="$root.getLz('term.disableShuffle')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0" :class="isDisabled() && 'disabled'"
|
||||
@click="mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small shuffle active" v-else :class="isDisabled() && 'disabled'"
|
||||
@click="mk.shuffleMode = 0" :title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button
|
||||
class="playback-button previous"
|
||||
@click="prevButton()"
|
||||
:class="isPrevDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.previous')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button class="playback-button previous" @click="prevButton()" :class="isPrevDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button
|
||||
class="playback-button stop"
|
||||
@click="mk.stop()"
|
||||
<button class="playback-button stop" @click="mk.stop()"
|
||||
v-if="mk.isPlaying && mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
|
||||
:title="$root.getLz('term.stop')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button pause"
|
||||
@click="mk.pause()"
|
||||
v-else-if="mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button play"
|
||||
@click="mk.play()"
|
||||
v-else
|
||||
:title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button pause" @click="mk.pause()" v-else-if="mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button play" @click="mk.play()" v-else :title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button
|
||||
class="playback-button next"
|
||||
@click="skipToNextItem()"
|
||||
:class="isNextDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.next')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button class="playback-button next" @click="skipToNextItem()" :class="isNextDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button
|
||||
class="playback-button--small repeat"
|
||||
v-if="mk.repeatMode == 0"
|
||||
:class="isDisabled() && 'disabled'"
|
||||
@click="mk.repeatMode = 1"
|
||||
:title="$root.getLz('term.enableRepeatOne')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button--small repeat repeatOne"
|
||||
@click="mk.repeatMode = 2"
|
||||
:class="isDisabled() && 'disabled'"
|
||||
v-else-if="mk.repeatMode == 1"
|
||||
:title="$root.getLz('term.disableRepeatOne')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button--small repeat active"
|
||||
@click="mk.repeatMode = 0"
|
||||
:class="isDisabled() && 'disabled'"
|
||||
v-else-if="mk.repeatMode == 2"
|
||||
:title="$root.getLz('term.disableRepeat')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0" :class="isDisabled() && 'disabled'"
|
||||
@click="mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
|
||||
:class="isDisabled() && 'disabled'" v-else-if="mk.repeatMode == 1"
|
||||
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 0"
|
||||
:class="isDisabled() && 'disabled'" v-else-if="mk.repeatMode == 2" :title="$root.getLz('term.disableRepeat')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="app-chrome--center">
|
||||
<div
|
||||
class="app-chrome-item playback-controls"
|
||||
v-if="getThemeDirective('windowLayout') != 'twopanel'"
|
||||
>
|
||||
<div class="app-chrome-item playback-controls" v-if="getThemeDirective('windowLayout') != 'twopanel'">
|
||||
<template v-if="mkReady()">
|
||||
<div
|
||||
class="app-playback-controls"
|
||||
@mouseover="chrome.progresshover = true"
|
||||
@mouseleave="chrome.progresshover = false"
|
||||
@contextmenu="nowPlayingContextMenu"
|
||||
>
|
||||
<div class="app-playback-controls" @mouseover="chrome.progresshover = true"
|
||||
@mouseleave="chrome.progresshover = false" @contextmenu="nowPlayingContextMenu">
|
||||
<div class="artwork" id="artworkLCD">
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<b-popover
|
||||
custom-class="mediainfo-popover"
|
||||
target="artworkLCD"
|
||||
triggers="hover"
|
||||
placement="bottom"
|
||||
>
|
||||
<b-popover custom-class="mediainfo-popover" target="artworkLCD" triggers="hover" placement="bottom">
|
||||
<div class="content">
|
||||
<div class="shadow-artwork">
|
||||
<mediaitem-artwork
|
||||
:url="currentArtUrl"
|
||||
:url="currentArtUrlRaw"
|
||||
></mediaitem-artwork>
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="popover-artwork">
|
||||
<mediaitem-artwork
|
||||
:size="210"
|
||||
:url="currentArtUrlRaw"
|
||||
></mediaitem-artwork>
|
||||
<mediaitem-artwork :size="210" :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="song-name">
|
||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||
</div>
|
||||
<div
|
||||
class="song-artist"
|
||||
@click="getNowPlayingItemDetailed(`artist`)"
|
||||
>
|
||||
<div class="song-artist" @click="getNowPlayingItemDetailed(`artist`)">
|
||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||
</div>
|
||||
<div
|
||||
class="song-album"
|
||||
@click="getNowPlayingItemDetailed(`album`)"
|
||||
>
|
||||
<div class="song-album" @click="getNowPlayingItemDetailed(`album`)">
|
||||
{{
|
||||
mk.nowPlayingItem["attributes"]["albumName"]
|
||||
? mk.nowPlayingItem["attributes"]["albumName"]
|
||||
: ""
|
||||
mk.nowPlayingItem["attributes"]["albumName"]
|
||||
? mk.nowPlayingItem["attributes"]["albumName"]
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
<hr />
|
||||
<div class="btn-group" style="width: 100%">
|
||||
<button
|
||||
class="md-btn md-btn-small"
|
||||
style="width: 100%"
|
||||
@click="drawer.open = false; miniPlayer(true)"
|
||||
>
|
||||
<button class="md-btn md-btn-small" style="width: 100%" @click="drawer.open = false; miniPlayer(true)">
|
||||
{{ $root.getLz("term.miniplayer") }}
|
||||
</button>
|
||||
<button
|
||||
class="md-btn md-btn-small"
|
||||
style="width: 100%"
|
||||
@click="drawer.open = false; fullscreen(true)"
|
||||
>
|
||||
<button class="md-btn md-btn-small" style="width: 100%" @click="drawer.open = false; fullscreen(true)">
|
||||
{{ $root.getLz("term.fullscreenView") }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -219,183 +120,121 @@
|
|||
</b-popover>
|
||||
<div class="playback-info">
|
||||
<div class="chrome-icon-container">
|
||||
<div
|
||||
class="audio-type private-icon"
|
||||
v-if="cfg.general.privateEnabled === true"
|
||||
></div>
|
||||
<div
|
||||
class="audio-type ppe-icon"
|
||||
v-if="cfg.audio.maikiwiAudio.ciderPPE === true"
|
||||
></div>
|
||||
<div class="audio-type private-icon" v-if="cfg.general.privateEnabled === true"></div>
|
||||
<div class="audio-type ppe-icon" v-if="cfg.audio.maikiwiAudio.ciderPPE === true"></div>
|
||||
</div>
|
||||
<div
|
||||
class="song-name"
|
||||
:class="[isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-name') ? 'marquee' : '']"
|
||||
>
|
||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||
<div
|
||||
class="explicit-icon"
|
||||
v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
|
||||
style="display: inline-block"
|
||||
></div>
|
||||
</div>
|
||||
<div class="song-artist-album">
|
||||
<div
|
||||
class="song-artist-album-content"
|
||||
:class="[isElementOverflowing('#app-main > .app-chrome .app-chrome-item > .app-playback-controls > div >.song-artist-album > .song-artist-album-content') ? 'marquee' : '']"
|
||||
style="
|
||||
<div class="info-rect">
|
||||
<div class="song-name"
|
||||
:class="[isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-name') ? 'marquee' : '']">
|
||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||
<div class="explicit-icon" v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
|
||||
style="display: inline-block"></div>
|
||||
</div>
|
||||
<div class="song-artist-album">
|
||||
<div class="song-artist-album-content"
|
||||
:class="[isElementOverflowing('#app-main > .app-chrome .app-chrome-item > .app-playback-controls > div >.song-artist-album > .song-artist-album-content') ? 'marquee' : '']"
|
||||
style="
|
||||
display: inline-block;
|
||||
-webkit-box-orient: horizontal;
|
||||
white-space: nowrap;
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="item-navigate song-artist"
|
||||
style="display: inline-block"
|
||||
@click="getNowPlayingItemDetailed(`artist`)"
|
||||
>
|
||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||
</div>
|
||||
<div
|
||||
class="song-artist item-navigate"
|
||||
style="display: inline-block"
|
||||
@click="getNowPlayingItemDetailed('album')"
|
||||
v-if="mk.nowPlayingItem['attributes']['albumName'] != ''"
|
||||
>
|
||||
<div class="separator" style="display: inline-block">
|
||||
{{ "—" }}
|
||||
">
|
||||
<div class="item-navigate song-artist" style="display: inline-block"
|
||||
@click="getNowPlayingItemDetailed(`artist`)">
|
||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||
</div>
|
||||
{{
|
||||
<div class="song-artist item-navigate" style="display: inline-block"
|
||||
@click="getNowPlayingItemDetailed('album')"
|
||||
v-if="mk.nowPlayingItem['attributes']['albumName'] != ''">
|
||||
<div class="separator" style="display: inline-block">
|
||||
{{ "—" }}
|
||||
</div>
|
||||
{{
|
||||
mk.nowPlayingItem["attributes"]["albumName"]
|
||||
? mk.nowPlayingItem["attributes"]["albumName"]
|
||||
: ""
|
||||
}}
|
||||
? mk.nowPlayingItem["attributes"]["albumName"]
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="song-progress">
|
||||
<div
|
||||
class="song-duration"
|
||||
style="justify-content: space-between; height: 1px"
|
||||
:style="[chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]"
|
||||
>
|
||||
<div class="song-duration" style="justify-content: space-between; height: 1px"
|
||||
:style="[chrome.progresshover ? {'display': 'flex'} : {'display' : 'none'} ]">
|
||||
<p style="width: auto">{{ convertTime(getSongProgress()) }}</p>
|
||||
<p style="width: auto">
|
||||
{{ convertTime(mk.currentPlaybackDuration) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="range"
|
||||
step="0.01"
|
||||
min="0"
|
||||
:style="progressBarStyle()"
|
||||
<input type="range" step="0.01" min="0" :style="progressBarStyle()"
|
||||
@input="playerLCD.desiredDuration = $event.target.value;playerLCD.userInteraction = true"
|
||||
@mouseup="mk.seekToTime($event.target.value);setTimeout(()=>{playerLCD.desiredDuration = 0;playerLCD.userInteraction = false}, 1000);"
|
||||
@touchend="mk.seekToTime($event.target.value);setTimeout(()=>{playerLCD.desiredDuration = 0;playerLCD.userInteraction = false}, 1000);"
|
||||
:max="mk.currentPlaybackDuration"
|
||||
:value="getSongProgress()"
|
||||
/>
|
||||
:max="mk.currentPlaybackDuration" :value="getSongProgress()" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="mk.nowPlayingItem['attributes']['playParams']">
|
||||
<div class="actions">
|
||||
<button
|
||||
class="lcdMenu"
|
||||
@click="nowPlayingContextMenu"
|
||||
:title="$root.getLz('term.more')"
|
||||
v-b-tooltip.hover
|
||||
>
|
||||
<button class="lcdMenu" @click="nowPlayingContextMenu" :title="$root.getLz('term.more')"
|
||||
v-b-tooltip.hover>
|
||||
<div class="svg-icon"></div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="app-playback-controls">
|
||||
<div class="artwork" id="artworkLCD" style="pointer-events: none;">
|
||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="playback-info">
|
||||
<div class="info-rect">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="app-chrome-item" v-else>
|
||||
<div class="top-nav-group">
|
||||
<sidebar-library-item
|
||||
:name="$root.getLz('home.title')"
|
||||
svg-icon="./assets/feather/home.svg"
|
||||
page="home"
|
||||
>
|
||||
<sidebar-library-item :name="$root.getLz('home.title')" svg-icon="./assets/feather/home.svg" page="home">
|
||||
</sidebar-library-item>
|
||||
<sidebar-library-item
|
||||
:name="$root.getLz('term.listenNow')"
|
||||
svg-icon="./assets/feather/play-circle.svg"
|
||||
page="listen_now"
|
||||
></sidebar-library-item>
|
||||
<sidebar-library-item
|
||||
:name="$root.getLz('term.browse')"
|
||||
svg-icon="./assets/feather/globe.svg"
|
||||
page="browse"
|
||||
>
|
||||
<sidebar-library-item :name="$root.getLz('term.listenNow')" svg-icon="./assets/feather/play-circle.svg"
|
||||
page="listen_now"></sidebar-library-item>
|
||||
<sidebar-library-item :name="$root.getLz('term.browse')" svg-icon="./assets/feather/globe.svg" page="browse">
|
||||
</sidebar-library-item>
|
||||
<sidebar-library-item :name="$root.getLz('term.radio')" svg-icon="./assets/feather/radio.svg" page="radio">
|
||||
</sidebar-library-item>
|
||||
<sidebar-library-item
|
||||
:name="$root.getLz('term.radio')"
|
||||
svg-icon="./assets/feather/radio.svg"
|
||||
page="radio"
|
||||
></sidebar-library-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome--right">
|
||||
<template v-if="getThemeDirective('windowLayout') != 'twopanel'">
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<button
|
||||
class="volume-button--small volume"
|
||||
@click="muteButtonPressed()"
|
||||
<button class="volume-button--small volume" @click="muteButtonPressed()"
|
||||
:class="{'active': this.cfg.audio.volume == 0}"
|
||||
:title="cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<input
|
||||
type="range"
|
||||
@wheel="volumeWheel"
|
||||
:step="cfg.audio.volumeStep"
|
||||
min="0"
|
||||
:max="cfg.audio.maxVolume"
|
||||
v-model="mk.volume"
|
||||
v-if="typeof mk.volume != 'undefined'"
|
||||
@change="checkMuteChange()"
|
||||
v-b-tooltip.hover
|
||||
:title="formatVolumeTooltip()"
|
||||
/>
|
||||
:title="cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')" v-b-tooltip.hover></button>
|
||||
<input type="range" @wheel="volumeWheel" :step="cfg.audio.volumeStep" min="0" :max="cfg.audio.maxVolume"
|
||||
v-model="mk.volume" v-if="typeof mk.volume != 'undefined'" @change="checkMuteChange()" v-b-tooltip.hover
|
||||
:title="formatVolumeTooltip()" />
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button
|
||||
class="playback-button--small cast"
|
||||
:title="$root.getLz('term.cast')"
|
||||
<button class="playback-button--small cast" :title="$root.getLz('term.cast')"
|
||||
@click="cfg.advanced.AudioContext ? modals.castMenu = true : $root.notyf.error($root.getLz('settings.warn.enableAdvancedFunctionality'))"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<button
|
||||
class="playback-button--small queue"
|
||||
:title="$root.getLz('term.queue')"
|
||||
v-b-tooltip.hover
|
||||
:class="{'active': drawer.panel == 'queue'}"
|
||||
@click="invokeDrawer('queue')"
|
||||
></button>
|
||||
<button class="playback-button--small queue" :title="$root.getLz('term.queue')" v-b-tooltip.hover
|
||||
:class="{'active': drawer.panel == 'queue'}" @click="invokeDrawer('queue')"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item generic">
|
||||
<template v-if="lyrics && lyrics != [] && lyrics.length > 0">
|
||||
<button
|
||||
class="playback-button--small lyrics"
|
||||
:title="$root.getLz('term.lyrics')"
|
||||
v-b-tooltip.hover
|
||||
:class="{'active': drawer.panel == 'lyrics'}"
|
||||
@click="invokeDrawer('lyrics')"
|
||||
></button>
|
||||
<button class="playback-button--small lyrics" :title="$root.getLz('term.lyrics')" v-b-tooltip.hover
|
||||
:class="{'active': drawer.panel == 'lyrics'}" @click="invokeDrawer('lyrics')"></button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button
|
||||
class="playback-button--small lyrics"
|
||||
:style="{'opacity': 0.3, 'pointer-events': 'none'}"
|
||||
></button>
|
||||
<button class="playback-button--small lyrics" :style="{'opacity': 0.3, 'pointer-events': 'none'}"></button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -403,31 +242,16 @@
|
|||
<div class="app-chrome-item search">
|
||||
<div class="search-input-container">
|
||||
<div class="search-input--icon"></div>
|
||||
<input
|
||||
type="search"
|
||||
spellcheck="false"
|
||||
@click="showSearch()"
|
||||
@focus="search.showHints = true"
|
||||
<input type="search" spellcheck="false" @click="showSearch()" @focus="search.showHints = true"
|
||||
@blur="setTimeout(()=>{search.showHints = false}, 300)"
|
||||
v-on:keyup.enter="searchQuery();search.showHints = false"
|
||||
@change="showSearch();"
|
||||
@input="getSearchHints()"
|
||||
:placeholder="$root.getLz('term.search') + '...'"
|
||||
v-model="search.term"
|
||||
ref="searchInput"
|
||||
class="search-input"
|
||||
/>
|
||||
v-on:keyup.enter="searchQuery();search.showHints = false" @change="showSearch();" @input="getSearchHints()"
|
||||
:placeholder="$root.getLz('term.search') + '...'" v-model="search.term" ref="searchInput"
|
||||
class="search-input" />
|
||||
|
||||
<div
|
||||
class="search-hints-container"
|
||||
v-if="search.showHints && search.hints.length != 0"
|
||||
>
|
||||
<div class="search-hints-container" v-if="search.showHints && search.hints.length != 0">
|
||||
<div class="search-hints">
|
||||
<button
|
||||
class="search-hint text-overflow-elipsis"
|
||||
v-for="hint in search.hints"
|
||||
@click="search.term = hint;search.showHints = false;searchQuery(hint)"
|
||||
>
|
||||
<button class="search-hint text-overflow-elipsis" v-for="hint in search.hints"
|
||||
@click="search.term = hint;search.showHints = false;searchQuery(hint)">
|
||||
{{ hint }}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -435,32 +259,18 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
class="app-chrome-item full-height"
|
||||
id="window-controls-container"
|
||||
v-if="chrome.windowControlPosition == 'right' && !chrome.nativeControls"
|
||||
>
|
||||
<div class="app-chrome-item full-height" id="window-controls-container"
|
||||
v-if="chrome.windowControlPosition == 'right' && !chrome.nativeControls">
|
||||
<div class="window-controls">
|
||||
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
||||
<div
|
||||
class="minmax restore"
|
||||
v-if="chrome.maximized"
|
||||
@click="ipcRenderer.send('maximize')"
|
||||
></div>
|
||||
<div class="minmax restore" v-if="chrome.maximized" @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="minmax" v-else @click="ipcRenderer.send('maximize')"></div>
|
||||
<div class="close" @click="ipcRenderer.send('close')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="app-chrome-item full-height"
|
||||
v-else-if="platform != 'darwin' && !chrome.nativeControls"
|
||||
>
|
||||
<button
|
||||
class="app-mainmenu"
|
||||
@blur="mainMenuVisibility(false)"
|
||||
@click="mainMenuVisibility(true)"
|
||||
:class="{active: chrome.menuOpened}"
|
||||
></button>
|
||||
<div class="app-chrome-item full-height" v-else-if="platform != 'darwin' && !chrome.nativeControls">
|
||||
<button class="app-mainmenu" @blur="mainMenuVisibility(false, true)" @click="mainMenuVisibility(true, false)"
|
||||
@contextmenu="mainMenuVisibility(true, true)" :class="{active: chrome.menuOpened}"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -13,9 +13,6 @@
|
|||
<transition name="modal">
|
||||
<add-to-playlist :playlists="playlists.listing" v-if="modals.addToPlaylist"></add-to-playlist>
|
||||
</transition>
|
||||
<transition name="modal">
|
||||
<spatial-properties v-if="modals.spatialProperties"></spatial-properties>
|
||||
</transition>
|
||||
<transition name="modal">
|
||||
<audio-controls v-if="modals.audioControls"></audio-controls>
|
||||
</transition>
|
||||
|
|
|
@ -183,136 +183,6 @@
|
|||
</sidebar-playlist>
|
||||
</template>
|
||||
</div>
|
||||
<transition name="wpfade">
|
||||
<div class="usermenu-container" v-if="chrome.menuOpened">
|
||||
<div class="usermenu-body">
|
||||
<button
|
||||
class="app-sidebar-button"
|
||||
style="width: 100%"
|
||||
@click="appRoute('apple-account-settings')"
|
||||
>
|
||||
<img
|
||||
class="sidebar-user-icon"
|
||||
loading="lazy"
|
||||
:src="getMediaItemArtwork(chrome.hideUserInfo ? 'http://localhost:9000/assets/logocut.png' : (chrome.userinfo.attributes['artwork'] ? chrome.userinfo.attributes['artwork']['url'] : ''), 26)"
|
||||
/>
|
||||
|
||||
<div class="sidebar-user-text" v-if="!chrome.hideUserInfo">
|
||||
<template v-if="chrome.userinfo.id || mk.isAuthorized">
|
||||
<div class="fullname text-overflow-elipsis">
|
||||
{{
|
||||
chrome.userinfo != null &&
|
||||
chrome.userinfo.attributes != null
|
||||
? chrome.userinfo.attributes.name ?? ""
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
<div class="handle-text text-overflow-elipsis">
|
||||
{{
|
||||
chrome.userinfo != null &&
|
||||
chrome.userinfo.attributes != null
|
||||
? chrome.userinfo.attributes.handle ?? ""
|
||||
: ""
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div @click="mk.authorize()">
|
||||
{{ $root.getLz("term.login") }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="sidebar-user-text" v-else>
|
||||
{{ $root.getLz("app.name") }}
|
||||
</div>
|
||||
</button>
|
||||
<!-- Use 20px SVG for usermenu icon -->
|
||||
<button
|
||||
class="usermenu-item"
|
||||
v-if="cfg.general.privateEnabled"
|
||||
@click="cfg.general.privateEnabled = false"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/x.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.disablePrivateSession")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('remote-pair')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/smartphone.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("action.showWebRemoteQR")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
@click="cfg.advanced.AudioContext ? modals.castMenu = true : $root.notyf.error($root.getLz('settings.warn.enableAdvancedFunctionality'))"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/cast.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.cast")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
@click="cfg.advanced.AudioContext ? modals.audioSettings = true : $root.notyf.error($root.getLz('settings.warn.enableAdvancedFunctionality'))"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/headphones.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.audioSettings")
|
||||
}}</span>
|
||||
</button>
|
||||
<button
|
||||
class="usermenu-item"
|
||||
v-if="pluginInstalled"
|
||||
@click="modals.pluginMenu = true"
|
||||
>
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/grid.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.plugin")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('about')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/info.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.about")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="appRoute('settings')">
|
||||
<span class="usermenu-item-icon">
|
||||
<%- include("../svg/settings.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.settings")
|
||||
}}</span>
|
||||
</button>
|
||||
<button class="usermenu-item" @click="unauthorize()">
|
||||
<span class="usermenu-item-icon" style="right: 2.5px">
|
||||
<%- include("../svg/log-out.svg") %>
|
||||
</span>
|
||||
<span class="usermenu-item-name">{{
|
||||
$root.getLz("term.logout")
|
||||
}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<div class="app-sidebar-footer collapseTab" v-if="cfg.advanced.experiments.includes('collapseSidebar')">
|
||||
<button @click="chrome.sidebarCollapsed = !chrome.sidebarCollapsed">
|
||||
Collapse
|
||||
</button>
|
||||
</div>
|
||||
<div class="app-sidebar-footer display--small app-sidebar-footer--controls">
|
||||
<div
|
||||
class="app-playback-controls"
|
||||
|
@ -326,6 +196,7 @@
|
|||
v-if="mk.shuffleMode == 0"
|
||||
@click="mk.shuffleMode = 1"
|
||||
:title="$root.getLz('term.enableShuffle')"
|
||||
:class="$root.isDisabled() && 'disabled'"
|
||||
v-b-tooltip.hover.righttop
|
||||
></button>
|
||||
<button
|
||||
|
@ -333,6 +204,7 @@
|
|||
v-else
|
||||
@click="mk.shuffleMode = 0"
|
||||
:title="$root.getLz('term.disableShuffle')"
|
||||
:class="$root.isDisabled() && 'disabled'"
|
||||
v-b-tooltip.hover.righttop
|
||||
></button>
|
||||
</div>
|
||||
|
@ -340,31 +212,26 @@
|
|||
<button
|
||||
class="playback-button previous"
|
||||
@click="prevButton()"
|
||||
:class="$root.isPrevDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.previous')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button
|
||||
class="playback-button pause"
|
||||
@click="mk.pause()"
|
||||
v-if="mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
class="playback-button play"
|
||||
@click="mk.play()"
|
||||
v-else
|
||||
:title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button class="playback-button stop" @click="$root.mk.stop()"
|
||||
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
|
||||
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button pause" @click="$root.mk.pause()" v-else-if="$root.mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button play" @click="$root.mk.play()" v-else :title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button
|
||||
class="playback-button next"
|
||||
@click="skipToNextItem()"
|
||||
:title="$root.getLz('term.next')"
|
||||
:class="$root.isNextDisabled() && 'disabled'"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
</div>
|
||||
|
@ -373,6 +240,7 @@
|
|||
class="playback-button--small repeat"
|
||||
v-if="mk.repeatMode == 0"
|
||||
@click="mk.repeatMode = 1"
|
||||
:class="$root.isDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.enableRepeatOne')"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
|
@ -381,6 +249,7 @@
|
|||
@click="mk.repeatMode = 2"
|
||||
v-else-if="mk.repeatMode == 1"
|
||||
:title="$root.getLz('term.disableRepeatOne')"
|
||||
:class="$root.isDisabled() && 'disabled'"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
<button
|
||||
|
@ -388,6 +257,7 @@
|
|||
@click="mk.repeatMode = 0"
|
||||
v-else-if="mk.repeatMode == 2"
|
||||
:title="$root.getLz('term.disableRepeat')"
|
||||
:class="$root.isDisabled() && 'disabled'"
|
||||
v-b-tooltip.hover
|
||||
></button>
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<script type="text/x-template" id="artist-chip">
|
||||
<div class="artist-chip" @click.self="route" tabindex="0">
|
||||
<div class="artist-chip__image">
|
||||
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="32"></mediaitem-artwork>
|
||||
<div class="artist-chip__image" v-if="image" :style="{backgroundColor: '#' + (artist.attributes.artwork?.bgColor ?? '000')}">
|
||||
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="80"></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="artist-chip__image" v-else>
|
||||
</div>
|
||||
<div class="artist-chip__name">
|
||||
<span>{{ item.attributes.name }}</span>
|
||||
</div>
|
||||
<button @click="$root.followArtistById(artist.id, true)" title="Follow" v-if="!$root.followingArtist(artist.id)" class="artist-chip__follow codicon codicon-add"></button>
|
||||
<button @click="$root.followArtistById(artist.id, false)" title="Following" v-else class="artist-chip__follow codicon codicon-check"></button>
|
||||
<button @click="$root.setArtistFavorite(artist.id, true)" title="Follow" v-if="!$root.followingArtist(artist.id)" class="artist-chip__follow codicon codicon-add"></button>
|
||||
<button @click="$root.setArtistFavorite(artist.id, false)" title="Following" v-else class="artist-chip__follow codicon codicon-check"></button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
@ -21,6 +23,7 @@
|
|||
},
|
||||
data: function() {
|
||||
return {
|
||||
image: false,
|
||||
artist: {
|
||||
id: null
|
||||
}
|
||||
|
@ -34,6 +37,7 @@
|
|||
}
|
||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artistId}`).then(response => {
|
||||
this.artist = response.data.data[0];
|
||||
this.image = true;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script type="text/x-template" id="artwork-material">
|
||||
<div class="artworkMaterial">
|
||||
<img :src="src" v-for="image in images"/>
|
||||
<mediaitem-artwork :url="src" :size="500" v-for="image in images"/>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
|
|
@ -35,6 +35,16 @@
|
|||
v-model="maxVolume"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.audio.advanced')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.audio.advanced" switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -298,7 +298,7 @@
|
|||
try {
|
||||
for (var i = 0; i < 21; i++) {
|
||||
CiderAudio.audioNodes.vibrantbassNode[i].gain.value = app.cfg.audio.maikiwiAudio.vibrantBass.gain[i] * (app.cfg.audio.equalizer.vibrantBass / 10);
|
||||
} CiderAudio.intelliGainComp_h0_0();
|
||||
} CiderAudio.intelliGainComp_n0_0();
|
||||
}
|
||||
catch (e) {
|
||||
CiderAudio.hierarchical_loading();
|
||||
|
@ -315,7 +315,7 @@
|
|||
for (var i = 0; i < 10; i++) {
|
||||
CiderAudio.audioNodes.audioBands[i].gain.value = app.cfg.audio.equalizer.gain[i] * app.cfg.audio.equalizer.mix
|
||||
}
|
||||
CiderAudio.intelliGainComp_h0_0();
|
||||
CiderAudio.intelliGainComp_n0_0();
|
||||
} catch (e) { CiderAudio.hierarchical_loading(); }
|
||||
}
|
||||
},
|
||||
|
@ -323,7 +323,7 @@
|
|||
if (Math.max(...app.cfg.audio.equalizer.gain) != 0) {
|
||||
try {
|
||||
CiderAudio.audioNodes.audioBands[i].gain.value = app.cfg.audio.equalizer.gain[i] * app.cfg.audio.equalizer.mix
|
||||
CiderAudio.intelliGainComp_h0_0();
|
||||
CiderAudio.intelliGainComp_n0_0();
|
||||
}
|
||||
catch (e) { CiderAudio.hierarchical_loading(); }
|
||||
}
|
||||
|
@ -413,7 +413,7 @@
|
|||
CiderAudio.audioNodes.audioBands[i].frequency.value = app.cfg.audio.equalizer.frequencies[i]
|
||||
CiderAudio.audioNodes.audioBands[i].Q.value = app.cfg.audio.equalizer.Q[i]
|
||||
}
|
||||
CiderAudio.intelliGainComp_h0_0();
|
||||
CiderAudio.intelliGainComp_n0_0();
|
||||
},
|
||||
changePreset(id) {
|
||||
let userPresets = app.cfg.audio.equalizer.presets
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
<div class="artwork" @click="app.fullscreen(false)">
|
||||
<mediaitem-artwork
|
||||
:size="600"
|
||||
:url="(image ?? '').replace('{w}','600').replace('{h}','600') "
|
||||
:video="video"
|
||||
:videoPriority="true"
|
||||
:url="(image ?? '').replace('{w}','600').replace('{h}','600')"
|
||||
></mediaitem-artwork>
|
||||
</div>
|
||||
<div class="controls-parents">
|
||||
|
@ -52,39 +54,40 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="control-buttons">
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small shuffle" v-if="app.mk.shuffleMode == 0"
|
||||
@click="app.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')"
|
||||
v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small shuffle active" v-else
|
||||
@click="app.mk.shuffleMode = 0" :title="$root.getLz('term.disableShuffle')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button previous" @click="app.prevButton()"
|
||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button pause" @click="app.mk.pause()" v-if="app.mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button play" @click="app.mk.play()" v-else
|
||||
:title="$root.getLz('term.play')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="app.skipToNextItem()"
|
||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"
|
||||
@click="app.mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')"
|
||||
v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="app.mk.repeatMode = 2"
|
||||
v-else-if="app.mk.repeatMode == 1" :title="$root.getLz('term.disableRepeatOne')"
|
||||
v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat active" @click="app.mk.repeatMode = 0"
|
||||
v-else-if="app.mk.repeatMode == 2" :title="$root.getLz('term.disableRepeat')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small shuffle" v-if="$root.mk.shuffleMode == 0" :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small shuffle active" v-else :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.shuffleMode = 0" :title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button previous" @click="$root.prevButton()" :class="$root.isPrevDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button stop" @click="$root.mk.stop()"
|
||||
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
|
||||
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button pause" @click="$root.mk.pause()" v-else-if="$root.mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button play" @click="$root.mk.play()" v-else :title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button next" @click="$root.skipToNextItem()" :class="$root.isNextDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small repeat" v-if="$root.mk.repeatMode == 0" :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
|
||||
:class="$root.isDisabled() && 'disabled'" v-else-if="$root.mk.repeatMode == 1"
|
||||
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat active" @click="$root.mk.repeatMode = 0"
|
||||
:class="$root.isDisabled() && 'disabled'" v-else-if="$root.mk.repeatMode == 2" :title="$root.getLz('term.disableRepeat')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<div class="input-container">
|
||||
|
@ -149,6 +152,37 @@
|
|||
return {
|
||||
app: this.$root,
|
||||
tabMode: "lyrics",
|
||||
video: null
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (app.mk.nowPlayingItem._container.type == "albums") {
|
||||
try {
|
||||
const result = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${app.mk.nowPlayingItem._container.type}/${app.mk.nowPlayingItem._container.id}`, {
|
||||
"fields": "editorialArtwork,editorialVideo",
|
||||
})).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
|
||||
if (result) {
|
||||
this.video = result
|
||||
} else {
|
||||
this.video = null
|
||||
}
|
||||
} catch (e) {
|
||||
this.video = null
|
||||
e = null
|
||||
}
|
||||
} else if (app.mk.nowPlayingItem._container.type == "library-albums") {
|
||||
try {
|
||||
const result = (await app.mk.api.v3.music(`/v1/me/library/albums/${app.mk.nowPlayingItem._container.id}/catalog`
|
||||
, { "fields": "editorialArtwork,editorialVideo" })).data.data[0].attributes?.editorialVideo?.motionDetailSquare?.video
|
||||
if (result) {
|
||||
this.video = result
|
||||
} else {
|
||||
this.video = null
|
||||
}
|
||||
} catch (e) {
|
||||
e = null
|
||||
this.video = null
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
class="cd-mediaitem-list-item"
|
||||
:class="{'mediaitem-selected': app.select_hasMediaItem(guid)}"
|
||||
@contextmenu="contextMenu">
|
||||
<template v-if="isVisible">
|
||||
<div class="artwork" v-if="showArtwork == true">
|
||||
<div class="artwork" v-show="isVisible" v-if="showArtwork == true">
|
||||
<mediaitem-artwork
|
||||
:url="getArtwork()"
|
||||
size="50"
|
||||
|
@ -17,7 +16,6 @@
|
|||
{{ item.attributes.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
<h3>{{ recom.attributes.title ? recom.attributes.title.stringForDisplay : " "}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="recom.relationships.contents.data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection(recom.relationships.contents, recom.attributes.title ? recom.attributes.title.stringForDisplay : '', 'listen_now')" >{{app.getLz('term.seeAll')}}</button>
|
||||
<button class="cd-btn-seeall" @click="showCollection(recom)" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="recom.attributes.display.kind == 'MusicCoverShelf'">
|
||||
<template v-if="recom.attributes.display.kind == 'MusicCoverShelf' || recom.attributes.display.kind == 'MusicCircleCoverShelf'">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="recom.relationships.contents.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
|
@ -39,6 +39,10 @@
|
|||
visibilityChanged: function (isVisible, entry) {
|
||||
// this.isVisible = isVisible
|
||||
},
|
||||
showCollection: function (recom) {
|
||||
console.debug(recom)
|
||||
app.showCollection(recom.relationships.contents, recom.attributes.title ? recom.attributes.title.stringForDisplay : '', 'listen_now')
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -1,9 +1,10 @@
|
|||
<script type="text/x-template" id="mediaitem-artwork">
|
||||
<div class="mediaitem-artwork" @contextmenu="contextMenu" :class="[{'rounded': (type == 'artists')}, classes]" :key="url">
|
||||
<div class="mediaitem-artwork" :style="awStyle" @contextmenu="contextMenu" :class="[{'rounded': (type == 'artists')}, classes]" :key="url">
|
||||
<img :src="app.getMediaItemArtwork(url, size, width)"
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
:style="{background: bgcolor}"
|
||||
:style="imgStyle"
|
||||
@load="imgLoaded()"
|
||||
class="mediaitem-artwork--img">
|
||||
<div v-if="video && getVideoPriority()" class="animatedartwork-view-box">
|
||||
<animatedartwork-view :priority="getVideoPriority()" :video="video"></animatedartwork-view>
|
||||
|
@ -50,11 +51,18 @@
|
|||
},
|
||||
data: function () {
|
||||
return {
|
||||
app:this.$root,
|
||||
app: this.$root,
|
||||
isVisible: false,
|
||||
style: {
|
||||
"box-shadow": ""
|
||||
},
|
||||
awStyle: {
|
||||
background: this.bgcolor
|
||||
},
|
||||
imgStyle: {
|
||||
opacity: 0,
|
||||
transition: "opacity .25s linear"
|
||||
},
|
||||
classes: []
|
||||
}
|
||||
},
|
||||
|
@ -62,6 +70,10 @@
|
|||
this.getClasses()
|
||||
},
|
||||
methods: {
|
||||
imgLoaded() {
|
||||
this.imgStyle.opacity = 1
|
||||
// this.awStyle.background = ""
|
||||
},
|
||||
contextMenu(event) {
|
||||
let self = this
|
||||
app.showMenuPanel({
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
@controller-click="route()"
|
||||
tabindex="0"
|
||||
:class="[{'mediaitem-selected': app.select_hasMediaItem(guid)}, addClasses]">
|
||||
<template v-if="isVisible">
|
||||
<div v-show="isVisible" class="listitem-content">
|
||||
<div class="popular" v-if="!showInLibrary && item?.meta?.popularity != null && item?.meta?.popularity > 0.7"></div>
|
||||
<div class="isLibrary" v-if="showLibraryStatus == true">
|
||||
<div v-if="showInLibrary" :style="{display: (showInLibrary ? 'block' : 'none'), 'margin-left':'11px'}">
|
||||
|
@ -87,7 +87,7 @@
|
|||
<div class="duration" v-if="item.attributes.playCount" @dblclick="route()">
|
||||
{{ item.attributes.playCount }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
<div v-if="reasonShown" class="reasonSP ">{{item?.meta?.reason?.stringForDisplay ?? ''}}</div>
|
||||
<div style="{'--spcolor': getBgColor()}"
|
||||
class="cd-mediaitem-square" :class="getClasses()" @contextmenu="getContextMenu">
|
||||
<template>
|
||||
<div class="artwork-container">
|
||||
<div class="artwork-container" v-show="isVisible">
|
||||
<div class="unavailable-overlay" v-if="unavailable">
|
||||
<div class="codicon codicon-circle-slash"></div>
|
||||
</div>
|
||||
|
@ -40,6 +39,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="info-rect" :class="{'info-rect-card': kind == 'card'}"
|
||||
v-show="isVisible"
|
||||
:style="{'--bgartwork': getArtworkUrl(size, true)}">
|
||||
<div class="title"
|
||||
:title="item.attributes?.name ?? (item.relationships?.contents?.data[0]?.attributes?.name ?? (item.attributes?.editorialNotes?.name ?? ''))"
|
||||
|
@ -58,7 +58,6 @@
|
|||
</div>
|
||||
<div class="subtitle" v-if="getSubtitle() == '' && kind != 'card'"> </div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -88,6 +87,11 @@
|
|||
default: false,
|
||||
required: false
|
||||
},
|
||||
noScale: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
},
|
||||
'contextExt': { type: Object, required: false },
|
||||
},
|
||||
data: function () {
|
||||
|
@ -252,6 +256,10 @@
|
|||
},
|
||||
getClasses() {
|
||||
let type = []
|
||||
let classes = []
|
||||
if(this.noScale) {
|
||||
classes.push("noscale")
|
||||
}
|
||||
try {
|
||||
type = this.item.type
|
||||
|
||||
|
@ -264,25 +272,26 @@
|
|||
}
|
||||
switch (type) {
|
||||
default:
|
||||
return []
|
||||
|
||||
break;
|
||||
case "editorial-elements":
|
||||
case "card":
|
||||
return ["mediaitem-card"]
|
||||
classes.push("mediaitem-card")
|
||||
break;
|
||||
case "385": // editorial
|
||||
return ["mediaitem-brick"]
|
||||
classes.push("mediaitem-brick")
|
||||
break;
|
||||
case "small":
|
||||
return ["mediaitem-small"]
|
||||
classes.push("mediaitem-small")
|
||||
break;
|
||||
case "music-videos":
|
||||
case "uploadedVideo":
|
||||
case "uploaded-videos":
|
||||
case "library-music-videos":
|
||||
return "mediaitem-video";
|
||||
classes.push("mediaitem-video")
|
||||
break;
|
||||
}
|
||||
return classes
|
||||
},
|
||||
visibilityChanged: function (isVisible, entry) {
|
||||
this.isVisible = isVisible
|
||||
|
@ -534,19 +543,16 @@
|
|||
let followActions = {
|
||||
follow: {
|
||||
icon: "./assets/feather/plus-circle.svg",
|
||||
name: app.getLz('action.follow'),
|
||||
name: app.getLz('action.favorite'),
|
||||
action: () => {
|
||||
self.app.cfg.home.followedArtists.push(this.item.id)
|
||||
self.$root.setArtistFavorite(this.item.id, true)
|
||||
}
|
||||
},
|
||||
unfollow: {
|
||||
icon: "./assets/feather/x-circle.svg",
|
||||
name: app.getLz('action.unfollow'),
|
||||
name: app.getLz('action.removeFavorite'),
|
||||
action: () => {
|
||||
let index = self.app.cfg.home.followedArtists.indexOf(this.item.id)
|
||||
if (index > -1) {
|
||||
self.app.cfg.home.followedArtists.splice(index, 1)
|
||||
}
|
||||
self.$root.setArtistFavorite(this.item.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,30 +66,40 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="control-buttons">
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small shuffle" v-if="app.mk.shuffleMode == 0"
|
||||
@click="app.mk.shuffleMode = 1"></button>
|
||||
<button class="playback-button--small shuffle active" v-else
|
||||
@click="app.mk.shuffleMode = 0"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button previous" @click="app.prevButton()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button pause" @click="app.mk.pause()" v-if="app.mk.isPlaying"></button>
|
||||
<button class="playback-button play" @click="app.mk.play()" v-else></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button next" @click="app.skipToNextItem()"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item">
|
||||
<button class="playback-button--small repeat" v-if="app.mk.repeatMode == 0"
|
||||
@click="app.mk.repeatMode = 1"></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="app.mk.repeatMode = 2"
|
||||
v-else-if="app.mk.repeatMode == 1"></button>
|
||||
<button class="playback-button--small repeat active" @click="app.mk.repeatMode = 0"
|
||||
v-else-if="app.mk.repeatMode == 2"></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small shuffle" v-if="$root.mk.shuffleMode == 0" :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small shuffle active" v-else :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.shuffleMode = 0" :title="$root.getLz('term.disableShuffle')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button previous" @click="$root.prevButton()" :class="$root.isPrevDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button stop" @click="$root.mk.stop()"
|
||||
v-if="$root.mk.isPlaying && $root.mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
|
||||
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button pause" @click="$root.mk.pause()" v-else-if="$root.mk.isPlaying"
|
||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button play" @click="$root.mk.play()" v-else :title="$root.getLz('term.play')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button next" @click="$root.skipToNextItem()" :class="$root.isNextDisabled() && 'disabled'"
|
||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||
</div>
|
||||
<div class="app-chrome-item display--large">
|
||||
<button class="playback-button--small repeat" v-if="$root.mk.repeatMode == 0" :class="$root.isDisabled() && 'disabled'"
|
||||
@click="$root.mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
|
||||
:class="$root.isDisabled() && 'disabled'" v-else-if="$root.mk.repeatMode == 1"
|
||||
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
|
||||
<button class="playback-button--small repeat active" @click="$root.mk.repeatMode = 0"
|
||||
:class="$root.isDisabled() && 'disabled'" v-else-if="$root.mk.repeatMode == 2" :title="$root.getLz('term.disableRepeat')"
|
||||
v-b-tooltip.hover></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-chrome-item volume display--large">
|
||||
<div class="input-container">
|
||||
|
|
|
@ -1,355 +0,0 @@
|
|||
<script type="text/x-template" id="spatial-properties">
|
||||
<div class="modal-fullscreen spatialproperties-panel" @click.self="close()" @contextmenu.self="close()">
|
||||
<div class="modal-window" v-if="ready">
|
||||
<div class="modal-header">
|
||||
<div class="modal-title">{{$root.getLz('spatial.spatialProperties')}}</div>
|
||||
<button class="close-btn" @click="close()" :aria-label="$root.getLz('action.close')"></button>
|
||||
</div>
|
||||
<div class="modal-content">
|
||||
<template v-if="roomEditType == 'dimensions'">
|
||||
<div class="row">
|
||||
<div class="col"><h3>{{$root.getLz('spatial.roomDimensions')}}</h3></div>
|
||||
<div class="col-auto flex-center">
|
||||
<button class="md-btn" @click="roomEditType = 'positions'">{{$root.getLz('spatial.setPositions')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
{{$root.getLz('spatial.width')}}
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="room_dimensions.width" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="room_dimensions.width" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
{{$root.getLz('spatial.height')}}
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="room_dimensions.height" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="room_dimensions.height" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
{{$root.getLz('spatial.depth')}}
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="room_dimensions.depth" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="room_dimensions.depth" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
<label v-if="!app.cfg.audio.normalization">
|
||||
{{$root.getLz('spatial.gain')}}
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;"
|
||||
v-model="app.cfg.audio.spatial_properties.gain" step="0.1"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col visual-container">
|
||||
<div class="visual" :style="objectContainerStyle()">
|
||||
<div class="face" :style="[faceStyle()]"></div>
|
||||
<div class="face" :style="[faceStyle(), topFaceStyle()]"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="roomEditType == 'positions'">
|
||||
<div class="row">
|
||||
<div class="col"><h3>{{$root.getLz('spatial.roomPositions')}}</h3></div>
|
||||
<div class="col-auto flex-center">
|
||||
<button class="md-btn" @click="roomEditType = 'dimensions'">{{$root.getLz('spatial.setDimensions')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
X ({{$root.getLz('spatial.listener')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="listener_position[0]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="listener_position[0]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
Y ({{$root.getLz('spatial.listener')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="listener_position[1]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="listener_position[1]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
Z ({{$root.getLz('spatial.listener')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="listener_position[2]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="listener_position[2]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
X ({{$root.getLz('spatial.audioSource')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="audio_position[0]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="audio_position[0]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
Y ({{$root.getLz('spatial.audioSource')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="audio_position[1]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="audio_position[1]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-3 flex-center">
|
||||
Z ({{$root.getLz('spatial.audioSource')}})
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<input type="range" class="md-slider" min="0" max="100" @change="setRoom()" style="width: 100%;"
|
||||
v-model="audio_position[2]" step="1"/>
|
||||
</div>
|
||||
<div class="col-3 flex-center">
|
||||
<input type="number" min="0" @change="setRoom()" style="width: 100%;text-align: center"
|
||||
v-model="audio_position[2]" step="1"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col visual-container">
|
||||
<div class="visual">
|
||||
<div class="face" :style="[faceStyle()]"></div>
|
||||
<div class="face" :style="[faceStyle(), topFaceStyle()]"></div>
|
||||
|
||||
<!-- <div class="listener" :style="[listenerStyle()]">L</div> -->
|
||||
<!-- <div class="audiosource" :style="[audioSourceStyle()]">A</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="row">
|
||||
<div class="col"><h3>{{$root.getLz('spatial.roomMaterials')}}</h3></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
<div class="col flex-center">
|
||||
<label>
|
||||
{{$root.getLz('spatial.up')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.up">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col flex-center">
|
||||
<label>
|
||||
{{$root.getLz('spatial.left')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.left">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<label>
|
||||
{{$root.getLz('spatial.front')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.front">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
{{$root.getLz('spatial.back')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.back">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col flex-center">
|
||||
<label>
|
||||
{{$root.getLz('spatial.right')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.right">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col"></div>
|
||||
<div class="col flex-center">
|
||||
<label>
|
||||
{{$root.getLz('spatial.down')}}
|
||||
<select class="md-select" @change="setRoom()"
|
||||
v-model="room_materials.down">
|
||||
<option v-for="prop in roomProps" :value="prop">{{ prop }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('spatial-properties', {
|
||||
template: '#spatial-properties',
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
room_dimensions: null,
|
||||
room_materials: null,
|
||||
listener_position: null,
|
||||
audio_position: null,
|
||||
roomEditType: "dimensions",
|
||||
roomProps: [
|
||||
'transparent',
|
||||
'acoustic-ceiling-tiles',
|
||||
'brick-bare',
|
||||
'brick-painted',
|
||||
'concrete-block-coarse',
|
||||
'concrete-block-painted',
|
||||
'curtain-heavy',
|
||||
'fiber-glass-insulation',
|
||||
'glass-thin',
|
||||
'glass-thick',
|
||||
'grass',
|
||||
'linoleum-on-concrete',
|
||||
'marble',
|
||||
'metal',
|
||||
'parquet-on-concrete',
|
||||
'plaster-smooth',
|
||||
'plywood-panel',
|
||||
'polished-concrete-or-tile',
|
||||
'sheetrock',
|
||||
'water-or-ice-surface',
|
||||
'wood-ceiling',
|
||||
'wood-panel',
|
||||
'uniform'
|
||||
],
|
||||
visualMultiplier: 4,
|
||||
ready: false
|
||||
}
|
||||
},
|
||||
props: {},
|
||||
mounted() {
|
||||
this.room_dimensions = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.room_dimensions))
|
||||
this.room_materials = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.room_materials))
|
||||
this.audio_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.audio_position))
|
||||
this.listener_position = JSON.parse(JSON.stringify(this.$root.cfg.audio.spatial_properties.listener_position))
|
||||
if (typeof this.app.mk.nowPlayingItem != "undefined") {
|
||||
this.setRoom()
|
||||
}
|
||||
this.ready = true
|
||||
},
|
||||
methods: {
|
||||
listenerStyle() {
|
||||
let style = {
|
||||
transform: `rotateX(60deg) rotateZ(-45deg) translateX(${this.listener_position[0]}px) translateY(${this.listener_position[2]}px) translateZ(${100 + +this.listener_position[1]}px)`
|
||||
}
|
||||
return style
|
||||
},
|
||||
audioSourceStyle() {
|
||||
let style = {
|
||||
transform: `rotateX(60deg) rotateZ(-45deg) translateX(${this.audio_position[0]}px) translateY(${this.audio_position[2]}px) translateZ(${100 + +this.audio_position[1]}px)`
|
||||
}
|
||||
return style
|
||||
},
|
||||
topFaceStyle() {
|
||||
let style = {
|
||||
transform: `rotateX(60deg) rotateZ(-45deg) translateZ(${this.room_dimensions.height * this.visualMultiplier}px)`
|
||||
}
|
||||
return style
|
||||
},
|
||||
objectContainerStyle() {
|
||||
let scale = 1
|
||||
if (this.room_dimensions.width * this.visualMultiplier > 300) {
|
||||
scale = 300 / (this.room_dimensions.width * this.visualMultiplier)
|
||||
}
|
||||
let style = {
|
||||
transform: `scale(${scale})`
|
||||
}
|
||||
return style
|
||||
},
|
||||
faceStyle() {
|
||||
let style = {
|
||||
width: `${this.room_dimensions.width * this.visualMultiplier}px`,
|
||||
height: `${this.room_dimensions.depth * this.visualMultiplier}px`,
|
||||
}
|
||||
return style
|
||||
},
|
||||
close() {
|
||||
this.$root.cfg.audio.spatial_properties.room_dimensions = this.room_dimensions
|
||||
this.$root.cfg.audio.spatial_properties.room_materials = this.room_materials
|
||||
this.$root.cfg.audio.spatial_properties.audio_position = this.audio_position
|
||||
this.$root.cfg.audio.spatial_properties.listener_position = this.listener_position
|
||||
app.resetState()
|
||||
},
|
||||
setRoom() {
|
||||
window.CiderAudio.audioNodes.spatialNode.setRoomProperties(this.room_dimensions, this.room_materials);
|
||||
CiderAudio.audioNodes.spatialInput.setPosition(...this.audio_position)
|
||||
CiderAudio.audioNodes.spatialNode.setListenerPosition(...this.listener_position)
|
||||
if (!this.app.cfg.audio.normalization) {
|
||||
window.CiderAudio.audioNodes.gainNode.gain.value = app.cfg.audio.spatial_properties.gain
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -58,6 +58,12 @@
|
|||
#LOADER>svg {
|
||||
width: 128px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
#LOADER {
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
@ -65,7 +71,7 @@
|
|||
<div id="LOADER">
|
||||
<%- include("../assets/cider-round.svg") %>
|
||||
</div>
|
||||
<div id="app" :class="getAppClasses()" :window-style="cfg.visual.directives.windowLayout">
|
||||
<div id="app" :class="getAppClasses()" :style="getAppStyle()" :library-visbile="(chrome.sidebarCollapsed ? 0 : 1)" :window-style="cfg.visual.directives.windowLayout">
|
||||
<transition name="fsModeSwitch">
|
||||
<div id="app-main" v-show="appMode == 'player'">
|
||||
<%- include('app/chrome-top'); %>
|
||||
|
@ -85,6 +91,11 @@
|
|||
</mini-view>
|
||||
</div>
|
||||
</transition>
|
||||
<transition name="fsModeSwitch">
|
||||
<div class="fullscreen-view-container oobe" v-if="appMode == 'oobe'">
|
||||
<cider-oobe></cider-oobe>
|
||||
</div>
|
||||
</transition>
|
||||
<%- include('app/panels'); %>
|
||||
<div class="cursor" v-if="chrome.showCursor"></div>
|
||||
</div>
|
||||
|
@ -94,7 +105,8 @@
|
|||
<% } %>
|
||||
|
||||
|
||||
<script async src="https://js-cdn.music.apple.com/musickit/v2/amp/musickit.js"></script>
|
||||
<script async src="<%- (env.useV3 ? "https://js-cdn.music.apple.com/musickit/v3/amp/musickit.js" : "https://js-cdn.music.apple.com/musickit/v2/amp/musickit.js" ) %>" data-web-components>
|
||||
</script>
|
||||
<script src="index.js?v=1"></script>
|
||||
|
||||
<script type="text/x-template" id="am-musiccovershelf">
|
||||
|
@ -104,7 +116,7 @@
|
|||
<!-- Sidebar Item -->
|
||||
<script type="text/x-template" id="sidebar-library-item">
|
||||
<button class="app-sidebar-item"
|
||||
:class="$parent.getSidebarItemClass(page)" @click="$root.appRoute(page)">
|
||||
:class="$parent.getSidebarItemClass(page)" @click="$root.setWindowHash(page)">
|
||||
<div class="sidebar-icon" v-html="svgIconData" v-if="svgIconData != ''"></div>
|
||||
{{ name }}
|
||||
</button>
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
<div class="col nopadding">
|
||||
<h3>{{app.getLz('home.followedArtists')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto nopadding flex-center">
|
||||
<button class="cd-btn-seeall" @click="syncFavorites()" v-if="!syncingFavs">{{app.getLz('home.syncFavorites')}}</button>
|
||||
<div class="spinner" style="height: 26px;" v-else></div>
|
||||
</div>
|
||||
</div>
|
||||
<vue-horizontal>
|
||||
<div v-for="artist in artists" style="margin: 6px;">
|
||||
|
@ -14,7 +18,7 @@
|
|||
<button @click="unfollow(artist.id)" class="md-btn md-btn-glyph" style="display:flex;">
|
||||
<div class="sidebar-icon">
|
||||
<div class="svg-icon" :style="{'--url': 'url(./assets/feather/x-circle.svg)'}"></div>
|
||||
</div> {{app.getLz('action.unfollow')}}
|
||||
</div> {{app.getLz('action.removeFavorite')}}
|
||||
</button>
|
||||
</div>
|
||||
</vue-horizontal>
|
||||
|
@ -53,7 +57,8 @@
|
|||
app: this.$root,
|
||||
followedArtists: this.$root.cfg.home.followedArtists,
|
||||
artistFeed: [],
|
||||
artists: []
|
||||
artists: [],
|
||||
syncingFavs: false
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
@ -61,7 +66,13 @@
|
|||
await this.getArtistFeed()
|
||||
},
|
||||
methods: {
|
||||
unfollow(id) {
|
||||
async syncFavorites() {
|
||||
this.syncingFavs = true
|
||||
await app.syncFavorites()
|
||||
await this.getArtistFeed()
|
||||
this.syncingFavs = false
|
||||
},
|
||||
async unfollow(id) {
|
||||
let index = this.followedArtists.indexOf(id)
|
||||
if (index > -1) {
|
||||
this.followedArtists.splice(index, 1)
|
||||
|
@ -71,6 +82,16 @@
|
|||
if (index2 > -1) {
|
||||
this.artists.splice(index2, 1)
|
||||
}
|
||||
await app.mk.api.v3.music(`/v1/me/favorites`, {
|
||||
"art[url]": "f",
|
||||
"ids[artists]": id,
|
||||
"l": app.mklang,
|
||||
"platform": "web"
|
||||
}, {
|
||||
fetchOptions: {
|
||||
method: "DELETE"
|
||||
}
|
||||
})
|
||||
this.getArtistFeed()
|
||||
},
|
||||
async getArtistFeed() {
|
||||
|
@ -78,7 +99,7 @@
|
|||
let self = this
|
||||
this.artists = []
|
||||
this.artistFeed = []
|
||||
|
||||
|
||||
// Apple limits the number of IDs we can provide in a single API call to 50.
|
||||
// Divide it into groups of 50 and send parallel requests
|
||||
let chunks = []
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
<script type="text/x-template" id="cider-artist">
|
||||
<div class="content-inner artist-page" :class="[data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9) ? 'animated' : '']">
|
||||
<div class="content-inner artist-page"
|
||||
:class="[(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9) || hasHero()) ? 'animated' : '']">
|
||||
<div class="artist-header" :key="data.id" v-observe-visibility="{callback: isHeaderVisible}">
|
||||
<animatedartwork-view
|
||||
:priority="true"
|
||||
v-if="data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)"
|
||||
v-if="hasAnimated()"
|
||||
:video="data.attributes.editorialVideo.motionArtistWide16x9.video ?? (data.attributes.editorialVideo.motionArtistFullscreen16x9.video ?? '')">
|
||||
</animatedartwork-view>
|
||||
<div class="header-content" style="pointer-events: all;">
|
||||
<div class="row">
|
||||
<div class="col-sm" style="width: auto;">
|
||||
<div class="artist-image" v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9))">
|
||||
<div class="artist-image"
|
||||
v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9))&& !hasHero()">
|
||||
<mediaitem-artwork
|
||||
shadow="large"
|
||||
:url="data.attributes.artwork ? data.attributes.artwork.url : ''"
|
||||
size="190" type="artists"></mediaitem-artwork>
|
||||
<button class="overlay-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
<button class="overlay-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
})" :aria-label="app.getLz('term.play')">
|
||||
<%- include("../svg/play.svg") %>
|
||||
|
@ -22,7 +24,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col flex-center artist-title"
|
||||
:class="{'artist-animation-on': (data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)) }"
|
||||
:class="{'artist-animation-on': (data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)) || hasHero() }"
|
||||
>
|
||||
<button class="artist-play" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
app.mk.play()
|
||||
|
@ -30,15 +32,25 @@
|
|||
<h1>{{ data.attributes.name }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<button class="more-btn-round" @click="artistMenu" style="pointer-events: all;" :aria-label="app.getLz('term.more')">
|
||||
<button class="more-btn-round favorite" @click="artistMenu" style="pointer-events: all;"
|
||||
:aria-label="app.getLz('term.more')">
|
||||
<div class="svg-icon"></div>
|
||||
</button>
|
||||
<button class="more-btn-round menu" @click="artistMenu" style="pointer-events: all;"
|
||||
:aria-label="app.getLz('term.more')">
|
||||
<div class="svg-icon"></div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="artworkContainer" v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9))">
|
||||
<artwork-material :url="data.attributes.artwork.url" size="190" images="1"></artwork-material>
|
||||
<div class="artworkContainer"
|
||||
v-if="!(data.attributes.editorialVideo && (data.attributes.editorialVideo.motionArtistWide16x9 || data.attributes.editorialVideo.motionArtistFullscreen16x9)) && !hasHero()">
|
||||
<artwork-material :url="data.attributes.artwork.url" size="190" images="1"></artwork-material>
|
||||
</div>
|
||||
<div class="artist-hero" v-if="hasHero() && !hasAnimated()">
|
||||
<mediaitem-artwork shadow="none" :url="hasHero()" size="2048" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="floating-header" :style="{opacity: (headerVisible ? 0 : 1),'pointer-events': (headerVisible ? 'none' : '')}">
|
||||
<div class="floating-header"
|
||||
:style="{opacity: (headerVisible ? 0 : 1),'pointer-events': (headerVisible ? 'none' : '')}">
|
||||
<div class="row">
|
||||
<div class="col-auto flex-center">
|
||||
<button class="artist-play" style="display:block;" @click="app.mk.setStationQueue({artist:'a-'+data.id}).then(()=>{
|
||||
|
@ -49,7 +61,7 @@
|
|||
<h3>{{ data.attributes.name }}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<button class="more-btn-round" @click="artistMenu" :aria-label="app.getLz('term.more')">
|
||||
<button class="more-btn-round menu" @click="artistMenu" :aria-label="app.getLz('term.more')">
|
||||
<div class="svg-icon"></div>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -60,8 +72,8 @@
|
|||
<div class="latestRelease" v-if="data.views['latest-release'].data.length != 0">
|
||||
<h3>{{app.getLz('term.latestReleases')}}</h3>
|
||||
<div style="width: auto;margin: 0 auto;">
|
||||
<mediaitem-square kind="card" v-for="song in data.views['latest-release'].data"
|
||||
:item="song">
|
||||
<mediaitem-square kind="card" :no-scale="true" v-for="song in data.views['latest-release'].data"
|
||||
:item="song">
|
||||
</mediaitem-square>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -70,8 +82,12 @@
|
|||
<div class="col" style="padding:0;">
|
||||
<h3>{{app.getLz('term.topSongs')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 20" style="padding:0;">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - Top Songs', 'top-songs')">{{app.getLz('term.seeAll')}}</button>
|
||||
<div class="col-auto flex-center" v-if="data.views['top-songs'].data.length >= 20"
|
||||
style="padding:0;">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showArtistView(data.id, data.attributes.name + ' - Top Songs', 'top-songs')">
|
||||
{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
@ -96,23 +112,27 @@
|
|||
</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="data.views[view].data.length >= 10">
|
||||
<button class="cd-btn-seeall" @click="app.showArtistView(data.id, data.attributes.name + ' - ' + data.views[view].attributes.title, view)">{{app.getLz('term.seeAll')}}</button>
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showArtistView(data.id, data.attributes.name + ' - ' + data.views[view].attributes.title, view)">
|
||||
{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!((data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('Video') || (data.views[view].attributes.title ?
|
||||
data.views[view].attributes.title : '???').includes('More To See'))">
|
||||
<mediaitem-scroller-horizontal-large :items="data.views[view].data.limit(10)">
|
||||
</mediaitem-scroller-horizontal-large>
|
||||
<mediaitem-scroller-horizontal-large :items="data.views[view].data.limit(10)">
|
||||
</mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="data.views[view].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
:items="data.views[view].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
<div class="row">
|
||||
<div class="col" v-if="data.attributes.artistBio">
|
||||
<h3>{{ $root.stringTemplateParser($root.getLz('term.aboutArtist'), {"artistName": data.attributes.name}) }}</h3>
|
||||
<h3>{{ $root.stringTemplateParser($root.getLz('term.aboutArtist'), {"artistName":
|
||||
data.attributes.name}) }}</h3>
|
||||
<p v-html="data.attributes.artistBio"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
|
@ -147,24 +167,40 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
hasAnimated() {
|
||||
if(this.data.attributes?.editorialVideo && (this.data.attributes?.editorialVideo?.motionArtistWide16x9 || this.data.attributes?.editorialVideo?.motionArtistFullscreen16x9)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
hasHero() {
|
||||
if(this.data.attributes?.editorialArtwork?.centeredFullscreenBackground){
|
||||
return this.data.attributes?.editorialArtwork?.centeredFullscreenBackground.url
|
||||
} else if(this.data.attributes?.editorialArtwork?.bannerUber) {
|
||||
return this.data.attributes?.editorialArtwork?.bannerUber.url
|
||||
}else if(this.data.attributes?.editorialArtwork?.subscriptionHero){
|
||||
return this.data.attributes?.editorialArtwork?.subscriptionHero.url
|
||||
}
|
||||
return false;
|
||||
},
|
||||
isHeaderVisible(visible) {
|
||||
this.headerVisible = visible
|
||||
},
|
||||
artistMenu (event) {
|
||||
async artistMenu(event) {
|
||||
let self = this
|
||||
let followAction = "follow"
|
||||
let followActions = {
|
||||
follow: {
|
||||
icon: "./assets/feather/plus-circle.svg",
|
||||
name: app.getLz('action.follow'),
|
||||
action: ()=>{
|
||||
action: () => {
|
||||
self.app.cfg.home.followedArtists.push(self.data.id)
|
||||
}
|
||||
},
|
||||
unfollow: {
|
||||
icon: "./assets/feather/x-circle.svg",
|
||||
name: app.getLz('action.unfollow'),
|
||||
action: ()=>{
|
||||
action: () => {
|
||||
let index = self.app.cfg.home.followedArtists.indexOf(self.data.id)
|
||||
if (index > -1) {
|
||||
self.app.cfg.home.followedArtists.splice(index, 1)
|
||||
|
@ -172,25 +208,45 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
let favoriteActions = {
|
||||
favorite: {
|
||||
icon: "./assets/star.svg",
|
||||
name: app.getLz('action.favorite'),
|
||||
action: () => {
|
||||
app.setArtistFavorite(app.artistPage.data.id, true)
|
||||
}
|
||||
},
|
||||
removeFavorite: {
|
||||
icon: "./assets/star.svg",
|
||||
name: app.getLz('action.removeFavorite'),
|
||||
action: () => {
|
||||
app.setArtistFavorite(app.artistPage.data.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.app.cfg.home.followedArtists.includes(self.data.id)) {
|
||||
followAction = "unfollow"
|
||||
}
|
||||
const inFavorites = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${app.artistPage.data.id}`, {
|
||||
"fields[artists]": "inFavorites"
|
||||
})).data.data[0].attributes?.inFavorites
|
||||
app.showMenuPanel({
|
||||
items: [
|
||||
{
|
||||
icon: "./assets/feather/play.svg",
|
||||
name: app.getLz('action.startRadio'),
|
||||
action: ()=>{
|
||||
app.mk.setStationQueue({artist:self.data.id}).then(()=>{
|
||||
action: () => {
|
||||
app.mk.setStationQueue({artist: self.data.id}).then(() => {
|
||||
app.mk.play()
|
||||
})
|
||||
}
|
||||
},
|
||||
followActions[followAction],
|
||||
favoriteActions[inFavorites ? "removeFavorite" : "favorite"],
|
||||
// followActions[followAction],
|
||||
{
|
||||
icon: "./assets/feather/share.svg",
|
||||
name: app.getLz('term.share'),
|
||||
action: ()=>{
|
||||
action: () => {
|
||||
self.app.copyToClipboard(self.data.attributes.url)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,12 @@
|
|||
<select class="md-select" style="width:180px;"
|
||||
v-model="app.cfg.audio.maikiwiAudio.ciderPPE_value"
|
||||
v-on:change="CiderAudio.hierarchical_loading()">
|
||||
<option value="MAIKIWI">Maikiwi</option>
|
||||
<option value="MAIKIWI">Maikiwi ({{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.adaptive')}})</option>
|
||||
<option value="MAIKIWI_LEGACY">Maikiwi ({{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.legacy')}})</option>
|
||||
<option value="NATURAL">
|
||||
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.standard')}}
|
||||
</option>
|
||||
<option value="LEGACY">{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPEStrength.legacy')}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -100,7 +102,7 @@
|
|||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" v-model="app.cfg.audio.maikiwiAudio.spatial"
|
||||
v-on:change="toggleMaikiwiSpatial" switch/>
|
||||
v-on:change="CiderAudio.hierarchical_loading();" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line"
|
||||
|
@ -113,7 +115,7 @@
|
|||
<div class="md-option-segment md-option-segment_auto">
|
||||
<select class="md-select" style="width:180px;"
|
||||
v-model="$root.cfg.audio.maikiwiAudio.spatialProfile"
|
||||
v-on:change="toggleMaikiwiSpatial">
|
||||
v-on:change="CiderAudio.hierarchical_loading();">
|
||||
<option v-for="profile in spprofiles" :value="profile.id">{{ getProfileLz("CTS", profile.name) }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -170,11 +172,10 @@
|
|||
},
|
||||
methods: {
|
||||
getProfileLz(type, name) {
|
||||
let result = "";
|
||||
|
||||
// Hard-coded shiz
|
||||
switch (name) {
|
||||
case "CRYPTO":
|
||||
return "Cryptofyre";
|
||||
break;
|
||||
|
||||
case "Maikiwi":
|
||||
return "Maikiwi";
|
||||
break;
|
||||
|
@ -183,43 +184,33 @@
|
|||
return "Maikiwi+";
|
||||
break;
|
||||
|
||||
case "Minimal+":
|
||||
return this.$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.minimal') + "+";
|
||||
break;
|
||||
|
||||
case "live":
|
||||
return "LIVE";
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
case "CAR":
|
||||
return this.$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.' + name);
|
||||
result = this.$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.' + name);
|
||||
if (result === "settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode." + name) {
|
||||
return name;
|
||||
}
|
||||
else {return result;}
|
||||
break;
|
||||
case "CTS":
|
||||
return this.$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.' + name.toLowerCase());
|
||||
result = this.$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.' + name.toLowerCase());
|
||||
if (result === "settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile." + name.toLowerCase()) {
|
||||
return name;
|
||||
}
|
||||
else {return result;}
|
||||
break;
|
||||
default:
|
||||
return name;
|
||||
}
|
||||
},
|
||||
toggleSpatial: function () {
|
||||
if (app.cfg.audio.maikiwiAudio.spatial) {
|
||||
CiderAudio.spatialOn()
|
||||
CiderAudio.hierarchical_loading();
|
||||
} else {
|
||||
CiderAudio.spatialOff()
|
||||
}
|
||||
},
|
||||
toggleMaikiwiSpatial: function () {
|
||||
if (app.cfg.audio.maikiwiAudio.spatial === true) {
|
||||
CiderAudio.spatialOn()
|
||||
CiderAudio.hierarchical_loading();
|
||||
//let normalized = Math.pow(10, (((Math.log10(app.mk.volume) * 20) - 14) / 20));
|
||||
//app.mk.volume = normalized
|
||||
// -13dBFS Target
|
||||
} else {
|
||||
//let normalized = Math.pow(10, (((Math.log10(app.mk.volume) * 20) + 14) / 20));
|
||||
//app.mk.volume = normalized
|
||||
CiderAudio.spatialOn()
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
133
src/renderer/views/pages/charts.ejs
Normal file
133
src/renderer/views/pages/charts.ejs
Normal file
|
@ -0,0 +1,133 @@
|
|||
<script type="text/x-template" id="cider-charts">
|
||||
<div class="content-inner">
|
||||
<h1 class="header-text">{{$root.getLz("term.charts")}}</h1>
|
||||
<template v-if="songs != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ songs.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="songs.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((songs ?? []), songs.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mediaitem-list-item__grid">
|
||||
<listitem-horizontal :items="(songs?.data ?? []).limit(12)">
|
||||
</listitem-horizontal>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="albums != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ albums.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="songs.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((albums ?? []), albums.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="(albums?.data ?? []).limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="playlists != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ playlists.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="playlists.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((playlists ?? []), playlists.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="(playlists?.data ?? []).limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="musicvideos != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ musicvideos.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="musicvideos.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((musicvideos ?? []), musicvideos.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="(musicvideos?.data ?? []).limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="globalcharts != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ globalcharts.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="globalcharts.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((globalcharts ?? []), globalcharts.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="(globalcharts?.data ?? []).limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="citycharts != []">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ citycharts.name ?? ""}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="citycharts.data.length > 12">
|
||||
<button class="cd-btn-seeall" @click="app.showCollection((citycharts ?? []), citycharts.name ?? '', 'default')" >{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="(citycharts?.data ?? []).limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('cider-charts', {
|
||||
template: "#cider-charts",
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root,
|
||||
songs: [],
|
||||
albums: [],
|
||||
playlists: [],
|
||||
musicvideos: [],
|
||||
citycharts: [],
|
||||
globalcharts: [],
|
||||
categories: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
let self = this;
|
||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/charts`, {
|
||||
types: 'albums,songs,music-videos,playlists',
|
||||
l: 'en-gb',
|
||||
platform: 'auto',
|
||||
limit: '50',
|
||||
genre: '34',
|
||||
include: 'tracks',
|
||||
with: 'cityCharts,dailyGlobalTopCharts',
|
||||
extend: 'artistUrl',
|
||||
'fields[albums]': 'artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url',
|
||||
'fields[playlists]': 'artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url,curatorName'
|
||||
}).then(res => {
|
||||
let page = res.data?.results ?? [];
|
||||
self.songs = page.songs[0] ?? [];
|
||||
self.albums = page.albums[0] ?? [];
|
||||
self.playlists = page.playlists[0] ?? [];
|
||||
self.musicvideos = page['music-videos'][0] ?? [];
|
||||
self.citycharts = page.cityCharts[0] ?? [];
|
||||
self.globalcharts = page.dailyGlobalTopCharts[0] ?? [];
|
||||
})
|
||||
// let self = this;
|
||||
// app.mk.api.music(`/v1/catalog/${app.mk.storefrontId}/charts?types=songs%2Calbums%2Cplaylists&limit=36`).then(res => {
|
||||
// let page = res.data?.results ?? [];
|
||||
// self.songs = page.songs[0] ?? [];
|
||||
// self.albums = page.albums[0] ?? [];
|
||||
// self.playlists = page.playlists[0] ?? [];
|
||||
// })
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -80,7 +80,7 @@
|
|||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="playlist-controls" v-observe-visibility="{callback: isHeaderVisible}">
|
||||
<div class="playlist-controls" v-observe-visibility="{callback: isHeaderVisible}" style="z-index: 20;">
|
||||
<button class="md-btn md-btn-primary md-btn-icon" style="min-width: 100px;"
|
||||
@click="app.mk.shuffleMode = 0; play()"><img class="md-ico-play">
|
||||
{{app.getLz('term.play')}}
|
||||
|
@ -121,7 +121,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="artworkContainer" v-if="data.attributes.artwork != null">
|
||||
<artwork-material :url="data.attributes.artwork.url" size="260" images="1"></artwork-material>
|
||||
<artwork-material :url="data.attributes.artwork.url" size="500" images="1"></artwork-material>
|
||||
</div>
|
||||
<button class="md-btn md-btn-small editTracksBtn" v-if="(data.attributes.canEdit && data.type == 'library-playlists')" @click="editing = !editing">
|
||||
<span v-if="!editing">
|
||||
|
@ -648,39 +648,11 @@
|
|||
app.copyToClipboard(res.data.data[0].attributes.url)
|
||||
})
|
||||
}
|
||||
},
|
||||
"follow": {
|
||||
name: app.getLz('action.follow'),
|
||||
icon: "./assets/feather/plus-circle.svg",
|
||||
hidden: false,
|
||||
action: () => {
|
||||
app.followArtistById(artistId, true)
|
||||
}
|
||||
},
|
||||
"unfollow": {
|
||||
name: app.getLz('action.unfollow'),
|
||||
icon: "./assets/feather/x-circle.svg",
|
||||
hidden: true,
|
||||
action: () => {
|
||||
app.followArtistById(artistId, false)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
app.showMenuPanel(menuItems, event)
|
||||
|
||||
if (artistId != null) {
|
||||
if (app.followingArtist(artistId)) {
|
||||
menuItems.items.follow.hidden = true
|
||||
menuItems.items.unfollow.hidden = false
|
||||
} else {
|
||||
menuItems.items.follow.hidden = false
|
||||
menuItems.items.unfollow.hidden = true
|
||||
}
|
||||
} else {
|
||||
menuItems.items.follow.hidden = true
|
||||
menuItems.items.unfollow.hidden = true
|
||||
}
|
||||
try {
|
||||
let rating = await app.getRating(self.data)
|
||||
if (rating == 0) {
|
||||
|
|
|
@ -58,19 +58,33 @@
|
|||
},
|
||||
methods: {
|
||||
getClasses() {
|
||||
if(this.commonKind != "song") {
|
||||
return "collection-list-square";
|
||||
}else{
|
||||
if ((this.data?.data?.length ?? 0) > 0) {
|
||||
let item = this.data.data[0]
|
||||
if (typeof item.kind != "undefined") {
|
||||
this.commonKind = item.kind;
|
||||
return item.kind
|
||||
}
|
||||
if (typeof item.attributes.playParams != "undefined") {
|
||||
this.commonKind = item.attributes.playParams.kind
|
||||
return item.attributes.playParams.kind
|
||||
}
|
||||
if (this.commonKind != "song") {
|
||||
return "collection-list-square";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
},
|
||||
getKind(item) {
|
||||
if (typeof item.kind != "undefined") {
|
||||
this.commonKind = item.kind;
|
||||
// this.commonKind = item.kind;
|
||||
return item.kind
|
||||
}
|
||||
if (typeof item.attributes.playParams != "undefined") {
|
||||
this.commonKind = item.attributes.playParams.kind
|
||||
// this.commonKind = item.attributes.playParams.kind
|
||||
return item.attributes.playParams.kind
|
||||
}
|
||||
return this.commonKind
|
||||
|
|
|
@ -61,18 +61,28 @@
|
|||
};
|
||||
},
|
||||
async mounted() {
|
||||
const queryDefaults = `?platform=web&l=en-us&extend=editorialArtwork%2CartistUrl&omit%5Bresource%3Aartists%5D=relationships&include[groupings]=curator&include[albums]=artists&include[songs]=artists&include[music-videos]=artists&fields%5Bartists%5D=name%2Curl%2Cartwork%2CeditorialArtwork%2CgenreNames%2CeditorialNotes`
|
||||
const queryDefaults = {
|
||||
"platform": "web",
|
||||
"l" : this.$root.mklang,
|
||||
"extend": "editorialArtwork,artistUrl",
|
||||
"omit[resource:artists]": "relationships",
|
||||
"include[groupings]": "curator",
|
||||
"include[albums]": "artists",
|
||||
"include[songs]": "artists",
|
||||
"include[music-videos]": "artists",
|
||||
"fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes",
|
||||
}
|
||||
const hash = window.location.hash;
|
||||
// get everything after the first / character but keep everything afterwards
|
||||
const query = hash.substring(hash.indexOf("/") + 1);
|
||||
const query = hash.substring(hash.indexOf("/") + 1, hash.indexOf("&") > 0 ? hash.indexOf("&") : hash.length);
|
||||
this.query = query;
|
||||
if(!this.query.includes("?")) {
|
||||
this.query += queryDefaults;
|
||||
}
|
||||
// if(!this.query.includes("?")) {
|
||||
// this.query += queryDefaults;
|
||||
// }
|
||||
console.debug(query);
|
||||
const result = await this.$root.mk.api.v3.music(
|
||||
`/v1/editorial/${this.$root.mk.storefrontId}/groupings/${this.query}`
|
||||
);
|
||||
,!this.query.includes("&") ? queryDefaults : {"platform": "web"});
|
||||
this.data = result.data.data[0];
|
||||
|
||||
console.log(this.data);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
<h3>{{app.getLz('home.artistsFeed')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto nopadding flex-center">
|
||||
<button class="cd-btn-seeall" @click="syncFavorites()" v-if="!syncingFavs">{{app.getLz('home.syncFavorites')}}</button>
|
||||
<div class="spinner" style="height: 26px;" v-else></div>
|
||||
<button class="cd-btn-seeall" @click="app.appRoute('artist-feed')">{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -113,7 +115,8 @@
|
|||
page: "main",
|
||||
sectionsReady: [],
|
||||
year: new Date().getFullYear(),
|
||||
seenReplay: localStorage.getItem('seenReplay')
|
||||
seenReplay: localStorage.getItem('seenReplay'),
|
||||
syncingFavs: false
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
@ -128,6 +131,12 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
async syncFavorites() {
|
||||
this.syncingFavs = true
|
||||
await app.syncFavorites()
|
||||
await this.getArtistFeed()
|
||||
this.syncingFavs = false
|
||||
},
|
||||
async seeAllRecentlyPlayed() {
|
||||
let hist = await app.mk.api.v3.music(`/v1/me/recent/played`, {
|
||||
l: this.$root.mklang,
|
||||
|
@ -188,7 +197,7 @@
|
|||
async getArtistFeed() {
|
||||
let artists = this.followedArtists
|
||||
let self = this
|
||||
|
||||
this.artistFeed = []
|
||||
let chunks = []
|
||||
for (let artistIdx = 0; artistIdx < artists.length; artistIdx += 50) {
|
||||
chunks.push(artists.slice(artistIdx, artistIdx + 50));
|
||||
|
|
|
@ -226,10 +226,10 @@
|
|||
name: "Reduce Visuals",
|
||||
file: "reduce_visuals.less"
|
||||
})
|
||||
themes.unshift({
|
||||
name: "Inline Drawer",
|
||||
file: "inline_drawer.less"
|
||||
})
|
||||
// themes.unshift({
|
||||
// name: "Inline Drawer",
|
||||
// file: "inline_drawer.less"
|
||||
// })
|
||||
themes.unshift({
|
||||
name: "Dark",
|
||||
file: "dark.less"
|
||||
|
|
|
@ -170,6 +170,11 @@
|
|||
Vue.component('keybinds-settings', {
|
||||
template: "#keybinds-settings",
|
||||
props: [],
|
||||
data: function () {
|
||||
return {
|
||||
app: this.$root
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
keyBindUpdate: function (action) {
|
||||
const blur = document.createElement('div');
|
||||
|
@ -230,14 +235,14 @@
|
|||
app.cfg.general.keybindings.browse = [app.platform == "darwin" ? "Command" : "Control", "B"];
|
||||
app.cfg.general.keybindings.recentAdd = [app.platform == "darwin" ? "Command" : "Control", "G"];
|
||||
app.cfg.general.keybindings.songs = [app.platform == "darwin" ? "Command" : "Control", "J"];
|
||||
app.cfg.general.keybindings.albums = [app.platform == "darwin" ? "Command" : "Control", "S"];
|
||||
app.cfg.general.keybindings.albums = [app.platform == "darwin" ? "Command" : "Control", "A"];
|
||||
app.cfg.general.keybindings.artists = [app.platform == "darwin" ? "Command" : "Control", "D"];
|
||||
app.cfg.general.keybindings.togglePrivateSession = [app.platform == "darwin" ? "Command" : "Control", "P"];
|
||||
app.cfg.general.keybindings.webRemote = [app.platform == "darwin" ? "Command" : "Control", "W"];
|
||||
app.cfg.general.keybindings.audioSettings = [app.platform == "darwin" ? "Option" : "Alt", "A"];
|
||||
app.cfg.general.keybindings.pluginMenu = [app.platform == "darwin" ? "Option" : "Alt", "P"];
|
||||
app.cfg.general.keybindings.castToDevices = [app.platform == "darwin" ? "Option" : "Alt", "C"];
|
||||
app.cfg.general.keybindings.settings = [app.platform == "darwin" ? "Option" : "Alt", "S"];
|
||||
app.cfg.general.keybindings.webRemote = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "W"];
|
||||
app.cfg.general.keybindings.audioSettings = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "A"];
|
||||
app.cfg.general.keybindings.pluginMenu = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "P"];
|
||||
app.cfg.general.keybindings.castToDevices = [app.platform == "darwin" ? "Command" : "Control",app.platform == "darwin" ? "Option" : (app.platform == "linux" ? "Shift" : "Alt"), "C"];
|
||||
app.cfg.general.keybindings.settings = [app.platform == "darwin" ? "Command" : "Control", ","];
|
||||
app.cfg.general.keybindings.openDeveloperTools = [app.platform == "darwin" ? "Command" : "Control", app.platform == "darwin" ? "Option" : "Shift", "I"];
|
||||
notyf.success(app.getLz('settings.notyf.general.keybindings.update.success'));
|
||||
bootbox.confirm(app.getLz("settings.prompt.general.keybindings.update.success"), (ok) => {
|
||||
|
|
|
@ -1,58 +1,70 @@
|
|||
<template v-if="page == 'library-recentlyadded'">
|
||||
<script type="text/x-template" id="cider-recentlyadded">
|
||||
<div class="content-inner">
|
||||
<div class="row">
|
||||
<div class="col" style="padding:0;">
|
||||
<h1 class="header-text">{{$root.getLz('term.recentlyAdded')}}</h1>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<button v-if="library.albums.downloadState == 2" @click="getLibraryAlbumsFull(true, 0)"
|
||||
class="reload-btn" :aria-label="app.getLz('menubar.options.reload')"><%- include('../svg/redo.svg') %></button>
|
||||
</div>
|
||||
<h1 class="header-text">{{$root.getLz('term.recentlyAdded')}}</h1>
|
||||
<div class="well itemContainer" v-if="itemSize == 'normal'">
|
||||
<mediaitem-square v-for="item in items" :item="item"></mediaitem-square>
|
||||
</div>
|
||||
<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="$root.getLz('term.search') + '...'"
|
||||
@input="searchLibraryAlbums"
|
||||
v-model="library.albums.search" class="search-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.sortOrder[0]"
|
||||
@change="searchLibraryAlbums(0)">
|
||||
<optgroup :label="$root.getLz('term.sortOrder')">
|
||||
<option value="asc">{{$root.getLz('term.sortOrder.ascending')}}</option>
|
||||
<option value="desc">{{$root.getLz('term.sortOrder.descending')}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<select class="md-select" v-model="library.albums.viewAs">
|
||||
<optgroup :label="$root.getLz('term.viewAs')">
|
||||
<option value="covers">{{$root.getLz('term.viewAs.coverArt')}}</option>
|
||||
<option value="list">{{$root.getLz('term.viewAs.list')}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="well itemContainer" v-else="itemSize == 'compact'">
|
||||
<mediaitem-list-item :show-meta-data="true" :show-library-status="false" v-for="item in items" :item="item"></mediaitem-list-item>
|
||||
</div>
|
||||
<div class="well">
|
||||
<div class="albums-square-container">
|
||||
<mediaitem-square v-if="library.albums.viewAs == 'covers'" :item="item"
|
||||
v-for="item in library.albums.displayListing">
|
||||
</mediaitem-square>
|
||||
</div>
|
||||
<mediaitem-list-item v-if="library.albums.viewAs == 'list'" :show-duration="false" :show-meta-data="true"
|
||||
:show-library-status="false" :item="item"
|
||||
v-for="item in library.albums.displayListing">
|
||||
</mediaitem-list-item>
|
||||
<div class="well itemContainer" v-show="loading">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
<button v-if="nextUrl && !loading" style="opacity:0;height: 32px;" v-observe-visibility="{callback: visibilityChanged}">{{$root.getLz('term.showMore')}}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component("cider-recentlyadded", {
|
||||
template: "#cider-recentlyadded",
|
||||
computed: {
|
||||
items() {
|
||||
return this.$store.state.pageState['recentlyAdded'].items;
|
||||
},
|
||||
nextUrl() {
|
||||
return this.$store.state.pageState['recentlyAdded'].nextUrl;
|
||||
},
|
||||
itemSize() {
|
||||
return this.$store.state.pageState['recentlyAdded'].size
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
loading: false,
|
||||
firstRoute: `/v1/me/library/recently-added?l=${app.mklang}&platform=web&include[library-albums]=artists&include[library-artists]=catalog&fields[artists]=url&fields%5Balbums%5D=artistName%2CartistUrl%2Cartwork%2CcontentRating%2CeditorialArtwork%2Cname%2CplayParams%2CreleaseDate%2Curl&includeOnly=catalog%2Cartists&limit=25`
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if(this.$store.state.pageState['recentlyAdded'].items.length !== 0) return
|
||||
|
||||
const firstResult = await app.mk.api.v3.music(this.firstRoute)
|
||||
this.$store.state.pageState["recentlyAdded"].items = firstResult.data.data
|
||||
this.$store.state.pageState["recentlyAdded"].nextUrl = firstResult.data.next
|
||||
},
|
||||
beforeDestroy() {
|
||||
// this.$store.state.pageState["recently-added"].scrollPosY = $("#app-content").scrollTop()
|
||||
},
|
||||
methods: {
|
||||
visibilityChanged: function(isVisible, entry) {
|
||||
if (isVisible && !this.loading) {
|
||||
this.getNextData();
|
||||
}
|
||||
},
|
||||
async getNextData() {
|
||||
if (this.$store.state.pageState["recentlyAdded"].nextUrl) {
|
||||
this.loading = true;
|
||||
const nextResult = await app.mk.api.v3.music(this.$store.state.pageState["recentlyAdded"].nextUrl)
|
||||
this.$store.state.pageState["recentlyAdded"].items = this.$store.state.pageState["recentlyAdded"].items.concat(nextResult.data.data)
|
||||
if (nextResult.data.next) {
|
||||
this.$store.state.pageState["recentlyAdded"].nextUrl = nextResult.data.next
|
||||
} else {
|
||||
this.$store.state.pageState["recentlyAdded"].nextUrl = null
|
||||
}
|
||||
this.loading = false;
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
179
src/renderer/views/pages/oobe.ejs
Normal file
179
src/renderer/views/pages/oobe.ejs
Normal file
|
@ -0,0 +1,179 @@
|
|||
<script type="text/x-template" id="cider-oobe">
|
||||
<div class="content-inner oobe">
|
||||
<!-- before_we_start-->
|
||||
<!-- <transition name=""> -->
|
||||
<div class="oobe-view" v-if="screen == 'before_we_start'">
|
||||
<div class="oobe-header">
|
||||
{{ getLz("oobe.amupsell.title") }}
|
||||
</div>
|
||||
<div class="oobe-body text">{{ getLz("oobe.amupsell.text") }}</div>
|
||||
<div class="oobe-footer">
|
||||
<div class="btn-group">
|
||||
<div class="md-btn" @click="screen = 'welcome'">{{ getLz("oobe.next") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </transition> -->
|
||||
|
||||
<!-- Welcome -->
|
||||
<!-- <transition name=""> -->
|
||||
<div class="oobe-view" v-if="screen == 'welcome'">
|
||||
<div class="oobe-header">
|
||||
{{ getLz("oobe.intro.title") }}
|
||||
</div>
|
||||
<div class="oobe-body text">{{ getLz("oobe.intro.text") }}</div>
|
||||
<div class="oobe-footer">
|
||||
<div class="btn-group">
|
||||
<div class="md-btn" @click="screen = 'before_we_start'">{{ getLz("oobe.previous") }}</div>
|
||||
<div class="md-btn" @click="screen = 'general'">{{ getLz("oobe.next") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </transition> -->
|
||||
|
||||
<!-- General -->
|
||||
<!-- <transition name=""> -->
|
||||
<div class="oobe-view" v-if="screen == 'general'">
|
||||
<div class="oobe-header">
|
||||
{{ getLz("oobe.general.title") }}
|
||||
</div>
|
||||
<div class="oobe-body text">{{ getLz("oobe.general.text") }}</div>
|
||||
<div class="oobe-footer">
|
||||
<div class="btn-group">
|
||||
<div class="md-btn" @click="screen = 'welcome'">{{ getLz("oobe.previous") }}</div>
|
||||
<div class="md-btn" @click="screen = 'visual'">{{ getLz("oobe.next") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </transition> -->
|
||||
|
||||
<!-- Visual -->
|
||||
<!-- <transition name=""> -->
|
||||
<div class="oobe-view" v-if="screen == 'visual'">
|
||||
<div class="oobe-header">
|
||||
{{ getLz("oobe.visual.title") }}
|
||||
</div>
|
||||
<div class="oobe-body visual">
|
||||
<b-row>
|
||||
<b-col>
|
||||
<div class="card bg-dark text-white stylePicker" @click="$root.cfg.visual.directives.windowLayout = 'twopanel'" :class="{'style-active': ($root.cfg.visual.directives.windowLayout == 'twopanel')}">
|
||||
<div class="card-body">
|
||||
<img class="visualPreview" src="./assets/oobe/mojave.png" alt="TEMP">
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Mojave
|
||||
</div>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<div class="card bg-dark text-white stylePicker" @click="$root.cfg.visual.directives.windowLayout = 'default'" :class="{'style-active': ($root.cfg.visual.directives.windowLayout == 'default')}">
|
||||
<div class="card-body">
|
||||
<img class="visualPreview" src="./assets/oobe/maverick.png" alt="TEMP">
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Maverick
|
||||
</div>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div class="blurb">{{getLz("oobe.visual.layout.text")}}</div>
|
||||
</div>
|
||||
<div class="oobe-footer">
|
||||
<div class="btn-group">
|
||||
<div class="md-btn" @click="screen = 'general'">{{ getLz("oobe.previous") }}</div>
|
||||
<div class="md-btn" @click="screen = 'audio'">{{ getLz("oobe.next") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </transition> -->
|
||||
|
||||
<!-- Audio -->
|
||||
<!-- <transition name=""> -->
|
||||
<div class="oobe-view" v-if="screen == 'audio'">
|
||||
<div class="oobe-header">
|
||||
{{ getLz("oobe.audio.title") }}
|
||||
</div>
|
||||
<div class="oobe-body">
|
||||
<div class="blurb">{{ getLz("oobe.audio.text") }}</div>
|
||||
<div class="md-option-container">
|
||||
<div class="settings-option-body">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{getLz('settings.option.audio.enableAdvancedFunctionality')}}
|
||||
<br>
|
||||
<small>{{getLz('settings.option.audio.enableAdvancedFunctionality.description')}}</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="$root.cfg.advanced.AudioContext"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="$root.cfg.advanced.AudioContext === true">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE')}}
|
||||
<br>
|
||||
<small>{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE.description')}}</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<input type="checkbox" v-model="$root.cfg.audio.maikiwiAudio.ciderPPE"
|
||||
switch/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oobe-footer">
|
||||
<div class="btn-group">
|
||||
<div class="md-btn" @click="screen = 'visual'">{{ getLz("oobe.previous") }}</div>
|
||||
<div class="md-btn" @click="signIn()">{{ getLz("oobe.next") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </transition> -->
|
||||
<div class="oobe-view" v-if="screen == 'signin'">
|
||||
<div class="oobe-header">
|
||||
Sign in with Apple Music
|
||||
</div>
|
||||
<div class="oobe-body">
|
||||
<div class="blurb"></div>
|
||||
</div>
|
||||
<div class="oobe-footer">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="oobe-titlebar">
|
||||
<div class="button-group" v-if="$root.platform !== 'darwin'">
|
||||
<button class="min" @click="$root.ipcRenderer.send('minimize')"></button>
|
||||
<button class="close" @click="$root.ipcRenderer.send('close')"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
Vue.component('cider-oobe', {
|
||||
template: '#cider-oobe',
|
||||
data: function () {
|
||||
return {
|
||||
screen: "before_we_start"
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
signIn() {
|
||||
if (localStorage.getItem("music.ampwebplay.media-user-token")) {
|
||||
localStorage.setItem("seenOOBE", 1)
|
||||
window.location.reload()
|
||||
}
|
||||
this.screen = "signin"
|
||||
capiInit()
|
||||
},
|
||||
getLz() {
|
||||
return this.$root.getLz.apply(this.$root, arguments);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -539,7 +539,7 @@
|
|||
icon: "./assets/feather/plus-circle.svg",
|
||||
hidden: false,
|
||||
action: () => {
|
||||
app.followArtistById(artistId, true)
|
||||
app.setArtistFavorite(artistId, true)
|
||||
}
|
||||
},
|
||||
"unfollow": {
|
||||
|
@ -547,7 +547,7 @@
|
|||
icon: "./assets/feather/x-circle.svg",
|
||||
hidden: true,
|
||||
action: () => {
|
||||
app.followArtistById(artistId, false)
|
||||
app.setArtistFavorite(artistId, false)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
redirect: 'follow'
|
||||
};
|
||||
|
||||
fetch("https://api.github.com/search/repositories?q=topic:cidermusicplugin fork:true", requestOptions)
|
||||
fetch("https://api.github.com/search/repositories?q=topic:cidermusicplugin fork:true&per_page=100", requestOptions)
|
||||
.then(response => response.text())
|
||||
.then(result => {
|
||||
self.repos = JSON.parse(result).items
|
||||
|
@ -185,4 +185,4 @@
|
|||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
<transition name="wpfade">
|
||||
<div class="podcasts-details" v-if="selected.id != -1">
|
||||
<div class="podcasts-details-header">
|
||||
<button class="close-btn" @click="selected.id = -1" :aria-label="app.getLz('action.close')"></button>
|
||||
<button class="close-btn" @click="selected.id = -1" :aria-label="$root.getLz('action.close')"></button>
|
||||
</div>
|
||||
<div class="podcast-artwork">
|
||||
<mediaitem-artwork shadow="large" :url="selected.attributes.artwork.url" size="300"></mediaitem-artwork>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<h4>{{ loaded.attributes.uniqueSongCount }} {{$root.getLz('term.uniqueSongs')}}</h4>
|
||||
</div>
|
||||
<div class="col-auto replay-playlist-container">
|
||||
<mediaitem-square kind="card" :force-video="true" :item="loaded.playlist"></mediaitem-square>
|
||||
<mediaitem-square kind="card" :no-scale="true" :force-video="true" :item="loaded.playlist"></mediaitem-square>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Top Artists-->
|
||||
|
|
|
@ -1,82 +1,105 @@
|
|||
<script type="text/x-template" id="cider-search">
|
||||
<div class="content-inner search-page">
|
||||
<div class="btn-group searchToggle">
|
||||
<button
|
||||
@click="searchType = 'catalog'"
|
||||
class="md-btn md-btn-small" :class="{'md-btn-primary': searchType == 'catalog'}">{{ $root.getLz("term.appleMusic") }}</button>
|
||||
<button
|
||||
@click="searchType = 'library';"
|
||||
class="md-btn md-btn-small" :class="{'md-btn-primary': searchType == 'library'}">{{ $root.getLz("term.library") }}</button>
|
||||
</div>
|
||||
<div v-if="search != null && search != [] && search.term != ''">
|
||||
<h3>{{app.getLz('term.topResult')}}</h3>
|
||||
<mediaitem-scroller-horizontal
|
||||
:items="search.results[search.results.meta.results.order[0]]['data']"></mediaitem-scroller-horizontal>
|
||||
<div class="row">
|
||||
<div v-else style="text-align: center">
|
||||
<h3>{{app.getLz('error.noResults')}}</h3>
|
||||
<p>{{app.getLz('error.noResults.description')}}</p>
|
||||
</div>
|
||||
<div class="col" v-if="search.results.song">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{app.getLz('term.songs')}}</h3>
|
||||
<template v-if="searchType == 'catalog'">
|
||||
<h3>{{app.getLz('term.topResult')}}</h3>
|
||||
<mediaitem-scroller-horizontal
|
||||
:items="search.results[search.results.meta.results.order[0]]['data']"></mediaitem-scroller-horizontal>
|
||||
<div class="row">
|
||||
<div v-else style="text-align: center">
|
||||
<h3>{{app.getLz('error.noResults')}}</h3>
|
||||
<p>{{app.getLz('error.noResults.description')}}</p>
|
||||
</div>
|
||||
<div class="col" v-if="search.results.song">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{app.getLz('term.songs')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center"
|
||||
@click="app.showSearchView(app.search.term, 'song', app.friendlyTypes('song'))"
|
||||
v-if="search.results.song.data.length >= 12">
|
||||
<button class="cd-btn-seeall">{{app.getLz('term.seeAll')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto flex-center"
|
||||
@click="app.showSearchView(app.search.term, 'song', app.friendlyTypes('song'))"
|
||||
v-if="search.results.song.data.length >= 12">
|
||||
<button class="cd-btn-seeall">{{app.getLz('term.seeAll')}}</button>
|
||||
<div class="mediaitem-list-item__grid">
|
||||
<listitem-horizontal :items="search.results.song.data.limit(12)">
|
||||
</listitem-horizontal>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mediaitem-list-item__grid">
|
||||
<listitem-horizontal :items="search.results.song.data.limit(12)">
|
||||
</listitem-horizontal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="search.results['meta'] != null">
|
||||
<template
|
||||
v-for="section in search.results.meta.results.order" v-if="section != 'song' && section != 'top'">
|
||||
<template v-if="search.results['meta'] != null">
|
||||
<template
|
||||
v-for="section in search.results.meta.results.order" v-if="section != 'song' && section != 'top'">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ app.friendlyTypes(section) }}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results[section].data.length >= 10">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showSearchView(app.search.term, section, app.friendlyTypes(section))">{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!app.friendlyTypes(section).includes('Video')">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="search.resultsSocial.playlist">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{ app.friendlyTypes(section) }}</h3>
|
||||
<h3>{{app.getLz('term.sharedPlaylists')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.results[section].data.length >= 10">
|
||||
<div class="col-auto flex-center" v-if="search.resultsSocial.playlist.data.length >= 10">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showSearchView(app.search.term, section, app.friendlyTypes(section))">{{app.getLz('term.seeAll')}}
|
||||
@click="app.showCollection(search.resultsSocial.playlist, 'Shared Playlists', 'default')">{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!app.friendlyTypes(section).includes('Video')">
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mediaitem-scroller-horizontal-mvview
|
||||
:items="search.results[section].data.limit(10)"></mediaitem-scroller-horizontal-mvview>
|
||||
</template>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.resultsSocial.playlist.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="search.resultsSocial.profile">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{app.getLz('term.people')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.resultsSocial.profile.data.length >= 10">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showCollection(search.resultsSocial.profile, 'People', 'default')">{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.resultsSocial.profile.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
</template>
|
||||
<template v-if="search.resultsSocial.playlist">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{app.getLz('term.sharedPlaylists')}}</h3>
|
||||
<template v-else>
|
||||
<h1>{{ $root.getLz("term.library") }}</h1>
|
||||
<div v-for="(section, key) in $root.search.resultsLibrary">
|
||||
<h3>{{app.friendlyTypes(key)}}</h3>
|
||||
<div class="mediaitem-list-item__grid" v-if="key.includes('songs')">
|
||||
<listitem-horizontal :items="section.data"></listitem-horizontal>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.resultsSocial.playlist.data.length >= 10">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showCollection(search.resultsSocial.playlist, 'Shared Playlists', 'default')">{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
<div class="well" v-else>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="section.data"></mediaitem-scroller-horizontal-large>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.resultsSocial.playlist.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
<template v-if="search.resultsSocial.profile">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>{{app.getLz('term.people')}}</h3>
|
||||
</div>
|
||||
<div class="col-auto flex-center" v-if="search.resultsSocial.profile.data.length >= 10">
|
||||
<button class="cd-btn-seeall"
|
||||
@click="app.showCollection(search.resultsSocial.profile, 'People', 'default')">{{app.getLz('term.seeAll')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<mediaitem-scroller-horizontal-large
|
||||
:items="search.resultsSocial.profile.data.limit(10)"></mediaitem-scroller-horizontal-large>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else>
|
||||
|
@ -111,6 +134,7 @@
|
|||
recentlyPlayed: [],
|
||||
categoriesView: [],
|
||||
categoriesReady: false,
|
||||
searchType: "catalog",
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -96,7 +96,8 @@
|
|||
<option value="listen_now">{{$root.getLz('term.listenNow')}}</option>
|
||||
<option value="browse">{{$root.getLz('term.browse')}}</option>
|
||||
<option value="radio">{{$root.getLz('term.radio')}}</option>
|
||||
<option value="library-recentlyadded">{{$root.getLz('term.recentlyAdded')}}</option>
|
||||
<option value="library-recentlyadded">{{$root.getLz('term.recentlyAdded')}}
|
||||
</option>
|
||||
<option value="library-songs">{{$root.getLz('term.songs')}}</option>
|
||||
<option value="library-albums">{{$root.getLz('term.albums')}}</option>
|
||||
<option value="library-artists">{{$root.getLz('term.artists')}}</option>
|
||||
|
@ -124,7 +125,8 @@
|
|||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.general.sidebarItems.recentlyAdded"
|
||||
<input type="checkbox"
|
||||
v-model="app.cfg.general.sidebarItems.recentlyAdded"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -135,7 +137,8 @@
|
|||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.general.sidebarItems.songs" switch/>
|
||||
<input type="checkbox" v-model="app.cfg.general.sidebarItems.songs"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -185,17 +188,17 @@
|
|||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.general.keybindings')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="md-btn" @click="app.appRoute('keybinds-settings')" >
|
||||
<button class="md-btn" @click="app.appRoute('keybinds-settings')">
|
||||
{{$root.getLz('settings.option.general.keybindings.open')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.general.themeUpdateNotification')}}
|
||||
|
@ -206,7 +209,7 @@
|
|||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.general.showLovedTracksInline')}}
|
||||
|
@ -217,7 +220,7 @@
|
|||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</b-tab>
|
||||
|
@ -241,7 +244,8 @@
|
|||
<option value="HIGH">{{$root.getLz('settings.header.audio.quality.high')}}
|
||||
({{$root.getLz('settings.header.audio.quality.high.description')}})
|
||||
</option>
|
||||
<option value="STANDARD">{{$root.getLz('settings.header.audio.quality.standard')}}
|
||||
<option value="STANDARD">
|
||||
{{$root.getLz('settings.header.audio.quality.standard')}}
|
||||
({{$root.getLz('settings.header.audio.quality.standard.description')}})
|
||||
</option>
|
||||
</select>
|
||||
|
@ -329,12 +333,13 @@
|
|||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.audio.normalization"
|
||||
v-on:change="toggleNormalization"
|
||||
:disabled="app.cfg.audio.spatial === true || app.cfg.audio.maikiwiAudio.spatial === true || app.cfg.audio.maikiwiAudio.ciderPPE === true || app.cfg.audio.maikiwiAudio.atmosphereRealizer1 === true || app.cfg.audio.maikiwiAudio.atmosphereRealizer2 === true"
|
||||
:disabled="app.cfg.audio.maikiwiAudio.spatial === true || app.cfg.audio.maikiwiAudio.ciderPPE === true || app.cfg.audio.maikiwiAudio.atmosphereRealizer1 === true || app.cfg.audio.maikiwiAudio.atmosphereRealizer2 === true"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="app.cfg.advanced.AudioContext && app.cfg.audio.normalization">
|
||||
<div class="md-option-line"
|
||||
v-show="app.cfg.advanced.AudioContext && app.cfg.audio.normalization">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.audio.dbspl.display')}}
|
||||
<br>
|
||||
|
@ -408,13 +413,131 @@
|
|||
<option value="image">
|
||||
{{$root.getLz('settings.header.visual.windowBackgroundStyle.image')}}
|
||||
</option>
|
||||
<option value="mica">
|
||||
<option value="color">
|
||||
{{$root.getLz('settings.header.visual.windowBackgroundStyle.color')}}
|
||||
</option>
|
||||
<option v-if="$root.platform == 'win32'" value="mica">
|
||||
Mica (Beta)
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line child" v-if="app.cfg.visual.window_background_style == 'color'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.windowColor')}}
|
||||
</div>
|
||||
<div class="md-option-segment_auto">
|
||||
<input type="color" v-model="app.cfg.visual.windowColor"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.customAccentColor')}}
|
||||
</div>
|
||||
<div class="md-option-segment_auto">
|
||||
<input type="checkbox" v-model="app.cfg.visual.customAccentColor" :disabled="app.cfg.visual.purplePodcastPlaybackBar" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line child" v-if="app.cfg.visual.customAccentColor">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.accentColor')}}
|
||||
</div>
|
||||
<div class="md-option-segment_auto">
|
||||
<input type="color" v-model="app.cfg.visual.accentColor"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.purplePodcastPlaybackBar')}}
|
||||
</div>
|
||||
<div class="md-option-segment_auto">
|
||||
<input type="checkbox" v-model="app.cfg.visual.purplePodcastPlaybackBar" :disabled="app.cfg.visual.customAccentColor" switch/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.hardwareAcceleration')}}<br>
|
||||
<small>({{$root.getLz('settings.option.visual.hardwareAcceleration.description')}})</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<select class="md-select" style="width:180px;"
|
||||
v-model="app.cfg.visual.hw_acceleration" @change="promptForRelaunch()">
|
||||
<option value="default">
|
||||
{{$root.getLz('settings.header.visual.hardwareAcceleration.default')}}
|
||||
</option>
|
||||
<option value="webgpu">
|
||||
{{$root.getLz('settings.header.visual.hardwareAcceleration.webGPU')}}
|
||||
</option>
|
||||
<option value="disabled">{{$root.getLz('term.disabled')}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.showPersonalInfo')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.visual.showuserinfo"
|
||||
v-on:change="toggleUserInfo"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Window Settings -->
|
||||
<div class="md-option-header">
|
||||
<span>{{$root.getLz('settings.header.window')}}</span>
|
||||
</div>
|
||||
<div class="settings-option-body">
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.close_button_hide")}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.general.close_button_hide" switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.useNativeTitleBar")}}<br>
|
||||
<small>({{$root.getLz("settings.option.visual.hardwareAcceleration.description")}})</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.visual.nativeTitleBar" switch
|
||||
@change="promptForRelaunch()"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle")}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<select class="md-select" v-model="app.cfg.visual.windowControlPosition">
|
||||
<option value="0">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle.right")}}
|
||||
</option>
|
||||
<option value="1">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle.left")}}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Advanced Visual -->
|
||||
<div class="md-option-header">
|
||||
<span>{{$root.getLz('settings.header.advanced')}}</span>
|
||||
</div>
|
||||
<div class="settings-option-body">
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.animatedArtwork')}}
|
||||
|
@ -483,83 +606,8 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.hardwareAcceleration')}}<br>
|
||||
<small>({{$root.getLz('settings.option.visual.hardwareAcceleration.description')}})</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<select class="md-select" style="width:180px;" v-model="app.cfg.visual.hw_acceleration" @change="promptForRelaunch()">
|
||||
<option value="default">
|
||||
{{$root.getLz('settings.header.visual.hardwareAcceleration.default')}}
|
||||
</option>
|
||||
<option value="webgpu">
|
||||
{{$root.getLz('settings.header.visual.hardwareAcceleration.webGPU')}}
|
||||
</option>
|
||||
<option value="disabled">{{$root.getLz('term.disabled')}}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.visual.showPersonalInfo')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.visual.showuserinfo"
|
||||
v-on:change="toggleUserInfo"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Window Settings -->
|
||||
<div class="md-option-header">
|
||||
<span>{{$root.getLz('settings.header.window')}}</span>
|
||||
</div>
|
||||
<div class="settings-option-body">
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.close_button_hide")}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.general.close_button_hide" switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.useNativeTitleBar")}}<br>
|
||||
<small>({{$root.getLz("settings.option.visual.hardwareAcceleration.description")}})</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.visual.nativeTitleBar" switch
|
||||
@change="promptForRelaunch()"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-option-line" v-show="app.platform !== 'darwin'">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle")}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<select class="md-select" v-model="app.cfg.visual.windowControlPosition">
|
||||
<option value="0">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle.right")}}
|
||||
</option>
|
||||
<option value="1">
|
||||
{{$root.getLz("settings.option.window.windowControlStyle.left")}}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</b-tab>
|
||||
<b-tab :title="$root.getLz('settings.header.lyrics')">
|
||||
|
@ -998,6 +1046,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.connectivity.discordRPC.reload')}}
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="md-btn" @click="reloadDiscordRPC()">
|
||||
{{$root.getLz('menubar.options.reload')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LastFM -->
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
|
@ -1005,7 +1064,7 @@
|
|||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<button class="md-btn" id="lfmConnect" ref="lfmConnect"
|
||||
onclick="app.LastFMAuthenticate()">
|
||||
@click="app.LastFMAuthenticate()">
|
||||
{{$root.getLz('term.connect')}}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -1036,7 +1095,8 @@
|
|||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.lastfm.enabledRemoveFeaturingArtists" switch/>
|
||||
<input type="checkbox" v-model="app.cfg.lastfm.enabledRemoveFeaturingArtists"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1125,6 +1185,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Use MusicKit V3
|
||||
<small>Requires relaunch</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.advanced.experiments.includes('ampv3')"
|
||||
@click="app.cfg.advanced.experiments.includes('ampv3') ? removeExperiment('ampv3') : addExperiment('ampv3')"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.advanced.playlistTrackMapping')}}
|
||||
|
@ -1138,28 +1212,16 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
Collapsable Sidebar
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.advanced.experiments.includes('collapseSidebar')"
|
||||
@click="app.cfg.advanced.experiments.includes('collapseSidebar') ? removeExperiment('collapseSidebar') : addExperiment('collapseSidebar')"
|
||||
switch/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="md-option-line">
|
||||
<div class="md-option-segment">
|
||||
{{$root.getLz('settings.option.experimental.compactUI')}}
|
||||
<small v-if="!!app.getThemeDirective('forceUI')">{{$root.getLz('term.themeManaged')}}</small>
|
||||
</div>
|
||||
<div class="md-option-segment md-option-segment_auto">
|
||||
<label>
|
||||
<input type="checkbox" v-model="app.cfg.advanced.experiments.includes('compactui')"
|
||||
@click="app.cfg.advanced.experiments.includes('compactui') ? removeExperiment('compactui') : addExperiment('compactui')"
|
||||
switch/>
|
||||
switch :disabled="!!app.getThemeDirective('forceUI')"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1187,7 +1249,8 @@
|
|||
<select class="md-select" @change="$root.setLz('');$root.setLzManual()"
|
||||
v-model="app.cfg.general.language">
|
||||
<optgroup :label="index" v-for="(categories, index) in getLanguages()">
|
||||
<option v-for="lang in categories" :value="lang.code">{{lang.nameNative}} ({{
|
||||
<option v-for="lang in categories" :value="lang.code">{{lang.nameNative}}
|
||||
({{
|
||||
lang.nameEnglish }})
|
||||
</option>
|
||||
</optgroup>
|
||||
|
@ -1211,9 +1274,10 @@
|
|||
</div>
|
||||
</b-tab>
|
||||
<!-- Connect Settings -->
|
||||
<!-- Not Prod Ready
|
||||
<b-tab :title="$root.getLz('settings.header.connect')">
|
||||
<div class="md-option-container">
|
||||
<!-- Cider Connect / Linking Settings -->
|
||||
<!!!!!-- Cider Connect / Linking Settings -!->
|
||||
<div class="md-option-header">
|
||||
<span>{{$root.getLz('settings.header.connect')}}</span>
|
||||
</div>
|
||||
|
@ -1295,6 +1359,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</b-tab>
|
||||
-->
|
||||
</b-tabs>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -1393,8 +1458,7 @@
|
|||
if (app.cfg.audio.normalization === true) {
|
||||
CiderAudio.normalizerOn()
|
||||
}
|
||||
if (app.cfg.audio.spatial === true) {
|
||||
CiderAudio.spatialOn()
|
||||
if (app.cfg.audio.maikiwiAudio.spatial === true) {
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
}
|
||||
|
@ -1404,8 +1468,7 @@
|
|||
if (app.cfg.audio.normalization === true) {
|
||||
CiderAudio.normalizerOn()
|
||||
}
|
||||
if (app.cfg.audio.spatial === true) {
|
||||
CiderAudio.spatialOn()
|
||||
if (app.cfg.audio.maikiwiAudio.spatial === true) {
|
||||
CiderAudio.hierarchical_loading();
|
||||
}
|
||||
}
|
||||
|
@ -1421,7 +1484,6 @@
|
|||
}
|
||||
},
|
||||
changeAudioQuality: function () {
|
||||
1
|
||||
app.mk.bitrate = MusicKit.PlaybackBitrate[app.cfg.audio.quality];
|
||||
},
|
||||
toggleUserInfo: function () {
|
||||
|
@ -1455,6 +1517,9 @@
|
|||
logoutCC() {
|
||||
ipcRenderer.send('cc-logout')
|
||||
},
|
||||
reloadDiscordRPC() {
|
||||
ipcRenderer.send('reloadRPC')
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
|
@ -184,7 +184,7 @@
|
|||
redirect: 'follow'
|
||||
};
|
||||
|
||||
fetch("https://api.github.com/search/repositories?q=topic:cidermusictheme fork:true", requestOptions)
|
||||
fetch("https://api.github.com/search/repositories?q=topic:cidermusictheme fork:true&per_page=100", requestOptions)
|
||||
.then(response => response.text())
|
||||
.then(result => {
|
||||
let items = JSON.parse(result).items
|
||||
|
@ -194,4 +194,4 @@
|
|||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -9,6 +9,20 @@
|
|||
v-if="artistLoaded"
|
||||
:item="artist"
|
||||
></artist-chip>
|
||||
|
||||
<amp-chrome-player/>
|
||||
<!-- <amp-footer-player/> -->
|
||||
<hr>
|
||||
<amp-lcd-progress/>
|
||||
<hr>
|
||||
<amp-playback-controls-shuffle/>
|
||||
<apple-music-playback-controls theme="dark" />
|
||||
<apple-music-progress theme="dark"></apple-music-progress>
|
||||
<apple-music-volume theme="dark"></apple-music-volume>
|
||||
<amp-user-menu/>
|
||||
<amp-tv-overlay/>
|
||||
<amp-podcast-playback-controls/>
|
||||
<amp-lcd/>
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
|
|
1
src/renderer/views/svg/external-link.svg
Normal file
1
src/renderer/views/svg/external-link.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>
|
After Width: | Height: | Size: 388 B |
Loading…
Add table
Add a link
Reference in a new issue