CHONKY BOY
This commit is contained in:
parent
31ed921a1a
commit
c15f55d0ee
213 changed files with 64188 additions and 55736 deletions
|
@ -1 +1,2 @@
|
||||||
bracketSameLine: true
|
bracketSameLine: true
|
||||||
|
printWidth: 240
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
let i = 1, k = 1;
|
let i = 1,
|
||||||
|
k = 1;
|
||||||
class ExamplePlugin {
|
class ExamplePlugin {
|
||||||
/**
|
/**
|
||||||
* Private variables for interaction in plugins
|
* Private variables for interaction in plugins
|
||||||
|
@ -10,10 +11,10 @@ class ExamplePlugin {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'examplePlugin';
|
public name: string = "examplePlugin";
|
||||||
public description: string = 'Example plugin';
|
public description: string = "Example plugin";
|
||||||
public version: string = '1.0.0';
|
public version: string = "1.0.0";
|
||||||
public author: string = 'Example author';
|
public author: string = "Example author";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
|
@ -44,8 +45,8 @@ class ExamplePlugin {
|
||||||
* @param attributes Music Attributes (attributes.status = current state)
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {
|
||||||
console.log('onPlaybackStateDidChange has been called ' + i + ' times');
|
console.log("onPlaybackStateDidChange has been called " + i + " times");
|
||||||
i++
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,10 +54,9 @@ class ExamplePlugin {
|
||||||
* @param attributes Music Attributes
|
* @param attributes Music Attributes
|
||||||
*/
|
*/
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {
|
||||||
console.log('onNowPlayingDidChange has been called ' + k + ' times');
|
console.log("onNowPlayingDidChange has been called " + k + " times");
|
||||||
k++
|
k++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ExamplePlugin;
|
module.exports = ExamplePlugin;
|
|
@ -2,10 +2,10 @@ class sendSongToTitlebar {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'sendSongToTitlebar';
|
public name: string = "sendSongToTitlebar";
|
||||||
public description: string = 'Sets the app\'s titlebar to the Song title';
|
public description: string = "Sets the app's titlebar to the Song title";
|
||||||
public version: string = '0.0.1';
|
public version: string = "0.0.1";
|
||||||
public author: string = 'Cider Collective (credit to 8times9 via #147)';
|
public author: string = "Cider Collective (credit to 8times9 via #147)";
|
||||||
/**
|
/**
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
*/
|
*/
|
||||||
|
@ -27,7 +27,7 @@ class sendSongToTitlebar {
|
||||||
* @param attributes Music Attributes (attributes.status = current state)
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: any): void {
|
onPlaybackStateDidChange(attributes: any): void {
|
||||||
this._win.setTitle(`${(attributes != null && attributes.name != null && attributes.name.length > 0) ? (attributes.name + " - ") : ''}Cider`)
|
this._win.setTitle(`${attributes != null && attributes.name != null && attributes.name.length > 0 ? attributes.name + " - " : ""}Cider`);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Runs on song change
|
* Runs on song change
|
||||||
|
|
|
@ -8,29 +8,13 @@
|
||||||
"protocols": [
|
"protocols": [
|
||||||
{
|
{
|
||||||
"name": "Cider",
|
"name": "Cider",
|
||||||
"schemes": [
|
"schemes": ["ame", "cider", "itms", "itmss", "musics", "music"]
|
||||||
"ame",
|
|
||||||
"cider",
|
|
||||||
"itms",
|
|
||||||
"itmss",
|
|
||||||
"musics",
|
|
||||||
"music"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"extends": null,
|
"extends": null,
|
||||||
"files": [
|
"files": ["**/*", "./src/**/*", "./resources/icons/icon.*"],
|
||||||
"**/*",
|
|
||||||
"./src/**/*",
|
|
||||||
"./resources/icons/icon.*"
|
|
||||||
],
|
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": [
|
"target": ["AppImage", "deb", "snap", "rpm"],
|
||||||
"AppImage",
|
|
||||||
"deb",
|
|
||||||
"snap",
|
|
||||||
"rpm"
|
|
||||||
],
|
|
||||||
"synopsis": "A new look into listening and enjoying music in style and performance. ",
|
"synopsis": "A new look into listening and enjoying music in style and performance. ",
|
||||||
"category": "AudioVideo",
|
"category": "AudioVideo",
|
||||||
"icon": "cider",
|
"icon": "cider",
|
||||||
|
@ -45,9 +29,7 @@
|
||||||
"setBuildNumber": true
|
"setBuildNumber": true
|
||||||
},
|
},
|
||||||
"win": {
|
"win": {
|
||||||
"target": [
|
"target": ["appx"],
|
||||||
"appx"
|
|
||||||
],
|
|
||||||
"icon": "resources/icons/icon.ico"
|
"icon": "resources/icons/icon.ico"
|
||||||
},
|
},
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|
35
package.json
35
package.json
|
@ -35,51 +35,48 @@
|
||||||
"msft": "yarn build && electron-builder -c msft-package.json",
|
"msft": "yarn build && electron-builder -c msft-package.json",
|
||||||
"mstest": "yarn build && electron-builder -c msft-test.json",
|
"mstest": "yarn build && electron-builder -c msft-test.json",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"prettier": "npx prettier --write '**/*.{js,json,ts}'"
|
"prettier": "npx prettier --write '**/*.{js,json,ts,css,less}'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/electron": "^3.0.7",
|
"@sentry/electron": "^3.0.7",
|
||||||
"@sentry/integrations": "^6.19.6",
|
"@sentry/integrations": "^7.8.1",
|
||||||
"@types/pouchdb": "^6.4.0",
|
"@types/pouchdb": "^6.4.0",
|
||||||
"@types/pouchdb-node": "^6.1.4",
|
"@types/pouchdb-node": "^6.1.4",
|
||||||
"adm-zip": "0.4.10",
|
"adm-zip": "0.4.10",
|
||||||
"airtunes2": "git+https://github.com/ciderapp/node_airtunes2.git",
|
"airtunes2": "git+https://github.com/ciderapp/node_airtunes2.git",
|
||||||
"castv2-client": "^1.2.0",
|
"castv2-client": "^1.2.0",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"discord-auto-rpc": "^1.0.16",
|
"discord-auto-rpc": "^1.0.17",
|
||||||
"dns-js": "git+https://github.com/ciderapp/node-dns-js.git",
|
"dns-js": "git+https://github.com/ciderapp/node-dns-js.git",
|
||||||
"ejs": "^3.1.6",
|
"ejs": "^3.1.8",
|
||||||
"electron-fetch": "^1.7.4",
|
"electron-fetch": "^1.7.4",
|
||||||
"electron-log": "^4.4.6",
|
"electron-log": "^4.4.8",
|
||||||
"electron-notarize": "^1.2.1",
|
"electron-notarize": "^1.2.1",
|
||||||
"electron-store": "^8.0.1",
|
"electron-store": "^8.1.0",
|
||||||
"electron-updater": "^5.0.1",
|
"electron-updater": "^5.2.1",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"express": "^4.17.3",
|
"express": "^4.18.1",
|
||||||
"get-port": "^5.1.1",
|
"get-port": "^5.1.1",
|
||||||
"jimp": "^0.16.1",
|
"jimp": "^0.16.1",
|
||||||
"jsonc": "^2.0.0",
|
|
||||||
"lastfmapi": "^0.1.1",
|
"lastfmapi": "^0.1.1",
|
||||||
"level": "^8.0.0",
|
"level": "^8.0.0",
|
||||||
"leveldown": "^6.1.1",
|
"leveldown": "^6.1.1",
|
||||||
"mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git",
|
"mdns-js": "git+https://github.com/ciderapp/node-mdns-js.git",
|
||||||
"mpris-service": "^2.1.2",
|
"mpris-service": "^2.1.2",
|
||||||
"music-metadata": "^7.12.4",
|
"music-metadata": "^7.12.5",
|
||||||
"node-gyp": "^9.0.0",
|
"node-gyp": "^9.1.0",
|
||||||
"node-ssdp": "^4.0.1",
|
"node-ssdp": "^4.0.1",
|
||||||
"pouchdb-adapter-leveldb": "^7.3.0",
|
"pouchdb-adapter-leveldb": "^7.3.0",
|
||||||
"pouchdb-node": "^7.3.0",
|
"pouchdb-node": "^7.3.0",
|
||||||
"pouchdb-upsert": "^2.2.0",
|
"pouchdb-upsert": "^2.2.0",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.1",
|
||||||
"react": "^18.0.0",
|
|
||||||
"react-dom": "^18.0.0",
|
|
||||||
"run-script-os": "^1.1.6",
|
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
|
"run-script-os": "^1.1.6",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"ts-md5": "^1.2.11",
|
"ts-md5": "^1.2.11",
|
||||||
"v8-compile-cache": "^2.3.0",
|
"v8-compile-cache": "^2.3.0",
|
||||||
"wallpaper": "5.0.1",
|
"wallpaper": "5.0.1",
|
||||||
"ws": "^8.5.0",
|
"ws": "^8.8.1",
|
||||||
"xml2js": "^0.4.23",
|
"xml2js": "^0.4.23",
|
||||||
"youtube-search-without-api-key": "^1.0.7"
|
"youtube-search-without-api-key": "^1.0.7"
|
||||||
},
|
},
|
||||||
|
@ -90,14 +87,14 @@
|
||||||
"@types/qrcode-terminal": "^0.12.0",
|
"@types/qrcode-terminal": "^0.12.0",
|
||||||
"@types/ws": "^8.5.3",
|
"@types/ws": "^8.5.3",
|
||||||
"electron": "git+https://github.com/castlabs/electron-releases.git#18-x-y",
|
"electron": "git+https://github.com/castlabs/electron-releases.git#18-x-y",
|
||||||
"electron-builder": "^23.0.3",
|
"electron-builder": "^23.3.3",
|
||||||
"electron-builder-notarize-pkg": "^1.2.0",
|
"electron-builder-notarize-pkg": "^1.2.0",
|
||||||
"electron-webpack": "^2.8.2",
|
"electron-webpack": "^2.8.2",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"musickit-typescript": "^1.2.4",
|
"musickit-typescript": "^1.2.4",
|
||||||
"typescript": "^4.6.4",
|
"typescript": "^4.7.4",
|
||||||
"vue-devtools": "^5.1.4",
|
"vue-devtools": "^5.1.4",
|
||||||
"webpack": "~5.72.0"
|
"webpack": "~5.74.0"
|
||||||
},
|
},
|
||||||
"fileAssociations": [
|
"fileAssociations": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
exports.default = function(context) {
|
exports.default = function (context) {
|
||||||
const { execSync } = require('child_process')
|
const { execSync } = require("child_process");
|
||||||
const fs = require('fs')
|
const fs = require("fs");
|
||||||
|
|
||||||
if (process.platform !== 'darwin')
|
if (process.platform !== "darwin") return;
|
||||||
return
|
|
||||||
|
|
||||||
if (fs.existsSync('dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig'))
|
if (fs.existsSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig"))
|
||||||
fs.unlinkSync('dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig')
|
fs.unlinkSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig");
|
||||||
if (fs.existsSync('dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig'))
|
if (fs.existsSync("dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig"))
|
||||||
fs.unlinkSync('dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig')
|
fs.unlinkSync("dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Electron Framework.sig");
|
||||||
// console.log('Castlabs-evs update start')
|
// console.log('Castlabs-evs update start')
|
||||||
// execSync('python3 -m pip install --upgrade castlabs-evs')
|
// execSync('python3 -m pip install --upgrade castlabs-evs')
|
||||||
// console.log('Castlabs-evs update complete')
|
// console.log('Castlabs-evs update complete')
|
||||||
|
|
||||||
// xcode 13
|
// xcode 13
|
||||||
if (fs.existsSync('dist/mac-universal--x64') && fs.existsSync('dist/mac-universal--arm64') && fs.existsSync('dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib'))
|
if (
|
||||||
execSync("cp 'dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib' 'dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib'",{stdio: 'inherit'})
|
fs.existsSync("dist/mac-universal--x64") &&
|
||||||
|
fs.existsSync("dist/mac-universal--arm64") &&
|
||||||
|
fs.existsSync("dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib")
|
||||||
|
)
|
||||||
|
execSync(
|
||||||
|
"cp 'dist/mac-universal--x64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib' 'dist/mac-universal--arm64/Cider.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib/keyedobjects-101300.nib'",
|
||||||
|
{ stdio: "inherit" }
|
||||||
|
);
|
||||||
|
|
||||||
// console.log('VMP signing start')
|
// console.log('VMP signing start')
|
||||||
// if (fs.existsSync('dist/mac-universal'))
|
// if (fs.existsSync('dist/mac-universal'))
|
||||||
|
@ -26,5 +32,4 @@ exports.default = function(context) {
|
||||||
// execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-arm64 -z',{stdio: 'inherit'})
|
// execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac-arm64 -z',{stdio: 'inherit'})
|
||||||
|
|
||||||
// console.log('VMP signing complete')
|
// console.log('VMP signing complete')
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
|
@ -6,6 +6,4 @@
|
||||||
"lang": ["en-US"]
|
"lang": ["en-US"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,16 +24,20 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
this.codeSigningInfo = new lazy_val_1.Lazy(() => {
|
this.codeSigningInfo = new lazy_val_1.Lazy(() => {
|
||||||
const cscLink = this.getCscLink();
|
const cscLink = this.getCscLink();
|
||||||
if (cscLink == null || process.platform !== "darwin") {
|
if (cscLink == null || process.platform !== "darwin") {
|
||||||
return Promise.resolve({ keychainFile: process.env.CSC_KEYCHAIN || null });
|
return Promise.resolve({
|
||||||
|
keychainFile: process.env.CSC_KEYCHAIN || null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return macCodeSign_1.createKeychain({
|
return macCodeSign_1
|
||||||
|
.createKeychain({
|
||||||
tmpDir: this.info.tempDirManager,
|
tmpDir: this.info.tempDirManager,
|
||||||
cscLink,
|
cscLink,
|
||||||
cscKeyPassword: this.getCscPassword(),
|
cscKeyPassword: this.getCscPassword(),
|
||||||
cscILink: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerLink, process.env.CSC_INSTALLER_LINK),
|
cscILink: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerLink, process.env.CSC_INSTALLER_LINK),
|
||||||
cscIKeyPassword: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerKeyPassword, process.env.CSC_INSTALLER_KEY_PASSWORD),
|
cscIKeyPassword: platformPackager_1.chooseNotNull(this.platformSpecificBuildOptions.cscInstallerKeyPassword, process.env.CSC_INSTALLER_KEY_PASSWORD),
|
||||||
currentDir: this.projectDir,
|
currentDir: this.projectDir,
|
||||||
}).then(result => {
|
})
|
||||||
|
.then((result) => {
|
||||||
const keychainFile = result.keychainFile;
|
const keychainFile = result.keychainFile;
|
||||||
if (keychainFile != null) {
|
if (keychainFile != null) {
|
||||||
this.info.disposeOnBuildFinish(() => macCodeSign_1.removeKeychain(keychainFile));
|
this.info.disposeOnBuildFinish(() => macCodeSign_1.removeKeychain(keychainFile));
|
||||||
|
@ -61,18 +65,18 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
case "dmg": {
|
case "dmg": {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const { DmgTarget } = require("dmg-builder");
|
const { DmgTarget } = require("dmg-builder");
|
||||||
mapper(name, outDir => new DmgTarget(this, outDir));
|
mapper(name, (outDir) => new DmgTarget(this, outDir));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "zip":
|
case "zip":
|
||||||
// https://github.com/electron-userland/electron-builder/issues/2313
|
// https://github.com/electron-userland/electron-builder/issues/2313
|
||||||
mapper(name, outDir => new ArchiveTarget_1.ArchiveTarget(name, outDir, this, true));
|
mapper(name, (outDir) => new ArchiveTarget_1.ArchiveTarget(name, outDir, this, true));
|
||||||
break;
|
break;
|
||||||
case "pkg":
|
case "pkg":
|
||||||
mapper(name, outDir => new pkg_1.PkgTarget(this, outDir));
|
mapper(name, (outDir) => new pkg_1.PkgTarget(this, outDir));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mapper(name, outDir => (name === "mas" || name === "mas-dev" ? new targetFactory_1.NoOpTarget(name) : targetFactory_1.createCommonTarget(name, outDir, this)));
|
mapper(name, (outDir) => (name === "mas" || name === "mas-dev" ? new targetFactory_1.NoOpTarget(name) : targetFactory_1.createCommonTarget(name, outDir, this)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,12 +94,15 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
const arm64AppOutPath = appOutDir + "--" + builder_util_1.Arch[arm64Arch];
|
const arm64AppOutPath = appOutDir + "--" + builder_util_1.Arch[arm64Arch];
|
||||||
await super.doPack(outDir, arm64AppOutPath, platformName, arm64Arch, platformSpecificBuildOptions, targets, false, true);
|
await super.doPack(outDir, arm64AppOutPath, platformName, arm64Arch, platformSpecificBuildOptions, targets, false, true);
|
||||||
const framework = this.info.framework;
|
const framework = this.info.framework;
|
||||||
builder_util_1.log.info({
|
builder_util_1.log.info(
|
||||||
|
{
|
||||||
platform: platformName,
|
platform: platformName,
|
||||||
arch: builder_util_1.Arch[arch],
|
arch: builder_util_1.Arch[arch],
|
||||||
[`${framework.name}`]: framework.version,
|
[`${framework.name}`]: framework.version,
|
||||||
appOutDir: builder_util_1.log.filePath(appOutDir),
|
appOutDir: builder_util_1.log.filePath(appOutDir),
|
||||||
}, `packaging`);
|
},
|
||||||
|
`packaging`
|
||||||
|
);
|
||||||
const appFile = `${this.appInfo.productFilename}.app`;
|
const appFile = `${this.appInfo.productFilename}.app`;
|
||||||
const { makeUniversalApp } = require("@electron/universal");
|
const { makeUniversalApp } = require("@electron/universal");
|
||||||
await makeUniversalApp({
|
await makeUniversalApp({
|
||||||
|
@ -113,10 +120,10 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
targets,
|
targets,
|
||||||
packager: this,
|
packager: this,
|
||||||
electronPlatformName: platformName,
|
electronPlatformName: platformName,
|
||||||
}
|
};
|
||||||
await this.info.afterPack(packContext)
|
await this.info.afterPack(packContext);
|
||||||
if (framework.afterPack != null) {
|
if (framework.afterPack != null) {
|
||||||
await framework.afterPack(packContext)
|
await framework.afterPack(packContext);
|
||||||
}
|
}
|
||||||
await this.doSignAfterPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
|
await this.doSignAfterPack(outDir, appOutDir, platformName, arch, platformSpecificBuildOptions, targets);
|
||||||
break;
|
break;
|
||||||
|
@ -125,13 +132,13 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
}
|
}
|
||||||
async pack(outDir, arch, targets, taskManager) {
|
async pack(outDir, arch, targets, taskManager) {
|
||||||
let nonMasPromise = null;
|
let nonMasPromise = null;
|
||||||
const hasMas = targets.length !== 0 && targets.some(it => it.name === "mas" || it.name === "mas-dev");
|
const hasMas = targets.length !== 0 && targets.some((it) => it.name === "mas" || it.name === "mas-dev");
|
||||||
const prepackaged = this.packagerOptions.prepackaged;
|
const prepackaged = this.packagerOptions.prepackaged;
|
||||||
if (!hasMas || targets.length > 1) {
|
if (!hasMas || targets.length > 1) {
|
||||||
const appPath = prepackaged == null ? path.join(this.computeAppOutDir(outDir, arch), `${this.appInfo.productFilename}.app`) : prepackaged;
|
const appPath = prepackaged == null ? path.join(this.computeAppOutDir(outDir, arch), `${this.appInfo.productFilename}.app`) : prepackaged;
|
||||||
nonMasPromise = (prepackaged
|
nonMasPromise = (prepackaged ? Promise.resolve() : this.doPack(outDir, path.dirname(appPath), this.platform.nodeName, arch, this.platformSpecificBuildOptions, targets)).then(() =>
|
||||||
? Promise.resolve()
|
this.packageInDistributableFormat(appPath, arch, targets, taskManager)
|
||||||
: this.doPack(outDir, path.dirname(appPath), this.platform.nodeName, arch, this.platformSpecificBuildOptions, targets)).then(() => this.packageInDistributableFormat(appPath, arch, targets, taskManager));
|
);
|
||||||
}
|
}
|
||||||
for (const target of targets) {
|
for (const target of targets) {
|
||||||
const targetName = target.name;
|
const targetName = target.name;
|
||||||
|
@ -148,8 +155,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
if (prepackaged == null) {
|
if (prepackaged == null) {
|
||||||
await this.doPack(outDir, targetOutDir, "mas", arch, masBuildOptions, [target]);
|
await this.doPack(outDir, targetOutDir, "mas", arch, masBuildOptions, [target]);
|
||||||
await this.sign(path.join(targetOutDir, `${this.appInfo.productFilename}.app`), targetOutDir, masBuildOptions, arch);
|
await this.sign(path.join(targetOutDir, `${this.appInfo.productFilename}.app`), targetOutDir, masBuildOptions, arch);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
await this.sign(prepackaged, targetOutDir, masBuildOptions, arch);
|
await this.sign(prepackaged, targetOutDir, masBuildOptions, arch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,20 +209,21 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
if (filter.length == 0) {
|
if (filter.length == 0) {
|
||||||
filter = null;
|
filter = null;
|
||||||
}
|
}
|
||||||
}
|
} else if (filter != null) {
|
||||||
else if (filter != null) {
|
|
||||||
filter = filter.length === 0 ? null : [filter];
|
filter = filter.length === 0 ? null : [filter];
|
||||||
}
|
}
|
||||||
const filterRe = filter == null ? null : filter.map(it => new RegExp(it));
|
const filterRe = filter == null ? null : filter.map((it) => new RegExp(it));
|
||||||
let binaries = options.binaries || undefined;
|
let binaries = options.binaries || undefined;
|
||||||
if (binaries) {
|
if (binaries) {
|
||||||
// Accept absolute paths for external binaries, else resolve relative paths from the artifact's app Contents path.
|
// Accept absolute paths for external binaries, else resolve relative paths from the artifact's app Contents path.
|
||||||
const userDefinedBinaries = await Promise.all(binaries.map(async (destination) => {
|
const userDefinedBinaries = await Promise.all(
|
||||||
|
binaries.map(async (destination) => {
|
||||||
if (await fs_1.statOrNull(destination)) {
|
if (await fs_1.statOrNull(destination)) {
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
return path.resolve(appPath, destination);
|
return path.resolve(appPath, destination);
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
// Insert at front to prioritize signing. We still sort by depth next
|
// Insert at front to prioritize signing. We still sort by depth next
|
||||||
binaries = userDefinedBinaries.concat(binaries);
|
binaries = userDefinedBinaries.concat(binaries);
|
||||||
builder_util_1.log.info("Signing addtional user-defined binaries: " + JSON.stringify(userDefinedBinaries, null, 1));
|
builder_util_1.log.info("Signing addtional user-defined binaries: " + JSON.stringify(userDefinedBinaries, null, 1));
|
||||||
|
@ -233,11 +240,13 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (file.endsWith(".kext") ||
|
return (
|
||||||
|
file.endsWith(".kext") ||
|
||||||
file.startsWith("/Contents/PlugIns", appPath.length) ||
|
file.startsWith("/Contents/PlugIns", appPath.length) ||
|
||||||
file.includes("/node_modules/puppeteer/.local-chromium") ||
|
file.includes("/node_modules/puppeteer/.local-chromium") ||
|
||||||
file.includes("/node_modules/playwright-firefox/.local-browsers") ||
|
file.includes("/node_modules/playwright-firefox/.local-browsers") ||
|
||||||
file.includes("/node_modules/playwright/.local-browsers"));
|
file.includes("/node_modules/playwright/.local-browsers")
|
||||||
|
);
|
||||||
/* Those are browser automating modules, browser (chromium, nightly) cannot be signed
|
/* Those are browser automating modules, browser (chromium, nightly) cannot be signed
|
||||||
https://github.com/electron-userland/electron-builder/issues/2010
|
https://github.com/electron-userland/electron-builder/issues/2010
|
||||||
https://github.com/electron-userland/electron-builder/issues/5383
|
https://github.com/electron-userland/electron-builder/issues/5383
|
||||||
|
@ -250,7 +259,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
app: appPath,
|
app: appPath,
|
||||||
keychain: keychainFile || undefined,
|
keychain: keychainFile || undefined,
|
||||||
binaries,
|
binaries,
|
||||||
timestamp: isMas ? masOptions === null || masOptions === void 0 ? void 0 : masOptions.timestamp : options.timestamp,
|
timestamp: isMas ? (masOptions === null || masOptions === void 0 ? void 0 : masOptions.timestamp) : options.timestamp,
|
||||||
requirements: isMas || this.platformSpecificBuildOptions.requirements == null ? undefined : await this.getResource(this.platformSpecificBuildOptions.requirements),
|
requirements: isMas || this.platformSpecificBuildOptions.requirements == null ? undefined : await this.getResource(this.platformSpecificBuildOptions.requirements),
|
||||||
// https://github.com/electron-userland/electron-osx-sign/issues/196
|
// https://github.com/electron-userland/electron-osx-sign/issues/196
|
||||||
// will fail on 10.14.5+ because a signed but unnotarized app is also rejected.
|
// will fail on 10.14.5+ because a signed but unnotarized app is also rejected.
|
||||||
|
@ -260,12 +269,15 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
hardenedRuntime: isMas ? masOptions && masOptions.hardenedRuntime === true : options.hardenedRuntime !== false,
|
hardenedRuntime: isMas ? masOptions && masOptions.hardenedRuntime === true : options.hardenedRuntime !== false,
|
||||||
};
|
};
|
||||||
await this.adjustSignOptions(signOptions, masOptions);
|
await this.adjustSignOptions(signOptions, masOptions);
|
||||||
builder_util_1.log.info({
|
builder_util_1.log.info(
|
||||||
|
{
|
||||||
file: builder_util_1.log.filePath(appPath),
|
file: builder_util_1.log.filePath(appPath),
|
||||||
identityName: identity.name,
|
identityName: identity.name,
|
||||||
identityHash: identity.hash,
|
identityHash: identity.hash,
|
||||||
provisioningProfile: signOptions["provisioning-profile"] || "none",
|
provisioningProfile: signOptions["provisioning-profile"] || "none",
|
||||||
}, "signing");
|
},
|
||||||
|
"signing"
|
||||||
|
);
|
||||||
await this.doSign(signOptions);
|
await this.doSign(signOptions);
|
||||||
// https://github.com/electron-userland/electron-builder/issues/1196#issuecomment-312310209
|
// https://github.com/electron-userland/electron-builder/issues/1196#issuecomment-312310209
|
||||||
if (masOptions != null && !isDevelopment) {
|
if (masOptions != null && !isDevelopment) {
|
||||||
|
@ -290,8 +302,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
const p = `entitlements.${entitlementsSuffix}.plist`;
|
const p = `entitlements.${entitlementsSuffix}.plist`;
|
||||||
if (resourceList.includes(p)) {
|
if (resourceList.includes(p)) {
|
||||||
entitlements = path.join(this.info.buildResourcesDir, p);
|
entitlements = path.join(this.info.buildResourcesDir, p);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
entitlements = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
entitlements = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,8 +312,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
const p = `entitlements.${entitlementsSuffix}.inherit.plist`;
|
const p = `entitlements.${entitlementsSuffix}.inherit.plist`;
|
||||||
if (resourceList.includes(p)) {
|
if (resourceList.includes(p)) {
|
||||||
entitlementsInherit = path.join(this.info.buildResourcesDir, p);
|
entitlementsInherit = path.join(this.info.buildResourcesDir, p);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
entitlementsInherit = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
entitlementsInherit = pathManager_1.getTemplatePath("entitlements.mac.plist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +367,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
appPlist.CFBundleIdentifier = appInfo.macBundleIdentifier;
|
appPlist.CFBundleIdentifier = appInfo.macBundleIdentifier;
|
||||||
appPlist.CFBundleShortVersionString = this.platformSpecificBuildOptions.bundleShortVersion || appInfo.version;
|
appPlist.CFBundleShortVersionString = this.platformSpecificBuildOptions.bundleShortVersion || appInfo.version;
|
||||||
appPlist.CFBundleVersion = appInfo.buildVersion;
|
appPlist.CFBundleVersion = appInfo.buildVersion;
|
||||||
builder_util_1.use(this.platformSpecificBuildOptions.category || this.config.category, it => (appPlist.LSApplicationCategoryType = it));
|
builder_util_1.use(this.platformSpecificBuildOptions.category || this.config.category, (it) => (appPlist.LSApplicationCategoryType = it));
|
||||||
appPlist.NSHumanReadableCopyright = appInfo.copyright;
|
appPlist.NSHumanReadableCopyright = appInfo.copyright;
|
||||||
if (this.platformSpecificBuildOptions.darkModeSupport) {
|
if (this.platformSpecificBuildOptions.darkModeSupport) {
|
||||||
appPlist.NSRequiresAquaSystemAppearance = false;
|
appPlist.NSRequiresAquaSystemAppearance = false;
|
||||||
|
@ -382,8 +392,7 @@ class MacPackager extends platformPackager_1.PlatformPackager {
|
||||||
await bluebird_lst_1.default.map(promise_1.orIfFileNotExist(promises_1.readdir(outResourcesDir), []), (file) => {
|
await bluebird_lst_1.default.map(promise_1.orIfFileNotExist(promises_1.readdir(outResourcesDir), []), (file) => {
|
||||||
if (file.endsWith(".app")) {
|
if (file.endsWith(".app")) {
|
||||||
return this.sign(path.join(outResourcesDir, file), null, null, null);
|
return this.sign(path.join(outResourcesDir, file), null, null, null);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
|
require("dotenv").config();
|
||||||
|
const { notarize } = require("electron-notarize");
|
||||||
require('dotenv').config();
|
|
||||||
const { notarize } = require('electron-notarize');
|
|
||||||
|
|
||||||
exports.default = async function notarizing(context) {
|
exports.default = async function notarizing(context) {
|
||||||
const { electronPlatformName, appOutDir } = context;
|
const { electronPlatformName, appOutDir } = context;
|
||||||
if (electronPlatformName !== 'darwin') {
|
if (electronPlatformName !== "darwin") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const appName = context.packager.appInfo.productFilename;
|
const appName = context.packager.appInfo.productFilename;
|
||||||
|
|
||||||
return await notarize({
|
return await notarize({
|
||||||
appBundleId: 'com.ciderapp.cider',
|
appBundleId: "com.ciderapp.cider",
|
||||||
appPath: `${appOutDir}/${appName}.app`,
|
appPath: `${appOutDir}/${appName}.app`,
|
||||||
appleId: process.env.APPLEID,
|
appleId: process.env.APPLEID,
|
||||||
appleIdPassword: process.env.APPLEIDPASS,
|
appleIdPassword: process.env.APPLEIDPASS,
|
||||||
|
|
|
@ -3,24 +3,24 @@ const CiderKit = {
|
||||||
musickit: {
|
musickit: {
|
||||||
async mkv3(route, body, options) {
|
async mkv3(route, body, options) {
|
||||||
let opts = {
|
let opts = {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
cache: 'no-cache',
|
cache: "no-cache",
|
||||||
credentials: 'same-origin',
|
credentials: "same-origin",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
redirect: 'follow',
|
redirect: "follow",
|
||||||
referrerPolicy: 'no-referrer',
|
referrerPolicy: "no-referrer",
|
||||||
body: {}
|
body: {},
|
||||||
}
|
};
|
||||||
opts.body = JSON.stringify({
|
opts.body = JSON.stringify({
|
||||||
route: route,
|
route: route,
|
||||||
body: body,
|
body: body,
|
||||||
options: options
|
options: options,
|
||||||
})
|
});
|
||||||
let response = await fetch("./api/musickit/v3", opts);
|
let response = await fetch("./api/musickit/v3", opts);
|
||||||
return response.json()
|
return response.json();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
|
@ -303,10 +303,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider wird die letzte Sitzung auf diesem Rechner fortsetzen.",
|
"settings.option.general.resumebehavior.locally.description": "Cider wird die letzte Sitzung auf diesem Rechner fortsetzen.",
|
||||||
"settings.option.general.resumebehavior.history": "Verlauf",
|
"settings.option.general.resumebehavior.history": "Verlauf",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider wird den letzten Song aus dem geräteübergreifenden Apple-Music-Verlauf in die Warteschlange stellen.",
|
"settings.option.general.resumebehavior.history.description": "Cider wird den letzten Song aus dem geräteübergreifenden Apple-Music-Verlauf in die Warteschlange stellen.",
|
||||||
"settings.option.general.resumetabs" : "Tab beim Start öffnen",
|
"settings.option.general.resumetabs": "Tab beim Start öffnen",
|
||||||
"settings.option.general.resumetabs.description" : "Wähle welcher Tab beim Starten von Cider geöffnet werden soll.",
|
"settings.option.general.resumetabs.description": "Wähle welcher Tab beim Starten von Cider geöffnet werden soll.",
|
||||||
"settings.option.general.resumetabs.dynamic" : "Dynamisch",
|
"settings.option.general.resumetabs.dynamic": "Dynamisch",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "Cider wird den zuletzt genutzten Tab öffnen.",
|
"settings.option.general.resumetabs.dynamic.description": "Cider wird den zuletzt genutzten Tab öffnen.",
|
||||||
"settings.option.general.keybindings": "Tastenkombinationen",
|
"settings.option.general.keybindings": "Tastenkombinationen",
|
||||||
"settings.option.general.keybindings.pressCombination": "Drücke eine Kombination aus zwei Tasten um die Tastenkombination zu aktualisieren.",
|
"settings.option.general.keybindings.pressCombination": "Drücke eine Kombination aus zwei Tasten um die Tastenkombination zu aktualisieren.",
|
||||||
"settings.option.general.keybindings.pressEscape": "Drücke Escape um zurückzukehren.",
|
"settings.option.general.keybindings.pressEscape": "Drücke Escape um zurückzukehren.",
|
||||||
|
@ -396,7 +396,7 @@
|
||||||
"action.selectAll": "Alles auswählen",
|
"action.selectAll": "Alles auswählen",
|
||||||
"action.delete": "Löschen",
|
"action.delete": "Löschen",
|
||||||
"home.syncFavorites": "Sync Favoriten",
|
"home.syncFavorites": "Sync Favoriten",
|
||||||
"term.quit" : "Beenden",
|
"term.quit": "Beenden",
|
||||||
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "Verhindert, dass geloopte Titel gescrobbelt oder in der (Hört Gerade)-Liste auf Last.fm angezeigt werden",
|
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "Verhindert, dass geloopte Titel gescrobbelt oder in der (Hört Gerade)-Liste auf Last.fm angezeigt werden",
|
||||||
"settings.option.connectivity.lastfmScrobble.filterTypes": "Medientypen filtern (Last.fm)",
|
"settings.option.connectivity.lastfmScrobble.filterTypes": "Medientypen filtern (Last.fm)",
|
||||||
"settings.option.connectivity.lastfmScrobble.manualToken": "Last.fm-Token manuell eingeben"
|
"settings.option.connectivity.lastfmScrobble.manualToken": "Last.fm-Token manuell eingeben"
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
"action.tray.minimize": "Minimise to Tray",
|
"action.tray.minimize": "Minimise to Tray",
|
||||||
"term.tracks": "songs",
|
"term.tracks": "songs",
|
||||||
"term.track": {
|
"term.track": {
|
||||||
"one" : "song",
|
"one": "song",
|
||||||
"other" : "songs"
|
"other": "songs"
|
||||||
},
|
},
|
||||||
"home.syncFavorites": "Sync Favourites",
|
"home.syncFavorites": "Sync Favourites",
|
||||||
"home.syncFavorites.gettingArtists": "Getting Favourited Artists...",
|
"home.syncFavorites.gettingArtists": "Getting Favourited Artists...",
|
||||||
|
|
|
@ -202,16 +202,16 @@
|
||||||
"term.confirmLogout": "Are you sure you want to logout?",
|
"term.confirmLogout": "Are you sure you want to logout?",
|
||||||
"term.creditDesignedBy": "Designed by ${authorUsername}",
|
"term.creditDesignedBy": "Designed by ${authorUsername}",
|
||||||
"term.discNumber": "Disc ${discNumber}",
|
"term.discNumber": "Disc ${discNumber}",
|
||||||
"term.reload" : "Reload Cider?",
|
"term.reload": "Reload Cider?",
|
||||||
"term.toggleprivate" : "Toggle Private Session",
|
"term.toggleprivate": "Toggle Private Session",
|
||||||
"term.webremote" : "Web Remote",
|
"term.webremote": "Web Remote",
|
||||||
"term.cast" : "Cast",
|
"term.cast": "Cast",
|
||||||
"term.cast2" : "Cast to Devices",
|
"term.cast2": "Cast to Devices",
|
||||||
"term.quit" : "Quit",
|
"term.quit": "Quit",
|
||||||
"term.zoomin" : "Zoom In",
|
"term.zoomin": "Zoom In",
|
||||||
"term.zoomout" : "Zoom Out",
|
"term.zoomout": "Zoom Out",
|
||||||
"term.zoomreset" : "Reset Zoom",
|
"term.zoomreset": "Reset Zoom",
|
||||||
"term.fullscreen" : "Fullscreen",
|
"term.fullscreen": "Fullscreen",
|
||||||
"term.nowPlaying": "Now Playing",
|
"term.nowPlaying": "Now Playing",
|
||||||
"home.syncFavorites": "Sync Favorites",
|
"home.syncFavorites": "Sync Favorites",
|
||||||
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
|
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
|
||||||
|
@ -340,10 +340,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider will resume your last session on this machine.",
|
"settings.option.general.resumebehavior.locally.description": "Cider will resume your last session on this machine.",
|
||||||
"settings.option.general.resumebehavior.history": "History",
|
"settings.option.general.resumebehavior.history": "History",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider will queue the last song from your overall Apple Music history, across devices.",
|
"settings.option.general.resumebehavior.history.description": "Cider will queue the last song from your overall Apple Music history, across devices.",
|
||||||
"settings.option.general.resumetabs" : "Open Tab on Launch",
|
"settings.option.general.resumetabs": "Open Tab on Launch",
|
||||||
"settings.option.general.resumetabs.description" : "You can choose what tab you want to open when you launch Cider.",
|
"settings.option.general.resumetabs.description": "You can choose what tab you want to open when you launch Cider.",
|
||||||
"settings.option.general.resumetabs.dynamic" : "Dynamic",
|
"settings.option.general.resumetabs.dynamic": "Dynamic",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "Cider will open the tab that you last used.",
|
"settings.option.general.resumetabs.dynamic.description": "Cider will open the tab that you last used.",
|
||||||
"settings.option.general.language.main": "Languages",
|
"settings.option.general.language.main": "Languages",
|
||||||
"settings.option.general.language.fun": "Fun Languages",
|
"settings.option.general.language.fun": "Fun Languages",
|
||||||
"settings.option.general.language.unsorted": "Unsorted",
|
"settings.option.general.language.unsorted": "Unsorted",
|
||||||
|
|
|
@ -201,16 +201,16 @@
|
||||||
"term.confirmLogout": "¿Estás seguro de que quieres cerrar sesión?",
|
"term.confirmLogout": "¿Estás seguro de que quieres cerrar sesión?",
|
||||||
"term.creditDesignedBy": "Diseñado por ${authorUsername}",
|
"term.creditDesignedBy": "Diseñado por ${authorUsername}",
|
||||||
"term.discNumber": "Disco ${discNumber}",
|
"term.discNumber": "Disco ${discNumber}",
|
||||||
"term.reload" : "¿ Recargar Cider ?",
|
"term.reload": "¿ Recargar Cider ?",
|
||||||
"term.toggleprivate" : "Cambiar a Sesión Privada",
|
"term.toggleprivate": "Cambiar a Sesión Privada",
|
||||||
"term.webremote" : "Web Remoto",
|
"term.webremote": "Web Remoto",
|
||||||
"term.cast" : "Transmitir",
|
"term.cast": "Transmitir",
|
||||||
"term.cast2" : "Transmitir a los Dispositivos",
|
"term.cast2": "Transmitir a los Dispositivos",
|
||||||
"term.quit" : "Salir",
|
"term.quit": "Salir",
|
||||||
"term.zoomin" : "Acercar",
|
"term.zoomin": "Acercar",
|
||||||
"term.zoomout" : "Alejar",
|
"term.zoomout": "Alejar",
|
||||||
"term.zoomreset" : "Restablecer",
|
"term.zoomreset": "Restablecer",
|
||||||
"term.fullscreen" : "Pantalla Completa",
|
"term.fullscreen": "Pantalla Completa",
|
||||||
"term.nowPlaying": "Reproduciendo Ahora",
|
"term.nowPlaying": "Reproduciendo Ahora",
|
||||||
"home.syncFavorites": "Sincronizar Favoritos",
|
"home.syncFavorites": "Sincronizar Favoritos",
|
||||||
"home.syncFavorites.gettingArtists": "Consiguiendo Artistas Favoritos...",
|
"home.syncFavorites.gettingArtists": "Consiguiendo Artistas Favoritos...",
|
||||||
|
|
|
@ -201,16 +201,16 @@
|
||||||
"term.confirmLogout": "¿Estás seguro de que quieres cerrar sesión?",
|
"term.confirmLogout": "¿Estás seguro de que quieres cerrar sesión?",
|
||||||
"term.creditDesignedBy": "Diseñado por ${authorUsername}",
|
"term.creditDesignedBy": "Diseñado por ${authorUsername}",
|
||||||
"term.discNumber": "Disco ${discNumber}",
|
"term.discNumber": "Disco ${discNumber}",
|
||||||
"term.reload" : "¿ Recargar Cider ?",
|
"term.reload": "¿ Recargar Cider ?",
|
||||||
"term.toggleprivate" : "Cambiar a Sesión Privada",
|
"term.toggleprivate": "Cambiar a Sesión Privada",
|
||||||
"term.webremote" : "Web Remoto",
|
"term.webremote": "Web Remoto",
|
||||||
"term.cast" : "Transmitir",
|
"term.cast": "Transmitir",
|
||||||
"term.cast2" : "Transmitir a los Dispositivos",
|
"term.cast2": "Transmitir a los Dispositivos",
|
||||||
"term.quit" : "Salir",
|
"term.quit": "Salir",
|
||||||
"term.zoomin" : "Acercar",
|
"term.zoomin": "Acercar",
|
||||||
"term.zoomout" : "Alejar",
|
"term.zoomout": "Alejar",
|
||||||
"term.zoomreset" : "Restablecer",
|
"term.zoomreset": "Restablecer",
|
||||||
"term.fullscreen" : "Pantalla Completa",
|
"term.fullscreen": "Pantalla Completa",
|
||||||
"term.nowPlaying": "Reproduciendo Ahora",
|
"term.nowPlaying": "Reproduciendo Ahora",
|
||||||
"home.syncFavorites": "Sincronizar Favoritos",
|
"home.syncFavorites": "Sincronizar Favoritos",
|
||||||
"home.syncFavorites.gettingArtists": "Consiguiendo Artistas Favoritos...",
|
"home.syncFavorites.gettingArtists": "Consiguiendo Artistas Favoritos...",
|
||||||
|
|
|
@ -309,5 +309,4 @@
|
||||||
"share.platform.email": "Sähköposti",
|
"share.platform.email": "Sähköposti",
|
||||||
"share.platform.songLink": "Kopioi song.link",
|
"share.platform.songLink": "Kopioi song.link",
|
||||||
"share.platform.clipboard": "Kopioi linkki"
|
"share.platform.clipboard": "Kopioi linkki"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,16 +195,16 @@
|
||||||
"term.confirmLogout": "Apakah Anda yakin ingin keluar??",
|
"term.confirmLogout": "Apakah Anda yakin ingin keluar??",
|
||||||
"term.creditDesignedBy": "Dirancang oleh ${authorUsername}",
|
"term.creditDesignedBy": "Dirancang oleh ${authorUsername}",
|
||||||
"term.discNumber": "Kaset ${discNumber}",
|
"term.discNumber": "Kaset ${discNumber}",
|
||||||
"term.reload" : "Muat ulang Cider?",
|
"term.reload": "Muat ulang Cider?",
|
||||||
"term.toggleprivate" : "Nyalakan Sesi Pribadi",
|
"term.toggleprivate": "Nyalakan Sesi Pribadi",
|
||||||
"term.webremote" : "Remot Web",
|
"term.webremote": "Remot Web",
|
||||||
"term.cast" : "Transmisi",
|
"term.cast": "Transmisi",
|
||||||
"term.cast2" : "Transmisikan ke Perangkat",
|
"term.cast2": "Transmisikan ke Perangkat",
|
||||||
"term.quit" : "Keluar",
|
"term.quit": "Keluar",
|
||||||
"term.zoomin" : "Perbesar",
|
"term.zoomin": "Perbesar",
|
||||||
"term.zoomout" : "Perkecil",
|
"term.zoomout": "Perkecil",
|
||||||
"term.zoomreset" : "Atur Ulang",
|
"term.zoomreset": "Atur Ulang",
|
||||||
"term.fullscreen" : "Layar Penuh",
|
"term.fullscreen": "Layar Penuh",
|
||||||
"home.syncFavorites": "Sinkronkan Favorit",
|
"home.syncFavorites": "Sinkronkan Favorit",
|
||||||
"home.syncFavorites.gettingArtists": "Mendapatkan artis favorit",
|
"home.syncFavorites.gettingArtists": "Mendapatkan artis favorit",
|
||||||
"home.title": "Beranda",
|
"home.title": "Beranda",
|
||||||
|
@ -331,10 +331,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider akan melanjutkan sesi terakhir Anda di perangkat ini.",
|
"settings.option.general.resumebehavior.locally.description": "Cider akan melanjutkan sesi terakhir Anda di perangkat ini.",
|
||||||
"settings.option.general.resumebehavior.history": "Riwayat",
|
"settings.option.general.resumebehavior.history": "Riwayat",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider akan melanjutkan lagu terakhir dari riwayat Apple Music di seluruh perangkat Anda.",
|
"settings.option.general.resumebehavior.history.description": "Cider akan melanjutkan lagu terakhir dari riwayat Apple Music di seluruh perangkat Anda.",
|
||||||
"settings.option.general.resumetabs" : "Buka Tab ketika Diluncurkan",
|
"settings.option.general.resumetabs": "Buka Tab ketika Diluncurkan",
|
||||||
"settings.option.general.resumetabs.description" : "Anda dapat memilih tab apa yang akan dibuka ketika Anda membuka Cider.",
|
"settings.option.general.resumetabs.description": "Anda dapat memilih tab apa yang akan dibuka ketika Anda membuka Cider.",
|
||||||
"settings.option.general.resumetabs.dynamic" : "Dinamis",
|
"settings.option.general.resumetabs.dynamic": "Dinamis",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "Cider akan membuka tab yang terakhir digunakan",
|
"settings.option.general.resumetabs.dynamic.description": "Cider akan membuka tab yang terakhir digunakan",
|
||||||
"settings.option.general.language.main": "Bahasa",
|
"settings.option.general.language.main": "Bahasa",
|
||||||
"settings.option.general.language.fun": "Bahasa Candaan",
|
"settings.option.general.language.fun": "Bahasa Candaan",
|
||||||
"settings.option.general.language.unsorted": "Tidak disortir",
|
"settings.option.general.language.unsorted": "Tidak disortir",
|
||||||
|
|
|
@ -341,10 +341,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "このコンピューターでの最終セッションを復元",
|
"settings.option.general.resumebehavior.locally.description": "このコンピューターでの最終セッションを復元",
|
||||||
"settings.option.general.resumebehavior.history": "履歴",
|
"settings.option.general.resumebehavior.history": "履歴",
|
||||||
"settings.option.general.resumebehavior.history.description": "Apple Musicの履歴から曲を復元",
|
"settings.option.general.resumebehavior.history.description": "Apple Musicの履歴から曲を復元",
|
||||||
"settings.option.general.resumetabs" : "起動時にタブを開く",
|
"settings.option.general.resumetabs": "起動時にタブを開く",
|
||||||
"settings.option.general.resumetabs.description" : "Ciderを起動したときに開くタブを選択することができます",
|
"settings.option.general.resumetabs.description": "Ciderを起動したときに開くタブを選択することができます",
|
||||||
"settings.option.general.resumetabs.dynamic" : "ダイナミック",
|
"settings.option.general.resumetabs.dynamic": "ダイナミック",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "最後のセッションで開いていたタブを開きます",
|
"settings.option.general.resumetabs.dynamic.description": "最後のセッションで開いていたタブを開きます",
|
||||||
"settings.option.general.language.main": "メイン",
|
"settings.option.general.language.main": "メイン",
|
||||||
"settings.option.general.language.fun": "荒らし",
|
"settings.option.general.language.fun": "荒らし",
|
||||||
"settings.option.general.language.unsorted": "未分類",
|
"settings.option.general.language.unsorted": "未分類",
|
||||||
|
|
|
@ -209,16 +209,16 @@
|
||||||
"term.confirmLogout": "Вы уверены, что хотите выйти?",
|
"term.confirmLogout": "Вы уверены, что хотите выйти?",
|
||||||
"term.creditDesignedBy": "Разработано ${authorUsername}",
|
"term.creditDesignedBy": "Разработано ${authorUsername}",
|
||||||
"term.discNumber": "Диск ${discNumber}",
|
"term.discNumber": "Диск ${discNumber}",
|
||||||
"term.reload" : "Перезагрузить Cider?",
|
"term.reload": "Перезагрузить Cider?",
|
||||||
"term.toggleprivate" : "Переключить частную сессию",
|
"term.toggleprivate": "Переключить частную сессию",
|
||||||
"term.webremote" : "Web Remote",
|
"term.webremote": "Web Remote",
|
||||||
"term.cast" : "Транслировать",
|
"term.cast": "Транслировать",
|
||||||
"term.cast2" : "Трансляция на устройства",
|
"term.cast2": "Трансляция на устройства",
|
||||||
"term.quit" : "Выход",
|
"term.quit": "Выход",
|
||||||
"term.zoomin" : "Приблизить",
|
"term.zoomin": "Приблизить",
|
||||||
"term.zoomout" : "Отдалить",
|
"term.zoomout": "Отдалить",
|
||||||
"term.zoomreset" : "Сбросить масштаб",
|
"term.zoomreset": "Сбросить масштаб",
|
||||||
"term.fullscreen" : "Полный экран",
|
"term.fullscreen": "Полный экран",
|
||||||
"term.nowPlaying": "Сейчас играет",
|
"term.nowPlaying": "Сейчас играет",
|
||||||
"home.syncFavorites": "Синхронизировать",
|
"home.syncFavorites": "Синхронизировать",
|
||||||
"home.syncFavorites.gettingArtists": "Получение отслеживаемых исполнителей...",
|
"home.syncFavorites.gettingArtists": "Получение отслеживаемых исполнителей...",
|
||||||
|
@ -347,10 +347,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider возобновит ваш последний сеанс на этом компьютере.",
|
"settings.option.general.resumebehavior.locally.description": "Cider возобновит ваш последний сеанс на этом компьютере.",
|
||||||
"settings.option.general.resumebehavior.history": "История",
|
"settings.option.general.resumebehavior.history": "История",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider поставит в очередь последнюю песню из вашей общей истории Apple Music на разных устройствах.",
|
"settings.option.general.resumebehavior.history.description": "Cider поставит в очередь последнюю песню из вашей общей истории Apple Music на разных устройствах.",
|
||||||
"settings.option.general.resumetabs" : "Раздел при запуске",
|
"settings.option.general.resumetabs": "Раздел при запуске",
|
||||||
"settings.option.general.resumetabs.description" : "Вы можете выбрать, какой раздел будет открыться при запуске Cider.",
|
"settings.option.general.resumetabs.description": "Вы можете выбрать, какой раздел будет открыться при запуске Cider.",
|
||||||
"settings.option.general.resumetabs.dynamic" : "Динамически",
|
"settings.option.general.resumetabs.dynamic": "Динамически",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "Cider откроет последний использованный раздел.",
|
"settings.option.general.resumetabs.dynamic.description": "Cider откроет последний использованный раздел.",
|
||||||
"settings.option.general.language.main": "Языки",
|
"settings.option.general.language.main": "Языки",
|
||||||
"settings.option.general.language.fun": "Забавные языки",
|
"settings.option.general.language.fun": "Забавные языки",
|
||||||
"settings.option.general.language.unsorted": "Неотсортированные",
|
"settings.option.general.language.unsorted": "Неотсортированные",
|
||||||
|
|
|
@ -202,16 +202,16 @@
|
||||||
"term.confirmLogout": "Are you sure you want to logout?",
|
"term.confirmLogout": "Are you sure you want to logout?",
|
||||||
"term.creditDesignedBy": "Designed by ${authorUsername}",
|
"term.creditDesignedBy": "Designed by ${authorUsername}",
|
||||||
"term.discNumber": "Disc ${discNumber}",
|
"term.discNumber": "Disc ${discNumber}",
|
||||||
"term.reload" : "Reload Cider?",
|
"term.reload": "Reload Cider?",
|
||||||
"term.toggleprivate" : "Toggle Private Session",
|
"term.toggleprivate": "Toggle Private Session",
|
||||||
"term.webremote" : "Web Remote",
|
"term.webremote": "Web Remote",
|
||||||
"term.cast" : "Cast",
|
"term.cast": "Cast",
|
||||||
"term.cast2" : "Cast to Devices",
|
"term.cast2": "Cast to Devices",
|
||||||
"term.quit" : "Quit",
|
"term.quit": "Quit",
|
||||||
"term.zoomin" : "Zoom In",
|
"term.zoomin": "Zoom In",
|
||||||
"term.zoomout" : "Zoom Out",
|
"term.zoomout": "Zoom Out",
|
||||||
"term.zoomreset" : "Reset Zoom",
|
"term.zoomreset": "Reset Zoom",
|
||||||
"term.fullscreen" : "Fullscreen",
|
"term.fullscreen": "Fullscreen",
|
||||||
"term.nowPlaying": "Now Playing",
|
"term.nowPlaying": "Now Playing",
|
||||||
"home.syncFavorites": "Sync Favorites",
|
"home.syncFavorites": "Sync Favorites",
|
||||||
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
|
"home.syncFavorites.gettingArtists": "Getting Favorited Artists...",
|
||||||
|
@ -340,10 +340,10 @@
|
||||||
"settings.option.general.resumebehavior.locally.description": "Cider will resume your last session on this machine.",
|
"settings.option.general.resumebehavior.locally.description": "Cider will resume your last session on this machine.",
|
||||||
"settings.option.general.resumebehavior.history": "History",
|
"settings.option.general.resumebehavior.history": "History",
|
||||||
"settings.option.general.resumebehavior.history.description": "Cider will queue the last song from your overall Apple Music history, across devices.",
|
"settings.option.general.resumebehavior.history.description": "Cider will queue the last song from your overall Apple Music history, across devices.",
|
||||||
"settings.option.general.resumetabs" : "Open Tab on Launch",
|
"settings.option.general.resumetabs": "Open Tab on Launch",
|
||||||
"settings.option.general.resumetabs.description" : "You can choose what tab you want to open when you launch Cider.",
|
"settings.option.general.resumetabs.description": "You can choose what tab you want to open when you launch Cider.",
|
||||||
"settings.option.general.resumetabs.dynamic" : "Dynamic",
|
"settings.option.general.resumetabs.dynamic": "Dynamic",
|
||||||
"settings.option.general.resumetabs.dynamic.description" : "Cider will open the tab that you last used.",
|
"settings.option.general.resumetabs.dynamic.description": "Cider will open the tab that you last used.",
|
||||||
"settings.option.general.language.main": "Languages",
|
"settings.option.general.language.main": "Languages",
|
||||||
"settings.option.general.language.fun": "Fun Languages",
|
"settings.option.general.language.fun": "Fun Languages",
|
||||||
"settings.option.general.language.unsorted": "Unsorted",
|
"settings.option.general.language.unsorted": "Unsorted",
|
||||||
|
|
|
@ -186,16 +186,16 @@
|
||||||
"term.confirmLogout": "你确定要退出登录吗?",
|
"term.confirmLogout": "你确定要退出登录吗?",
|
||||||
"term.creditDesignedBy": "由 ${authorUsername} 设计",
|
"term.creditDesignedBy": "由 ${authorUsername} 设计",
|
||||||
"term.discNumber": "碟 ${discNumber}",
|
"term.discNumber": "碟 ${discNumber}",
|
||||||
"term.reload" : "重新载入 Cider?",
|
"term.reload": "重新载入 Cider?",
|
||||||
"term.toggleprivate": "切换隐身聆听",
|
"term.toggleprivate": "切换隐身聆听",
|
||||||
"term.webremote": "远程控制",
|
"term.webremote": "远程控制",
|
||||||
"term.cast": "投射",
|
"term.cast": "投射",
|
||||||
"term.cast2" : "投射到设备",
|
"term.cast2": "投射到设备",
|
||||||
"term.quit" : "退出应用",
|
"term.quit": "退出应用",
|
||||||
"term.zoomin" : "放大",
|
"term.zoomin": "放大",
|
||||||
"term.zoomout" : "缩小",
|
"term.zoomout": "缩小",
|
||||||
"term.zoomreset" : "重置缩放",
|
"term.zoomreset": "重置缩放",
|
||||||
"term.fullscreen" : "全屏模式",
|
"term.fullscreen": "全屏模式",
|
||||||
"term.nowPlaying": "正在播放",
|
"term.nowPlaying": "正在播放",
|
||||||
"home.syncFavorites": "同步喜爱艺人",
|
"home.syncFavorites": "同步喜爱艺人",
|
||||||
"home.syncFavorites.gettingArtists": "获取喜爱艺人...",
|
"home.syncFavorites.gettingArtists": "获取喜爱艺人...",
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
"term.accountSettings": "帳戶設定",
|
"term.accountSettings": "帳戶設定",
|
||||||
"term.logout": "登出",
|
"term.logout": "登出",
|
||||||
"term.login": "登入",
|
"term.login": "登入",
|
||||||
"term.quit" : "結束",
|
"term.quit": "結束",
|
||||||
"term.about": "關於",
|
"term.about": "關於",
|
||||||
"term.cast" : "投影",
|
"term.cast": "投影",
|
||||||
"term.cast2" : "投影到裝置",
|
"term.cast2": "投影到裝置",
|
||||||
"term.privateSession": "私人時間",
|
"term.privateSession": "私人時間",
|
||||||
"term.queue": "待播清單",
|
"term.queue": "待播清單",
|
||||||
"term.lyrics": "歌詞",
|
"term.lyrics": "歌詞",
|
||||||
|
@ -146,14 +146,14 @@
|
||||||
"term.plugins": "模組",
|
"term.plugins": "模組",
|
||||||
"term.pluginMenu": "模組選單",
|
"term.pluginMenu": "模組選單",
|
||||||
"term.pluginMenu.none": "沒有交互式模組",
|
"term.pluginMenu.none": "沒有交互式模組",
|
||||||
"term.fullscreen" : "全螢幕模式",
|
"term.fullscreen": "全螢幕模式",
|
||||||
"home.title": "首頁",
|
"home.title": "首頁",
|
||||||
"home.recentlyPlayed": "最近播放",
|
"home.recentlyPlayed": "最近播放",
|
||||||
"home.recentlyAdded": "最近加入",
|
"home.recentlyAdded": "最近加入",
|
||||||
"home.artistsFeed": "藝人追蹤",
|
"home.artistsFeed": "藝人追蹤",
|
||||||
"home.artistsFeed.noArtist": "追蹤你喜愛的藝人來取得他們的最新發行歌曲。",
|
"home.artistsFeed.noArtist": "追蹤你喜愛的藝人來取得他們的最新發行歌曲。",
|
||||||
"home.syncFavorites" : "同步追蹤" ,
|
"home.syncFavorites": "同步追蹤",
|
||||||
"home.syncFavorites.gettingArtists" : "取得追蹤的藝人歌手列表... " ,
|
"home.syncFavorites.gettingArtists": "取得追蹤的藝人歌手列表... ",
|
||||||
"home.madeForYou": "為您推薦",
|
"home.madeForYou": "為您推薦",
|
||||||
"home.friendsListeningTo": "朋友正在聆聽",
|
"home.friendsListeningTo": "朋友正在聆聽",
|
||||||
"home.followedArtists": "追蹤的藝人",
|
"home.followedArtists": "追蹤的藝人",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {app, Menu, nativeImage, Tray, ipcMain, clipboard, shell} from 'electron';
|
import { app, Menu, nativeImage, Tray, ipcMain, clipboard, shell } from "electron";
|
||||||
import {readFileSync} from "fs";
|
import { readFileSync } from "fs";
|
||||||
import * as path from 'path';
|
import * as path from "path";
|
||||||
import * as log from 'electron-log';
|
import * as log from "electron-log";
|
||||||
import {utils} from './utils';
|
import { utils } from "./utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file Creates App instance
|
* @file Creates App instance
|
||||||
|
@ -11,14 +11,7 @@ import {utils} from './utils';
|
||||||
|
|
||||||
/** @namespace */
|
/** @namespace */
|
||||||
export class AppEvents {
|
export class AppEvents {
|
||||||
private protocols: string[] = [
|
private protocols: string[] = ["ame", "cider", "itms", "itmss", "musics", "music"];
|
||||||
"ame",
|
|
||||||
"cider",
|
|
||||||
"itms",
|
|
||||||
"itmss",
|
|
||||||
"musics",
|
|
||||||
"music"
|
|
||||||
]
|
|
||||||
private plugin: any = undefined;
|
private plugin: any = undefined;
|
||||||
private tray: any = undefined;
|
private tray: any = undefined;
|
||||||
private i18n: any = undefined;
|
private i18n: any = undefined;
|
||||||
|
@ -33,68 +26,68 @@ export class AppEvents {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
private start(): void {
|
private start(): void {
|
||||||
AppEvents.initLogging()
|
AppEvents.initLogging();
|
||||||
console.info('[AppEvents] App started');
|
console.info("[AppEvents] App started");
|
||||||
|
|
||||||
/**********************************************************************************************************************
|
/**********************************************************************************************************************
|
||||||
* Startup arguments handling
|
* Startup arguments handling
|
||||||
**********************************************************************************************************************/
|
**********************************************************************************************************************/
|
||||||
if (app.commandLine.hasSwitch('version') || app.commandLine.hasSwitch('v')) {
|
if (app.commandLine.hasSwitch("version") || app.commandLine.hasSwitch("v")) {
|
||||||
console.log(app.getVersion())
|
console.log(app.getVersion());
|
||||||
app.exit()
|
app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verbose Check
|
// Verbose Check
|
||||||
if (app.commandLine.hasSwitch('verbose')) {
|
if (app.commandLine.hasSwitch("verbose")) {
|
||||||
console.log("[Cider] User has launched the application with --verbose");
|
console.log("[Cider] User has launched the application with --verbose");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log File Location
|
// Log File Location
|
||||||
if (app.commandLine.hasSwitch('log') || app.commandLine.hasSwitch('l')) {
|
if (app.commandLine.hasSwitch("log") || app.commandLine.hasSwitch("l")) {
|
||||||
console.log(path.join(app.getPath('userData'), 'logs'))
|
console.log(path.join(app.getPath("userData"), "logs"));
|
||||||
app.exit()
|
app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try limiting JS memory to 350MB.
|
// Try limiting JS memory to 350MB.
|
||||||
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=350');
|
app.commandLine.appendSwitch("js-flags", "--max-old-space-size=350");
|
||||||
|
|
||||||
// Expose GC
|
// Expose GC
|
||||||
app.commandLine.appendSwitch('js-flags', '--expose_gc')
|
app.commandLine.appendSwitch("js-flags", "--expose_gc");
|
||||||
|
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
app.setAppUserModelId(app.getName()) // For notification name
|
app.setAppUserModelId(app.getName()); // For notification name
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************
|
/***********************************************************************************************************************
|
||||||
* Commandline arguments
|
* Commandline arguments
|
||||||
**********************************************************************************************************************/
|
**********************************************************************************************************************/
|
||||||
switch (utils.getStoreValue('visual.hw_acceleration') as string) {
|
switch (utils.getStoreValue("visual.hw_acceleration") as string) {
|
||||||
default:
|
default:
|
||||||
case "default":
|
case "default":
|
||||||
app.commandLine.appendSwitch('enable-accelerated-mjpeg-decode')
|
app.commandLine.appendSwitch("enable-accelerated-mjpeg-decode");
|
||||||
app.commandLine.appendSwitch('enable-accelerated-video')
|
app.commandLine.appendSwitch("enable-accelerated-video");
|
||||||
app.commandLine.appendSwitch('disable-gpu-driver-bug-workarounds')
|
app.commandLine.appendSwitch("disable-gpu-driver-bug-workarounds");
|
||||||
app.commandLine.appendSwitch('ignore-gpu-blacklist')
|
app.commandLine.appendSwitch("ignore-gpu-blacklist");
|
||||||
app.commandLine.appendSwitch('enable-native-gpu-memory-buffers')
|
app.commandLine.appendSwitch("enable-native-gpu-memory-buffers");
|
||||||
app.commandLine.appendSwitch('enable-accelerated-video-decode');
|
app.commandLine.appendSwitch("enable-accelerated-video-decode");
|
||||||
app.commandLine.appendSwitch('enable-gpu-rasterization');
|
app.commandLine.appendSwitch("enable-gpu-rasterization");
|
||||||
app.commandLine.appendSwitch('enable-native-gpu-memory-buffers');
|
app.commandLine.appendSwitch("enable-native-gpu-memory-buffers");
|
||||||
app.commandLine.appendSwitch('enable-oop-rasterization');
|
app.commandLine.appendSwitch("enable-oop-rasterization");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "webgpu":
|
case "webgpu":
|
||||||
console.info("WebGPU is enabled.");
|
console.info("WebGPU is enabled.");
|
||||||
app.commandLine.appendSwitch('enable-unsafe-webgpu')
|
app.commandLine.appendSwitch("enable-unsafe-webgpu");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "disabled":
|
case "disabled":
|
||||||
console.info("Hardware acceleration is disabled.");
|
console.info("Hardware acceleration is disabled.");
|
||||||
app.commandLine.appendSwitch('disable-gpu')
|
app.commandLine.appendSwitch("disable-gpu");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === "linux") {
|
if (process.platform === "linux") {
|
||||||
app.commandLine.appendSwitch('disable-features', 'MediaSessionService');
|
app.commandLine.appendSwitch("disable-features", "MediaSessionService");
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************
|
/***********************************************************************************************************************
|
||||||
|
@ -104,48 +97,50 @@ export class AppEvents {
|
||||||
if (process.defaultApp) {
|
if (process.defaultApp) {
|
||||||
if (process.argv.length >= 2) {
|
if (process.argv.length >= 2) {
|
||||||
this.protocols.forEach((protocol: string) => {
|
this.protocols.forEach((protocol: string) => {
|
||||||
app.setAsDefaultProtocolClient(protocol, process.execPath, [path.resolve(process.argv[1])])
|
app.setAsDefaultProtocolClient(protocol, process.execPath, [path.resolve(process.argv[1])]);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.protocols.forEach((protocol: string) => {
|
this.protocols.forEach((protocol: string) => {
|
||||||
app.setAsDefaultProtocolClient(protocol)
|
app.setAsDefaultProtocolClient(protocol);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public quit() {
|
public quit() {
|
||||||
console.log('[AppEvents] App quit');
|
console.log("[AppEvents] App quit");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ready(plug: any) {
|
public ready(plug: any) {
|
||||||
this.plugin = plug
|
this.plugin = plug;
|
||||||
console.log('[AppEvents] App ready');
|
console.log("[AppEvents] App ready");
|
||||||
|
|
||||||
AppEvents.setLoginSettings()
|
AppEvents.setLoginSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bwCreated() {
|
public bwCreated() {
|
||||||
app.on('open-url', (event, url) => {
|
app.on("open-url", (event, url) => {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
if (this.protocols.some((protocol: string) => url.includes(protocol))) {
|
if (this.protocols.some((protocol: string) => url.includes(protocol))) {
|
||||||
this.LinkHandler(url)
|
this.LinkHandler(url);
|
||||||
console.log(url)
|
console.log(url);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
if (process.platform === "darwin") {
|
if (process.platform === "darwin") {
|
||||||
app.setUserActivity('8R23J2835D.com.ciderapp.webremote.play', {
|
app.setUserActivity(
|
||||||
title: 'Web Remote',
|
"8R23J2835D.com.ciderapp.webremote.play",
|
||||||
description: 'Connect to your Web Remote',
|
{
|
||||||
}, "https://webremote.cider.sh")
|
title: "Web Remote",
|
||||||
|
description: "Connect to your Web Remote",
|
||||||
|
},
|
||||||
|
"https://webremote.cider.sh"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.InstanceHandler()
|
this.InstanceHandler();
|
||||||
if (process.platform !== "darwin") {
|
if (process.platform !== "darwin") {
|
||||||
this.InitTray()
|
this.InitTray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,58 +156,61 @@ export class AppEvents {
|
||||||
if (!arg) return;
|
if (!arg) return;
|
||||||
|
|
||||||
// LastFM Auth URL
|
// LastFM Auth URL
|
||||||
if (arg.includes('auth')) {
|
if (arg.includes("auth")) {
|
||||||
const authURI = arg.split('/auth/')[1]
|
const authURI = arg.split("/auth/")[1];
|
||||||
if (authURI.startsWith('lastfm')) { // If we wanted more auth options
|
if (authURI.startsWith("lastfm")) {
|
||||||
console.log('token: ', authURI.split('lastfm?token=')[1])
|
// If we wanted more auth options
|
||||||
utils.getWindow().webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', "${authURI.split('lastfm?token=')[1]}")`).catch(console.error)
|
console.log("token: ", authURI.split("lastfm?token=")[1]);
|
||||||
|
utils
|
||||||
|
.getWindow()
|
||||||
|
.webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', "${authURI.split("lastfm?token=")[1]}")`)
|
||||||
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
}
|
} else if (arg.includes("playpause")) {
|
||||||
else if (arg.includes('playpause')) {
|
|
||||||
//language=JS
|
//language=JS
|
||||||
utils.getWindow().webContents.executeJavaScript('MusicKitInterop.playPause()')
|
utils.getWindow().webContents.executeJavaScript("MusicKitInterop.playPause()");
|
||||||
}
|
} else if (arg.includes("nextitem")) {
|
||||||
else if (arg.includes('nextitem')) {
|
|
||||||
//language=JS
|
//language=JS
|
||||||
utils.getWindow().webContents.executeJavaScript('app.mk.skipToNextItem()')
|
utils.getWindow().webContents.executeJavaScript("app.mk.skipToNextItem()");
|
||||||
}
|
}
|
||||||
// Play
|
// Play
|
||||||
else if (arg.includes('/play/')) { //Steer away from protocol:// specific conditionals
|
else if (arg.includes("/play/")) {
|
||||||
const playParam = arg.split('/play/')[1]
|
//Steer away from protocol:// specific conditionals
|
||||||
|
const playParam = arg.split("/play/")[1];
|
||||||
|
|
||||||
const mediaType = {
|
const mediaType = {
|
||||||
"s/": "song",
|
"s/": "song",
|
||||||
"a/": "album",
|
"a/": "album",
|
||||||
"p/": "playlist"
|
"p/": "playlist",
|
||||||
}
|
};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(mediaType)) {
|
for (const [key, value] of Object.entries(mediaType)) {
|
||||||
if (playParam.includes(key)) {
|
if (playParam.includes(key)) {
|
||||||
const id = playParam.split(key)[1]
|
const id = playParam.split(key)[1];
|
||||||
utils.getWindow().webContents.send('play', value, id)
|
utils.getWindow().webContents.send("play", value, id);
|
||||||
console.debug(`[LinkHandler] Attempting to load ${value} by id: ${id}`)
|
console.debug(`[LinkHandler] Attempting to load ${value} by id: ${id}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (arg.includes("music.apple.com")) {
|
||||||
} else if (arg.includes('music.apple.com')) { // URL (used with itms/itmss/music/musics uris)
|
// URL (used with itms/itmss/music/musics uris)
|
||||||
console.log(arg)
|
console.log(arg);
|
||||||
let url = arg.split('//')[1]
|
let url = arg.split("//")[1];
|
||||||
console.warn(`[LinkHandler] Attempting to load url: ${url}`);
|
console.warn(`[LinkHandler] Attempting to load url: ${url}`);
|
||||||
utils.getWindow().webContents.send('play', 'url', url)
|
utils.getWindow().webContents.send("play", "url", url);
|
||||||
} else if (arg.includes('/debug/appdata')) {
|
} else if (arg.includes("/debug/appdata")) {
|
||||||
shell.openPath(app.getPath('userData'))
|
shell.openPath(app.getPath("userData"));
|
||||||
} else if (arg.includes('/debug/logs')) {
|
} else if (arg.includes("/debug/logs")) {
|
||||||
shell.openPath(app.getPath('logs'))
|
shell.openPath(app.getPath("logs"));
|
||||||
} else if (arg.includes('/discord')) {
|
} else if (arg.includes("/discord")) {
|
||||||
shell.openExternal('https://discord.gg/applemusic')
|
shell.openExternal("https://discord.gg/applemusic");
|
||||||
} else if (arg.includes('/github')) {
|
} else if (arg.includes("/github")) {
|
||||||
shell.openExternal('https://github.com/ciderapp/cider')
|
shell.openExternal("https://github.com/ciderapp/cider");
|
||||||
} else if (arg.includes('/donate')) {
|
} else if (arg.includes("/donate")) {
|
||||||
shell.openExternal('https://opencollective.com/ciderapp')
|
shell.openExternal("https://opencollective.com/ciderapp");
|
||||||
} else if (arg.includes('/beep')) {
|
} else if (arg.includes("/beep")) {
|
||||||
shell.beep()
|
shell.beep();
|
||||||
} else {
|
} else {
|
||||||
utils.getWindow().webContents.executeJavaScript(`app.appRoute('${arg.split('//')[1]}')`)
|
utils.getWindow().webContents.executeJavaScript(`app.appRoute('${arg.split("//")[1]}')`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,32 +219,33 @@ export class AppEvents {
|
||||||
*/
|
*/
|
||||||
private InstanceHandler() {
|
private InstanceHandler() {
|
||||||
// Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found)
|
// Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found)
|
||||||
const gotTheLock = app.requestSingleInstanceLock()
|
const gotTheLock = app.requestSingleInstanceLock();
|
||||||
|
|
||||||
if (!gotTheLock) { // Runs on the new instance if another instance has been found
|
if (!gotTheLock) {
|
||||||
console.log('[Cider] Another instance has been found, quitting.')
|
// Runs on the new instance if another instance has been found
|
||||||
app.quit()
|
console.log("[Cider] Another instance has been found, quitting.");
|
||||||
} else { // Runs on the first instance if no other instance has been found
|
app.quit();
|
||||||
app.on('second-instance', (_event, startArgs) => {
|
} else {
|
||||||
console.log("[InstanceHandler] (second-instance) Instance started with " + startArgs.toString())
|
// Runs on the first instance if no other instance has been found
|
||||||
|
app.on("second-instance", (_event, startArgs) => {
|
||||||
|
console.log("[InstanceHandler] (second-instance) Instance started with " + startArgs.toString());
|
||||||
|
|
||||||
startArgs.forEach(arg => {
|
startArgs.forEach((arg) => {
|
||||||
console.log(arg)
|
console.log(arg);
|
||||||
if (arg.includes("cider://")) {
|
if (arg.includes("cider://")) {
|
||||||
console.debug('[InstanceHandler] (second-instance) Link detected with ' + arg)
|
console.debug("[InstanceHandler] (second-instance) Link detected with " + arg);
|
||||||
this.LinkHandler(arg)
|
this.LinkHandler(arg);
|
||||||
} else if (arg.includes("--force-quit")) {
|
} else if (arg.includes("--force-quit")) {
|
||||||
console.warn('[InstanceHandler] (second-instance) Force Quit found. Quitting App.');
|
console.warn("[InstanceHandler] (second-instance) Force Quit found. Quitting App.");
|
||||||
app.quit()
|
app.quit();
|
||||||
} else if (utils.getWindow()) {
|
} else if (utils.getWindow()) {
|
||||||
if (utils.getWindow().isMinimized()) utils.getWindow().restore()
|
if (utils.getWindow().isMinimized()) utils.getWindow().restore();
|
||||||
utils.getWindow().show()
|
utils.getWindow().show();
|
||||||
utils.getWindow().focus()
|
utils.getWindow().focus();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,48 +253,48 @@ export class AppEvents {
|
||||||
*/
|
*/
|
||||||
private InitTray() {
|
private InitTray() {
|
||||||
const icons = {
|
const icons = {
|
||||||
"win32": nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.ico`)).resize({
|
win32: nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.ico`)).resize({
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32
|
height: 32,
|
||||||
}),
|
}),
|
||||||
"linux": nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
linux: nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
||||||
width: 32,
|
width: 32,
|
||||||
height: 32
|
height: 32,
|
||||||
}),
|
}),
|
||||||
"darwin": nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
darwin: nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20,
|
||||||
}),
|
}),
|
||||||
}
|
};
|
||||||
this.tray = new Tray(process.platform === 'win32' ? icons.win32 : (process.platform === 'darwin' ? icons.darwin : icons.linux))
|
this.tray = new Tray(process.platform === "win32" ? icons.win32 : process.platform === "darwin" ? icons.darwin : icons.linux);
|
||||||
this.tray.setToolTip(app.getName())
|
this.tray.setToolTip(app.getName());
|
||||||
this.setTray(false)
|
this.setTray(false);
|
||||||
|
|
||||||
this.tray.on('double-click', () => {
|
this.tray.on("double-click", () => {
|
||||||
if (utils.getWindow()) {
|
if (utils.getWindow()) {
|
||||||
if (utils.getWindow().isVisible()) {
|
if (utils.getWindow().isVisible()) {
|
||||||
utils.getWindow().focus()
|
utils.getWindow().focus();
|
||||||
} else {
|
} else {
|
||||||
utils.getWindow().show()
|
utils.getWindow().show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
utils.getWindow().on('show', () => {
|
utils.getWindow().on("show", () => {
|
||||||
this.setTray(true)
|
this.setTray(true);
|
||||||
})
|
});
|
||||||
|
|
||||||
utils.getWindow().on('restore', () => {
|
utils.getWindow().on("restore", () => {
|
||||||
this.setTray(true)
|
this.setTray(true);
|
||||||
})
|
});
|
||||||
|
|
||||||
utils.getWindow().on('hide', () => {
|
utils.getWindow().on("hide", () => {
|
||||||
this.setTray(false)
|
this.setTray(false);
|
||||||
})
|
});
|
||||||
|
|
||||||
utils.getWindow().on('minimize', () => {
|
utils.getWindow().on("minimize", () => {
|
||||||
this.setTray(false)
|
this.setTray(false);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,23 +302,21 @@ export class AppEvents {
|
||||||
* @param visible - BrowserWindow Visibility
|
* @param visible - BrowserWindow Visibility
|
||||||
*/
|
*/
|
||||||
private setTray(visible: boolean = utils.getWindow().isVisible()) {
|
private setTray(visible: boolean = utils.getWindow().isVisible()) {
|
||||||
this.i18n = utils.getLocale(utils.getStoreValue('general.language'))
|
this.i18n = utils.getLocale(utils.getStoreValue("general.language"));
|
||||||
|
|
||||||
const ciderIcon = nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
const ciderIcon = nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24
|
height: 24,
|
||||||
})
|
});
|
||||||
|
|
||||||
const menu = Menu.buildFromTemplate([
|
const menu = Menu.buildFromTemplate([
|
||||||
|
|
||||||
{
|
{
|
||||||
label: app.getName(),
|
label: app.getName(),
|
||||||
enabled: false,
|
enabled: false,
|
||||||
icon: ciderIcon,
|
icon: ciderIcon,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
|
|
||||||
/* For now only idea i dont know if posible to implement
|
/* For now only idea i dont know if posible to implement
|
||||||
|
|
||||||
|
@ -340,50 +337,50 @@ export class AppEvents {
|
||||||
|
|
||||||
{
|
{
|
||||||
visible: !visible,
|
visible: !visible,
|
||||||
label: this.i18n['term.playpause'],
|
label: this.i18n["term.playpause"],
|
||||||
click: () => {
|
click: () => {
|
||||||
utils.getWindow().webContents.executeJavaScript('MusicKitInterop.playPause()')
|
utils.getWindow().webContents.executeJavaScript("MusicKitInterop.playPause()");
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
visible: !visible,
|
visible: !visible,
|
||||||
label: this.i18n['term.next'],
|
label: this.i18n["term.next"],
|
||||||
click: () => {
|
click: () => {
|
||||||
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`)
|
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
visible: !visible,
|
visible: !visible,
|
||||||
label: this.i18n['term.previous'],
|
label: this.i18n["term.previous"],
|
||||||
click: () => {
|
click: () => {
|
||||||
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`)
|
utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{type: 'separator', visible: !visible},
|
{ type: "separator", visible: !visible },
|
||||||
|
|
||||||
{
|
{
|
||||||
label: (visible ? this.i18n['action.tray.minimize'] : `${this.i18n['action.tray.show']}`),
|
label: visible ? this.i18n["action.tray.minimize"] : `${this.i18n["action.tray.show"]}`,
|
||||||
click: () => {
|
click: () => {
|
||||||
if (utils.getWindow()) {
|
if (utils.getWindow()) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
utils.getWindow().hide()
|
utils.getWindow().hide();
|
||||||
} else {
|
} else {
|
||||||
utils.getWindow().show()
|
utils.getWindow().show();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: this.i18n['term.quit'],
|
label: this.i18n["term.quit"],
|
||||||
click: () => {
|
click: () => {
|
||||||
app.quit()
|
app.quit();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
]);
|
||||||
this.tray.setContextMenu(menu)
|
this.tray.setContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,18 +388,21 @@ export class AppEvents {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private static initLogging() {
|
private static initLogging() {
|
||||||
log.transports.console.format = '[{h}:{i}:{s}.{ms}] [{level}] {text}';
|
log.transports.console.format = "[{h}:{i}:{s}.{ms}] [{level}] {text}";
|
||||||
Object.assign(console, log.functions);
|
Object.assign(console, log.functions);
|
||||||
console.debug = function(...args: any[]) {
|
console.debug = function (...args: any[]) {
|
||||||
if (!app.isPackaged) {
|
if (!app.isPackaged) {
|
||||||
log.debug(...args)
|
log.debug(...args);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ipcMain.on('fetch-log', (_event) => {
|
ipcMain.on("fetch-log", (_event) => {
|
||||||
const data = readFileSync(log.transports.file.getFile().path, {encoding: 'utf8', flag: 'r'});
|
const data = readFileSync(log.transports.file.getFile().path, {
|
||||||
clipboard.writeText(data)
|
encoding: "utf8",
|
||||||
})
|
flag: "r",
|
||||||
|
});
|
||||||
|
clipboard.writeText(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -410,17 +410,17 @@ export class AppEvents {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private static setLoginSettings() {
|
private static setLoginSettings() {
|
||||||
if (utils.getStoreValue('general.onStartup.enabled')) {
|
if (utils.getStoreValue("general.onStartup.enabled")) {
|
||||||
app.setLoginItemSettings({
|
app.setLoginItemSettings({
|
||||||
openAtLogin: true,
|
openAtLogin: true,
|
||||||
path: app.getPath('exe'),
|
path: app.getPath("exe"),
|
||||||
args: [`${utils.getStoreValue('general.onStartup.hidden') ? '--hidden' : ''}`]
|
args: [`${utils.getStoreValue("general.onStartup.hidden") ? "--hidden" : ""}`],
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
app.setLoginItemSettings({
|
app.setLoginItemSettings({
|
||||||
openAtLogin: false,
|
openAtLogin: false,
|
||||||
path: app.getPath('exe')
|
path: app.getPath("exe"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,10 @@
|
||||||
var util = require('util');
|
var util = require("util");
|
||||||
var castv2Cli = require('castv2-client');
|
var castv2Cli = require("castv2-client");
|
||||||
var RequestResponseController = castv2Cli.RequestResponseController;
|
var RequestResponseController = castv2Cli.RequestResponseController;
|
||||||
|
|
||||||
function CiderCastController(client, sourceId, destinationId) {
|
function CiderCastController(client, sourceId, destinationId) {
|
||||||
RequestResponseController.call(this, client, sourceId, destinationId, 'urn:x-cast:com.ciderapp.customdata');
|
RequestResponseController.call(this, client, sourceId, destinationId, "urn:x-cast:com.ciderapp.customdata");
|
||||||
this.once('close', onclose);
|
this.once("close", onclose);
|
||||||
var self = this;
|
var self = this;
|
||||||
function onclose() {
|
function onclose() {
|
||||||
self.stop();
|
self.stop();
|
||||||
|
@ -13,19 +13,19 @@ function CiderCastController(client, sourceId, destinationId) {
|
||||||
|
|
||||||
util.inherits(CiderCastController, RequestResponseController);
|
util.inherits(CiderCastController, RequestResponseController);
|
||||||
|
|
||||||
CiderCastController.prototype.sendIp = function(ip) {
|
CiderCastController.prototype.sendIp = function (ip) {
|
||||||
// TODO: Implement Callback
|
// TODO: Implement Callback
|
||||||
let data = {
|
let data = {
|
||||||
ip : ip
|
ip: ip,
|
||||||
}
|
};
|
||||||
this.request(data);
|
this.request(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderCastController.prototype.kill = function() {
|
CiderCastController.prototype.kill = function () {
|
||||||
// TODO: Implement Callback
|
// TODO: Implement Callback
|
||||||
let data = {
|
let data = {
|
||||||
action : "stop"
|
action: "stop",
|
||||||
}
|
};
|
||||||
this.request(data);
|
this.request(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//@ts-nocheck
|
//@ts-nocheck
|
||||||
var util = require('util');
|
var util = require("util");
|
||||||
// var debug = require('debug')('castv2-client');
|
// var debug = require('debug')('castv2-client');
|
||||||
var Application = require('castv2-client').Application;
|
var Application = require("castv2-client").Application;
|
||||||
var MediaController = require('castv2-client').MediaController;
|
var MediaController = require("castv2-client").MediaController;
|
||||||
var CiderCastController = require('./castcontroller');
|
var CiderCastController = require("./castcontroller");
|
||||||
|
|
||||||
function CiderReceiver(client, session) {
|
function CiderReceiver(client, session) {
|
||||||
Application.apply(this, arguments);
|
Application.apply(this, arguments);
|
||||||
|
@ -11,70 +11,69 @@ function CiderReceiver(client, session) {
|
||||||
this.media = this.createController(MediaController);
|
this.media = this.createController(MediaController);
|
||||||
this.mediaReceiver = this.createController(CiderCastController);
|
this.mediaReceiver = this.createController(CiderCastController);
|
||||||
|
|
||||||
this.media.on('status', onstatus);
|
this.media.on("status", onstatus);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
function onstatus(status) {
|
function onstatus(status) {
|
||||||
self.emit('status', status);
|
self.emit("status", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// FE96A351
|
// FE96A351
|
||||||
// 27E1334F
|
// 27E1334F
|
||||||
CiderReceiver.APP_ID = 'FE96A351';
|
CiderReceiver.APP_ID = "FE96A351";
|
||||||
|
|
||||||
util.inherits(CiderReceiver, Application);
|
util.inherits(CiderReceiver, Application);
|
||||||
|
|
||||||
CiderReceiver.prototype.getStatus = function(callback) {
|
CiderReceiver.prototype.getStatus = function (callback) {
|
||||||
this.media.getStatus.apply(this.media, arguments);
|
this.media.getStatus.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.load = function(media, options, callback) {
|
CiderReceiver.prototype.load = function (media, options, callback) {
|
||||||
this.media.load.apply(this.media, arguments);
|
this.media.load.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.play = function(callback) {
|
CiderReceiver.prototype.play = function (callback) {
|
||||||
this.media.play.apply(this.media, arguments);
|
this.media.play.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.pause = function(callback) {
|
CiderReceiver.prototype.pause = function (callback) {
|
||||||
this.media.pause.apply(this.media, arguments);
|
this.media.pause.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.stop = function(callback) {
|
CiderReceiver.prototype.stop = function (callback) {
|
||||||
this.media.stop.apply(this.media, arguments);
|
this.media.stop.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.seek = function(currentTime, callback) {
|
CiderReceiver.prototype.seek = function (currentTime, callback) {
|
||||||
this.media.seek.apply(this.media, arguments);
|
this.media.seek.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.queueLoad = function(items, options, callback) {
|
CiderReceiver.prototype.queueLoad = function (items, options, callback) {
|
||||||
this.media.queueLoad.apply(this.media, arguments);
|
this.media.queueLoad.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.queueInsert = function(items, options, callback) {
|
CiderReceiver.prototype.queueInsert = function (items, options, callback) {
|
||||||
this.media.queueInsert.apply(this.media, arguments);
|
this.media.queueInsert.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.queueRemove = function(itemIds, options, callback) {
|
CiderReceiver.prototype.queueRemove = function (itemIds, options, callback) {
|
||||||
this.media.queueRemove.apply(this.media, arguments);
|
this.media.queueRemove.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.queueReorder = function(itemIds, options, callback) {
|
CiderReceiver.prototype.queueReorder = function (itemIds, options, callback) {
|
||||||
this.media.queueReorder.apply(this.media, arguments);
|
this.media.queueReorder.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.queueUpdate = function(items, callback) {
|
CiderReceiver.prototype.queueUpdate = function (items, callback) {
|
||||||
this.media.queueUpdate.apply(this.media, arguments);
|
this.media.queueUpdate.apply(this.media, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.sendIp = function(opts){
|
CiderReceiver.prototype.sendIp = function (opts) {
|
||||||
this.mediaReceiver.sendIp.apply(this.mediaReceiver, arguments);
|
this.mediaReceiver.sendIp.apply(this.mediaReceiver, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
CiderReceiver.prototype.kill = function(opts){
|
CiderReceiver.prototype.kill = function (opts) {
|
||||||
this.mediaReceiver.kill.apply(this.mediaReceiver, arguments);
|
this.mediaReceiver.kill.apply(this.mediaReceiver, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
import * as path from 'path';
|
import * as path from "path";
|
||||||
import * as electron from 'electron'
|
import * as electron from "electron";
|
||||||
import {utils} from './utils';
|
import { utils } from "./utils";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hello, this is our loader for the various plugins that the Cider Development Team built for our
|
// Hello, this is our loader for the various plugins that the Cider Development Team built for our
|
||||||
|
@ -17,8 +17,8 @@ import {utils} from './utils';
|
||||||
*/
|
*/
|
||||||
export class Plugins {
|
export class Plugins {
|
||||||
private static PluginMap: any = {};
|
private static PluginMap: any = {};
|
||||||
private basePluginsPath = path.join(__dirname, '../plugins');
|
private basePluginsPath = path.join(__dirname, "../plugins");
|
||||||
private userPluginsPath = path.join(electron.app.getPath('userData'), 'Plugins');
|
private userPluginsPath = path.join(electron.app.getPath("userData"), "Plugins");
|
||||||
private readonly pluginsList: any = {};
|
private readonly pluginsList: any = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -36,10 +36,9 @@ export class Plugins {
|
||||||
public getPlugins(): any {
|
public getPlugins(): any {
|
||||||
let plugins: any = {};
|
let plugins: any = {};
|
||||||
|
|
||||||
|
|
||||||
if (fs.existsSync(this.basePluginsPath)) {
|
if (fs.existsSync(this.basePluginsPath)) {
|
||||||
fs.readdirSync(this.basePluginsPath).forEach(file => {
|
fs.readdirSync(this.basePluginsPath).forEach((file) => {
|
||||||
if (file.endsWith('.ts') || file.endsWith('.js')) {
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
||||||
const plugin = require(path.join(this.basePluginsPath, file)).default;
|
const plugin = require(path.join(this.basePluginsPath, file)).default;
|
||||||
if (plugins[file] || plugin.name in plugins) {
|
if (plugins[file] || plugin.name in plugins) {
|
||||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||||
|
@ -50,14 +49,13 @@ export class Plugins {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (fs.existsSync(this.userPluginsPath)) {
|
if (fs.existsSync(this.userPluginsPath)) {
|
||||||
fs.readdirSync(this.userPluginsPath).forEach(file => {
|
fs.readdirSync(this.userPluginsPath).forEach((file) => {
|
||||||
// Plugins V1
|
// Plugins V1
|
||||||
if (file.endsWith('.ts') || file.endsWith('.js')) {
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
||||||
if (!electron.app.isPackaged) {
|
if (!electron.app.isPackaged) {
|
||||||
const plugin = require(path.join(this.userPluginsPath, file)).default;
|
const plugin = require(path.join(this.userPluginsPath, file)).default;
|
||||||
file = file.replace('.ts', '').replace('.js', '');
|
file = file.replace(".ts", "").replace(".js", "");
|
||||||
if (plugins[file] || plugin in plugins) {
|
if (plugins[file] || plugin in plugins) {
|
||||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,7 +63,7 @@ export class Plugins {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const plugin = require(path.join(this.userPluginsPath, file));
|
const plugin = require(path.join(this.userPluginsPath, file));
|
||||||
file = file.replace('.ts', '').replace('.js', '');
|
file = file.replace(".ts", "").replace(".js", "");
|
||||||
if (plugins[file] || plugin in plugins) {
|
if (plugins[file] || plugin in plugins) {
|
||||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,7 +74,7 @@ export class Plugins {
|
||||||
// Plugins V2
|
// Plugins V2
|
||||||
else if (fs.lstatSync(path.join(this.userPluginsPath, file)).isDirectory()) {
|
else if (fs.lstatSync(path.join(this.userPluginsPath, file)).isDirectory()) {
|
||||||
const pluginPath = path.join(this.userPluginsPath, file);
|
const pluginPath = path.join(this.userPluginsPath, file);
|
||||||
if (fs.existsSync(path.join(pluginPath, 'package.json'))) {
|
if (fs.existsSync(path.join(pluginPath, "package.json"))) {
|
||||||
const pluginPackage = require(path.join(pluginPath, "package.json"));
|
const pluginPackage = require(path.join(pluginPath, "package.json"));
|
||||||
const plugin = require(path.join(pluginPath, pluginPackage.main));
|
const plugin = require(path.join(pluginPath, pluginPackage.main));
|
||||||
if (plugins[plugin.name] || plugin.name in plugins) {
|
if (plugins[plugin.name] || plugin.name in plugins) {
|
||||||
|
@ -89,15 +87,15 @@ export class Plugins {
|
||||||
utils: utils,
|
utils: utils,
|
||||||
win: utils.getWindow(),
|
win: utils.getWindow(),
|
||||||
dir: pluginPath,
|
dir: pluginPath,
|
||||||
dirName: file
|
dirName: file,
|
||||||
}
|
};
|
||||||
plugins[plugin.name] = new plugin(pluginEnv);
|
plugins[plugin.name] = new plugin(pluginEnv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log('[PluginHandler] Loaded plugins:', Object.keys(plugins));
|
console.log("[PluginHandler] Loaded plugins:", Object.keys(plugins));
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +106,7 @@ export class Plugins {
|
||||||
this.pluginsList[plugin][event](...args);
|
this.pluginsList[plugin][event](...args);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[${plugin}] An error was encountered: ${e}`);
|
console.error(`[${plugin}] An error was encountered: ${e}`);
|
||||||
console.error(e)
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,5 +117,4 @@ export class Plugins {
|
||||||
this.pluginsList[plugin][event](...args);
|
this.pluginsList[plugin][event](...args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,333 +1,279 @@
|
||||||
import * as ElectronStore from 'electron-store';
|
import * as ElectronStore from "electron-store";
|
||||||
import * as electron from "electron";
|
import * as electron from "electron";
|
||||||
import {app} from "electron";
|
import { app } from "electron";
|
||||||
import fetch from "electron-fetch";
|
import fetch from "electron-fetch";
|
||||||
|
|
||||||
export class Store {
|
export class Store {
|
||||||
static cfg: ElectronStore;
|
static cfg: ElectronStore;
|
||||||
|
|
||||||
private defaults: any = {
|
private defaults: any = {
|
||||||
"main": {
|
main: {
|
||||||
"PLATFORM": process.platform,
|
PLATFORM: process.platform,
|
||||||
"UPDATABLE": app.isPackaged && (!process.mas || !process.windowsStore || !process.env.FLATPAK_ID)
|
UPDATABLE: app.isPackaged && (!process.mas || !process.windowsStore || !process.env.FLATPAK_ID),
|
||||||
},
|
},
|
||||||
"general": {
|
general: {
|
||||||
"close_button_hide": false,
|
close_button_hide: false,
|
||||||
"language": "en_US", // electron.app.getLocale().replace('-', '_') this can be used in future
|
language: "en_US", // electron.app.getLocale().replace('-', '_') this can be used in future
|
||||||
"playbackNotifications": true,
|
playbackNotifications: true,
|
||||||
"resumeOnStartupBehavior": "local",
|
resumeOnStartupBehavior: "local",
|
||||||
"privateEnabled": false,
|
privateEnabled: false,
|
||||||
"themeUpdateNotification": true,
|
themeUpdateNotification: true,
|
||||||
"sidebarItems": {
|
sidebarItems: {
|
||||||
"recentlyAdded": true,
|
recentlyAdded: true,
|
||||||
"songs": true,
|
songs: true,
|
||||||
"albums": true,
|
albums: true,
|
||||||
"artists": true,
|
artists: true,
|
||||||
"videos": true,
|
videos: true,
|
||||||
"podcasts": true
|
podcasts: true,
|
||||||
},
|
},
|
||||||
"sidebarCollapsed": {
|
sidebarCollapsed: {
|
||||||
"cider": false,
|
cider: false,
|
||||||
"applemusic": false,
|
applemusic: false,
|
||||||
"library": false,
|
library: false,
|
||||||
"amplaylists": false,
|
amplaylists: false,
|
||||||
"playlists": false,
|
playlists: false,
|
||||||
"localLibrary": false
|
localLibrary: false,
|
||||||
},
|
},
|
||||||
"onStartup": {
|
onStartup: {
|
||||||
"enabled": false,
|
enabled: false,
|
||||||
"hidden": false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
"resumeTabs": {
|
resumeTabs: {
|
||||||
"tab": "home",
|
tab: "home",
|
||||||
"dynamicData": ""
|
dynamicData: "",
|
||||||
},
|
},
|
||||||
"keybindings": {
|
keybindings: {
|
||||||
"search": [
|
search: ["CommandOrControl", "F"],
|
||||||
"CommandOrControl",
|
listnow: ["CommandOrControl", "L"],
|
||||||
"F"
|
browse: ["CommandOrControl", "B"],
|
||||||
],
|
recentAdd: ["CommandOrControl", "G"],
|
||||||
"listnow": [
|
songs: ["CommandOrControl", "J"],
|
||||||
"CommandOrControl",
|
albums: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "A"],
|
||||||
"L"
|
artists: ["CommandOrControl", "D"],
|
||||||
],
|
togglePrivateSession: ["CommandOrControl", "P"],
|
||||||
"browse": [
|
webRemote: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "W"],
|
||||||
"CommandOrControl",
|
audioSettings: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "A"],
|
||||||
"B"
|
pluginMenu: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "P"],
|
||||||
],
|
castToDevices: ["CommandOrControl", process.platform == "darwin" ? "Option" : process.platform == "linux" ? "Shift" : "Alt", "C"],
|
||||||
"recentAdd": [
|
settings: [
|
||||||
"CommandOrControl",
|
|
||||||
"G"
|
|
||||||
],
|
|
||||||
"songs": [
|
|
||||||
"CommandOrControl",
|
|
||||||
"J"
|
|
||||||
],
|
|
||||||
"albums": [
|
|
||||||
"CommandOrControl",
|
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
|
||||||
"A"
|
|
||||||
],
|
|
||||||
"artists": [
|
|
||||||
"CommandOrControl",
|
|
||||||
"D"
|
|
||||||
],
|
|
||||||
"togglePrivateSession": [
|
|
||||||
"CommandOrControl",
|
|
||||||
"P"
|
|
||||||
],
|
|
||||||
"webRemote": [
|
|
||||||
"CommandOrControl",
|
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
|
||||||
"W"
|
|
||||||
],
|
|
||||||
"audioSettings": [
|
|
||||||
"CommandOrControl",
|
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
|
||||||
"A"
|
|
||||||
],
|
|
||||||
"pluginMenu": [
|
|
||||||
"CommandOrControl",
|
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
|
||||||
"P"
|
|
||||||
],
|
|
||||||
"castToDevices": [
|
|
||||||
"CommandOrControl",
|
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
|
||||||
"C"
|
|
||||||
],
|
|
||||||
"settings": [
|
|
||||||
"CommandOrControl", // Who the hell uses a different key for this? Fucking Option?
|
"CommandOrControl", // Who the hell uses a different key for this? Fucking Option?
|
||||||
","
|
",",
|
||||||
],
|
],
|
||||||
"zoomn": [
|
zoomn: ["Control", "numadd"],
|
||||||
"Control",
|
zoomt: ["Control", "numsub"],
|
||||||
"numadd",
|
zoomrst: ["Control", "num0"],
|
||||||
],
|
openDeveloperTools: ["CommandOrControl", "Shift", "I"],
|
||||||
"zoomt": [
|
|
||||||
"Control",
|
|
||||||
"numsub",
|
|
||||||
],
|
|
||||||
"zoomrst": [
|
|
||||||
"Control",
|
|
||||||
"num0",
|
|
||||||
],
|
|
||||||
"openDeveloperTools": [
|
|
||||||
"CommandOrControl",
|
|
||||||
"Shift",
|
|
||||||
"I"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"showLovedTracksInline": true
|
showLovedTracksInline: true,
|
||||||
},
|
},
|
||||||
"connectivity": {
|
connectivity: {
|
||||||
"discord_rpc": {
|
discord_rpc: {
|
||||||
"enabled": true,
|
enabled: true,
|
||||||
"client": "Cider",
|
client: "Cider",
|
||||||
"clear_on_pause": true,
|
clear_on_pause: true,
|
||||||
"hide_buttons": false,
|
hide_buttons: false,
|
||||||
"hide_timestamp": false,
|
hide_timestamp: false,
|
||||||
"state_format": "by {artist}",
|
state_format: "by {artist}",
|
||||||
"details_format": "{title}",
|
details_format: "{title}",
|
||||||
},
|
},
|
||||||
"lastfm": {
|
lastfm: {
|
||||||
"enabled": false,
|
enabled: false,
|
||||||
"scrobble_after": 50,
|
scrobble_after: 50,
|
||||||
"filter_loop": false,
|
filter_loop: false,
|
||||||
"filter_types": {},
|
filter_types: {},
|
||||||
"remove_featured": false,
|
remove_featured: false,
|
||||||
"secrets": {
|
secrets: {
|
||||||
"username": "",
|
username: "",
|
||||||
"key": ""
|
key: "",
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"home": {
|
|
||||||
"followedArtists": [],
|
|
||||||
"favoriteItems": []
|
|
||||||
},
|
},
|
||||||
"libraryPrefs": {
|
home: {
|
||||||
"songs": {
|
followedArtists: [],
|
||||||
"scroll": "paged",
|
favoriteItems: [],
|
||||||
"sort": "name",
|
|
||||||
"sortOrder": "asc",
|
|
||||||
"size": "normal"
|
|
||||||
},
|
},
|
||||||
"albums": {
|
libraryPrefs: {
|
||||||
"scroll": "paged",
|
songs: {
|
||||||
"sort": "name",
|
scroll: "paged",
|
||||||
"sortOrder": "asc",
|
sort: "name",
|
||||||
"viewAs": "covers"
|
sortOrder: "asc",
|
||||||
|
size: "normal",
|
||||||
},
|
},
|
||||||
"playlists": {
|
albums: {
|
||||||
"scroll": "infinite"
|
scroll: "paged",
|
||||||
|
sort: "name",
|
||||||
|
sortOrder: "asc",
|
||||||
|
viewAs: "covers",
|
||||||
},
|
},
|
||||||
"localPaths": [],
|
playlists: {
|
||||||
"pageSize": 250
|
scroll: "infinite",
|
||||||
},
|
},
|
||||||
"audio": {
|
localPaths: [],
|
||||||
"volume": 1,
|
pageSize: 250,
|
||||||
"volumeStep": 0.05,
|
|
||||||
"maxVolume": 1,
|
|
||||||
"lastVolume": 1,
|
|
||||||
"muted": false,
|
|
||||||
"playbackRate": 1,
|
|
||||||
"quality": "HIGH",
|
|
||||||
"seamless_audio": true,
|
|
||||||
"normalization": true,
|
|
||||||
"dBSPL": false,
|
|
||||||
"dBSPLcalibration": 90,
|
|
||||||
"maikiwiAudio": {
|
|
||||||
"ciderPPE": true,
|
|
||||||
"ciderPPE_value": "MAIKIWI",
|
|
||||||
"opportunisticCorrection_state": "OFF",
|
|
||||||
"atmosphereRealizer1": false,
|
|
||||||
"atmosphereRealizer1_value": "NATURAL_STANDARD",
|
|
||||||
"atmosphereRealizer2": false,
|
|
||||||
"atmosphereRealizer2_value": "NATURAL_STANDARD",
|
|
||||||
"spatial": false,
|
|
||||||
"spatialProfile": "BPLK",
|
|
||||||
"vibrantBass": { // Hard coded into the app. Don't include any of this config into exporting presets in store.ts
|
|
||||||
'frequencies': [17.182, 42.169, 53.763, 112.69, 119.65, 264.59, 336.57, 400.65, 505.48, 612.7, 838.7, 1155.3, 1175.6, 3406.8, 5158.6, 5968.1, 6999.9, 7468.6, 8862.9, 9666, 10109],
|
|
||||||
'Q': [2.5, 0.388, 5, 5, 2.5, 7.071, 14.14, 10, 7.071, 14.14, 8.409, 0.372, 7.071, 10, 16.82, 7.071, 28.28, 20, 8.409, 40, 40],
|
|
||||||
'gain': [-0.34, 2.49, 0.23, -0.49, 0.23, -0.12, 0.32, -0.29, 0.33, 0.19, -0.18, -1.27, -0.11, 0.25, -0.18, -0.53, 0.34, 1.32, 1.78, 0.41, -0.28]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"spatial": false,
|
audio: {
|
||||||
"spatial_properties": {
|
volume: 1,
|
||||||
"presets": [],
|
volumeStep: 0.05,
|
||||||
"gain": 0.8,
|
maxVolume: 1,
|
||||||
"listener_position": [0, 0, 0],
|
lastVolume: 1,
|
||||||
"audio_position": [0, 0, 0],
|
muted: false,
|
||||||
"room_dimensions": {
|
playbackRate: 1,
|
||||||
"width": 32,
|
quality: "HIGH",
|
||||||
"height": 12,
|
seamless_audio: true,
|
||||||
"depth": 32
|
normalization: true,
|
||||||
},
|
dBSPL: false,
|
||||||
"room_materials": {
|
dBSPLcalibration: 90,
|
||||||
"left": 'metal',
|
maikiwiAudio: {
|
||||||
"right": 'metal',
|
ciderPPE: true,
|
||||||
"front": 'brick-bare',
|
ciderPPE_value: "MAIKIWI",
|
||||||
"back": 'brick-bare',
|
opportunisticCorrection_state: "OFF",
|
||||||
"down": 'acoustic-ceiling-tiles',
|
atmosphereRealizer1: false,
|
||||||
"up": 'acoustic-ceiling-tiles',
|
atmosphereRealizer1_value: "NATURAL_STANDARD",
|
||||||
}
|
atmosphereRealizer2: false,
|
||||||
},
|
atmosphereRealizer2_value: "NATURAL_STANDARD",
|
||||||
"equalizer": {
|
spatial: false,
|
||||||
'preset': "default",
|
spatialProfile: "BPLK",
|
||||||
'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
vibrantBass: {
|
||||||
'gain': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
// Hard coded into the app. Don't include any of this config into exporting presets in store.ts
|
||||||
'Q': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
frequencies: [17.182, 42.169, 53.763, 112.69, 119.65, 264.59, 336.57, 400.65, 505.48, 612.7, 838.7, 1155.3, 1175.6, 3406.8, 5158.6, 5968.1, 6999.9, 7468.6, 8862.9, 9666, 10109],
|
||||||
'mix': 1,
|
Q: [2.5, 0.388, 5, 5, 2.5, 7.071, 14.14, 10, 7.071, 14.14, 8.409, 0.372, 7.071, 10, 16.82, 7.071, 28.28, 20, 8.409, 40, 40],
|
||||||
'vibrantBass': 0,
|
gain: [-0.34, 2.49, 0.23, -0.49, 0.23, -0.12, 0.32, -0.29, 0.33, 0.19, -0.18, -1.27, -0.11, 0.25, -0.18, -0.53, 0.34, 1.32, 1.78, 0.41, -0.28],
|
||||||
'presets': [],
|
|
||||||
'userGenerated': false
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"visual": {
|
spatial: false,
|
||||||
"theme": "",
|
spatial_properties: {
|
||||||
"styles": [],
|
presets: [],
|
||||||
"scrollbars": 0, // 0 = show on hover, 2 = always hide, 3 = always show
|
gain: 0.8,
|
||||||
"refresh_rate": 0,
|
listener_position: [0, 0, 0],
|
||||||
"window_background_style": "none", // "none", "artwork", "color"
|
audio_position: [0, 0, 0],
|
||||||
"animated_artwork": "limited", // 0 = always, 1 = limited, 2 = never
|
room_dimensions: {
|
||||||
"animated_artwork_qualityLevel": 1,
|
width: 32,
|
||||||
"bg_artwork_rotation": false,
|
height: 12,
|
||||||
"hw_acceleration": "default", // default, webgpu, disabled
|
depth: 32,
|
||||||
"showuserinfo": true,
|
|
||||||
"transparent": false,
|
|
||||||
"miniplayer_top_toggle": true,
|
|
||||||
"directives": {
|
|
||||||
"windowLayout": "default"
|
|
||||||
},
|
},
|
||||||
"windowControlPosition": 0, // 0 default right
|
room_materials: {
|
||||||
"nativeTitleBar": false,
|
left: "metal",
|
||||||
"windowColor": "#000000",
|
right: "metal",
|
||||||
"customAccentColor": false,
|
front: "brick-bare",
|
||||||
"accentColor": "#fc3c44",
|
back: "brick-bare",
|
||||||
"purplePodcastPlaybackBar": false,
|
down: "acoustic-ceiling-tiles",
|
||||||
"maxElementScale": -1 // -1 default, anything else is a custom scale
|
up: "acoustic-ceiling-tiles",
|
||||||
},
|
},
|
||||||
"lyrics": {
|
|
||||||
"enable_mxm": true,
|
|
||||||
"mxm_karaoke": false,
|
|
||||||
"mxm_language": "disabled",
|
|
||||||
"enable_qq": false,
|
|
||||||
"enable_yt": false,
|
|
||||||
},
|
},
|
||||||
"advanced": {
|
equalizer: {
|
||||||
"AudioContext": true,
|
preset: "default",
|
||||||
"experiments": [],
|
frequencies: [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||||
"playlistTrackMapping": true,
|
gain: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
"ffmpegLocation": "",
|
Q: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
"disableLogging": true
|
mix: 1,
|
||||||
|
vibrantBass: 0,
|
||||||
|
presets: [],
|
||||||
|
userGenerated: false,
|
||||||
},
|
},
|
||||||
"connectUser": {
|
},
|
||||||
"auth": null,
|
visual: {
|
||||||
"sync": {
|
theme: "",
|
||||||
|
styles: [],
|
||||||
|
scrollbars: 0, // 0 = show on hover, 2 = always hide, 3 = always show
|
||||||
|
refresh_rate: 0,
|
||||||
|
window_background_style: "none", // "none", "artwork", "color"
|
||||||
|
animated_artwork: "limited", // 0 = always, 1 = limited, 2 = never
|
||||||
|
animated_artwork_qualityLevel: 1,
|
||||||
|
bg_artwork_rotation: false,
|
||||||
|
hw_acceleration: "default", // default, webgpu, disabled
|
||||||
|
showuserinfo: true,
|
||||||
|
transparent: false,
|
||||||
|
miniplayer_top_toggle: true,
|
||||||
|
directives: {
|
||||||
|
windowLayout: "default",
|
||||||
|
},
|
||||||
|
windowControlPosition: 0, // 0 default right
|
||||||
|
nativeTitleBar: false,
|
||||||
|
windowColor: "#000000",
|
||||||
|
customAccentColor: false,
|
||||||
|
accentColor: "#fc3c44",
|
||||||
|
purplePodcastPlaybackBar: false,
|
||||||
|
maxElementScale: -1, // -1 default, anything else is a custom scale
|
||||||
|
},
|
||||||
|
lyrics: {
|
||||||
|
enable_mxm: true,
|
||||||
|
mxm_karaoke: false,
|
||||||
|
mxm_language: "disabled",
|
||||||
|
enable_qq: false,
|
||||||
|
enable_yt: false,
|
||||||
|
},
|
||||||
|
advanced: {
|
||||||
|
AudioContext: true,
|
||||||
|
experiments: [],
|
||||||
|
playlistTrackMapping: true,
|
||||||
|
ffmpegLocation: "",
|
||||||
|
disableLogging: true,
|
||||||
|
},
|
||||||
|
connectUser: {
|
||||||
|
auth: null,
|
||||||
|
sync: {
|
||||||
themes: false,
|
themes: false,
|
||||||
plugins: false,
|
plugins: false,
|
||||||
settings: false,
|
settings: false,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
private migrations: any = {}
|
};
|
||||||
|
private migrations: any = {};
|
||||||
private schema: ElectronStore.Schema<any> = {
|
private schema: ElectronStore.Schema<any> = {
|
||||||
"connectivity.discord_rpc": {
|
"connectivity.discord_rpc": {
|
||||||
type: 'object'
|
type: "object",
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
Store.cfg = new ElectronStore({
|
Store.cfg = new ElectronStore({
|
||||||
name: 'cider-config',
|
name: "cider-config",
|
||||||
defaults: this.defaults,
|
defaults: this.defaults,
|
||||||
schema: this.schema,
|
schema: this.schema,
|
||||||
migrations: this.migrations,
|
migrations: this.migrations,
|
||||||
clearInvalidConfig: false //disabled for now
|
clearInvalidConfig: false, //disabled for now
|
||||||
});
|
});
|
||||||
|
|
||||||
Store.cfg.set(this.mergeStore(this.defaults, Store.cfg.store))
|
Store.cfg.set(this.mergeStore(this.defaults, Store.cfg.store));
|
||||||
this.ipcHandler();
|
this.ipcHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
static pushToCloud(): void {
|
static pushToCloud(): void {
|
||||||
if (Store.cfg.get('connectUser.auth') === null) return;
|
if (Store.cfg.get("connectUser.auth") === null) return;
|
||||||
var syncData = Object();
|
var syncData = Object();
|
||||||
if (Store.cfg.get('connectUser.sync.themes')) {
|
if (Store.cfg.get("connectUser.sync.themes")) {
|
||||||
syncData.push({
|
syncData.push({
|
||||||
themes: Store.cfg.store.themes
|
themes: Store.cfg.store.themes,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
if (Store.cfg.get('connectUser.sync.plugins')) {
|
if (Store.cfg.get("connectUser.sync.plugins")) {
|
||||||
syncData.push({
|
syncData.push({
|
||||||
plugins: Store.cfg.store.plugins
|
plugins: Store.cfg.store.plugins,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Store.cfg.get('connectUser.sync.settings')) {
|
if (Store.cfg.get("connectUser.sync.settings")) {
|
||||||
syncData.push({
|
syncData.push({
|
||||||
general: Store.cfg.get('general'),
|
general: Store.cfg.get("general"),
|
||||||
home: Store.cfg.get('home'),
|
home: Store.cfg.get("home"),
|
||||||
libraryPrefs: Store.cfg.get('libraryPrefs'),
|
libraryPrefs: Store.cfg.get("libraryPrefs"),
|
||||||
advanced: Store.cfg.get('advanced'),
|
advanced: Store.cfg.get("advanced"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
let postBody = {
|
let postBody = {
|
||||||
id: Store.cfg.get('connectUser.id'),
|
id: Store.cfg.get("connectUser.id"),
|
||||||
app: electron.app.getName(),
|
app: electron.app.getName(),
|
||||||
version: electron.app.isPackaged ? electron.app.getVersion() : 'dev',
|
version: electron.app.isPackaged ? electron.app.getVersion() : "dev",
|
||||||
syncData: syncData
|
syncData: syncData,
|
||||||
}
|
};
|
||||||
|
|
||||||
fetch('https://connect.cidercollective.dev/api/v1/setttings/set', {
|
fetch("https://connect.cidercollective.dev/api/v1/setttings/set", {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(postBody)
|
body: JSON.stringify(postBody),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -335,40 +281,40 @@ export class Store {
|
||||||
* @param target The target configuration
|
* @param target The target configuration
|
||||||
* @param source The source configuration
|
* @param source The source configuration
|
||||||
*/
|
*/
|
||||||
private mergeStore = (target: { [x: string]: any; }, source: { [x: string]: any; }) => {
|
private mergeStore = (target: { [x: string]: any }, source: { [x: string]: any }) => {
|
||||||
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
|
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
|
||||||
for (const key of Object.keys(source)) {
|
for (const key of Object.keys(source)) {
|
||||||
if (key.includes('migrations')) {
|
if (key.includes("migrations")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (source[key] instanceof Array) {
|
if (source[key] instanceof Array) {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key]))
|
if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key]));
|
||||||
}
|
}
|
||||||
// Join `target` and modified `source`
|
// Join `target` and modified `source`
|
||||||
Object.assign(target || {}, source)
|
Object.assign(target || {}, source);
|
||||||
return target
|
return target;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPC Handler
|
* IPC Handler
|
||||||
*/
|
*/
|
||||||
private ipcHandler(): void {
|
private ipcHandler(): void {
|
||||||
electron.ipcMain.handle('getStoreValue', (_event, key, defaultValue) => {
|
electron.ipcMain.handle("getStoreValue", (_event, key, defaultValue) => {
|
||||||
return (defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key));
|
return defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.handle('setStoreValue', (_event, key, value) => {
|
electron.ipcMain.handle("setStoreValue", (_event, key, value) => {
|
||||||
Store.cfg.set(key, value);
|
Store.cfg.set(key, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('getStore', (event) => {
|
electron.ipcMain.on("getStore", (event) => {
|
||||||
event.returnValue = Store.cfg.store
|
event.returnValue = Store.cfg.store;
|
||||||
})
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('setStore', (_event, store) => {
|
electron.ipcMain.on("setStore", (_event, store) => {
|
||||||
Store.cfg.store = store
|
Store.cfg.store = store;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +1,35 @@
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import {Store} from "./store";
|
import { Store } from "./store";
|
||||||
import {BrowserWindow as bw} from "./browserwindow";
|
import { BrowserWindow as bw } from "./browserwindow";
|
||||||
import {app, BrowserWindow, ipcMain} from "electron";
|
import { app, BrowserWindow, ipcMain } from "electron";
|
||||||
import fetch from "electron-fetch";
|
import fetch from "electron-fetch";
|
||||||
import ElectronStore from "electron-store";
|
import ElectronStore from "electron-store";
|
||||||
|
|
||||||
export class utils {
|
export class utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playback Functions
|
* Playback Functions
|
||||||
*/
|
*/
|
||||||
static playback = {
|
static playback = {
|
||||||
pause: () => {
|
pause: () => {
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.pause()")
|
bw.win.webContents.executeJavaScript("MusicKitInterop.pause()");
|
||||||
},
|
},
|
||||||
play: () => {
|
play: () => {
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.play()")
|
bw.win.webContents.executeJavaScript("MusicKitInterop.play()");
|
||||||
},
|
},
|
||||||
playPause: () => {
|
playPause: () => {
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()")
|
bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()");
|
||||||
},
|
},
|
||||||
next: () => {
|
next: () => {
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.next()")
|
bw.win.webContents.executeJavaScript("MusicKitInterop.next()");
|
||||||
},
|
},
|
||||||
previous: () => {
|
previous: () => {
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.previous()")
|
bw.win.webContents.executeJavaScript("MusicKitInterop.previous()");
|
||||||
},
|
},
|
||||||
seek: (seconds: number) => {
|
seek: (seconds: number) => {
|
||||||
bw.win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${seconds})`)
|
bw.win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${seconds})`);
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* Paths for the application to use
|
* Paths for the application to use
|
||||||
*/
|
*/
|
||||||
|
@ -68,7 +67,7 @@ export class utils {
|
||||||
* Get the IPCMain
|
* Get the IPCMain
|
||||||
*/
|
*/
|
||||||
static getIPCMain(): Electron.IpcMain {
|
static getIPCMain(): Electron.IpcMain {
|
||||||
return ipcMain
|
return ipcMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -76,7 +75,7 @@ export class utils {
|
||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
static getExpress(): any {
|
static getExpress(): any {
|
||||||
return bw.express
|
return bw.express;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,9 +104,9 @@ export class utils {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
return i18n[key]
|
return i18n[key];
|
||||||
} else {
|
} else {
|
||||||
return i18n
|
return i18n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ export class utils {
|
||||||
* @returns store value
|
* @returns store value
|
||||||
*/
|
*/
|
||||||
static getStoreValue(key: string): any {
|
static getStoreValue(key: string): any {
|
||||||
return Store.cfg.get(key)
|
return Store.cfg.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,7 +124,7 @@ export class utils {
|
||||||
* @returns store
|
* @returns store
|
||||||
*/
|
*/
|
||||||
static getStore(): Object {
|
static getStore(): Object {
|
||||||
return Store.cfg.store
|
return Store.cfg.store;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,7 +132,7 @@ export class utils {
|
||||||
* @returns {Store}
|
* @returns {Store}
|
||||||
*/
|
*/
|
||||||
static getStoreInstance(): ElectronStore {
|
static getStoreInstance(): ElectronStore {
|
||||||
return Store.cfg
|
return Store.cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,7 +141,7 @@ export class utils {
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
static setStoreValue(key: string, value: any): void {
|
static setStoreValue(key: string, value: any): void {
|
||||||
Store.cfg.set(key, value)
|
Store.cfg.set(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,7 +149,7 @@ export class utils {
|
||||||
* @return Function
|
* @return Function
|
||||||
*/
|
*/
|
||||||
static pushStoreToConnect(): Function {
|
static pushStoreToConnect(): Function {
|
||||||
return Store.pushToCloud
|
return Store.pushToCloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,15 +157,13 @@ export class utils {
|
||||||
*/
|
*/
|
||||||
static getWindow(): Electron.BrowserWindow {
|
static getWindow(): Electron.BrowserWindow {
|
||||||
if (bw.win) {
|
if (bw.win) {
|
||||||
return bw.win
|
return bw.win;
|
||||||
} else {
|
} else {
|
||||||
return BrowserWindow.getAllWindows()[0]
|
return BrowserWindow.getAllWindows()[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static loadPluginFrontend(path: string): void {
|
static loadPluginFrontend(path: string): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static loadJSFrontend(path: string): void {
|
static loadJSFrontend(path: string): void {
|
||||||
bw.win.webContents.executeJavaScript(fs.readFileSync(path, "utf8"));
|
bw.win.webContents.executeJavaScript(fs.readFileSync(path, "utf8"));
|
||||||
|
|
|
@ -100,7 +100,8 @@
|
||||||
"component": "<cider-groupings :data=\"browsepage\"></cider-groupings>",
|
"component": "<cider-groupings :data=\"browsepage\"></cider-groupings>",
|
||||||
"condition": "page == 'groupings'",
|
"condition": "page == 'groupings'",
|
||||||
"onEnter": ""
|
"onEnter": ""
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
"page": "charts",
|
"page": "charts",
|
||||||
"component": "<cider-charts :data=\"browsepage\"></cider-charts>",
|
"component": "<cider-charts :data=\"browsepage\"></cider-charts>",
|
||||||
"condition": "page == 'charts'",
|
"condition": "page == 'charts'",
|
||||||
|
|
|
@ -4,73 +4,71 @@ import * as electron from "electron";
|
||||||
const WebSocketServer = ws.Server;
|
const WebSocketServer = ws.Server;
|
||||||
|
|
||||||
interface standardResponse {
|
interface standardResponse {
|
||||||
status?: Number,
|
status?: Number;
|
||||||
message?: String,
|
message?: String;
|
||||||
data?: any,
|
data?: any;
|
||||||
type?: string,
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class wsapi {
|
export class wsapi {
|
||||||
static clients: any;
|
static clients: any;
|
||||||
port: any = 26369
|
port: any = 26369;
|
||||||
wss: any = null
|
wss: any = null;
|
||||||
clients: any = []
|
clients: any = [];
|
||||||
private _win: any;
|
private _win: any;
|
||||||
|
|
||||||
constructor(win: any) {
|
constructor(win: any) {
|
||||||
this._win = win;
|
this._win = win;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
createId() {
|
createId() {
|
||||||
// create random guid
|
// create random guid
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||||
var r = Math.random() * 16 | 0,
|
var r = (Math.random() * 16) | 0,
|
||||||
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
v = c == "x" ? r : (r & 0x3) | 0x8;
|
||||||
return v.toString(16);
|
return v.toString(16);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async InitWebSockets() {
|
public async InitWebSockets() {
|
||||||
electron.ipcMain.on('wsapi-updatePlaybackState', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-updatePlaybackState", (_event: any, arg: any) => {
|
||||||
this.updatePlaybackState(arg);
|
this.updatePlaybackState(arg);
|
||||||
})
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnQueue', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-returnQueue", (_event: any, arg: any) => {
|
||||||
this.returnQueue(JSON.parse(arg));
|
this.returnQueue(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnSearch', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-returnSearch", (_event: any, arg: any) => {
|
||||||
console.log("SEARCH")
|
console.log("SEARCH");
|
||||||
this.returnSearch(JSON.parse(arg));
|
this.returnSearch(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnSearchLibrary', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-returnSearchLibrary", (_event: any, arg: any) => {
|
||||||
this.returnSearchLibrary(JSON.parse(arg));
|
this.returnSearchLibrary(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnDynamic', (_event: any, arg: any, type: any) => {
|
electron.ipcMain.on("wsapi-returnDynamic", (_event: any, arg: any, type: any) => {
|
||||||
this.returnDynamic(JSON.parse(arg), type);
|
this.returnDynamic(JSON.parse(arg), type);
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnMusicKitApi', (_event: any, arg: any, method: any) => {
|
electron.ipcMain.on("wsapi-returnMusicKitApi", (_event: any, arg: any, method: any) => {
|
||||||
this.returnMusicKitApi(JSON.parse(arg), method);
|
this.returnMusicKitApi(JSON.parse(arg), method);
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('wsapi-returnLyrics', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-returnLyrics", (_event: any, arg: any) => {
|
||||||
this.returnLyrics(JSON.parse(arg));
|
this.returnLyrics(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
electron.ipcMain.on('wsapi-returnvolumeMax', (_event: any, arg: any) => {
|
electron.ipcMain.on("wsapi-returnvolumeMax", (_event: any, arg: any) => {
|
||||||
this.returnmaxVolume(JSON.parse(arg));
|
this.returnmaxVolume(JSON.parse(arg));
|
||||||
});
|
});
|
||||||
electron.ipcMain.on('wsapi-libraryStatus', (_event: any, inLibrary: boolean, rating: number) => {
|
electron.ipcMain.on("wsapi-libraryStatus", (_event: any, inLibrary: boolean, rating: number) => {
|
||||||
this.returnLibraryStatus(inLibrary, rating);
|
this.returnLibraryStatus(inLibrary, rating);
|
||||||
});
|
});
|
||||||
electron.ipcMain.on('wsapi-rate', (_event: any, kind: string, id: string, rating: number) => {
|
electron.ipcMain.on("wsapi-rate", (_event: any, kind: string, id: string, rating: number) => {
|
||||||
this.returnRatingStatus(kind, id, rating);
|
this.returnRatingStatus(kind, id, rating);
|
||||||
});
|
});
|
||||||
electron.ipcMain.on('wsapi-change-library', (_event: any, kind: string, id: string, shouldAdd: boolean) => {
|
electron.ipcMain.on("wsapi-change-library", (_event: any, kind: string, id: string, shouldAdd: boolean) => {
|
||||||
this.returnLibraryChange(kind, id, shouldAdd);
|
this.returnLibraryChange(kind, id, shouldAdd);
|
||||||
});
|
});
|
||||||
this.wss = new WebSocketServer({
|
this.wss = new WebSocketServer({
|
||||||
|
@ -80,10 +78,10 @@ export class wsapi {
|
||||||
// See zlib defaults.
|
// See zlib defaults.
|
||||||
chunkSize: 1024,
|
chunkSize: 1024,
|
||||||
memLevel: 7,
|
memLevel: 7,
|
||||||
level: 3
|
level: 3,
|
||||||
},
|
},
|
||||||
zlibInflateOptions: {
|
zlibInflateOptions: {
|
||||||
chunkSize: 10 * 1024
|
chunkSize: 10 * 1024,
|
||||||
},
|
},
|
||||||
// Other options settable:
|
// Other options settable:
|
||||||
clientNoContextTakeover: true, // Defaults to negotiated value.
|
clientNoContextTakeover: true, // Defaults to negotiated value.
|
||||||
|
@ -91,26 +89,33 @@ export class wsapi {
|
||||||
serverMaxWindowBits: 10, // Defaults to negotiated value.
|
serverMaxWindowBits: 10, // Defaults to negotiated value.
|
||||||
// Below options specified as default values.
|
// Below options specified as default values.
|
||||||
concurrencyLimit: 10, // Limits zlib concurrency for perf.
|
concurrencyLimit: 10, // Limits zlib concurrency for perf.
|
||||||
threshold: 1024 // Size (in bytes) below which messages
|
threshold: 1024, // Size (in bytes) below which messages
|
||||||
// should not be compressed if context takeover is disabled.
|
// should not be compressed if context takeover is disabled.
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
console.log(`WebSocketServer started on port: ${this.port}`);
|
console.log(`WebSocketServer started on port: ${this.port}`);
|
||||||
|
|
||||||
const defaultResponse: standardResponse = {status: 0, data: {}, message: "OK", type: "generic"};
|
const defaultResponse: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: {},
|
||||||
|
message: "OK",
|
||||||
|
type: "generic",
|
||||||
|
};
|
||||||
|
|
||||||
|
this.wss.on("connection", (ws: any) => {
|
||||||
this.wss.on('connection', (ws: any) => {
|
|
||||||
ws.id = this.createId();
|
ws.id = this.createId();
|
||||||
console.log(`Client ${ws.id} connected`)
|
console.log(`Client ${ws.id} connected`);
|
||||||
this.clients.push(ws);
|
this.clients.push(ws);
|
||||||
ws.on('message', function incoming(_message: any) {
|
ws.on("message", function incoming(_message: any) {});
|
||||||
|
|
||||||
});
|
|
||||||
// ws on message
|
// ws on message
|
||||||
ws.on('message', (message: any) => {
|
ws.on("message", (message: any) => {
|
||||||
let data = JSON.parse(message);
|
let data = JSON.parse(message);
|
||||||
let response: standardResponse = {status: 0, data: {}, message: "OK", type: "generic"};
|
let response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: {},
|
||||||
|
message: "OK",
|
||||||
|
type: "generic",
|
||||||
|
};
|
||||||
if (data.action) {
|
if (data.action) {
|
||||||
data.action.toLowerCase();
|
data.action.toLowerCase();
|
||||||
}
|
}
|
||||||
|
@ -119,16 +124,16 @@ export class wsapi {
|
||||||
response.message = "Action not found";
|
response.message = "Action not found";
|
||||||
break;
|
break;
|
||||||
case "identify":
|
case "identify":
|
||||||
response.message = "Thanks for identifying!"
|
response.message = "Thanks for identifying!";
|
||||||
response.data = {
|
response.data = {
|
||||||
id: ws.id
|
id: ws.id,
|
||||||
}
|
};
|
||||||
ws.identity = {
|
ws.identity = {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
author: data.author,
|
author: data.author,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
version: data.version
|
version: data.version,
|
||||||
}
|
};
|
||||||
break;
|
break;
|
||||||
case "play-next":
|
case "play-next":
|
||||||
this._win.webContents.executeJavaScript(`wsapi.playNext(\`${data.type}\`,\`${data.id}\`)`);
|
this._win.webContents.executeJavaScript(`wsapi.playNext(\`${data.type}\`,\`${data.id}\`)`);
|
||||||
|
@ -169,7 +174,7 @@ export class wsapi {
|
||||||
case "playpause":
|
case "playpause":
|
||||||
this._win.webContents.executeJavaScript(`MusicKitInterop.playPause()`);
|
this._win.webContents.executeJavaScript(`MusicKitInterop.playPause()`);
|
||||||
response.message = "Play/Pause";
|
response.message = "Play/Pause";
|
||||||
break
|
break;
|
||||||
case "play":
|
case "play":
|
||||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().play()`);
|
this._win.webContents.executeJavaScript(`MusicKit.getInstance().play()`);
|
||||||
response.message = "Playing";
|
response.message = "Playing";
|
||||||
|
@ -203,7 +208,9 @@ export class wsapi {
|
||||||
response.message = "Next";
|
response.message = "Next";
|
||||||
break;
|
break;
|
||||||
case "previous":
|
case "previous":
|
||||||
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex)}`);
|
this._win.webContents.executeJavaScript(
|
||||||
|
`if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex)}`
|
||||||
|
);
|
||||||
response.message = "Previous";
|
response.message = "Previous";
|
||||||
break;
|
break;
|
||||||
case "musickit-api":
|
case "musickit-api":
|
||||||
|
@ -233,10 +240,10 @@ export class wsapi {
|
||||||
this._win.webContents.executeJavaScript(`wsapi.searchLibrary(\`${data.term}\`, \`${data.limit}\`)`);
|
this._win.webContents.executeJavaScript(`wsapi.searchLibrary(\`${data.term}\`, \`${data.limit}\`)`);
|
||||||
break;
|
break;
|
||||||
case "show-window":
|
case "show-window":
|
||||||
this._win.show()
|
this._win.show();
|
||||||
break;
|
break;
|
||||||
case "hide-window":
|
case "hide-window":
|
||||||
this._win.hide()
|
this._win.hide();
|
||||||
break;
|
break;
|
||||||
case "play-mediaitem":
|
case "play-mediaitem":
|
||||||
this._win.webContents.executeJavaScript(`wsapi.playTrackById("${data.id}", \`${data.kind}\`)`);
|
this._win.webContents.executeJavaScript(`wsapi.playTrackById("${data.id}", \`${data.kind}\`)`);
|
||||||
|
@ -244,7 +251,7 @@ export class wsapi {
|
||||||
break;
|
break;
|
||||||
case "get-status":
|
case "get-status":
|
||||||
response.data = {
|
response.data = {
|
||||||
isAuthorized: true
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
response.message = "Status";
|
response.message = "Status";
|
||||||
break;
|
break;
|
||||||
|
@ -267,7 +274,7 @@ export class wsapi {
|
||||||
ws.send(JSON.stringify(response));
|
ws.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.on('close', () => {
|
ws.on("close", () => {
|
||||||
// remove client from list
|
// remove client from list
|
||||||
this.clients.splice(wsapi.clients.indexOf(ws), 1);
|
this.clients.splice(wsapi.clients.indexOf(ws), 1);
|
||||||
console.log(`Client ${ws.id} disconnected`);
|
console.log(`Client ${ws.id} disconnected`);
|
||||||
|
@ -281,56 +288,96 @@ export class wsapi {
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlaybackState(attr: any) {
|
updatePlaybackState(attr: any) {
|
||||||
const response: standardResponse = {status: 0, data: attr, message: "OK", type: "playbackStateUpdate"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: attr,
|
||||||
|
message: "OK",
|
||||||
|
type: "playbackStateUpdate",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnMusicKitApi(results: any, method: any) {
|
returnMusicKitApi(results: any, method: any) {
|
||||||
const response: standardResponse = {status: 0, data: results, message: "OK", type: `musickitapi.${method}`};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: results,
|
||||||
|
message: "OK",
|
||||||
|
type: `musickitapi.${method}`,
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnDynamic(results: any, type: any) {
|
returnDynamic(results: any, type: any) {
|
||||||
const response: standardResponse = {status: 0, data: results, message: "OK", type: type};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: results,
|
||||||
|
message: "OK",
|
||||||
|
type: type,
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnLyrics(results: any) {
|
returnLyrics(results: any) {
|
||||||
const response: standardResponse = {status: 0, data: results, message: "OK", type: "lyrics"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: results,
|
||||||
|
message: "OK",
|
||||||
|
type: "lyrics",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnSearch(results: any) {
|
returnSearch(results: any) {
|
||||||
const response: standardResponse = {status: 0, data: results, message: "OK", type: "searchResults"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: results,
|
||||||
|
message: "OK",
|
||||||
|
type: "searchResults",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnSearchLibrary(results: any) {
|
returnSearchLibrary(results: any) {
|
||||||
const response: standardResponse = {status: 0, data: results, message: "OK", type: "searchResultsLibrary"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: results,
|
||||||
|
message: "OK",
|
||||||
|
type: "searchResultsLibrary",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnQueue(queue: any) {
|
returnQueue(queue: any) {
|
||||||
const response: standardResponse = {status: 0, data: queue, message: "OK", type: "queue"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: queue,
|
||||||
|
message: "OK",
|
||||||
|
type: "queue",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
returnmaxVolume(vol: any) {
|
returnmaxVolume(vol: any) {
|
||||||
const response: standardResponse = {status: 0, data: vol, message: "OK", type: "maxVolume"};
|
const response: standardResponse = {
|
||||||
|
status: 0,
|
||||||
|
data: vol,
|
||||||
|
message: "OK",
|
||||||
|
type: "maxVolume",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
|
@ -338,10 +385,14 @@ export class wsapi {
|
||||||
|
|
||||||
returnLibraryStatus(inLibrary: boolean, rating: number) {
|
returnLibraryStatus(inLibrary: boolean, rating: number) {
|
||||||
const response: standardResponse = {
|
const response: standardResponse = {
|
||||||
status: 0, data: {
|
status: 0,
|
||||||
inLibrary, rating
|
data: {
|
||||||
}, message: "OK", type: "libraryStatus"
|
inLibrary,
|
||||||
}
|
rating,
|
||||||
|
},
|
||||||
|
message: "OK",
|
||||||
|
type: "libraryStatus",
|
||||||
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
});
|
});
|
||||||
|
@ -349,8 +400,10 @@ export class wsapi {
|
||||||
|
|
||||||
returnRatingStatus(kind: string, id: string, rating: number) {
|
returnRatingStatus(kind: string, id: string, rating: number) {
|
||||||
const response: standardResponse = {
|
const response: standardResponse = {
|
||||||
status: 0, data: { kind, id, rating },
|
status: 0,
|
||||||
message: "OK", type: "rate"
|
data: { kind, id, rating },
|
||||||
|
message: "OK",
|
||||||
|
type: "rate",
|
||||||
};
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
|
@ -359,8 +412,10 @@ export class wsapi {
|
||||||
|
|
||||||
returnLibraryChange(kind: string, id: string, shouldAdd: boolean) {
|
returnLibraryChange(kind: string, id: string, shouldAdd: boolean) {
|
||||||
const response: standardResponse = {
|
const response: standardResponse = {
|
||||||
status: 0, data: { kind, id, add: shouldAdd },
|
status: 0,
|
||||||
message: "OK", type: "change-library"
|
data: { kind, id, add: shouldAdd },
|
||||||
|
message: "OK",
|
||||||
|
type: "change-library",
|
||||||
};
|
};
|
||||||
this.clients.forEach(function each(client: any) {
|
this.clients.forEach(function each(client: any) {
|
||||||
client.send(JSON.stringify(response));
|
client.send(JSON.stringify(response));
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
require("v8-compile-cache");
|
require("v8-compile-cache");
|
||||||
|
|
||||||
import {join} from "path";
|
import { join } from "path";
|
||||||
import {app} from "electron"
|
import { app } from "electron";
|
||||||
if (!app.isPackaged) {
|
if (!app.isPackaged) {
|
||||||
app.setPath("userData", join(app.getPath("appData"), "Cider"));
|
app.setPath("userData", join(app.getPath("appData"), "Cider"));
|
||||||
}
|
}
|
||||||
|
|
||||||
import {Store} from "./base/store";
|
import { Store } from "./base/store";
|
||||||
import {AppEvents} from "./base/app";
|
import { AppEvents } from "./base/app";
|
||||||
import {Plugins} from "./base/plugins";
|
import { Plugins } from "./base/plugins";
|
||||||
import {BrowserWindow} from "./base/browserwindow";
|
import { BrowserWindow } from "./base/browserwindow";
|
||||||
import {init as Sentry} from "@sentry/electron";
|
import { init as Sentry } from "@sentry/electron";
|
||||||
import {RewriteFrames} from "@sentry/integrations";
|
import { RewriteFrames } from "@sentry/integrations";
|
||||||
import {components, ipcMain} from "electron"
|
import { components, ipcMain } from "electron";
|
||||||
|
|
||||||
// Analytics for debugging fun yeah.
|
// Analytics for debugging fun yeah.
|
||||||
Sentry({
|
Sentry({
|
||||||
|
@ -35,29 +35,28 @@ const CiderPlug = new Plugins();
|
||||||
app.on("ready", () => {
|
app.on("ready", () => {
|
||||||
Cider.ready(CiderPlug);
|
Cider.ready(CiderPlug);
|
||||||
|
|
||||||
console.log("[Cider] Application is Ready. Creating Window.")
|
console.log("[Cider] Application is Ready. Creating Window.");
|
||||||
if (!app.isPackaged) {
|
if (!app.isPackaged) {
|
||||||
console.info("[Cider] Running in development mode.")
|
console.info("[Cider] Running in development mode.");
|
||||||
require("vue-devtools").install()
|
require("vue-devtools").install();
|
||||||
}
|
}
|
||||||
|
|
||||||
components.whenReady().then(async () => {
|
components.whenReady().then(async () => {
|
||||||
const bw = new BrowserWindow()
|
const bw = new BrowserWindow();
|
||||||
const win = await bw.createWindow()
|
const win = await bw.createWindow();
|
||||||
|
|
||||||
app.getGPUInfo("complete").then(gpuInfo => {
|
app.getGPUInfo("complete").then((gpuInfo) => {
|
||||||
console.log(gpuInfo)
|
console.log(gpuInfo);
|
||||||
})
|
});
|
||||||
|
|
||||||
console.log("[Cider][Widevine] Status:", components.status());
|
console.log("[Cider][Widevine] Status:", components.status());
|
||||||
Cider.bwCreated();
|
Cider.bwCreated();
|
||||||
win.on("ready-to-show", () => {
|
win.on("ready-to-show", () => {
|
||||||
console.debug("[Cider] Window is Ready.")
|
console.debug("[Cider] Window is Ready.");
|
||||||
CiderPlug.callPlugins("onReady", win);
|
CiderPlug.callPlugins("onReady", win);
|
||||||
win.show();
|
win.show();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -66,7 +65,7 @@ app.on("ready", () => {
|
||||||
|
|
||||||
ipcMain.handle("renderer-ready", (event) => {
|
ipcMain.handle("renderer-ready", (event) => {
|
||||||
CiderPlug.callPlugins("onRendererReady", event);
|
CiderPlug.callPlugins("onRendererReady", event);
|
||||||
})
|
});
|
||||||
|
|
||||||
ipcMain.on("playbackStateDidChange", (_event, attributes) => {
|
ipcMain.on("playbackStateDidChange", (_event, attributes) => {
|
||||||
CiderPlug.callPlugins("onPlaybackStateDidChange", attributes);
|
CiderPlug.callPlugins("onPlaybackStateDidChange", attributes);
|
||||||
|
@ -88,19 +87,19 @@ app.on("before-quit", () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
app.on("widevine-ready", (version, lastVersion) => {
|
app.on("widevine-ready", (version, lastVersion) => {
|
||||||
if (null !== lastVersion) {
|
if (null !== lastVersion) {
|
||||||
console.log("[Cider][Widevine] Widevine " + version + ", upgraded from " + lastVersion + ", is ready to be used!")
|
console.log("[Cider][Widevine] Widevine " + version + ", upgraded from " + lastVersion + ", is ready to be used!");
|
||||||
} else {
|
} else {
|
||||||
console.log("[Cider][Widevine] Widevine " + version + " is ready to be used!")
|
console.log("[Cider][Widevine] Widevine " + version + " is ready to be used!");
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
app.on("widevine-update-pending", (currentVersion, pendingVersion) => {
|
app.on("widevine-update-pending", (currentVersion, pendingVersion) => {
|
||||||
console.log("[Cider][Widevine] Widevine " + currentVersion + " is ready to be upgraded to " + pendingVersion + "!")
|
console.log("[Cider][Widevine] Widevine " + currentVersion + " is ready to be upgraded to " + pendingVersion + "!");
|
||||||
})
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
app.on("widevine-error", (error) => {
|
app.on("widevine-error", (error) => {
|
||||||
console.log("[Cider][Widevine] Widevine installation encountered an error: " + error)
|
console.log("[Cider][Widevine] Widevine installation encountered an error: " + error);
|
||||||
app.exit()
|
app.exit();
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import * as electron from 'electron';
|
import * as electron from "electron";
|
||||||
import * as os from 'os';
|
import * as os from "os";
|
||||||
import {resolve} from 'path';
|
import { resolve } from "path";
|
||||||
import * as CiderReceiver from '../base/castreceiver';
|
import * as CiderReceiver from "../base/castreceiver";
|
||||||
|
|
||||||
export default class ChromecastPlugin {
|
export default class ChromecastPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private variables for interaction in plugins
|
* Private variables for interaction in plugins
|
||||||
*/
|
*/
|
||||||
|
@ -13,8 +12,8 @@ export default class ChromecastPlugin {
|
||||||
private _lastfm: any;
|
private _lastfm: any;
|
||||||
private _store: any;
|
private _store: any;
|
||||||
private _timer: any;
|
private _timer: any;
|
||||||
private audioClient = require('castv2-client').Client;
|
private audioClient = require("castv2-client").Client;
|
||||||
private mdns = require('mdns-js');
|
private mdns = require("mdns-js");
|
||||||
|
|
||||||
private devices: any = [];
|
private devices: any = [];
|
||||||
private castDevices: any = [];
|
private castDevices: any = [];
|
||||||
|
@ -28,48 +27,45 @@ export default class ChromecastPlugin {
|
||||||
// private GCstream = new Stream.PassThrough(),
|
// private GCstream = new Stream.PassThrough(),
|
||||||
private connectedHosts: any = {};
|
private connectedHosts: any = {};
|
||||||
private connectedPlayer: any;
|
private connectedPlayer: any;
|
||||||
private ciderPort :any = 9000;
|
private ciderPort: any = 9000;
|
||||||
// private server = false;
|
// private server = false;
|
||||||
// private bufcount = 0;
|
// private bufcount = 0;
|
||||||
// private bufcount2 = 0;
|
// private bufcount2 = 0;
|
||||||
// private headerSent = false;
|
// private headerSent = false;
|
||||||
|
|
||||||
|
|
||||||
private searchForGCDevices() {
|
private searchForGCDevices() {
|
||||||
try {
|
try {
|
||||||
|
let browser = this.mdns.createBrowser(this.mdns.tcp("googlecast"));
|
||||||
|
browser.on("ready", browser.discover);
|
||||||
|
|
||||||
let browser = this.mdns.createBrowser(this.mdns.tcp('googlecast'));
|
browser.on("update", (service: any) => {
|
||||||
browser.on('ready', browser.discover);
|
if (service.addresses && service.fullname && service.fullname.includes("_googlecast._tcp")) {
|
||||||
|
let a = service.txt.filter((u: any) => String(u).startsWith("fn="));
|
||||||
browser.on('update', (service: any) => {
|
let name = (a[0] ?? "").substring(3) != "" ? (a[0] ?? "").substring(3) : service.fullname.substring(0, service.fullname.indexOf("._googlecast"));
|
||||||
if (service.addresses && service.fullname && service.fullname.includes('_googlecast._tcp')) {
|
this.ondeviceup(service.addresses[0], name + " (" + (service.type[0]?.description ?? "") + ")", "", "googlecast");
|
||||||
let a = service.txt.filter((u: any) => String(u).startsWith('fn='))
|
|
||||||
let name = (((a[0] ?? "").substring(3)) != "") ? ((a[0] ?? "").substring(3)) : (service.fullname.substring(0, service.fullname.indexOf("._googlecast")) )
|
|
||||||
this.ondeviceup(service.addresses[0], name+ " (" + (service.type[0]?.description ?? "") + ")" , '', 'googlecast');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const Client = require('node-ssdp').Client;
|
const Client = require("node-ssdp").Client;
|
||||||
// also do a SSDP/UPnP search
|
// also do a SSDP/UPnP search
|
||||||
let ssdpBrowser = new Client();
|
let ssdpBrowser = new Client();
|
||||||
ssdpBrowser.on('response', (headers: any, statusCode: any, rinfo: any) => {
|
ssdpBrowser.on("response", (headers: any, statusCode: any, rinfo: any) => {
|
||||||
var location = getLocation(headers);
|
var location = getLocation(headers);
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
this.getServiceDescription(location, rinfo.address);
|
this.getServiceDescription(location, rinfo.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function getLocation(headers: any) {
|
function getLocation(headers: any) {
|
||||||
let location = null;
|
let location = null;
|
||||||
if (headers["LOCATION"] != null) {
|
if (headers["LOCATION"] != null) {
|
||||||
location = headers["LOCATION"]
|
location = headers["LOCATION"];
|
||||||
} else if (headers["Location"] != null) {
|
} else if (headers["Location"] != null) {
|
||||||
location = headers["Location"]
|
location = headers["Location"];
|
||||||
}
|
}
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssdpBrowser.search('urn:dial-multiscreen-org:device:dial:1');
|
ssdpBrowser.search("urn:dial-multiscreen-org:device:dial:1");
|
||||||
|
|
||||||
// // actual upnp devices
|
// // actual upnp devices
|
||||||
// if (app.cfg.get("audio.enableDLNA")) {
|
// if (app.cfg.get("audio.enableDLNA")) {
|
||||||
|
@ -84,15 +80,13 @@ export default class ChromecastPlugin {
|
||||||
// ssdpBrowser2.search('urn:schemas-upnp-org:device:MediaRenderer:1');
|
// ssdpBrowser2.search('urn:schemas-upnp-org:device:MediaRenderer:1');
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Search GC err', e);
|
console.log("Search GC err", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getServiceDescription(url: any, address: any) {
|
private getServiceDescription(url: any, address: any) {
|
||||||
const request = require('request');
|
const request = require("request");
|
||||||
request.get(url, (error: any, response: any, body: any) => {
|
request.get(url, (error: any, response: any, body: any) => {
|
||||||
if (!error && response.statusCode === 200) {
|
if (!error && response.statusCode === 200) {
|
||||||
this.parseServiceDescription(body, address, url);
|
this.parseServiceDescription(body, address, url);
|
||||||
|
@ -106,7 +100,7 @@ export default class ChromecastPlugin {
|
||||||
name: name,
|
name: name,
|
||||||
host: host,
|
host: host,
|
||||||
location: location,
|
location: location,
|
||||||
type: type
|
type: type,
|
||||||
});
|
});
|
||||||
if (this.devices.indexOf(host) === -1) {
|
if (this.devices.indexOf(host) === -1) {
|
||||||
this.devices.push(host);
|
this.devices.push(host);
|
||||||
|
@ -122,22 +116,21 @@ export default class ChromecastPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseServiceDescription(body: any, address: any, url: any) {
|
private parseServiceDescription(body: any, address: any, url: any) {
|
||||||
const parseString = require('xml2js').parseString;
|
const parseString = require("xml2js").parseString;
|
||||||
parseString(body, (err: any, result: any) => {
|
parseString(body, (err: any, result: any) => {
|
||||||
if (!err && result && result.root && result.root.device) {
|
if (!err && result && result.root && result.root.device) {
|
||||||
const device = result.root.device[0];
|
const device = result.root.device[0];
|
||||||
console.log('device', device);
|
console.log("device", device);
|
||||||
let devicetype = 'googlecast';
|
let devicetype = "googlecast";
|
||||||
console.log()
|
console.log();
|
||||||
if (device.deviceType && device.deviceType.toString() === 'urn:schemas-upnp-org:device:MediaRenderer:1') {
|
if (device.deviceType && device.deviceType.toString() === "urn:schemas-upnp-org:device:MediaRenderer:1") {
|
||||||
devicetype = 'upnp';
|
devicetype = "upnp";
|
||||||
}
|
}
|
||||||
this.ondeviceup(address, device.friendlyName.toString(), url, devicetype);
|
this.ondeviceup(address, device.friendlyName.toString(), url, devicetype);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private loadMedia(client: any, song: any, artist: any, album: any, albumart: any, cb?: any) {
|
private loadMedia(client: any, song: any, artist: any, album: any, albumart: any, cb?: any) {
|
||||||
// const u = 'http://' + this.getIp() + ':' + server.address().port + '/';
|
// const u = 'http://' + this.getIp() + ':' + server.address().port + '/';
|
||||||
// const DefaultMediaReceiver : any = require('castv2-client').DefaultMediaReceiver;
|
// const DefaultMediaReceiver : any = require('castv2-client').DefaultMediaReceiver;
|
||||||
|
@ -148,9 +141,9 @@ export default class ChromecastPlugin {
|
||||||
}
|
}
|
||||||
let media = {
|
let media = {
|
||||||
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
|
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
|
||||||
contentId: 'http://' + this.getIp() + ':'+ this.ciderPort +'/audio.wav',
|
contentId: "http://" + this.getIp() + ":" + this.ciderPort + "/audio.wav",
|
||||||
contentType: 'audio/wav',
|
contentType: "audio/wav",
|
||||||
streamType: 'LIVE', // or LIVE
|
streamType: "LIVE", // or LIVE
|
||||||
|
|
||||||
// Title and cover displayed while buffering
|
// Title and cover displayed while buffering
|
||||||
metadata: {
|
metadata: {
|
||||||
|
@ -159,23 +152,25 @@ export default class ChromecastPlugin {
|
||||||
title: song ?? "",
|
title: song ?? "",
|
||||||
albumName: album ?? "",
|
albumName: album ?? "",
|
||||||
artist: artist ?? "",
|
artist: artist ?? "",
|
||||||
images: [
|
images: [{ url: albumart ?? "" }],
|
||||||
{url: albumart ?? ""}]
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
player.on('status', (status: any) => {
|
player.on("status", (status: any) => {
|
||||||
console.log('status broadcast playerState=%s', status);
|
console.log("status broadcast playerState=%s", status);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('app "%s" launched, loading media %s ...', player, media);
|
console.log('app "%s" launched, loading media %s ...', player, media);
|
||||||
|
|
||||||
player.load(media, {
|
player.load(
|
||||||
autoplay: true
|
media,
|
||||||
}, (err: any, status: any) => {
|
{
|
||||||
console.log('media loaded playerState=%s', status);
|
autoplay: true,
|
||||||
});
|
},
|
||||||
|
(err: any, status: any) => {
|
||||||
|
console.log("media loaded playerState=%s", status);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
client.getStatus((x: any, status: any) => {
|
client.getStatus((x: any, status: any) => {
|
||||||
if (status && status.volume) {
|
if (status && status.volume) {
|
||||||
|
@ -183,40 +178,37 @@ export default class ChromecastPlugin {
|
||||||
client.muted = status.volume.muted;
|
client.muted = status.volume.muted;
|
||||||
client.stepInterval = status.volume.stepInterval;
|
client.stepInterval = status.volume.stepInterval;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// send websocket ip
|
// send websocket ip
|
||||||
|
|
||||||
player.sendIp("ws://" + this.getIp() + ":26369");
|
player.sendIp("ws://" + this.getIp() + ":26369");
|
||||||
electron.ipcMain.on('stopGCast', (_event) => {
|
electron.ipcMain.on("stopGCast", (_event) => {
|
||||||
player.kill();
|
player.kill();
|
||||||
})
|
});
|
||||||
electron.app.on('before-quit', (_event) => {
|
electron.app.on("before-quit", (_event) => {
|
||||||
player.kill();
|
player.kill();
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getIp(){
|
private getIp() {
|
||||||
let ip: string = '';
|
let ip: string = "";
|
||||||
let ip2: any = [];
|
let ip2: any = [];
|
||||||
let alias = 0;
|
let alias = 0;
|
||||||
const ifaces: any = os.networkInterfaces();
|
const ifaces: any = os.networkInterfaces();
|
||||||
for (let dev in ifaces) {
|
for (let dev in ifaces) {
|
||||||
ifaces[dev].forEach((details: any) => {
|
ifaces[dev].forEach((details: any) => {
|
||||||
if (details.family === 'IPv4' && !details.internal) {
|
if (details.family === "IPv4" && !details.internal) {
|
||||||
if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ':' + alias : ''))) {
|
if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ":" + alias : ""))) {
|
||||||
if (details.address.substring(0, 8) === '192.168.' ||
|
if (details.address.substring(0, 8) === "192.168." || details.address.substring(0, 7) === "172.16." || details.address.substring(0, 3) === "10.") {
|
||||||
details.address.substring(0, 7) === '172.16.' ||
|
if (
|
||||||
details.address.substring(0, 3) === '10.'
|
!ip.startsWith("192.168.") ||
|
||||||
|
(ip2.startsWith("192.168.") && !ip.startsWith("192.168.") && ip2.startsWith("172.16.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.")) ||
|
||||||
|
(ip2.startsWith("10.") && !ip.startsWith("192.168.") && !ip.startsWith("172.16.") && !ip.startsWith("10."))
|
||||||
) {
|
) {
|
||||||
if (!ip.startsWith('192.168.') ||
|
ip = details.address;
|
||||||
(ip2.startsWith('192.168.') && !ip.startsWith('192.168.')) &&
|
}
|
||||||
(ip2.startsWith('172.16.') && !ip.startsWith('192.168.') && !ip.startsWith('172.16.')) ||
|
|
||||||
(ip2.startsWith('10.') && !ip.startsWith('192.168.') && !ip.startsWith('172.16.') && !ip.startsWith('10.'))
|
|
||||||
){ip = details.address;}
|
|
||||||
++alias;
|
++alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,13 +219,13 @@ export default class ChromecastPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private stream(device: any, song: any, artist: any, album: any, albumart: any) {
|
private stream(device: any, song: any, artist: any, album: any, albumart: any) {
|
||||||
let castMode = 'googlecast';
|
let castMode = "googlecast";
|
||||||
let UPNPDesc = '';
|
let UPNPDesc = "";
|
||||||
castMode = device.type;
|
castMode = device.type;
|
||||||
UPNPDesc = device.location;
|
UPNPDesc = device.location;
|
||||||
|
|
||||||
let client;
|
let client;
|
||||||
if (castMode === 'googlecast') {
|
if (castMode === "googlecast") {
|
||||||
let client = new this.audioClient();
|
let client = new this.audioClient();
|
||||||
client.volume = 100;
|
client.volume = 100;
|
||||||
client.stepInterval = 0.5;
|
client.stepInterval = 0.5;
|
||||||
|
@ -248,7 +240,7 @@ export default class ChromecastPlugin {
|
||||||
this.loadMedia(client, song, artist, album, albumart);
|
this.loadMedia(client, song, artist, album, albumart);
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('close', () => {
|
client.on("close", () => {
|
||||||
console.info("Client Closed");
|
console.info("Client Closed");
|
||||||
for (let i = this.activeConnections.length - 1; i >= 0; i--) {
|
for (let i = this.activeConnections.length - 1; i >= 0; i--) {
|
||||||
if (this.activeConnections[i] === client) {
|
if (this.activeConnections[i] === client) {
|
||||||
|
@ -258,12 +250,11 @@ export default class ChromecastPlugin {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('error', (err: any) => {
|
client.on("error", (err: any) => {
|
||||||
console.log('Error: %s', err.message);
|
console.log("Error: %s", err.message);
|
||||||
client.close();
|
client.close();
|
||||||
delete this.connectedHosts[device.host];
|
delete this.connectedHosts[device.host];
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// upnp devices
|
// upnp devices
|
||||||
//try {
|
//try {
|
||||||
|
@ -280,36 +271,33 @@ export default class ChromecastPlugin {
|
||||||
// // protocolInfo: 'DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000;
|
// // protocolInfo: 'DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000;
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// client.load('http://' + getIp() + ':' + server.address().port + '/a.wav', options, function (err, _result) {
|
// client.load('http://' + getIp() + ':' + server.address().port + '/a.wav', options, function (err, _result) {
|
||||||
// if (err) throw err;
|
// if (err) throw err;
|
||||||
// console.log('playing ...');
|
// console.log('playing ...');
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// } catch (e) {
|
// } catch (e) {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setupGCServer() {
|
private async setupGCServer() {
|
||||||
return ''
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'Chromecast';
|
public name: string = "Chromecast";
|
||||||
public description: string = 'LastFM plugin for Cider';
|
public description: string = "LastFM plugin for Cider";
|
||||||
public version: string = '0.0.1';
|
public version: string = "0.0.1";
|
||||||
public author: string = 'vapormusic / Cider Collective';
|
public author: string = "vapormusic / Cider Collective";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
*/
|
*/
|
||||||
constructor(utils: { getApp: () => any; getStore: () => any; }) {
|
constructor(utils: { getApp: () => any; getStore: () => any }) {
|
||||||
this._app = utils.getApp();
|
this._app = utils.getApp();
|
||||||
this._store = utils.getStore()
|
this._store = utils.getStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -317,11 +305,11 @@ export default class ChromecastPlugin {
|
||||||
*/
|
*/
|
||||||
onReady(win: any): void {
|
onReady(win: any): void {
|
||||||
this._win = win;
|
this._win = win;
|
||||||
electron.ipcMain.on('getKnownCastDevices', (event) => {
|
electron.ipcMain.on("getKnownCastDevices", (event) => {
|
||||||
event.returnValue = this.castDevices
|
event.returnValue = this.castDevices;
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('performGCCast', (event, device, song, artist, album, albumart) => {
|
electron.ipcMain.on("performGCCast", (event, device, song, artist, album, albumart) => {
|
||||||
// this.setupGCServer().then( () => {
|
// this.setupGCServer().then( () => {
|
||||||
this._win.webContents.setAudioMuted(true);
|
this._win.webContents.setAudioMuted(true);
|
||||||
console.log(device);
|
console.log(device);
|
||||||
|
@ -329,44 +317,36 @@ export default class ChromecastPlugin {
|
||||||
// })
|
// })
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('getChromeCastDevices', (_event, _data) => {
|
electron.ipcMain.on("getChromeCastDevices", (_event, _data) => {
|
||||||
this.searchForGCDevices();
|
this.searchForGCDevices();
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('stopGCast', (_event) => {
|
electron.ipcMain.on("stopGCast", (_event) => {
|
||||||
this._win.webContents.setAudioMuted(false);
|
this._win.webContents.setAudioMuted(false);
|
||||||
this.activeConnections.forEach((client: any) => {
|
this.activeConnections.forEach((client: any) => {
|
||||||
try{
|
try {
|
||||||
client.stop();
|
client.stop();
|
||||||
} catch(e){}
|
} catch (e) {}
|
||||||
})
|
});
|
||||||
this.activeConnections = [];
|
this.activeConnections = [];
|
||||||
this.connectedHosts = {};
|
this.connectedHosts = {};
|
||||||
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on app stop
|
* Runs on app stop
|
||||||
*/
|
*/
|
||||||
onBeforeQuit(): void {
|
onBeforeQuit(): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on song change
|
* Runs on song change
|
||||||
* @param attributes Music Attributes
|
* @param attributes Music Attributes
|
||||||
*/
|
*/
|
||||||
onNowPlayingItemDidChange(attributes: any): void {
|
onNowPlayingItemDidChange(attributes: any): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onRendererReady(): void {
|
onRendererReady(): void {
|
||||||
this._win.webContents.executeJavaScript(
|
this._win.webContents.executeJavaScript(`ipcRenderer.sendSync('get-port')`).then((result: any) => {
|
||||||
`ipcRenderer.sendSync('get-port')`
|
|
||||||
).then((result: any) => {
|
|
||||||
this.ciderPort = result;
|
this.ciderPort = result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,16 +1,15 @@
|
||||||
import {AutoClient} from 'discord-auto-rpc'
|
import { AutoClient } from "discord-auto-rpc";
|
||||||
import {ipcMain} from "electron";
|
import { ipcMain } from "electron";
|
||||||
import fetch from 'electron-fetch'
|
import fetch from "electron-fetch";
|
||||||
|
|
||||||
export default class DiscordRPC {
|
export default class DiscordRPC {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'Discord Rich Presence';
|
public name: string = "Discord Rich Presence";
|
||||||
public description: string = 'Discord RPC plugin for Cider';
|
public description: string = "Discord RPC plugin for Cider";
|
||||||
public version: string = '1.1.0';
|
public version: string = "1.1.0";
|
||||||
public author: string = 'vapormusic/Core (Cider Collective)';
|
public author: string = "vapormusic/Core (Cider Collective)";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private variables for interaction in plugins
|
* Private variables for interaction in plugins
|
||||||
|
@ -24,13 +23,13 @@ export default class DiscordRPC {
|
||||||
*/
|
*/
|
||||||
private _client: any = null;
|
private _client: any = null;
|
||||||
private _activityCache: any = {
|
private _activityCache: any = {
|
||||||
details: '',
|
details: "",
|
||||||
state: '',
|
state: "",
|
||||||
largeImageKey: '',
|
largeImageKey: "",
|
||||||
largeImageText: '',
|
largeImageText: "",
|
||||||
smallImageKey: '',
|
smallImageKey: "",
|
||||||
smallImageText: '',
|
smallImageText: "",
|
||||||
instance: false
|
instance: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
|
@ -49,74 +48,71 @@ export default class DiscordRPC {
|
||||||
* Runs on app ready
|
* Runs on app ready
|
||||||
*/
|
*/
|
||||||
onReady(_win: any): void {
|
onReady(_win: any): void {
|
||||||
const self = this
|
const self = this;
|
||||||
this.connect();
|
this.connect();
|
||||||
console.debug(`[Plugin][${this.name}] Ready.`);
|
console.debug(`[Plugin][${this.name}] Ready.`);
|
||||||
ipcMain.on('updateRPCImage', async (_event, imageurl) => {
|
ipcMain.on("updateRPCImage", async (_event, imageurl) => {
|
||||||
if (!this._utils.getStoreValue("general.privateEnabled")) {
|
if (!this._utils.getStoreValue("general.privateEnabled")) {
|
||||||
let b64data = ""
|
let b64data = "";
|
||||||
let postbody = ""
|
let postbody = "";
|
||||||
if (imageurl.startsWith("/ciderlocalart")){
|
if (imageurl.startsWith("/ciderlocalart")) {
|
||||||
let port = await _win.webContents.executeJavaScript(
|
let port = await _win.webContents.executeJavaScript(`app.clientPort`);
|
||||||
`app.clientPort`
|
console.log("http://localhost:" + port + imageurl);
|
||||||
);
|
const response = await fetch("http://localhost:" + port + imageurl);
|
||||||
console.log("http://localhost:"+port+imageurl)
|
b64data = (await response.buffer()).toString("base64");
|
||||||
const response = await fetch("http://localhost:"+port+imageurl)
|
postbody = JSON.stringify({ data: b64data });
|
||||||
b64data = (await response.buffer()).toString('base64');
|
fetch("https://api.cider.sh/v1/images", {
|
||||||
postbody = JSON.stringify({data: b64data})
|
method: "POST",
|
||||||
fetch('https://api.cider.sh/v1/images', {
|
|
||||||
|
|
||||||
method: 'POST',
|
|
||||||
body: postbody,
|
body: postbody,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
'User-Agent': _win.webContents.getUserAgent()
|
"User-Agent": _win.webContents.getUserAgent(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then((res) => res.json())
|
||||||
.then(function (json) {
|
.then(function (json) {
|
||||||
self._attributes["artwork"]["url"] = json.url
|
self._attributes["artwork"]["url"] = json.url;
|
||||||
self.setActivity(self._attributes)
|
self.setActivity(self._attributes);
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
postbody = JSON.stringify({url: imageurl})
|
postbody = JSON.stringify({ url: imageurl });
|
||||||
fetch('https://api.cider.sh/v1/images', {
|
fetch("https://api.cider.sh/v1/images", {
|
||||||
|
method: "POST",
|
||||||
method: 'POST',
|
|
||||||
body: postbody,
|
body: postbody,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
'User-Agent': _win.webContents.getUserAgent()
|
"User-Agent": _win.webContents.getUserAgent(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then((res) => res.json())
|
||||||
.then(function (json) {
|
.then(function (json) {
|
||||||
self._attributes["artwork"]["url"] = json.url
|
self._attributes["artwork"]["url"] = json.url;
|
||||||
self.setActivity(self._attributes)
|
self.setActivity(self._attributes);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
ipcMain.on("reloadRPC", () => {
|
ipcMain.on("reloadRPC", () => {
|
||||||
console.log(`[DiscordRPC][reload] Reloading DiscordRPC.`);
|
console.log(`[DiscordRPC][reload] Reloading DiscordRPC.`);
|
||||||
this._client.destroy()
|
this._client.destroy();
|
||||||
|
|
||||||
this._client.endlessLogin({clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? '911790844204437504' : '886578863147192350'})
|
this._client
|
||||||
|
.endlessLogin({
|
||||||
|
clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? "911790844204437504" : "886578863147192350",
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.ready = true
|
this.ready = true;
|
||||||
this._utils.getWindow().webContents.send("rpcReloaded", this._client.user)
|
this._utils.getWindow().webContents.send("rpcReloaded", this._client.user);
|
||||||
if (this._activityCache && this._activityCache.details && this._activityCache.state) {
|
if (this._activityCache && this._activityCache.details && this._activityCache.state) {
|
||||||
console.info(`[DiscordRPC][reload] Restoring activity cache.`);
|
console.info(`[DiscordRPC][reload] Restoring activity cache.`);
|
||||||
this._client.setActivity(this._activityCache)
|
this._client.setActivity(this._activityCache);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((e: any) => console.error(`[DiscordRPC][reload] ${e}`));
|
.catch((e: any) => console.error(`[DiscordRPC][reload] ${e}`));
|
||||||
// this.connect(true)
|
// this.connect(true)
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on app stop
|
* Runs on app stop
|
||||||
*/
|
*/
|
||||||
|
@ -129,9 +125,8 @@ export default class DiscordRPC {
|
||||||
* @param attributes Music Attributes (attributes.status = current state)
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {
|
||||||
this._attributes = attributes
|
this._attributes = attributes;
|
||||||
this.setActivity(attributes)
|
this.setActivity(attributes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,12 +134,10 @@ export default class DiscordRPC {
|
||||||
* @param attributes Music Attributes
|
* @param attributes Music Attributes
|
||||||
*/
|
*/
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {
|
||||||
this._attributes = attributes
|
this._attributes = attributes;
|
||||||
this.setActivity(attributes)
|
this.setActivity(attributes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
* Private Methods
|
* Private Methods
|
||||||
* ****************************************************************************************/
|
* ****************************************************************************************/
|
||||||
|
@ -159,22 +152,25 @@ export default class DiscordRPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the client
|
// Create the client
|
||||||
this._client = new AutoClient({transport: "ipc"});
|
this._client = new AutoClient({ transport: "ipc" });
|
||||||
|
|
||||||
// Runs on Ready
|
// Runs on Ready
|
||||||
this._client.once('ready', () => {
|
this._client.once("ready", () => {
|
||||||
console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`);
|
console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`);
|
||||||
|
|
||||||
if (this._activityCache && this._activityCache.details && this._activityCache.state) {
|
if (this._activityCache && this._activityCache.details && this._activityCache.state) {
|
||||||
console.info(`[DiscordRPC][connect] Restoring activity cache.`);
|
console.info(`[DiscordRPC][connect] Restoring activity cache.`);
|
||||||
this._client.setActivity(this._activityCache)
|
this._client.setActivity(this._activityCache);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// Login to Discord
|
// Login to Discord
|
||||||
this._client.endlessLogin({clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? '911790844204437504' : '886578863147192350'})
|
this._client
|
||||||
|
.endlessLogin({
|
||||||
|
clientId: this._utils.getStoreValue("connectivity.discord_rpc.client") === "Cider" ? "911790844204437504" : "886578863147192350",
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.ready = true
|
this.ready = true;
|
||||||
})
|
})
|
||||||
.catch((e: any) => console.error(`[DiscordRPC][connect] ${e}`));
|
.catch((e: any) => console.error(`[DiscordRPC][connect] ${e}`));
|
||||||
}
|
}
|
||||||
|
@ -185,31 +181,31 @@ export default class DiscordRPC {
|
||||||
*/
|
*/
|
||||||
private setActivity(attributes: any) {
|
private setActivity(attributes: any) {
|
||||||
if (!this._client) {
|
if (!this._client) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if show buttons is (true) or (false)
|
// Check if show buttons is (true) or (false)
|
||||||
let activity: Object = {
|
let activity: Object = {
|
||||||
details: this._utils.getStoreValue("connectivity.discord_rpc.details_format"),
|
details: this._utils.getStoreValue("connectivity.discord_rpc.details_format"),
|
||||||
state: this._utils.getStoreValue("connectivity.discord_rpc.state_format"),
|
state: this._utils.getStoreValue("connectivity.discord_rpc.state_format"),
|
||||||
largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'),
|
largeImageKey: attributes?.artwork?.url?.replace("{w}", "1024").replace("{h}", "1024"),
|
||||||
largeImageText: attributes.albumName,
|
largeImageText: attributes.albumName,
|
||||||
instance: false // Whether the activity is in a game session
|
instance: false, // Whether the activity is in a game session
|
||||||
}
|
};
|
||||||
|
|
||||||
// Filter the activity
|
// Filter the activity
|
||||||
activity = this.filterActivity(activity, attributes)
|
activity = this.filterActivity(activity, attributes);
|
||||||
|
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
this._activityCache = activity
|
this._activityCache = activity;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the activity
|
// Set the activity
|
||||||
if (!attributes.status && this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
|
if (!attributes.status && this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
|
||||||
this._client.clearActivity()
|
this._client.clearActivity();
|
||||||
} else if (activity && this._activityCache !== activity) {
|
} else if (activity && this._activityCache !== activity) {
|
||||||
this._client.setActivity(activity)
|
this._client.setActivity(activity);
|
||||||
}
|
}
|
||||||
this._activityCache = activity;
|
this._activityCache = activity;
|
||||||
}
|
}
|
||||||
|
@ -218,25 +214,24 @@ export default class DiscordRPC {
|
||||||
* Filter the Discord activity object
|
* Filter the Discord activity object
|
||||||
*/
|
*/
|
||||||
private filterActivity(activity: any, attributes: any): Object {
|
private filterActivity(activity: any, attributes: any): Object {
|
||||||
|
|
||||||
// Add the buttons if people want them
|
// Add the buttons if people want them
|
||||||
if (!this._utils.getStoreValue("connectivity.discord_rpc.hide_buttons")) {
|
if (!this._utils.getStoreValue("connectivity.discord_rpc.hide_buttons")) {
|
||||||
activity.buttons = [
|
activity.buttons = [
|
||||||
{label: 'Listen on Cider', url: attributes.url.cider},
|
{ label: "Listen on Cider", url: attributes.url.cider },
|
||||||
{label: 'View on Apple Music', url: attributes.url.appleMusic}
|
{ label: "View on Apple Music", url: attributes.url.appleMusic },
|
||||||
] //To change attributes.url => preload/cider-preload.js
|
]; //To change attributes.url => preload/cider-preload.js
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the timestamp if its playing and people want them
|
// Add the timestamp if its playing and people want them
|
||||||
if (!this._utils.getStoreValue("connectivity.discord_rpc.hide_timestamp") && attributes.status) {
|
if (!this._utils.getStoreValue("connectivity.discord_rpc.hide_timestamp") && attributes.status) {
|
||||||
activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime)
|
activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime);
|
||||||
activity.endTimestamp = attributes.endTime
|
activity.endTimestamp = attributes.endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants to keep the activity when paused
|
// If the user wants to keep the activity when paused
|
||||||
if (!this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
|
if (!this._utils.getStoreValue("connectivity.discord_rpc.clear_on_pause")) {
|
||||||
activity.smallImageKey = attributes.status ? 'play' : 'pause';
|
activity.smallImageKey = attributes.status ? "play" : "pause";
|
||||||
activity.smallImageText = attributes.status ? 'Playing' : 'Paused';
|
activity.smallImageText = attributes.status ? "Playing" : "Paused";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,36 +243,36 @@ export default class DiscordRPC {
|
||||||
* {trackNumber}
|
* {trackNumber}
|
||||||
*/
|
*/
|
||||||
const rpcVars: any = {
|
const rpcVars: any = {
|
||||||
"artist": attributes.artistName,
|
artist: attributes.artistName,
|
||||||
"composer": attributes.composerName,
|
composer: attributes.composerName,
|
||||||
"title": attributes.name,
|
title: attributes.name,
|
||||||
"album": attributes.albumName,
|
album: attributes.albumName,
|
||||||
"trackNumber": attributes.trackNumber
|
trackNumber: attributes.trackNumber,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Replace the variables
|
// Replace the variables
|
||||||
Object.keys(rpcVars).forEach((key) => {
|
Object.keys(rpcVars).forEach((key) => {
|
||||||
if (activity.details.includes(`{${key}}`)) {
|
if (activity.details.includes(`{${key}}`)) {
|
||||||
activity.details = activity.details.replace(`{${key}}`, rpcVars[key])
|
activity.details = activity.details.replace(`{${key}}`, rpcVars[key]);
|
||||||
}
|
}
|
||||||
if (activity.state.includes(`{${key}}`)) {
|
if (activity.state.includes(`{${key}}`)) {
|
||||||
activity.state = activity.state.replace(`{${key}}`, rpcVars[key])
|
activity.state = activity.state.replace(`{${key}}`, rpcVars[key]);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
// Checks if the details is greater than 128 because some songs can be that long
|
// Checks if the details is greater than 128 because some songs can be that long
|
||||||
if (activity.details && activity.details.length >= 128) {
|
if (activity.details && activity.details.length >= 128) {
|
||||||
activity.details = activity.details.substring(0, 125) + '...'
|
activity.details = activity.details.substring(0, 125) + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the state is greater than 128 because some songs can be that long
|
// Checks if the state is greater than 128 because some songs can be that long
|
||||||
if (activity.state && activity.state.length >= 128) {
|
if (activity.state && activity.state.length >= 128) {
|
||||||
activity.state = activity.state.substring(0, 125) + '...'
|
activity.state = activity.state.substring(0, 125) + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the state is greater than 128 because some songs can be that long
|
// Checks if the state is greater than 128 because some songs can be that long
|
||||||
if (activity.largeImageText && activity.largeImageText.length >= 128) {
|
if (activity.largeImageText && activity.largeImageText.length >= 128) {
|
||||||
activity.largeImageText = activity.largeImageText.substring(0, 125) + '...'
|
activity.largeImageText = activity.largeImageText.substring(0, 125) + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check large image
|
// Check large image
|
||||||
|
@ -287,8 +282,8 @@ export default class DiscordRPC {
|
||||||
|
|
||||||
// Timestamp
|
// Timestamp
|
||||||
if (new Date(attributes.endTime).getTime() < 0) {
|
if (new Date(attributes.endTime).getTime() < 0) {
|
||||||
delete activity.startTime
|
delete activity.startTime;
|
||||||
delete activity.endTime
|
delete activity.endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not sure
|
// not sure
|
||||||
|
@ -297,8 +292,8 @@ export default class DiscordRPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!activity.largeImageText || activity.largeImageText.length < 2) {
|
if (!activity.largeImageText || activity.largeImageText.length < 2) {
|
||||||
delete activity.largeImageText
|
delete activity.largeImageText;
|
||||||
}
|
}
|
||||||
return activity
|
return activity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
export default class lastfm {
|
export default class lastfm {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Information
|
* Base Plugin Information
|
||||||
*/
|
*/
|
||||||
public name: string = 'LastFM Plugin';
|
public name: string = "LastFM Plugin";
|
||||||
public version: string = '2.0.0';
|
public version: string = "2.0.0";
|
||||||
public author: string = 'Core (Cider Collective)';
|
public author: string = "Core (Cider Collective)";
|
||||||
|
|
||||||
|
|
||||||
private _apiCredentials = {
|
private _apiCredentials = {
|
||||||
key: "f9986d12aab5a0fe66193c559435ede3",
|
key: "f9986d12aab5a0fe66193c559435ede3",
|
||||||
secret: "acba3c29bd5973efa38cc2f0b63cc625"
|
secret: "acba3c29bd5973efa38cc2f0b63cc625",
|
||||||
}
|
};
|
||||||
/**
|
/**
|
||||||
* Plugin Initialization
|
* Plugin Initialization
|
||||||
*/
|
*/
|
||||||
|
@ -31,42 +29,41 @@ export default class lastfm {
|
||||||
}
|
}
|
||||||
|
|
||||||
onReady(_win: Electron.BrowserWindow): void {
|
onReady(_win: Electron.BrowserWindow): void {
|
||||||
this.initializeLastFM("", this._apiCredentials)
|
this.initializeLastFM("", this._apiCredentials);
|
||||||
|
|
||||||
// Register the ipcMain handlers
|
// Register the ipcMain handlers
|
||||||
this._utils.getIPCMain().handle('lastfm:url', (event: any) => {
|
this._utils.getIPCMain().handle("lastfm:url", (event: any) => {
|
||||||
console.debug(`[${lastfm.name}:url] Called.`)
|
console.debug(`[${lastfm.name}:url] Called.`);
|
||||||
return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"})
|
return this._lfm.getAuthenticationUrl({ cb: "cider://auth/lastfm" });
|
||||||
})
|
});
|
||||||
|
|
||||||
this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => {
|
this._utils.getIPCMain().on("lastfm:auth", (event: any, token: string) => {
|
||||||
console.debug(`[${lastfm.name}:auth] Token: `, token)
|
console.debug(`[${lastfm.name}:auth] Token: `, token);
|
||||||
this.authenticateLastFM(token)
|
this.authenticateLastFM(token);
|
||||||
})
|
});
|
||||||
|
|
||||||
this._utils.getIPCMain().on('lastfm:disconnect', (_event: any) => {
|
this._utils.getIPCMain().on("lastfm:disconnect", (_event: any) => {
|
||||||
this._lfm.setSessionCredentials(null, null);
|
this._lfm.setSessionCredentials(null, null);
|
||||||
this._authenticated = false;
|
this._authenticated = false;
|
||||||
console.debug(`[${lastfm.name}:disconnect] Disconnected`)
|
console.debug(`[${lastfm.name}:disconnect] Disconnected`);
|
||||||
})
|
});
|
||||||
|
|
||||||
this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => {
|
this._utils.getIPCMain().on("lastfm:nowPlayingChange", (event: any, attributes: any) => {
|
||||||
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop") || this._utils.getStoreValue("general.privateEnabled")) return;
|
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop") || this._utils.getStoreValue("general.privateEnabled")) return;
|
||||||
this.updateNowPlayingTrack(attributes)
|
this.updateNowPlayingTrack(attributes);
|
||||||
})
|
});
|
||||||
|
|
||||||
this._utils.getIPCMain().on('lastfm:scrobbleTrack', (event: any, attributes: any) => {
|
this._utils.getIPCMain().on("lastfm:scrobbleTrack", (event: any, attributes: any) => {
|
||||||
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
||||||
this.scrobbleTrack(attributes)
|
this.scrobbleTrack(attributes);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on playback State Change
|
* Runs on playback State Change
|
||||||
* @param attributes Music Attributes (attributes.status = current state)
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on song change
|
* Runs on song change
|
||||||
|
@ -75,7 +72,7 @@ export default class lastfm {
|
||||||
*/
|
*/
|
||||||
onNowPlayingItemDidChange(attributes: any, scrobble = false): void {
|
onNowPlayingItemDidChange(attributes: any, scrobble = false): void {
|
||||||
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
||||||
this.updateNowPlayingTrack(attributes)
|
this.updateNowPlayingTrack(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,19 +81,19 @@ export default class lastfm {
|
||||||
* @param api
|
* @param api
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private initializeLastFM(token: string, api: { key: string, secret: string }): void {
|
private initializeLastFM(token: string, api: { key: string; secret: string }): void {
|
||||||
console.debug(`[${lastfm.name}:initialize] Initializing LastFM`)
|
console.debug(`[${lastfm.name}:initialize] Initializing LastFM`);
|
||||||
const LastfmAPI = require("lastfmapi")
|
const LastfmAPI = require("lastfmapi");
|
||||||
this._lfm = new LastfmAPI({
|
this._lfm = new LastfmAPI({
|
||||||
'api_key': api.key,
|
api_key: api.key,
|
||||||
'secret': api.secret,
|
secret: api.secret,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this._utils.getStoreValue("connectivity.lastfm.secrets.username") && this._utils.getStoreValue("connectivity.lastfm.secrets.key")) {
|
if (this._utils.getStoreValue("connectivity.lastfm.secrets.username") && this._utils.getStoreValue("connectivity.lastfm.secrets.key")) {
|
||||||
this._lfm.setSessionCredentials(this._utils.getStoreValue("connectivity.lastfm.secrets.username"), this._utils.getStoreValue("connectivity.lastfm.secrets.key"));
|
this._lfm.setSessionCredentials(this._utils.getStoreValue("connectivity.lastfm.secrets.username"), this._utils.getStoreValue("connectivity.lastfm.secrets.key"));
|
||||||
this._authenticated = true;
|
this._authenticated = true;
|
||||||
} else {
|
} else {
|
||||||
this.authenticateLastFM(token)
|
this.authenticateLastFM(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,12 +108,12 @@ export default class lastfm {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`[${lastfm.name}:authenticate] Error: ${typeof err === "string" ? err : err.message}`);
|
console.error(`[${lastfm.name}:authenticate] Error: ${typeof err === "string" ? err : err.message}`);
|
||||||
|
|
||||||
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`)
|
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._utils.getWindow().webContents.send('lastfm:authenticated', session)
|
this._utils.getWindow().webContents.send("lastfm:authenticated", session);
|
||||||
this._authenticated = true;
|
this._authenticated = true;
|
||||||
console.debug(`[${lastfm.name}:authenticate] Authenticated as ${session.username}`)
|
console.debug(`[${lastfm.name}:authenticate] Authenticated as ${session.username}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,33 +127,34 @@ export default class lastfm {
|
||||||
if (!attributes) return attributes;
|
if (!attributes) return attributes;
|
||||||
|
|
||||||
if (!attributes.lfmAlbum) {
|
if (!attributes.lfmAlbum) {
|
||||||
this._lfm.album.getInfo({
|
this._lfm.album.getInfo(
|
||||||
"artist": attributes.primaryArtist,
|
{
|
||||||
"album": attributes.albumName
|
artist: attributes.primaryArtist,
|
||||||
}, (err: any, data: any) => {
|
album: attributes.albumName,
|
||||||
|
},
|
||||||
|
(err: any, data: any) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`)
|
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
attributes.lfmAlbum = data
|
attributes.lfmAlbum = data;
|
||||||
callback(attributes)
|
callback(attributes);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this._lfm.track.getCorrection(attributes.primaryArtist, attributes.name, (err: any, data: any) => {
|
this._lfm.track.getCorrection(attributes.primaryArtist, attributes.name, (err: any, data: any) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`)
|
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
attributes.lfmTrack = data.correction.track
|
attributes.lfmTrack = data.correction.track;
|
||||||
callback(attributes)
|
callback(attributes);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,26 +165,32 @@ export default class lastfm {
|
||||||
private scrobbleTrack(attributes: any): void {
|
private scrobbleTrack(attributes: any): void {
|
||||||
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
||||||
this.verifyTrack(attributes, (a: any) => {
|
this.verifyTrack(attributes, (a: any) => {
|
||||||
this.scrobbleTrack(a)
|
this.scrobbleTrack(a);
|
||||||
})
|
});
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)) return;
|
if (
|
||||||
|
!this._authenticated ||
|
||||||
|
!attributes ||
|
||||||
|
this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] ||
|
||||||
|
(this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._scrobbleCache.track === attributes.lfmTrack.name)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
// Scrobble
|
// Scrobble
|
||||||
const scrobble = {
|
const scrobble = {
|
||||||
'artist': attributes.lfmTrack.artist.name,
|
artist: attributes.lfmTrack.artist.name,
|
||||||
'track': attributes.lfmTrack.name,
|
track: attributes.lfmTrack.name,
|
||||||
'album': attributes.lfmAlbum.name,
|
album: attributes.lfmAlbum.name,
|
||||||
'albumArtist': attributes.lfmAlbum.artist,
|
albumArtist: attributes.lfmAlbum.artist,
|
||||||
'timestamp': new Date().getTime() / 1000,
|
timestamp: new Date().getTime() / 1000,
|
||||||
'trackNumber': attributes.trackNumber,
|
trackNumber: attributes.trackNumber,
|
||||||
'duration': attributes.durationInMillis / 1000,
|
duration: attributes.durationInMillis / 1000,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Easy Debugging
|
// Easy Debugging
|
||||||
console.debug(`[${lastfm.name}:scrobble] Scrobbling ${scrobble.artist} - ${scrobble.track}`)
|
console.debug(`[${lastfm.name}:scrobble] Scrobbling ${scrobble.artist} - ${scrobble.track}`);
|
||||||
|
|
||||||
// Scrobble the track
|
// Scrobble the track
|
||||||
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
|
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
|
||||||
|
@ -194,7 +198,7 @@ export default class lastfm {
|
||||||
console.error(`[${lastfm.name}:scrobble] Scrobble failed: ${err.message}`);
|
console.error(`[${lastfm.name}:scrobble] Scrobble failed: ${err.message}`);
|
||||||
} else {
|
} else {
|
||||||
console.debug(`[${lastfm.name}:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`);
|
console.debug(`[${lastfm.name}:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`);
|
||||||
this._scrobbleCache = scrobble
|
this._scrobbleCache = scrobble;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -207,30 +211,35 @@ export default class lastfm {
|
||||||
private updateNowPlayingTrack(attributes: any): void {
|
private updateNowPlayingTrack(attributes: any): void {
|
||||||
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
||||||
this.verifyTrack(attributes, (a: any) => {
|
this.verifyTrack(attributes, (a: any) => {
|
||||||
this.updateNowPlayingTrack(a)
|
this.updateNowPlayingTrack(a);
|
||||||
})
|
});
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._authenticated || !attributes || this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] || (this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)) return;
|
if (
|
||||||
|
!this._authenticated ||
|
||||||
|
!attributes ||
|
||||||
|
this._utils.getStoreValue("connectivity.lastfm.filter_types")[attributes.playParams.kind] ||
|
||||||
|
(this._utils.getStoreValue("connectivity.lastfm.filter_loop") && this._nowPlayingCache.track === attributes.lfmTrack.name)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
const nowPlaying = {
|
const nowPlaying = {
|
||||||
'artist': attributes.lfmTrack.artist.name,
|
artist: attributes.lfmTrack.artist.name,
|
||||||
'track': attributes.lfmTrack.name,
|
track: attributes.lfmTrack.name,
|
||||||
'album': attributes.lfmAlbum.name,
|
album: attributes.lfmAlbum.name,
|
||||||
'trackNumber': attributes.trackNumber,
|
trackNumber: attributes.trackNumber,
|
||||||
'duration': attributes.durationInMillis / 1000,
|
duration: attributes.durationInMillis / 1000,
|
||||||
'albumArtist': attributes.lfmAlbum.artist,
|
albumArtist: attributes.lfmAlbum.artist,
|
||||||
}
|
};
|
||||||
|
|
||||||
this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => {
|
this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
|
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
|
||||||
} else {
|
} else {
|
||||||
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
|
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
|
||||||
this._nowPlayingCache = nowPlaying
|
this._nowPlayingCache = nowPlaying;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,313 +1,301 @@
|
||||||
import {app, Menu, shell} from "electron";
|
import { app, Menu, shell } from "electron";
|
||||||
import {utils} from "../base/utils";
|
import { utils } from "../base/utils";
|
||||||
|
|
||||||
export default class Thumbar {
|
export default class Thumbar {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'Menubar Plugin';
|
public name: string = "Menubar Plugin";
|
||||||
public description: string = 'Creates the menubar';
|
public description: string = "Creates the menubar";
|
||||||
public version: string = '1.0.0';
|
public version: string = "1.0.0";
|
||||||
public author: string = 'Core';
|
public author: string = "Core";
|
||||||
public contributors: string[] = ['Core', 'Qwack', 'Monochromish'];
|
public contributors: string[] = ["Core", "Qwack", "Monochromish"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menubar Assets
|
* Menubar Assets
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private isNotMac: boolean = process.platform !== 'darwin';
|
private isNotMac: boolean = process.platform !== "darwin";
|
||||||
private isMac: boolean = process.platform === 'darwin';
|
private isMac: boolean = process.platform === "darwin";
|
||||||
private _menuTemplate: any = [
|
private _menuTemplate: any = [
|
||||||
{
|
{
|
||||||
label: app.getName(),
|
label: app.getName(),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: `${utils.getLocale(utils.getStoreValue('general.language'), 'term.about')} ${app.getName()}`,
|
label: `${utils.getLocale(utils.getStoreValue("general.language"), "term.about")} ${app.getName()}`,
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('about')`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('about')`),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.toggleprivate'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.toggleprivate"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.togglePrivateSession").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.togglePrivateSession").join("+"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.cfg.general.privateEnabled = !app.cfg.general.privateEnabled`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.cfg.general.privateEnabled = !app.cfg.general.privateEnabled`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.settings'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.settings"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.settings").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.settings").join("+"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.openSettingsPage()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.openSettingsPage()`),
|
||||||
},
|
},
|
||||||
...(this.isMac ? [
|
...(this.isMac ? [{ type: "separator" }, { role: "services" }, { type: "separator" }, { role: "hide" }, { role: "hideOthers" }, { role: "unhide" }, { type: "separator" }, { role: "quit" }] : []),
|
||||||
{type: 'separator'},
|
...(this.isNotMac
|
||||||
{role: 'services'},
|
? [
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{role: 'hide'},
|
|
||||||
{role: 'hideOthers'},
|
|
||||||
{role: 'unhide'},
|
|
||||||
{type: 'separator'},
|
|
||||||
{role: 'quit'}
|
|
||||||
] : []),
|
|
||||||
...(this.isNotMac ? [
|
|
||||||
{type: 'separator'},
|
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.quit'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.quit"),
|
||||||
accelerator: 'Control+Q',
|
accelerator: "Control+Q",
|
||||||
click: () => app.quit()
|
click: () => app.quit(),
|
||||||
|
|
||||||
}
|
|
||||||
] : [])
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.view'),
|
|
||||||
submenu: [
|
|
||||||
...(this.isMac ? [
|
|
||||||
{role: 'reload'},
|
|
||||||
{role: 'forceReload'},
|
|
||||||
{role: 'toggleDevTools'},
|
|
||||||
{type: 'separator'},
|
|
||||||
{role: 'resetZoom'},
|
|
||||||
{role: 'zoomIn'},
|
|
||||||
{role: 'zoomOut'},
|
|
||||||
{type: 'separator'},
|
|
||||||
{role: 'togglefullscreen'},
|
|
||||||
{type: 'separator'},
|
|
||||||
] : []),
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.search'),
|
|
||||||
accelerator: utils.getStoreValue("general.keybindings.search").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript('app.focusSearch()')
|
|
||||||
},
|
|
||||||
{type:'separator'},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.listenNow'),
|
|
||||||
accelerator: utils.getStoreValue('general.keybindings.listnow').join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('listen_now')`)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.browse'),
|
|
||||||
accelerator: utils.getStoreValue("general.keybindings.browse").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('browse')`)
|
|
||||||
},
|
|
||||||
{type: 'separator'},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.recentlyAdded')
|
|
||||||
,accelerator: utils.getStoreValue("general.keybindings.recentAdd").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-recentlyadded')`)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.songs'),
|
|
||||||
accelerator: utils.getStoreValue("general.keybindings.songs").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-songs')`)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.albums'),
|
|
||||||
accelerator: utils.getStoreValue("general.keybindings.albums").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-albums')`)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.artists'),
|
|
||||||
accelerator: utils.getStoreValue("general.keybindings.artists").join('+'),
|
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-artists')`)
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.window'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.view"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{role: 'minimize', label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.minimize')},
|
...(this.isMac
|
||||||
{type: 'separator'},
|
? [
|
||||||
...(this.isMac ? [
|
{ role: "reload" },
|
||||||
{
|
{ role: "forceReload" },
|
||||||
label: 'Show',
|
{ role: "toggleDevTools" },
|
||||||
click: () => utils.getWindow().show()
|
{ type: "separator" },
|
||||||
},
|
{ role: "resetZoom" },
|
||||||
{role: 'zoom'},
|
{ role: "zoomIn" },
|
||||||
{type: 'separator'},
|
{ role: "zoomOut" },
|
||||||
{role: 'front'},
|
{ type: "separator" },
|
||||||
{role: 'close'},
|
{ role: "togglefullscreen" },
|
||||||
{
|
{ type: "separator" },
|
||||||
label: 'Edit',
|
|
||||||
submenu: [
|
|
||||||
{role: 'undo'},
|
|
||||||
{role: 'redo'},
|
|
||||||
{type: 'separator'},
|
|
||||||
{role: 'cut'},
|
|
||||||
{role: 'copy'},
|
|
||||||
{role: 'paste'},
|
|
||||||
]
|
]
|
||||||
},
|
: []),
|
||||||
{type: 'separator'},
|
|
||||||
] : [ ]),
|
|
||||||
...(this.isNotMac ? [
|
|
||||||
|
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.zoom'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.search"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.search").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript("app.focusSearch()"),
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.listenNow"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.listnow").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('listen_now')`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.browse"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.browse").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('browse')`),
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.recentlyAdded"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.recentAdd").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-recentlyadded')`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.songs"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.songs").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-songs')`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.albums"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.albums").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-albums')`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.artists"),
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.artists").join("+"),
|
||||||
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('library-artists')`),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.window"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.zoomin'),
|
role: "minimize",
|
||||||
role: 'zoomIn',
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.minimize"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.zoomn").join('+')
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
...(this.isMac
|
||||||
|
? [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.zoomout'),
|
label: "Show",
|
||||||
role: 'zoomOut',
|
click: () => utils.getWindow().show(),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.zoomt").join('+')
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
{ role: "zoom" },
|
||||||
|
{ type: "separator" },
|
||||||
|
{ role: "front" },
|
||||||
|
{ role: "close" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.zoomreset'),
|
label: "Edit",
|
||||||
role: 'resetZoom',
|
submenu: [{ role: "undo" }, { role: "redo" }, { type: "separator" }, { role: "cut" }, { role: "copy" }, { role: "paste" }],
|
||||||
accelerator: utils.getStoreValue("general.keybindings.zoomrst").join('+')
|
},
|
||||||
}
|
{ type: "separator" },
|
||||||
]
|
]
|
||||||
},
|
: []),
|
||||||
{type: 'separator'},
|
...(this.isNotMac
|
||||||
|
? [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.fullscreen'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.zoom"),
|
||||||
accelerator: 'Control+Enter',
|
submenu: [
|
||||||
role: 'togglefullscreen'
|
|
||||||
},
|
|
||||||
{type: 'separator'},
|
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'action.close'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomin"),
|
||||||
accelerator: 'Control+W',
|
role: "zoomIn",
|
||||||
role: 'close'
|
accelerator: utils.getStoreValue("general.keybindings.zoomn").join("+"),
|
||||||
},
|
|
||||||
{type:'separator'},
|
|
||||||
{
|
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.reload'),
|
|
||||||
accelerator: 'Control+R',
|
|
||||||
role: 'reload'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.forcereload'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomout"),
|
||||||
accelerator: 'Control+Shift+R',
|
role: "zoomOut",
|
||||||
role: 'forceReload'
|
accelerator: utils.getStoreValue("general.keybindings.zoomt").join("+"),
|
||||||
},
|
},
|
||||||
] : []),
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.zoomreset"),
|
||||||
|
role: "resetZoom",
|
||||||
|
accelerator: utils.getStoreValue("general.keybindings.zoomrst").join("+"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.fullscreen"),
|
||||||
|
accelerator: "Control+Enter",
|
||||||
|
role: "togglefullscreen",
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "action.close"),
|
||||||
|
accelerator: "Control+W",
|
||||||
|
role: "close",
|
||||||
|
},
|
||||||
|
{ type: "separator" },
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.reload"),
|
||||||
|
accelerator: "Control+R",
|
||||||
|
role: "reload",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.forcereload"),
|
||||||
|
accelerator: "Control+Shift+R",
|
||||||
|
role: "forceReload",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.controls'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.controls"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.playpause'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.playpause"),
|
||||||
accelerator: 'Space',
|
accelerator: "Space",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.SpacePause()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.SpacePause()`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.next'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.next"),
|
||||||
accelerator: 'CommandOrControl+Right',
|
accelerator: "CommandOrControl+Right",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.next()`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.previous'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.previous"),
|
||||||
accelerator: 'CommandOrControl+Left',
|
accelerator: "CommandOrControl+Left",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.previous()`),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.volumeup'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.volumeup"),
|
||||||
accelerator: 'CommandOrControl+Up',
|
accelerator: "CommandOrControl+Up",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeUp()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeUp()`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.volumedown'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.volumedown"),
|
||||||
accelerator: 'CommandOrControl+Down',
|
accelerator: "CommandOrControl+Down",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeDown()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.volumeDown()`),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.cast2'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.cast2"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.castToDevices").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.castToDevices").join("+"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.castMenu = true`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.castMenu = true`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.webremote'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.webremote"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.webRemote").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.webRemote").join("+"),
|
||||||
sublabel: 'Opens in external window',
|
sublabel: "Opens in external window",
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('remote-pair')`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('remote-pair')`),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.audioSettings'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.audioSettings"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.audioSettings").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.audioSettings").join("+"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.audioSettings = true`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.audioSettings = true`),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.plugins'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.plugins"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.pluginMenu").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.pluginMenu").join("+"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.pluginMenu = true`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.modals.pluginMenu = true`),
|
||||||
}
|
},
|
||||||
|
],
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.account'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.account"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.accountSettings'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.accountSettings"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('apple-account-settings')`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.appRoute('apple-account-settings')`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.signout'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.signout"),
|
||||||
click: () => utils.getWindow().webContents.executeJavaScript(`app.unauthorize()`)
|
click: () => utils.getWindow().webContents.executeJavaScript(`app.unauthorize()`),
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.support'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.support"),
|
||||||
role: 'help',
|
role: "help",
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.discord'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.discord"),
|
||||||
click: () => shell.openExternal("https://discord.gg/AppleMusic").catch(console.error)
|
click: () => shell.openExternal("https://discord.gg/AppleMusic").catch(console.error),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'term.github'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "term.github"),
|
||||||
click: () => shell.openExternal("https://github.com/ciderapp/Cider/wiki/Troubleshooting").catch(console.error)
|
click: () => shell.openExternal("https://github.com/ciderapp/Cider/wiki/Troubleshooting").catch(console.error),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.report'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.report"),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.bug'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.bug"),
|
||||||
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=bug%2Ctriage&template=bug_report.yaml&title=%5BBug%5D%3A+").catch(console.error)
|
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=bug%2Ctriage&template=bug_report.yaml&title=%5BBug%5D%3A+").catch(console.error),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.feature'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.feature"),
|
||||||
click: () => shell.openExternal("https://github.com/ciderapp/Cider/discussions/new?category=feature-request").catch(console.error)
|
click: () => shell.openExternal("https://github.com/ciderapp/Cider/discussions/new?category=feature-request").catch(console.error),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.trans'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.trans"),
|
||||||
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=%F0%9F%8C%90+Translations&template=translation.yaml&title=%5BTranslation%5D%3A+").catch(console.error)
|
click: () => shell.openExternal("https://github.com/ciderapp/Cider/issues/new?assignees=&labels=%F0%9F%8C%90+Translations&template=translation.yaml&title=%5BTranslation%5D%3A+").catch(console.error),
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.license'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.license"),
|
||||||
click: () => shell.openExternal("https://github.com/ciderapp/Cider/blob/main/LICENSE").catch(console.error)
|
click: () => shell.openExternal("https://github.com/ciderapp/Cider/blob/main/LICENSE").catch(console.error),
|
||||||
},
|
},
|
||||||
{type: 'separator'},
|
{ type: "separator" },
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.toggledevtools'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.toggledevtools"),
|
||||||
accelerator: utils.getStoreValue("general.keybindings.openDeveloperTools").join('+'),
|
accelerator: utils.getStoreValue("general.keybindings.openDeveloperTools").join("+"),
|
||||||
click: () => utils.getWindow().webContents.openDevTools()
|
click: () => utils.getWindow().webContents.openDevTools(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: utils.getLocale(utils.getStoreValue('general.language'), 'menubar.options.conf'),
|
label: utils.getLocale(utils.getStoreValue("general.language"), "menubar.options.conf"),
|
||||||
click: () => utils.getStoreInstance().openInEditor()
|
click: () => utils.getStoreInstance().openInEditor(),
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
|
@ -326,7 +314,7 @@ export default class Thumbar {
|
||||||
*/
|
*/
|
||||||
onReady(_win: Electron.BrowserWindow): void {
|
onReady(_win: Electron.BrowserWindow): void {
|
||||||
const menu = Menu.buildFromTemplate(this._menuTemplate);
|
const menu = Menu.buildFromTemplate(this._menuTemplate);
|
||||||
Menu.setApplicationMenu(menu)
|
Menu.setApplicationMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -340,16 +328,11 @@ export default class Thumbar {
|
||||||
* Runs on playback State Change
|
* Runs on playback State Change
|
||||||
* @param attributes Music Attributes (attributes.status = current state)
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on song change
|
* Runs on song change
|
||||||
* @param attributes Music Attributes
|
* @param attributes Music Attributes
|
||||||
*/
|
*/
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import * as Player from 'mpris-service';
|
import * as Player from "mpris-service";
|
||||||
|
|
||||||
export default class mpris {
|
export default class mpris {
|
||||||
/**
|
/**
|
||||||
|
@ -13,10 +13,10 @@ export default class mpris {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'MPRIS Service';
|
public name: string = "MPRIS Service";
|
||||||
public description: string = 'Handles MPRIS service calls for Linux systems.';
|
public description: string = "Handles MPRIS service calls for Linux systems.";
|
||||||
public version: string = '1.0.0';
|
public version: string = "1.0.0";
|
||||||
public author: string = 'Core';
|
public author: string = "Core";
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
* Private Methods
|
* Private Methods
|
||||||
|
@ -26,7 +26,7 @@ export default class mpris {
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
*/
|
*/
|
||||||
constructor(utils: any) {
|
constructor(utils: any) {
|
||||||
mpris.utils = utils
|
mpris.utils = utils;
|
||||||
|
|
||||||
console.debug(`[Plugin][${mpris.name}] Loading Complete.`);
|
console.debug(`[Plugin][${mpris.name}] Loading Complete.`);
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,10 @@ export default class mpris {
|
||||||
* @decorator
|
* @decorator
|
||||||
*/
|
*/
|
||||||
private static linuxOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
private static linuxOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
if (process.platform !== 'linux') {
|
if (process.platform !== "linux") {
|
||||||
descriptor.value = function () {
|
descriptor.value = function () {
|
||||||
return
|
return;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,37 +48,36 @@ export default class mpris {
|
||||||
* Connects to MPRIS Service
|
* Connects to MPRIS Service
|
||||||
*/
|
*/
|
||||||
private static connect() {
|
private static connect() {
|
||||||
|
|
||||||
const player = Player({
|
const player = Player({
|
||||||
name: 'cider',
|
name: "cider",
|
||||||
identity: 'Cider',
|
identity: "Cider",
|
||||||
supportedInterfaces: ['player']
|
supportedInterfaces: ["player"],
|
||||||
});
|
});
|
||||||
|
|
||||||
console.debug(`[${mpris.name}:connect] Successfully connected.`);
|
console.debug(`[${mpris.name}:connect] Successfully connected.`);
|
||||||
|
|
||||||
const renderer = mpris.utils.getWindow().webContents
|
const renderer = mpris.utils.getWindow().webContents;
|
||||||
const loopType: { [key: string]: number; } = {
|
const loopType: { [key: string]: number } = {
|
||||||
'none': 0,
|
none: 0,
|
||||||
'track': 1,
|
track: 1,
|
||||||
'playlist': 2,
|
playlist: 2,
|
||||||
}
|
};
|
||||||
|
|
||||||
player.on('next', () => mpris.utils.playback.next())
|
player.on("next", () => mpris.utils.playback.next());
|
||||||
player.on('previous', () => mpris.utils.playback.previous())
|
player.on("previous", () => mpris.utils.playback.previous());
|
||||||
player.on('playpause', () => mpris.utils.playback.playPause())
|
player.on("playpause", () => mpris.utils.playback.playPause());
|
||||||
player.on('play', () => mpris.utils.playback.play())
|
player.on("play", () => mpris.utils.playback.play());
|
||||||
player.on('pause', () => mpris.utils.playback.pause())
|
player.on("pause", () => mpris.utils.playback.pause());
|
||||||
player.on('quit', () => mpris.utils.getApp().exit())
|
player.on("quit", () => mpris.utils.getApp().exit());
|
||||||
player.on('position', (args: { position: any; }) => mpris.utils.playback.seek(args.position / 1000 / 1000))
|
player.on("position", (args: { position: any }) => mpris.utils.playback.seek(args.position / 1000 / 1000));
|
||||||
player.on('loopStatus', (status: string) => renderer.executeJavaScript(`app.mk.repeatMode = ${loopType[status.toLowerCase()]}`))
|
player.on("loopStatus", (status: string) => renderer.executeJavaScript(`app.mk.repeatMode = ${loopType[status.toLowerCase()]}`));
|
||||||
player.on('shuffle', () => renderer.executeJavaScript('app.mk.shuffleMode = (app.mk.shuffleMode === 0) ? 1 : 0'))
|
player.on("shuffle", () => renderer.executeJavaScript("app.mk.shuffleMode = (app.mk.shuffleMode === 0) ? 1 : 0"));
|
||||||
|
|
||||||
mpris.utils.getIPCMain().on('mpris:playbackTimeDidChange', (event: any, time: number) => {
|
mpris.utils.getIPCMain().on("mpris:playbackTimeDidChange", (event: any, time: number) => {
|
||||||
player.getPosition = () => time;
|
player.getPosition = () => time;
|
||||||
})
|
});
|
||||||
|
|
||||||
mpris.utils.getIPCMain().on('repeatModeDidChange', (_e: any, mode: number) => {
|
mpris.utils.getIPCMain().on("repeatModeDidChange", (_e: any, mode: number) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
case 0:
|
||||||
player.loopStatus = Player.LOOP_STATUS_NONE;
|
player.loopStatus = Player.LOOP_STATUS_NONE;
|
||||||
|
@ -90,11 +89,11 @@ export default class mpris {
|
||||||
player.loopStatus = Player.LOOP_STATUS_PLAYLIST;
|
player.loopStatus = Player.LOOP_STATUS_PLAYLIST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
mpris.utils.getIPCMain().on('shuffleModeDidChange', (_e: any, mode: number) => {
|
mpris.utils.getIPCMain().on("shuffleModeDidChange", (_e: any, mode: number) => {
|
||||||
player.shuffle = mode === 1
|
player.shuffle = mode === 1;
|
||||||
})
|
});
|
||||||
|
|
||||||
mpris.player = player;
|
mpris.player = player;
|
||||||
}
|
}
|
||||||
|
@ -103,15 +102,14 @@ export default class mpris {
|
||||||
* Update M.P.R.I.S Player Attributes
|
* Update M.P.R.I.S Player Attributes
|
||||||
*/
|
*/
|
||||||
private static updateMetaData(attributes: any) {
|
private static updateMetaData(attributes: any) {
|
||||||
|
|
||||||
mpris.player.metadata = {
|
mpris.player.metadata = {
|
||||||
'mpris:trackid': mpris.player.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`),
|
"mpris:trackid": mpris.player.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`),
|
||||||
'mpris:length': attributes.durationInMillis * 1000, // In microseconds
|
"mpris:length": attributes.durationInMillis * 1000, // In microseconds
|
||||||
'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'),
|
"mpris:artUrl": attributes.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb"),
|
||||||
'xesam:title': `${attributes.name}`,
|
"xesam:title": `${attributes.name}`,
|
||||||
'xesam:album': `${attributes.albumName}`,
|
"xesam:album": `${attributes.albumName}`,
|
||||||
'xesam:artist': [`${attributes.artistName}`],
|
"xesam:artist": [`${attributes.artistName}`],
|
||||||
'xesam:genre': attributes.genreNames
|
"xesam:genre": attributes.genreNames,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +123,11 @@ export default class mpris {
|
||||||
*/
|
*/
|
||||||
private static clearState() {
|
private static clearState() {
|
||||||
if (!mpris.player) {
|
if (!mpris.player) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
mpris.player.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'}
|
mpris.player.metadata = {
|
||||||
|
"mpris:trackid": "/org/mpris/MediaPlayer2/TrackList/NoTrack",
|
||||||
|
};
|
||||||
mpris.player.playbackStatus = Player.PLAYBACK_STATUS_STOPPED;
|
mpris.player.playbackStatus = Player.PLAYBACK_STATUS_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ export default class mpris {
|
||||||
*/
|
*/
|
||||||
@mpris.linuxOnly
|
@mpris.linuxOnly
|
||||||
onRendererReady(): void {
|
onRendererReady(): void {
|
||||||
mpris.connect()
|
mpris.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,7 +153,7 @@ export default class mpris {
|
||||||
@mpris.linuxOnly
|
@mpris.linuxOnly
|
||||||
onBeforeQuit(): void {
|
onBeforeQuit(): void {
|
||||||
console.debug(`[Plugin][${mpris.name}] Stopped.`);
|
console.debug(`[Plugin][${mpris.name}] Stopped.`);
|
||||||
mpris.clearState()
|
mpris.clearState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,7 +162,7 @@ export default class mpris {
|
||||||
*/
|
*/
|
||||||
@mpris.linuxOnly
|
@mpris.linuxOnly
|
||||||
onPlaybackStateDidChange(attributes: any): void {
|
onPlaybackStateDidChange(attributes: any): void {
|
||||||
mpris.player.playbackStatus = attributes?.status ? Player.PLAYBACK_STATUS_PLAYING : Player.PLAYBACK_STATUS_PAUSED
|
mpris.player.playbackStatus = attributes?.status ? Player.PLAYBACK_STATUS_PLAYING : Player.PLAYBACK_STATUS_PAUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,5 +173,4 @@ export default class mpris {
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {
|
||||||
mpris.updateMetaData(attributes);
|
mpris.updateMetaData(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import fetch from "electron-fetch";
|
import fetch from "electron-fetch";
|
||||||
import {app, nativeImage, Notification} from "electron";
|
import { app, nativeImage, Notification } from "electron";
|
||||||
import NativeImage = Electron.NativeImage;
|
import NativeImage = Electron.NativeImage;
|
||||||
import {createWriteStream} from "fs";
|
import { createWriteStream } from "fs";
|
||||||
import {join} from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
export default class playbackNotifications {
|
export default class playbackNotifications {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'Playback Notifications';
|
public name: string = "Playback Notifications";
|
||||||
public description: string = 'Creates notifications on playback.';
|
public description: string = "Creates notifications on playback.";
|
||||||
public version: string = '1.0.0';
|
public version: string = "1.0.0";
|
||||||
public author: string = 'Core';
|
public author: string = "Core";
|
||||||
public contributors: string[] = ['Core', 'Monochromish'];
|
public contributors: string[] = ["Core", "Monochromish"];
|
||||||
|
|
||||||
private _utils: any;
|
private _utils: any;
|
||||||
private _notification: Notification | undefined;
|
private _notification: Notification | undefined;
|
||||||
|
@ -35,50 +33,48 @@ export default class playbackNotifications {
|
||||||
body: `${a.artistName} — ${a.albumName}`,
|
body: `${a.artistName} — ${a.albumName}`,
|
||||||
silent: true,
|
silent: true,
|
||||||
icon: this._artworkImage[a.artwork.url],
|
icon: this._artworkImage[a.artwork.url],
|
||||||
urgency: 'low',
|
urgency: "low",
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
'type': 'button',
|
type: "button",
|
||||||
'text': `${this._utils.getLocale(this._utils.getStoreValue('general.language'), 'term.skip')}`
|
text: `${this._utils.getLocale(this._utils.getStoreValue("general.language"), "term.skip")}`,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
toastXml: `
|
toastXml: `
|
||||||
<toast>
|
<toast>
|
||||||
<audio silent="true" />
|
<audio silent="true" />
|
||||||
<visual>
|
<visual>
|
||||||
<binding template="ToastImageAndText02">
|
<binding template="ToastImageAndText02">
|
||||||
<image id="1" src="${join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split('/').pop()}`)}" name="Image" />
|
<image id="1" src="${join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split("/").pop()}`)}" name="Image" />
|
||||||
<text id="1">${a?.name.replace(/&/g, '&')}</text>
|
<text id="1">${a?.name.replace(/&/g, "&")}</text>
|
||||||
<text id="2">${a?.artistName.replace(/&/g, '&')} — ${a?.albumName.replace(/&/g, '&')}</text>
|
<text id="2">${a?.artistName.replace(/&/g, "&")} — ${a?.albumName.replace(/&/g, "&")}</text>
|
||||||
</binding>
|
</binding>
|
||||||
</visual>
|
</visual>
|
||||||
<actions>
|
<actions>
|
||||||
<action content="${this._utils.getLocale(this._utils.getStoreValue('general.language'), 'term.playpause')}" activationType="protocol" arguments="cider://playpause/"/>
|
<action content="${this._utils.getLocale(this._utils.getStoreValue("general.language"), "term.playpause")}" activationType="protocol" arguments="cider://playpause/"/>
|
||||||
<action content="${this._utils.getLocale(this._utils.getStoreValue('general.language'), 'term.next')}" activationType="protocol" arguments="cider://nextitem/"/>
|
<action content="${this._utils.getLocale(this._utils.getStoreValue("general.language"), "term.next")}" activationType="protocol" arguments="cider://nextitem/"/>
|
||||||
</actions>
|
</actions>
|
||||||
</toast>`
|
</toast>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(this._notification.toastXml);
|
console.log(this._notification.toastXml);
|
||||||
|
|
||||||
this._notification.on('click', (_: any) => {
|
this._notification.on("click", (_: any) => {
|
||||||
this._utils.getWindow().show()
|
this._utils.getWindow().show();
|
||||||
this._utils.getWindow().focus()
|
this._utils.getWindow().focus();
|
||||||
})
|
});
|
||||||
|
|
||||||
this._notification.on('close', (_: any) => {
|
this._notification.on("close", (_: any) => {
|
||||||
this._notification = undefined;
|
this._notification = undefined;
|
||||||
})
|
});
|
||||||
|
|
||||||
this._notification.on('action', (event: any, action: any) => {
|
this._notification.on("action", (event: any, action: any) => {
|
||||||
this._utils.playback.next()
|
this._utils.playback.next();
|
||||||
})
|
});
|
||||||
|
|
||||||
this._notification.show();
|
this._notification.show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
* Public Methods
|
* Public Methods
|
||||||
* ****************************************************************************************/
|
* ****************************************************************************************/
|
||||||
|
@ -90,8 +86,8 @@ export default class playbackNotifications {
|
||||||
this._utils = utils;
|
this._utils = utils;
|
||||||
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
||||||
|
|
||||||
utils.getIPCMain().on('playbackNotifications:create', (event: any, a: any) => {
|
utils.getIPCMain().on("playbackNotifications:create", (event: any, a: any) => {
|
||||||
a.artwork.url = a.artwork.url.replace('/{w}x{h}bb', '/512x512bb').replace('/2000x2000bb', '/35x35bb');
|
a.artwork.url = a.artwork.url.replace("/{w}x{h}bb", "/512x512bb").replace("/2000x2000bb", "/35x35bb");
|
||||||
|
|
||||||
if (this._artworkNums.length > 20) {
|
if (this._artworkNums.length > 20) {
|
||||||
delete this._artworkImage[this._artworkNums[0]];
|
delete this._artworkImage[this._artworkNums[0]];
|
||||||
|
@ -102,23 +98,21 @@ export default class playbackNotifications {
|
||||||
this.createNotification(a);
|
this.createNotification(a);
|
||||||
} else {
|
} else {
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
fetch(a.artwork.url)
|
fetch(a.artwork.url).then((res) => {
|
||||||
.then(res => {
|
console.log(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split("/").pop()}`));
|
||||||
console.log(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split('/').pop()}`));
|
const dest = createWriteStream(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split("/").pop()}`));
|
||||||
const dest = createWriteStream(join(app.getPath("temp"), `${a.songId}-${a.artwork.url.split('/').pop()}`));
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
res.body.pipe(dest)
|
res.body.pipe(dest);
|
||||||
this.createNotification(a);
|
this.createNotification(a);
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
fetch(a.artwork.url).then(async blob => {
|
fetch(a.artwork.url).then(async (blob) => {
|
||||||
this._artworkImage[a.artwork.url] = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer()));
|
this._artworkImage[a.artwork.url] = nativeImage.createFromBuffer(Buffer.from(await blob.arrayBuffer()));
|
||||||
this._artworkNums[this._artworkNums.length] = a.artwork.url;
|
this._artworkNums[this._artworkNums.length] = a.artwork.url;
|
||||||
this.createNotification(a);
|
this.createNotification(a);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
import * as electron from 'electron';
|
import * as electron from "electron";
|
||||||
import * as os from 'os';
|
import * as os from "os";
|
||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
import { join, resolve } from 'path';
|
import { join, resolve } from "path";
|
||||||
import * as CiderReceiver from '../base/castreceiver';
|
import * as CiderReceiver from "../base/castreceiver";
|
||||||
import fetch from 'electron-fetch';
|
import fetch from "electron-fetch";
|
||||||
import {Stream} from "stream";
|
import { Stream } from "stream";
|
||||||
import {spawn} from 'child_process';
|
import { spawn } from "child_process";
|
||||||
import {Worker} from 'worker_threads';
|
import { Worker } from "worker_threads";
|
||||||
import { Blob } from 'buffer';
|
import { Blob } from "buffer";
|
||||||
|
|
||||||
|
|
||||||
export default class RAOP {
|
export default class RAOP {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private variables for interaction in plugins
|
* Private variables for interaction in plugins
|
||||||
*/
|
*/
|
||||||
|
@ -26,7 +24,7 @@ export default class RAOP {
|
||||||
|
|
||||||
private airtunes: any;
|
private airtunes: any;
|
||||||
private device: any;
|
private device: any;
|
||||||
private mdns = require('mdns-js');
|
private mdns = require("mdns-js");
|
||||||
private ok: any = 1;
|
private ok: any = 1;
|
||||||
private devices: any = [];
|
private devices: any = [];
|
||||||
private castDevices: any = [];
|
private castDevices: any = [];
|
||||||
|
@ -35,7 +33,6 @@ export default class RAOP {
|
||||||
private ffmpeg: any = null;
|
private ffmpeg: any = null;
|
||||||
private worker: any = null;
|
private worker: any = null;
|
||||||
|
|
||||||
|
|
||||||
private processNode = `
|
private processNode = `
|
||||||
import {parentPort, workerData} from "worker_threads";
|
import {parentPort, workerData} from "worker_threads";
|
||||||
function getAudioConv (buffers) {
|
function getAudioConv (buffers) {
|
||||||
|
@ -90,14 +87,18 @@ export default class RAOP {
|
||||||
|
|
||||||
private ondeviceup(name: any, host: any, port: any, addresses: any, text: any, airplay2: any = null) {
|
private ondeviceup(name: any, host: any, port: any, addresses: any, text: any, airplay2: any = null) {
|
||||||
// console.log(this.castDevices.findIndex((item: any) => {return (item.name == host.replace(".local","") && item.port == port )}))
|
// console.log(this.castDevices.findIndex((item: any) => {return (item.name == host.replace(".local","") && item.port == port )}))
|
||||||
if (this.castDevices.findIndex((item: any) => {return (item != null && item.name == (host ?? "Unknown").replace(".local","") && item.port == port )}) == -1) {
|
if (
|
||||||
|
this.castDevices.findIndex((item: any) => {
|
||||||
|
return item != null && item.name == (host ?? "Unknown").replace(".local", "") && item.port == port;
|
||||||
|
}) == -1
|
||||||
|
) {
|
||||||
this.castDevices.push({
|
this.castDevices.push({
|
||||||
name: (host ?? "Unknown").replace(".local",""),
|
name: (host ?? "Unknown").replace(".local", ""),
|
||||||
host: addresses ? addresses[0] : '',
|
host: addresses ? addresses[0] : "",
|
||||||
port: port,
|
port: port,
|
||||||
addresses: addresses,
|
addresses: addresses,
|
||||||
txt: text,
|
txt: text,
|
||||||
airplay2: airplay2
|
airplay2: airplay2,
|
||||||
});
|
});
|
||||||
if (this.devices.indexOf(host) === -1) {
|
if (this.devices.indexOf(host) === -1) {
|
||||||
this.devices.push(host);
|
this.devices.push(host);
|
||||||
|
@ -115,41 +116,40 @@ export default class RAOP {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'RAOP';
|
public name: string = "RAOP";
|
||||||
public description: string = 'RAOP Plugin';
|
public description: string = "RAOP Plugin";
|
||||||
public version: string = '0.0.1';
|
public version: string = "0.0.1";
|
||||||
public author: string = 'vapormusic / Cider Collective';
|
public author: string = "vapormusic / Cider Collective";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
*/
|
*/
|
||||||
constructor(utils: { getStore: () => any; getApp: () => any; }) {
|
constructor(utils: { getStore: () => any; getApp: () => any }) {
|
||||||
this._utils = utils;
|
this._utils = utils;
|
||||||
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
||||||
this._app = utils.getApp();
|
this._app = utils.getApp();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on app ready
|
* Runs on app ready
|
||||||
*/
|
*/
|
||||||
onReady(win: any): void {
|
onReady(win: any): void {
|
||||||
this.u = require('airtunes2');
|
this.u = require("airtunes2");
|
||||||
this._win = win;
|
this._win = win;
|
||||||
|
|
||||||
electron.ipcMain.on('getKnownAirplayDevices', (event) => {
|
electron.ipcMain.on("getKnownAirplayDevices", (event) => {
|
||||||
event.returnValue = this.castDevices
|
event.returnValue = this.castDevices;
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on("getAirplayDevice", (event, data) => {
|
electron.ipcMain.on("getAirplayDevice", (event, data) => {
|
||||||
this.castDevices = [];
|
this.castDevices = [];
|
||||||
console.log("scan for airplay devices");
|
console.log("scan for airplay devices");
|
||||||
|
|
||||||
const browser = this.mdns.createBrowser(this.mdns.tcp('raop'));
|
const browser = this.mdns.createBrowser(this.mdns.tcp("raop"));
|
||||||
browser.on('ready', browser.discover);
|
browser.on("ready", browser.discover);
|
||||||
|
|
||||||
browser.on('update', (service: any) => {
|
browser.on("update", (service: any) => {
|
||||||
if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp'))) {
|
if (service.addresses && service.fullname && service.fullname.includes("_raop._tcp")) {
|
||||||
// console.log(service.txt)
|
// console.log(service.txt)
|
||||||
this._win.webContents.executeJavaScript(`console.log(
|
this._win.webContents.executeJavaScript(`console.log(
|
||||||
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
||||||
|
@ -158,11 +158,11 @@ export default class RAOP {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay'));
|
const browser2 = this.mdns.createBrowser(this.mdns.tcp("airplay"));
|
||||||
browser2.on('ready', browser2.discover);
|
browser2.on("ready", browser2.discover);
|
||||||
|
|
||||||
browser2.on('update', (service: any) => {
|
browser2.on("update", (service: any) => {
|
||||||
if (service.addresses && service.fullname && (service.fullname.includes('_airplay._tcp'))) {
|
if (service.addresses && service.fullname && service.fullname.includes("_airplay._tcp")) {
|
||||||
// console.log(service.txt)
|
// console.log(service.txt)
|
||||||
this._win.webContents.executeJavaScript(`console.log(
|
this._win.webContents.executeJavaScript(`console.log(
|
||||||
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
"${service.name} ${service.host}:${service.port} ${service.addresses}"
|
||||||
|
@ -183,15 +183,13 @@ export default class RAOP {
|
||||||
// this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
|
// this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv) => {
|
||||||
|
|
||||||
electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL,txt,airplay2dv) => {
|
|
||||||
|
|
||||||
if (ipv4 != this.ipairplay || ipport != this.portairplay) {
|
if (ipv4 != this.ipairplay || ipport != this.portairplay) {
|
||||||
if (this.airtunes == null) { this.airtunes = new this.u()}
|
if (this.airtunes == null) {
|
||||||
|
this.airtunes = new this.u();
|
||||||
|
}
|
||||||
this.ipairplay = ipv4;
|
this.ipairplay = ipv4;
|
||||||
this.portairplay = ipport;
|
this.portairplay = ipport;
|
||||||
this.device = this.airtunes.add(ipv4, {
|
this.device = this.airtunes.add(ipv4, {
|
||||||
|
@ -200,66 +198,58 @@ export default class RAOP {
|
||||||
password: sepassword,
|
password: sepassword,
|
||||||
txt: txt,
|
txt: txt,
|
||||||
airplay2: airplay2dv,
|
airplay2: airplay2dv,
|
||||||
debug: true
|
debug: true,
|
||||||
});
|
});
|
||||||
// console.log('lol',txt)
|
// console.log('lol',txt)
|
||||||
this.device.on('status', (status: any) => {
|
this.device.on("status", (status: any) => {
|
||||||
console.log('device status', status);
|
console.log("device status", status);
|
||||||
if (status == "ready"){
|
if (status == "ready") {
|
||||||
this._win.webContents.setAudioMuted(true);
|
this._win.webContents.setAudioMuted(true);
|
||||||
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
|
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
|
||||||
}
|
}
|
||||||
if (status == "need_password"){
|
if (status == "need_password") {
|
||||||
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI()`)
|
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI()`);
|
||||||
}
|
}
|
||||||
if (status == "pair_success"){
|
if (status == "pair_success") {
|
||||||
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess()`)
|
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess()`);
|
||||||
}
|
}
|
||||||
if (status == "pair_failed"){
|
if (status == "pair_failed") {
|
||||||
this._win.webContents.executeJavaScript(`app.sendAirPlayFailed()`)
|
this._win.webContents.executeJavaScript(`app.sendAirPlayFailed()`);
|
||||||
}
|
}
|
||||||
if (status == 'stopped') {
|
if (status == "stopped") {
|
||||||
this.airtunes.stopAll(() => {
|
this.airtunes.stopAll(() => {
|
||||||
console.log('end');
|
console.log("end");
|
||||||
});
|
});
|
||||||
this.airtunes = null;
|
this.airtunes = null;
|
||||||
this.device = null;
|
this.device = null;
|
||||||
this.ipairplay = '';
|
this.ipairplay = "";
|
||||||
this.portairplay = '';
|
this.portairplay = "";
|
||||||
this.ok = 1;
|
this.ok = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.ok == 1) {
|
if (this.ok == 1) {
|
||||||
console.log(this.device.key, title ?? '', artist ?? '', album ?? '');
|
console.log(this.device.key, title ?? "", artist ?? "", album ?? "");
|
||||||
this.airtunes.setTrackInfo(this.device.key, title ?? '', artist?? '', album?? '');
|
this.airtunes.setTrackInfo(this.device.key, title ?? "", artist ?? "", album ?? "");
|
||||||
this.uploadImageAirplay(artworkURL);
|
this.uploadImageAirplay(artworkURL);
|
||||||
console.log('done');
|
console.log("done");
|
||||||
this.ok == 2
|
this.ok == 2;
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.on("setAirPlayPasscode", (event, passcode) => {
|
||||||
|
if (this.device) {
|
||||||
|
this.device.setPasscode(passcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('setAirPlayPasscode', (event, passcode) => {
|
electron.ipcMain.on("writeWAV", (event, leftbuffer, rightbuffer) => {
|
||||||
if (this.device){
|
|
||||||
this.device.setPasscode(passcode)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
electron.ipcMain.on('writeWAV', (event, leftbuffer, rightbuffer) => {
|
|
||||||
if (this.airtunes != null) {
|
if (this.airtunes != null) {
|
||||||
if (this.worker == null) {
|
if (this.worker == null) {
|
||||||
try{
|
try {
|
||||||
const toDataUrl = (js: any) => new URL(`data:text/javascript,${encodeURIComponent(js)}`);
|
const toDataUrl = (js: any) => new URL(`data:text/javascript,${encodeURIComponent(js)}`);
|
||||||
// let blob = new Blob([this.processNode], { type: 'application/javascript' });
|
// let blob = new Blob([this.processNode], { type: 'application/javascript' });
|
||||||
//Create new worker
|
//Create new worker
|
||||||
|
@ -275,11 +265,12 @@ export default class RAOP {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.worker.on("error", (error: any) => {
|
this.worker.on("error", (error: any) => {
|
||||||
console.log("bruh",error);
|
console.log("bruh", error);
|
||||||
});
|
});
|
||||||
this.worker.postMessage({buffer: [leftbuffer, rightbuffer]});
|
this.worker.postMessage({ buffer: [leftbuffer, rightbuffer] });
|
||||||
} catch (e){console.log(e)}
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
// this.ffmpeg != null ? this.ffmpeg.kill() : null;
|
// this.ffmpeg != null ? this.ffmpeg.kill() : null;
|
||||||
// this.ffmpeg = spawn(this._utils.getStoreValue("advanced.ffmpegLocation"), [
|
// this.ffmpeg = spawn(this._utils.getStoreValue("advanced.ffmpegLocation"), [
|
||||||
|
@ -299,64 +290,59 @@ export default class RAOP {
|
||||||
// this.ffmpeg.stdout.pipe(this.airtunes);
|
// this.ffmpeg.stdout.pipe(this.airtunes);
|
||||||
// this.i = true;
|
// this.i = true;
|
||||||
} else {
|
} else {
|
||||||
this.worker.postMessage({buffer: [leftbuffer, rightbuffer]});
|
this.worker.postMessage({ buffer: [leftbuffer, rightbuffer] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.on("disconnectAirplay", (event) => {
|
||||||
|
|
||||||
electron.ipcMain.on('disconnectAirplay', (event) => {
|
|
||||||
this._win.webContents.setAudioMuted(false);
|
this._win.webContents.setAudioMuted(false);
|
||||||
this.airtunes.stopAll(function () {
|
this.airtunes.stopAll(function () {
|
||||||
console.log('end');
|
console.log("end");
|
||||||
});
|
});
|
||||||
this.airtunes = null;
|
this.airtunes = null;
|
||||||
this.device = null;
|
this.device = null;
|
||||||
this.ipairplay = '';
|
this.ipairplay = "";
|
||||||
this.portairplay = '';
|
this.portairplay = "";
|
||||||
this.ok = 1;
|
this.ok = 1;
|
||||||
this.i = false;
|
this.i = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('updateAirplayInfo', (event, title, artist, album, artworkURL) => {
|
electron.ipcMain.on("updateAirplayInfo", (event, title, artist, album, artworkURL) => {
|
||||||
if (this.airtunes && this.device) {
|
if (this.airtunes && this.device) {
|
||||||
console.log(this.device.key, title, artist, album);
|
console.log(this.device.key, title, artist, album);
|
||||||
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
||||||
this.uploadImageAirplay(artworkURL)
|
this.uploadImageAirplay(artworkURL);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
electron.ipcMain.on('updateRPCImage', (_event, imageurl) => {
|
electron.ipcMain.on("updateRPCImage", (_event, imageurl) => {
|
||||||
this.uploadImageAirplay(imageurl)
|
this.uploadImageAirplay(imageurl);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private uploadImageAirplay = (url: any) => {
|
private uploadImageAirplay = (url: any) => {
|
||||||
try {
|
try {
|
||||||
if (url != null && url != '') {
|
if (url != null && url != "") {
|
||||||
//console.log(join(this._app.getPath('userData'), 'temp.png'), url);
|
//console.log(join(this._app.getPath('userData'), 'temp.png'), url);
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(res => res.buffer())
|
.then((res) => res.buffer())
|
||||||
.then((buffer) => {
|
.then((buffer) => {
|
||||||
this.airtunes.setArtwork(this.device.key, buffer, "image/png");
|
this.airtunes.setArtwork(this.device.key, buffer, "image/png");
|
||||||
}).catch(err => {
|
})
|
||||||
console.log(err)
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) { console.log(e) }
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on app stop
|
* Runs on app stop
|
||||||
*/
|
*/
|
||||||
onBeforeQuit(): void {
|
onBeforeQuit(): void {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Runs on song change
|
// * Runs on song change
|
||||||
|
@ -381,15 +367,15 @@ export default class RAOP {
|
||||||
*/
|
*/
|
||||||
onPlaybackStateDidChange(attributes: any): void {
|
onPlaybackStateDidChange(attributes: any): void {
|
||||||
if (this.airtunes && this.device) {
|
if (this.airtunes && this.device) {
|
||||||
let title = attributes?.name ?? '';
|
let title = attributes?.name ?? "";
|
||||||
let artist = attributes?.artistName ?? '';
|
let artist = attributes?.artistName ?? "";
|
||||||
let album = attributes?.albumName ?? '';
|
let album = attributes?.albumName ?? "";
|
||||||
let artworkURL = attributes?.artwork?.url ?? null;
|
let artworkURL = attributes?.artwork?.url ?? null;
|
||||||
console.log(this.device.key, title, artist, album);
|
console.log(this.device.key, title, artist, album);
|
||||||
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
||||||
if (artworkURL != null){}
|
if (artworkURL != null) {
|
||||||
this.uploadImageAirplay(artworkURL.replace('{w}', '1024').replace('{h}', '1024'))
|
}
|
||||||
|
this.uploadImageAirplay(artworkURL.replace("{w}", "1024").replace("{h}", "1024"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {nativeImage, nativeTheme} from "electron";
|
import { nativeImage, nativeTheme } from "electron";
|
||||||
import {utils} from "../base/utils";
|
import { utils } from "../base/utils";
|
||||||
import {join} from "path";
|
import { join } from "path";
|
||||||
|
|
||||||
export default class Thumbar {
|
export default class Thumbar {
|
||||||
/**
|
/**
|
||||||
|
@ -12,20 +12,20 @@ export default class Thumbar {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'Thumbnail Toolbar Plugin';
|
public name: string = "Thumbnail Toolbar Plugin";
|
||||||
public description: string = 'Creates and managed the thumbnail toolbar buttons and their events';
|
public description: string = "Creates and managed the thumbnail toolbar buttons and their events";
|
||||||
public version: string = '1.0.0';
|
public version: string = "1.0.0";
|
||||||
public author: string = 'Core';
|
public author: string = "Core";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thumbnail Toolbar Assets
|
* Thumbnail Toolbar Assets
|
||||||
*/
|
*/
|
||||||
private icons: { [key: string]: Electron.NativeImage } = {
|
private icons: { [key: string]: Electron.NativeImage } = {
|
||||||
pause: nativeImage.createFromPath(join(utils.getPath('resourcePath'), 'icons/thumbar', `${nativeTheme.shouldUseDarkColors ? 'light' : 'dark'}_pause.png`)),
|
pause: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_pause.png`)),
|
||||||
play: nativeImage.createFromPath(join(utils.getPath('resourcePath'), 'icons/thumbar', `${nativeTheme.shouldUseDarkColors ? 'light' : 'dark'}_play.png`)),
|
play: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_play.png`)),
|
||||||
next: nativeImage.createFromPath(join(utils.getPath('resourcePath'), 'icons/thumbar', `${nativeTheme.shouldUseDarkColors ? 'light' : 'dark'}_next.png`)),
|
next: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_next.png`)),
|
||||||
previous: nativeImage.createFromPath(join(utils.getPath('resourcePath'), 'icons/thumbar', `${nativeTheme.shouldUseDarkColors ? 'light' : 'dark'}_previous.png`)),
|
previous: nativeImage.createFromPath(join(utils.getPath("resourcePath"), "icons/thumbar", `${nativeTheme.shouldUseDarkColors ? "light" : "dark"}_previous.png`)),
|
||||||
}
|
};
|
||||||
|
|
||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
* Private Methods
|
* Private Methods
|
||||||
|
@ -37,10 +37,10 @@ export default class Thumbar {
|
||||||
* @decorator
|
* @decorator
|
||||||
*/
|
*/
|
||||||
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== "win32") {
|
||||||
descriptor.value = function () {
|
descriptor.value = function () {
|
||||||
return
|
return;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,39 +48,38 @@ export default class Thumbar {
|
||||||
* Update the thumbnail toolbar
|
* Update the thumbnail toolbar
|
||||||
*/
|
*/
|
||||||
private updateButtons(attributes: any) {
|
private updateButtons(attributes: any) {
|
||||||
|
console.log(attributes);
|
||||||
console.log(attributes)
|
|
||||||
|
|
||||||
if (!attributes) {
|
if (!attributes) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
{
|
{
|
||||||
tooltip: 'Previous',
|
tooltip: "Previous",
|
||||||
icon: this.icons.previous,
|
icon: this.icons.previous,
|
||||||
click() {
|
click() {
|
||||||
utils.playback.previous()
|
utils.playback.previous();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tooltip: attributes.status ? 'Pause' : 'Play',
|
tooltip: attributes.status ? "Pause" : "Play",
|
||||||
icon: attributes.status ? this.icons.pause : this.icons.play,
|
icon: attributes.status ? this.icons.pause : this.icons.play,
|
||||||
click() {
|
click() {
|
||||||
utils.playback.playPause()
|
utils.playback.playPause();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tooltip: 'Next',
|
tooltip: "Next",
|
||||||
icon: this.icons.next,
|
icon: this.icons.next,
|
||||||
click() {
|
click() {
|
||||||
utils.playback.next()
|
utils.playback.next();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!attributes.playParams || attributes.playParams.id === 'no-id-found') {
|
if (!attributes.playParams || attributes.playParams.id === "no-id-found") {
|
||||||
this._win.setThumbarButtons([])
|
this._win.setThumbarButtons([]);
|
||||||
} else {
|
} else {
|
||||||
this._win.setThumbarButtons(buttons);
|
this._win.setThumbarButtons(buttons);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +92,7 @@ export default class Thumbar {
|
||||||
/**
|
/**
|
||||||
* Runs on plugin load (Currently run on application start)
|
* Runs on plugin load (Currently run on application start)
|
||||||
*/
|
*/
|
||||||
constructor(a: { getApp: () => any; }) {
|
constructor(a: { getApp: () => any }) {
|
||||||
this._app = utils.getApp();
|
this._app = utils.getApp();
|
||||||
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +120,7 @@ export default class Thumbar {
|
||||||
*/
|
*/
|
||||||
@Thumbar.windowsOnly
|
@Thumbar.windowsOnly
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {
|
||||||
this.updateButtons(attributes)
|
this.updateButtons(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +129,6 @@ export default class Thumbar {
|
||||||
*/
|
*/
|
||||||
@Thumbar.windowsOnly
|
@Thumbar.windowsOnly
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {
|
||||||
this.updateButtons(attributes)
|
this.updateButtons(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from "ws";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0-pad a number.
|
* 0-pad a number.
|
||||||
|
@ -6,7 +6,7 @@ import * as WebSocket from 'ws';
|
||||||
* @param {Number} length
|
* @param {Number} length
|
||||||
* @returns String
|
* @returns String
|
||||||
*/
|
*/
|
||||||
const pad = (number: number, length: number) => String(number).padStart(length, '0');
|
const pad = (number: number, length: number) => String(number).padStart(length, "0");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert seconds to a time string acceptable to Rainmeter
|
* Convert seconds to a time string acceptable to Rainmeter
|
||||||
|
@ -20,21 +20,21 @@ const convertTimeToString = (timeInSeconds: number) => {
|
||||||
return timeInMinutes + ":" + pad(Math.floor(timeInSeconds % 60), 2);
|
return timeInMinutes + ":" + pad(Math.floor(timeInSeconds % 60), 2);
|
||||||
}
|
}
|
||||||
return Math.floor(timeInMinutes / 60) + ":" + pad(Math.floor(timeInMinutes % 60), 2) + ":" + pad(Math.floor(timeInSeconds % 60), 2);
|
return Math.floor(timeInMinutes / 60) + ":" + pad(Math.floor(timeInMinutes % 60), 2) + ":" + pad(Math.floor(timeInSeconds % 60), 2);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default class WebNowPlaying {
|
export default class WebNowPlaying {
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
||||||
*/
|
*/
|
||||||
public name: string = 'WebNowPlaying';
|
public name: string = "WebNowPlaying";
|
||||||
public description: string = 'Song info and playback control for the Rainmeter WebNowPlaying plugin.';
|
public description: string = "Song info and playback control for the Rainmeter WebNowPlaying plugin.";
|
||||||
public version: string = '1.0.1';
|
public version: string = "1.0.1";
|
||||||
public author: string = 'Zennn <me@jozen.blue>';
|
public author: string = "Zennn <me@jozen.blue>";
|
||||||
|
|
||||||
private _win: any;
|
private _win: any;
|
||||||
private ws?: WebSocket;
|
private ws?: WebSocket;
|
||||||
private wsapiConn?: WebSocket;
|
private wsapiConn?: WebSocket;
|
||||||
private playerName: string = 'Cider';
|
private playerName: string = "Cider";
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
console.debug(`[Plugin][${this.name}] Loading Complete.`);
|
||||||
|
@ -46,7 +46,7 @@ export default class WebNowPlaying {
|
||||||
* @decorator
|
* @decorator
|
||||||
*/
|
*/
|
||||||
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
private static windowsOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== "win32") {
|
||||||
descriptor.value = () => void 0;
|
descriptor.value = () => void 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,39 +54,39 @@ export default class WebNowPlaying {
|
||||||
private sendSongInfo(attributes: any) {
|
private sendSongInfo(attributes: any) {
|
||||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
||||||
|
|
||||||
const fields = ['STATE', 'TITLE', 'ARTIST', 'ALBUM', 'COVER', 'DURATION', 'POSITION', 'VOLUME', 'REPEAT', 'SHUFFLE'];
|
const fields = ["STATE", "TITLE", "ARTIST", "ALBUM", "COVER", "DURATION", "POSITION", "VOLUME", "REPEAT", "SHUFFLE"];
|
||||||
fields.forEach((field) => {
|
fields.forEach((field) => {
|
||||||
try {
|
try {
|
||||||
let value: any = '';
|
let value: any = "";
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'STATE':
|
case "STATE":
|
||||||
value = attributes.status ? 1 : 2;
|
value = attributes.status ? 1 : 2;
|
||||||
break;
|
break;
|
||||||
case 'TITLE':
|
case "TITLE":
|
||||||
value = attributes.name;
|
value = attributes.name;
|
||||||
break;
|
break;
|
||||||
case 'ARTIST':
|
case "ARTIST":
|
||||||
value = attributes.artistName;
|
value = attributes.artistName;
|
||||||
break;
|
break;
|
||||||
case 'ALBUM':
|
case "ALBUM":
|
||||||
value = attributes.albumName;
|
value = attributes.albumName;
|
||||||
break;
|
break;
|
||||||
case 'COVER':
|
case "COVER":
|
||||||
value = attributes.artwork.url.replace('{w}', attributes.artwork.width).replace('{h}', attributes.artwork.height);
|
value = attributes.artwork.url.replace("{w}", attributes.artwork.width).replace("{h}", attributes.artwork.height);
|
||||||
break;
|
break;
|
||||||
case 'DURATION':
|
case "DURATION":
|
||||||
value = convertTimeToString(attributes.durationInMillis / 1000);
|
value = convertTimeToString(attributes.durationInMillis / 1000);
|
||||||
break;
|
break;
|
||||||
case 'POSITION':
|
case "POSITION":
|
||||||
value = convertTimeToString((attributes.durationInMillis - attributes.remainingTime) / 1000);
|
value = convertTimeToString((attributes.durationInMillis - attributes.remainingTime) / 1000);
|
||||||
break;
|
break;
|
||||||
case 'VOLUME':
|
case "VOLUME":
|
||||||
value = attributes.volume * 100;
|
value = attributes.volume * 100;
|
||||||
break;
|
break;
|
||||||
case 'REPEAT':
|
case "REPEAT":
|
||||||
value = attributes.repeatMode;
|
value = attributes.repeatMode;
|
||||||
break;
|
break;
|
||||||
case 'SHUFFLE':
|
case "SHUFFLE":
|
||||||
value = attributes.shuffleMode;
|
value = attributes.shuffleMode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -104,42 +104,42 @@ export default class WebNowPlaying {
|
||||||
if (!evt.data) return;
|
if (!evt.data) return;
|
||||||
const data = <string>evt.data;
|
const data = <string>evt.data;
|
||||||
|
|
||||||
let value: string = '';
|
let value: string = "";
|
||||||
if (data.split(/ (.+)/).length > 1) {
|
if (data.split(/ (.+)/).length > 1) {
|
||||||
value = data.split(/ (.+)/)[1];
|
value = data.split(/ (.+)/)[1];
|
||||||
}
|
}
|
||||||
const eventName = data.split(' ')[0].toLowerCase();
|
const eventName = data.split(" ")[0].toLowerCase();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (eventName) {
|
switch (eventName) {
|
||||||
case 'playpause':
|
case "playpause":
|
||||||
this._win.webContents.executeJavaScript('MusicKitInterop.playPause()').catch(console.error);
|
this._win.webContents.executeJavaScript("MusicKitInterop.playPause()").catch(console.error);
|
||||||
break;
|
break;
|
||||||
case 'next':
|
case "next":
|
||||||
this._win.webContents.executeJavaScript('MusicKitInterop.next()').catch(console.error);
|
this._win.webContents.executeJavaScript("MusicKitInterop.next()").catch(console.error);
|
||||||
break;
|
break;
|
||||||
case 'previous':
|
case "previous":
|
||||||
this._win.webContents.executeJavaScript('MusicKitInterop.previous()').catch(console.error);
|
this._win.webContents.executeJavaScript("MusicKitInterop.previous()").catch(console.error);
|
||||||
break;
|
break;
|
||||||
case 'setposition':
|
case "setposition":
|
||||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(value)})`);
|
this._win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(value)})`);
|
||||||
break;
|
break;
|
||||||
case 'setvolume':
|
case "setvolume":
|
||||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(value) / 100}`);
|
this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(value) / 100}`);
|
||||||
break;
|
break;
|
||||||
case 'repeat':
|
case "repeat":
|
||||||
this._win.webContents.executeJavaScript('wsapi.toggleRepeat()').catch(console.error);
|
this._win.webContents.executeJavaScript("wsapi.toggleRepeat()").catch(console.error);
|
||||||
break;
|
break;
|
||||||
case 'shuffle':
|
case "shuffle":
|
||||||
this._win.webContents.executeJavaScript('wsapi.toggleShuffle()').catch(console.error);
|
this._win.webContents.executeJavaScript("wsapi.toggleShuffle()").catch(console.error);
|
||||||
break;
|
break;
|
||||||
case 'togglethumbsup':
|
case "togglethumbsup":
|
||||||
// not implemented
|
// not implemented
|
||||||
break;
|
break;
|
||||||
case 'togglethumbsdown':
|
case "togglethumbsdown":
|
||||||
// not implemented
|
// not implemented
|
||||||
break;
|
break;
|
||||||
case 'rating':
|
case "rating":
|
||||||
// not implemented
|
// not implemented
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -162,10 +162,10 @@ export default class WebNowPlaying {
|
||||||
// Connect to Rainmeter plugin and retry on disconnect.
|
// Connect to Rainmeter plugin and retry on disconnect.
|
||||||
const init = () => {
|
const init = () => {
|
||||||
try {
|
try {
|
||||||
this.ws = new WebSocket('ws://127.0.0.1:8974/');
|
this.ws = new WebSocket("ws://127.0.0.1:8974/");
|
||||||
let retry: NodeJS.Timeout;
|
let retry: NodeJS.Timeout;
|
||||||
this.ws.onopen = () => {
|
this.ws.onopen = () => {
|
||||||
console.info('[WebNowPlaying] Connected to Rainmeter');
|
console.info("[WebNowPlaying] Connected to Rainmeter");
|
||||||
this.ws?.send(`PLAYER:${this.playerName}`);
|
this.ws?.send(`PLAYER:${this.playerName}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -189,15 +189,15 @@ export default class WebNowPlaying {
|
||||||
|
|
||||||
// Connect to wsapi. Only used to update progress.
|
// Connect to wsapi. Only used to update progress.
|
||||||
try {
|
try {
|
||||||
this.wsapiConn = new WebSocket('ws://127.0.0.1:26369/');
|
this.wsapiConn = new WebSocket("ws://127.0.0.1:26369/");
|
||||||
|
|
||||||
this.wsapiConn.onopen = () => {
|
this.wsapiConn.onopen = () => {
|
||||||
console.info('[WebNowPlaying] Connected to wsapi');
|
console.info("[WebNowPlaying] Connected to wsapi");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.wsapiConn.onmessage = (evt: WebSocket.MessageEvent) => {
|
this.wsapiConn.onmessage = (evt: WebSocket.MessageEvent) => {
|
||||||
const response = JSON.parse(<string>evt.data);
|
const response = JSON.parse(<string>evt.data);
|
||||||
if (response.type === 'playbackStateUpdate') {
|
if (response.type === "playbackStateUpdate") {
|
||||||
this.sendSongInfo(response.data);
|
this.sendSongInfo(response.data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -214,7 +214,7 @@ export default class WebNowPlaying {
|
||||||
@WebNowPlaying.windowsOnly
|
@WebNowPlaying.windowsOnly
|
||||||
public onBeforeQuit() {
|
public onBeforeQuit() {
|
||||||
if (this.ws) {
|
if (this.ws) {
|
||||||
this.ws.send('STATE:0');
|
this.ws.send("STATE:0");
|
||||||
this.ws.onclose = () => void 0; // disable onclose handler first to stop it from retrying
|
this.ws.onclose = () => void 0; // disable onclose handler first to stop it from retrying
|
||||||
this.ws.close();
|
this.ws.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as PouchDB from 'pouchdb-node';
|
import * as PouchDB from "pouchdb-node";
|
||||||
import {join} from 'path';
|
import { join } from "path";
|
||||||
import {app} from "electron";
|
import { app } from "electron";
|
||||||
PouchDB.plugin(require('pouchdb-upsert'));
|
PouchDB.plugin(require("pouchdb-upsert"));
|
||||||
export class ProviderDB {
|
export class ProviderDB {
|
||||||
public static db: any = null
|
public static db: any = null;
|
||||||
static init() {
|
static init() {
|
||||||
if (ProviderDB.db == null){
|
if (ProviderDB.db == null) {
|
||||||
ProviderDB.db = new PouchDB(join(app.getPath('userData'), 'tracksdb'))
|
ProviderDB.db = new PouchDB(join(app.getPath("userData"), "tracksdb"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
import { ProviderDB } from "./db";
|
import { ProviderDB } from "./db";
|
||||||
import * as path from 'path';
|
import * as path from "path";
|
||||||
const { readdir } = require('fs').promises;
|
const { readdir } = require("fs").promises;
|
||||||
import { utils } from '../../base/utils';
|
import { utils } from "../../base/utils";
|
||||||
import * as mm from 'music-metadata';
|
import * as mm from "music-metadata";
|
||||||
import {Md5} from 'ts-md5/dist/md5';
|
import { Md5 } from "ts-md5/dist/md5";
|
||||||
import e from "express";
|
import e from "express";
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from "events";
|
||||||
|
|
||||||
export class LocalFiles {
|
export class LocalFiles {
|
||||||
static localSongs: any = [];
|
static localSongs: any = [];
|
||||||
|
@ -13,38 +13,41 @@ export class LocalFiles {
|
||||||
public static DB = ProviderDB.db;
|
public static DB = ProviderDB.db;
|
||||||
static eventEmitter = new EventEmitter();
|
static eventEmitter = new EventEmitter();
|
||||||
|
|
||||||
static getDataType(item_id : String | any){
|
static getDataType(item_id: String | any) {
|
||||||
if ((item_id ?? ('')).startsWith('ciderlocalart'))
|
if ((item_id ?? "").startsWith("ciderlocalart")) return "artwork";
|
||||||
return 'artwork'
|
else if ((item_id ?? "").startsWith("ciderlocal")) return "track";
|
||||||
else if ((item_id ?? ('')).startsWith('ciderlocal'))
|
|
||||||
return 'track'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async sendOldLibrary() {
|
static async sendOldLibrary() {
|
||||||
ProviderDB.init()
|
ProviderDB.init();
|
||||||
let rows = (await ProviderDB.db.allDocs({include_docs: true,
|
let rows = (await ProviderDB.db.allDocs({ include_docs: true, attachments: true })).rows.map((item: any) => {
|
||||||
attachments: true})).rows.map((item: any)=>{return item.doc})
|
return item.doc;
|
||||||
let tracks = rows.filter((item: any) => {return this.getDataType(item._id) == "track"})
|
});
|
||||||
let arts = rows.filter((item: any) => {return this.getDataType(item._id) == "artwork"})
|
let tracks = rows.filter((item: any) => {
|
||||||
|
return this.getDataType(item._id) == "track";
|
||||||
|
});
|
||||||
|
let arts = rows.filter((item: any) => {
|
||||||
|
return this.getDataType(item._id) == "artwork";
|
||||||
|
});
|
||||||
this.localSongs = tracks;
|
this.localSongs = tracks;
|
||||||
this.localSongsArts = arts;
|
this.localSongsArts = arts;
|
||||||
return tracks;
|
return tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async scanLibrary() {
|
static async scanLibrary() {
|
||||||
ProviderDB.init()
|
ProviderDB.init();
|
||||||
let folders = utils.getStoreValue("libraryPrefs.localPaths")
|
let folders = utils.getStoreValue("libraryPrefs.localPaths");
|
||||||
if (folders == null || folders.length == null || folders.length == 0) folders = []
|
if (folders == null || folders.length == null || folders.length == 0) folders = [];
|
||||||
let files: any[] = []
|
let files: any[] = [];
|
||||||
for (var folder of folders) {
|
for (var folder of folders) {
|
||||||
// get files from the Music folder
|
// get files from the Music folder
|
||||||
files = files.concat(await LocalFiles.getFiles(folder))
|
files = files.concat(await LocalFiles.getFiles(folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
let supporttedformats = ["mp3", "aac", "webm", "flac", "m4a", "ogg", "wav", "opus"]
|
let supporttedformats = ["mp3", "aac", "webm", "flac", "m4a", "ogg", "wav", "opus"];
|
||||||
let audiofiles = files.filter(f => supporttedformats.includes(f.substring(f.lastIndexOf('.') + 1)));
|
let audiofiles = files.filter((f) => supporttedformats.includes(f.substring(f.lastIndexOf(".") + 1)));
|
||||||
let metadatalist = []
|
let metadatalist = [];
|
||||||
let metadatalistart = []
|
let metadatalistart = [];
|
||||||
let numid = 0;
|
let numid = 0;
|
||||||
for (var audio of audiofiles) {
|
for (var audio of audiofiles) {
|
||||||
try {
|
try {
|
||||||
|
@ -52,46 +55,44 @@ export class LocalFiles {
|
||||||
let lochash = Md5.hashStr(audio) ?? numid;
|
let lochash = Md5.hashStr(audio) ?? numid;
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
let form = {
|
let form = {
|
||||||
"id": "ciderlocal" + lochash,
|
id: "ciderlocal" + lochash,
|
||||||
"_id": "ciderlocal" + lochash,
|
_id: "ciderlocal" + lochash,
|
||||||
"type": "podcast-episodes",
|
type: "podcast-episodes",
|
||||||
"href": audio,
|
href: audio,
|
||||||
"attributes": {
|
attributes: {
|
||||||
"artwork": {
|
artwork: {
|
||||||
"width": 3000,
|
width: 3000,
|
||||||
"height": 3000,
|
height: 3000,
|
||||||
"url": "/ciderlocalart/" + "ciderlocal" + lochash,
|
url: "/ciderlocalart/" + "ciderlocal" + lochash,
|
||||||
},
|
},
|
||||||
"topics": [],
|
topics: [],
|
||||||
"url": "",
|
url: "",
|
||||||
"subscribable": true,
|
subscribable: true,
|
||||||
"mediaKind": "audio",
|
mediaKind: "audio",
|
||||||
"genreNames": [
|
genreNames: [""],
|
||||||
""
|
|
||||||
],
|
|
||||||
// "playParams": {
|
// "playParams": {
|
||||||
// "id": "ciderlocal" + numid,
|
// "id": "ciderlocal" + numid,
|
||||||
// "kind": "podcast",
|
// "kind": "podcast",
|
||||||
// "isLibrary": true,
|
// "isLibrary": true,
|
||||||
// "reporting": false },
|
// "reporting": false },
|
||||||
"trackNumber": metadata.common.track?.no ?? 0,
|
trackNumber: metadata.common.track?.no ?? 0,
|
||||||
"discNumber": metadata.common.disk?.no ?? 0,
|
discNumber: metadata.common.disk?.no ?? 0,
|
||||||
"name": metadata.common.title ?? audio.substring(audio.lastIndexOf('\\') + 1),
|
name: metadata.common.title ?? audio.substring(audio.lastIndexOf("\\") + 1),
|
||||||
"albumName": metadata.common.album,
|
albumName: metadata.common.album,
|
||||||
"artistName": metadata.common.artist,
|
artistName: metadata.common.artist,
|
||||||
"copyright": metadata.common.copyright ?? "",
|
copyright: metadata.common.copyright ?? "",
|
||||||
"assetUrl": "file:///" + audio,
|
assetUrl: "file:///" + audio,
|
||||||
"contentAdvisory": "",
|
contentAdvisory: "",
|
||||||
"releaseDateTime": `${metadata?.common?.year ?? '2022'}-05-13T00:23:00Z`,
|
releaseDateTime: `${metadata?.common?.year ?? "2022"}-05-13T00:23:00Z`,
|
||||||
"durationInMillis": Math.floor((metadata.format.duration ?? 0) * 1000),
|
durationInMillis: Math.floor((metadata.format.duration ?? 0) * 1000),
|
||||||
"bitrate": Math.floor((metadata.format?.bitrate ?? 0) / 1000),
|
bitrate: Math.floor((metadata.format?.bitrate ?? 0) / 1000),
|
||||||
"offers": [
|
offers: [
|
||||||
{
|
{
|
||||||
"kind": "get",
|
kind: "get",
|
||||||
"type": "STDQ"
|
type: "STDQ",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"contentRating": "clean"
|
contentRating: "clean",
|
||||||
},
|
},
|
||||||
flavor: Math.floor((metadata.format?.bitrate ?? 0) / 1000),
|
flavor: Math.floor((metadata.format?.bitrate ?? 0) / 1000),
|
||||||
localFilesMetadata: {
|
localFilesMetadata: {
|
||||||
|
@ -104,18 +105,22 @@ export class LocalFiles {
|
||||||
let art = {
|
let art = {
|
||||||
id: "ciderlocal" + lochash,
|
id: "ciderlocal" + lochash,
|
||||||
_id: "ciderlocalart" + lochash,
|
_id: "ciderlocalart" + lochash,
|
||||||
url: metadata.common.picture != undefined ? metadata.common.picture[0].data.toString('base64') : "",
|
url: metadata.common.picture != undefined ? metadata.common.picture[0].data.toString("base64") : "",
|
||||||
}
|
};
|
||||||
metadatalistart.push(art)
|
metadatalistart.push(art);
|
||||||
numid += 1;
|
numid += 1;
|
||||||
ProviderDB.db.putIfNotExists(form)
|
ProviderDB.db.putIfNotExists(form);
|
||||||
ProviderDB.db.putIfNotExists(art)
|
ProviderDB.db.putIfNotExists(art);
|
||||||
metadatalist.push(form)
|
metadatalist.push(form);
|
||||||
|
|
||||||
if (this.localSongs.length === 0 && numid % 10 === 0) { // send updated chunks only if there is no previous database
|
if (this.localSongs.length === 0 && numid % 10 === 0) {
|
||||||
this.eventEmitter.emit('newtracks', metadatalist)}
|
// send updated chunks only if there is no previous database
|
||||||
|
this.eventEmitter.emit("newtracks", metadatalist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("localfiles error:", e);
|
||||||
}
|
}
|
||||||
} catch (e) {console.error("localfiles error:", e)}
|
|
||||||
}
|
}
|
||||||
// console.log('metadatalist', metadatalist);
|
// console.log('metadatalist', metadatalist);
|
||||||
this.localSongs = metadatalist;
|
this.localSongs = metadatalist;
|
||||||
|
@ -124,40 +129,53 @@ export class LocalFiles {
|
||||||
}
|
}
|
||||||
static async getFiles(dir: any) {
|
static async getFiles(dir: any) {
|
||||||
const dirents = await readdir(dir, { withFileTypes: true });
|
const dirents = await readdir(dir, { withFileTypes: true });
|
||||||
const files = await Promise.all(dirents.map((dirent: any) => {
|
const files = await Promise.all(
|
||||||
|
dirents.map((dirent: any) => {
|
||||||
const res = path.resolve(dir, dirent.name);
|
const res = path.resolve(dir, dirent.name);
|
||||||
return dirent.isDirectory() ? this.getFiles(res) : res;
|
return dirent.isDirectory() ? this.getFiles(res) : res;
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
return Array.prototype.concat(...files);
|
return Array.prototype.concat(...files);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async cleanUpDB(){
|
static async cleanUpDB() {
|
||||||
let folders = utils.getStoreValue("libraryPrefs.localPaths")
|
let folders = utils.getStoreValue("libraryPrefs.localPaths");
|
||||||
let rows = (await ProviderDB.db.allDocs({include_docs: true,
|
let rows = (await ProviderDB.db.allDocs({ include_docs: true, attachments: true })).rows.map((item: any) => {
|
||||||
attachments: true})).rows.map((item: any)=>{return item.doc})
|
return item.doc;
|
||||||
let tracks = rows.filter((item: any) => {return this.getDataType(item._id) == "track" && !folders.some((i: String) => {return item["attributes"]["assetUrl"].startsWith("file:///" + i)})})
|
});
|
||||||
let hashs = tracks.map((i: any) => {return i._id})
|
let tracks = rows.filter((item: any) => {
|
||||||
for (let hash of hashs){
|
return (
|
||||||
try{
|
this.getDataType(item._id) == "track" &&
|
||||||
|
!folders.some((i: String) => {
|
||||||
|
return item["attributes"]["assetUrl"].startsWith("file:///" + i);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let hashs = tracks.map((i: any) => {
|
||||||
|
return i._id;
|
||||||
|
});
|
||||||
|
for (let hash of hashs) {
|
||||||
|
try {
|
||||||
ProviderDB.db.get(hash).then(function (doc: any) {
|
ProviderDB.db.get(hash).then(function (doc: any) {
|
||||||
return ProviderDB.db.remove(doc);
|
return ProviderDB.db.remove(doc);
|
||||||
});} catch(e){}
|
});
|
||||||
try{
|
} catch (e) {}
|
||||||
ProviderDB.db.get(hash.replace('ciderlocal','ciderlocalart')).then(function (doc: any) {
|
try {
|
||||||
|
ProviderDB.db.get(hash.replace("ciderlocal", "ciderlocalart")).then(function (doc: any) {
|
||||||
return ProviderDB.db.remove(doc);
|
return ProviderDB.db.remove(doc);
|
||||||
});} catch(e){}
|
});
|
||||||
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static setupHandlers () {
|
static setupHandlers() {
|
||||||
const app = utils.getExpress()
|
const app = utils.getExpress();
|
||||||
console.log("Setting up handlers for local files")
|
console.log("Setting up handlers for local files");
|
||||||
app.get("/ciderlocal/:songs", (req: any, res: any) => {
|
app.get("/ciderlocal/:songs", (req: any, res: any) => {
|
||||||
const audio = atob(req.params.songs.replace(/_/g, '/').replace(/-/g, '+'));
|
const audio = atob(req.params.songs.replace(/_/g, "/").replace(/-/g, "+"));
|
||||||
//console.log('auss', audio)
|
//console.log('auss', audio)
|
||||||
let data = {
|
let data = {
|
||||||
data:
|
data: LocalFiles.localSongs.filter((f: any) => audio.split(",").includes(f.id)),
|
||||||
LocalFiles.localSongs.filter((f: any) => audio.split(',').includes(f.id))
|
|
||||||
};
|
};
|
||||||
res.send(data);
|
res.send(data);
|
||||||
});
|
});
|
||||||
|
@ -166,15 +184,14 @@ export class LocalFiles {
|
||||||
const audio = req.params.songs;
|
const audio = req.params.songs;
|
||||||
// metadata.common.picture[0].data.toString('base64')
|
// metadata.common.picture[0].data.toString('base64')
|
||||||
|
|
||||||
res.setHeader('Cache-Control', 'public, max-age=31536000');
|
res.setHeader("Cache-Control", "public, max-age=31536000");
|
||||||
res.setHeader('Expires', new Date(Date.now() + 31536000000).toUTCString());
|
res.setHeader("Expires", new Date(Date.now() + 31536000000).toUTCString());
|
||||||
res.setHeader('Content-Type', 'image/jpeg');
|
res.setHeader("Content-Type", "image/jpeg");
|
||||||
|
|
||||||
let data =
|
let data = LocalFiles.localSongsArts.filter((f: any) => f.id == audio);
|
||||||
LocalFiles.localSongsArts.filter((f: any) => f.id == audio);
|
res.status(200).send(Buffer.from(data[0]?.url, "base64"));
|
||||||
res.status(200).send(Buffer.from(data[0]?.url, 'base64'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return app
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,51 +1,51 @@
|
||||||
global.ipcRenderer = require('electron').ipcRenderer;
|
global.ipcRenderer = require("electron").ipcRenderer;
|
||||||
console.info('Loaded Preload')
|
console.info("Loaded Preload");
|
||||||
|
|
||||||
let cache = {playParams: {id: 0}, status: null, remainingTime: 0},
|
let cache = { playParams: { id: 0 }, status: null, remainingTime: 0 },
|
||||||
playbackCache = {status: null, time: Date.now()};
|
playbackCache = { status: null, time: Date.now() };
|
||||||
|
|
||||||
const MusicKitInterop = {
|
const MusicKitInterop = {
|
||||||
init: function () {
|
init: function () {
|
||||||
/* MusicKit.Events.playbackStateDidChange */
|
/* MusicKit.Events.playbackStateDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => {
|
||||||
const attributes = MusicKitInterop.getAttributes()
|
const attributes = MusicKitInterop.getAttributes();
|
||||||
if (MusicKitInterop.filterTrack(attributes, true, false)) {
|
if (MusicKitInterop.filterTrack(attributes, true, false)) {
|
||||||
global.ipcRenderer.send('playbackStateDidChange', attributes)
|
global.ipcRenderer.send("playbackStateDidChange", attributes);
|
||||||
global.ipcRenderer.send('wsapi-updatePlaybackState', attributes);
|
global.ipcRenderer.send("wsapi-updatePlaybackState", attributes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.playbackProgressDidChange */
|
/* MusicKit.Events.playbackProgressDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, async () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, async () => {
|
||||||
const attributes = MusicKitInterop.getAttributes()
|
const attributes = MusicKitInterop.getAttributes();
|
||||||
// wsapi call
|
// wsapi call
|
||||||
ipcRenderer.send('wsapi-updatePlaybackState', attributes);
|
ipcRenderer.send("wsapi-updatePlaybackState", attributes);
|
||||||
// lastfm call
|
// lastfm call
|
||||||
if (app.mk.currentPlaybackProgress === (app.cfg.connectivity.lastfm.scrobble_after / 100)) {
|
if (app.mk.currentPlaybackProgress === app.cfg.connectivity.lastfm.scrobble_after / 100) {
|
||||||
attributes.primaryArtist = (app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured) ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName;
|
attributes.primaryArtist = app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName;
|
||||||
ipcRenderer.send('lastfm:scrobbleTrack', attributes);
|
ipcRenderer.send("lastfm:scrobbleTrack", attributes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.playbackTimeDidChange */
|
/* MusicKit.Events.playbackTimeDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackTimeDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.playbackTimeDidChange, () => {
|
||||||
ipcRenderer.send('mpris:playbackTimeDidChange', (MusicKit.getInstance()?.currentPlaybackTime * 1000 * 1000) ?? 0);
|
ipcRenderer.send("mpris:playbackTimeDidChange", MusicKit.getInstance()?.currentPlaybackTime * 1000 * 1000 ?? 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.nowPlayingItemDidChange */
|
/* MusicKit.Events.nowPlayingItemDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
|
||||||
console.debug('[cider:preload] nowPlayingItemDidChange')
|
console.debug("[cider:preload] nowPlayingItemDidChange");
|
||||||
const attributes = MusicKitInterop.getAttributes()
|
const attributes = MusicKitInterop.getAttributes();
|
||||||
attributes.primaryArtist = (app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured) ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName;
|
attributes.primaryArtist = app.cfg.connectivity.lastfm.enabled && app.cfg.connectivity.lastfm.remove_featured ? await this.fetchPrimaryArtist(attributes.artistName) : attributes.artistName;
|
||||||
|
|
||||||
if (MusicKitInterop.filterTrack(attributes, false, true)) {
|
if (MusicKitInterop.filterTrack(attributes, false, true)) {
|
||||||
global.ipcRenderer.send('nowPlayingItemDidChange', attributes);
|
global.ipcRenderer.send("nowPlayingItemDidChange", attributes);
|
||||||
} else if (attributes.name !== 'no-title-found' && attributes.playParams.id !== "no-id-found") {
|
} else if (attributes.name !== "no-title-found" && attributes.playParams.id !== "no-id-found") {
|
||||||
global.ipcRenderer.send('lastfm:nowPlayingChange', attributes);
|
global.ipcRenderer.send("lastfm:nowPlayingChange", attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.cfg.general.playbackNotifications && !document.hasFocus() && attributes.artistName && attributes.artwork && attributes.name) {
|
if (app.cfg.general.playbackNotifications && !document.hasFocus() && attributes.artistName && attributes.artwork && attributes.name) {
|
||||||
global.ipcRenderer.send('playbackNotifications:create', attributes);
|
global.ipcRenderer.send("playbackNotifications:create", attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MusicKit.getInstance().nowPlayingItem) {
|
if (MusicKit.getInstance().nowPlayingItem) {
|
||||||
|
@ -56,7 +56,7 @@ const MusicKitInterop = {
|
||||||
|
|
||||||
/* MusicKit.Events.authorizationStatusDidChange */
|
/* MusicKit.Events.authorizationStatusDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => {
|
||||||
global.ipcRenderer.send('authorizationStatusDidChange', MusicKit.getInstance().authorizationStatus)
|
global.ipcRenderer.send("authorizationStatusDidChange", MusicKit.getInstance().authorizationStatus);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.mediaPlaybackError */
|
/* MusicKit.Events.mediaPlaybackError */
|
||||||
|
@ -66,12 +66,12 @@ const MusicKitInterop = {
|
||||||
|
|
||||||
/* MusicKit.Events.shuffleModeDidChange */
|
/* MusicKit.Events.shuffleModeDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.shuffleModeDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.shuffleModeDidChange, () => {
|
||||||
global.ipcRenderer.send('shuffleModeDidChange', MusicKit.getInstance().shuffleMode)
|
global.ipcRenderer.send("shuffleModeDidChange", MusicKit.getInstance().shuffleMode);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* MusicKit.Events.repeatModeDidChange */
|
/* MusicKit.Events.repeatModeDidChange */
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.repeatModeDidChange, () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.repeatModeDidChange, () => {
|
||||||
global.ipcRenderer.send('repeatModeDidChange', MusicKit.getInstance().repeatMode)
|
global.ipcRenderer.send("repeatModeDidChange", MusicKit.getInstance().repeatMode);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -83,65 +83,60 @@ const MusicKitInterop = {
|
||||||
|
|
||||||
async fetchPrimaryArtist(artist) {
|
async fetchPrimaryArtist(artist) {
|
||||||
if (app.mk.nowPlayingItem?.relationships?.artists) {
|
if (app.mk.nowPlayingItem?.relationships?.artists) {
|
||||||
const artist = await app.mk.api.artist(app.mk.nowPlayingItem.relationships.artists.data[0].id)
|
const artist = await app.mk.api.artist(app.mk.nowPlayingItem.relationships.artists.data[0].id);
|
||||||
return artist.attributes.name
|
return artist.attributes.name;
|
||||||
} else {
|
} else {
|
||||||
return artist
|
return artist;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getAttributes: function () {
|
getAttributes: function () {
|
||||||
const mk = MusicKit.getInstance()
|
const mk = MusicKit.getInstance();
|
||||||
const nowPlayingItem = mk.nowPlayingItem;
|
const nowPlayingItem = mk.nowPlayingItem;
|
||||||
const isPlayingExport = mk.isPlaying;
|
const isPlayingExport = mk.isPlaying;
|
||||||
const remainingTimeExport = mk.currentPlaybackTimeRemaining;
|
const remainingTimeExport = mk.currentPlaybackTimeRemaining;
|
||||||
const currentPlaybackProgress = mk.currentPlaybackProgress;
|
const currentPlaybackProgress = mk.currentPlaybackProgress;
|
||||||
const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {});
|
const attributes = nowPlayingItem != null ? nowPlayingItem.attributes : {};
|
||||||
|
|
||||||
attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id
|
attributes.songId = attributes.songId ?? attributes.playParams?.catalogId ?? attributes.playParams?.id;
|
||||||
attributes.status = isPlayingExport ?? null;
|
attributes.status = isPlayingExport ?? null;
|
||||||
attributes.name = attributes?.name ?? 'no-title-found';
|
attributes.name = attributes?.name ?? "no-title-found";
|
||||||
attributes.artwork = attributes?.artwork ?? {url: ''};
|
attributes.artwork = attributes?.artwork ?? { url: "" };
|
||||||
attributes.artwork.url = (attributes?.artwork?.url ?? '').replace(`{f}`, "png");
|
attributes.artwork.url = (attributes?.artwork?.url ?? "").replace(`{f}`, "png");
|
||||||
attributes.playParams = attributes?.playParams ?? {id: 'no-id-found'};
|
attributes.playParams = attributes?.playParams ?? { id: "no-id-found" };
|
||||||
attributes.playParams.id = attributes?.playParams?.id ?? 'no-id-found';
|
attributes.playParams.id = attributes?.playParams?.id ?? "no-id-found";
|
||||||
attributes.url = {
|
attributes.url = {
|
||||||
cider: `https://cider.sh/link?play/s/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? 'no-id-found')}`,
|
cider: `https://cider.sh/link?play/s/${nowPlayingItem?._songId ?? nowPlayingItem?.songId ?? "no-id-found"}`,
|
||||||
appleMusic: attributes.websiteUrl ? attributes.websiteUrl : `https://music.apple.com/${mk.storefrontId}/song/${nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? 'no-id-found')}`
|
appleMusic: attributes.websiteUrl ? attributes.websiteUrl : `https://music.apple.com/${mk.storefrontId}/song/${nowPlayingItem?._songId ?? nowPlayingItem?.songId ?? "no-id-found"}`,
|
||||||
|
};
|
||||||
|
if (attributes.playParams.id === "no-id-found") {
|
||||||
|
attributes.playParams.id = nowPlayingItem?.id ?? "no-id-found";
|
||||||
}
|
}
|
||||||
if (attributes.playParams.id === 'no-id-found') {
|
attributes.albumName = attributes?.albumName ?? "";
|
||||||
attributes.playParams.id = nowPlayingItem?.id ?? 'no-id-found';
|
attributes.artistName = attributes?.artistName ?? "";
|
||||||
}
|
|
||||||
attributes.albumName = attributes?.albumName ?? '';
|
|
||||||
attributes.artistName = attributes?.artistName ?? '';
|
|
||||||
attributes.genreNames = attributes?.genreNames ?? [];
|
attributes.genreNames = attributes?.genreNames ?? [];
|
||||||
attributes.remainingTime = remainingTimeExport
|
attributes.remainingTime = remainingTimeExport ? remainingTimeExport * 1000 : 0;
|
||||||
? remainingTimeExport * 1000
|
|
||||||
: 0;
|
|
||||||
attributes.durationInMillis = attributes?.durationInMillis ?? 0;
|
attributes.durationInMillis = attributes?.durationInMillis ?? 0;
|
||||||
attributes.currentPlaybackTime = mk?.currentPlaybackTime ?? 0;
|
attributes.currentPlaybackTime = mk?.currentPlaybackTime ?? 0;
|
||||||
attributes.currentPlaybackProgress = currentPlaybackProgress ?? 0;
|
attributes.currentPlaybackProgress = currentPlaybackProgress ?? 0;
|
||||||
attributes.startTime = Date.now();
|
attributes.startTime = Date.now();
|
||||||
attributes.endTime = Math.round(
|
attributes.endTime = Math.round(attributes?.playParams?.id === cache.playParams.id ? Date.now() + attributes?.remainingTime : attributes?.startTime + attributes?.durationInMillis);
|
||||||
attributes?.playParams?.id === cache.playParams.id
|
|
||||||
? Date.now() + attributes?.remainingTime
|
|
||||||
: attributes?.startTime + attributes?.durationInMillis
|
|
||||||
);
|
|
||||||
return attributes;
|
return attributes;
|
||||||
},
|
},
|
||||||
|
|
||||||
filterTrack: function (a, playbackCheck, mediaCheck) {
|
filterTrack: function (a, playbackCheck, mediaCheck) {
|
||||||
if (a.name === 'no-title-found' || a.playParams.id === "no-id-found") {
|
if (a.name === "no-title-found" || a.playParams.id === "no-id-found") {
|
||||||
return;
|
return;
|
||||||
} else if (mediaCheck && a.playParams.id === cache.playParams.id) {
|
} else if (mediaCheck && a.playParams.id === cache.playParams.id) {
|
||||||
return;
|
return;
|
||||||
} else if (playbackCheck && a.status === playbackCache.status) {
|
} else if (playbackCheck && a.status === playbackCache.status) {
|
||||||
return;
|
return;
|
||||||
} else if (playbackCheck && !a.status && a.remainingTime === playbackCache.time) { /* Pretty much have to do this to prevent multiple runs when a song starts playing */
|
} else if (playbackCheck && !a.status && a.remainingTime === playbackCache.time) {
|
||||||
|
/* Pretty much have to do this to prevent multiple runs when a song starts playing */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cache = a;
|
cache = a;
|
||||||
if (playbackCheck) playbackCache = {status: a.status, time: a.remainingTime};
|
if (playbackCheck) playbackCache = { status: a.status, time: a.remainingTime };
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -167,19 +162,21 @@ const MusicKitInterop = {
|
||||||
// } catch (e) { }
|
// } catch (e) { }
|
||||||
// if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null)
|
// if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null)
|
||||||
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);
|
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);
|
||||||
MusicKit.getInstance().skipToNextItem().then(r => console.debug(`[cider:preload] [next] Skipping to Next ${r}`));
|
MusicKit.getInstance()
|
||||||
|
.skipToNextItem()
|
||||||
|
.then((r) => console.debug(`[cider:preload] [next] Skipping to Next ${r}`));
|
||||||
},
|
},
|
||||||
|
|
||||||
previous: () => {
|
previous: () => {
|
||||||
// if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null)
|
// if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null)
|
||||||
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);
|
// MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex);
|
||||||
MusicKit.getInstance().skipToPreviousItem().then(r => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
|
MusicKit.getInstance()
|
||||||
}
|
.skipToPreviousItem()
|
||||||
|
.then((r) => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
}
|
process.once("loaded", () => {
|
||||||
|
console.debug("[cider:preload] IPC Listeners Created!");
|
||||||
|
|
||||||
process.once('loaded', () => {
|
|
||||||
console.debug("[cider:preload] IPC Listeners Created!")
|
|
||||||
global.MusicKitInterop = MusicKitInterop;
|
global.MusicKitInterop = MusicKitInterop;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"js": {
|
|
||||||
"beautify.ignore": "src/renderer/index.js"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,154 +1,136 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Thin.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Thin.woff2?v=3.19") format("woff2"), url("Inter-Thin.woff?v=3.19") format("woff");
|
||||||
url("Inter-Thin.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-ThinItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-ThinItalic.woff2?v=3.19") format("woff2"), url("Inter-ThinItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-ThinItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-ExtraLight.woff2?v=3.19") format("woff2"),
|
src: url("Inter-ExtraLight.woff2?v=3.19") format("woff2"), url("Inter-ExtraLight.woff?v=3.19") format("woff");
|
||||||
url("Inter-ExtraLight.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-ExtraLightItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-ExtraLightItalic.woff2?v=3.19") format("woff2"), url("Inter-ExtraLightItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-ExtraLightItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Light.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Light.woff2?v=3.19") format("woff2"), url("Inter-Light.woff?v=3.19") format("woff");
|
||||||
url("Inter-Light.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-LightItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-LightItalic.woff2?v=3.19") format("woff2"), url("Inter-LightItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-LightItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Regular.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Regular.woff2?v=3.19") format("woff2"), url("Inter-Regular.woff?v=3.19") format("woff");
|
||||||
url("Inter-Regular.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Italic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Italic.woff2?v=3.19") format("woff2"), url("Inter-Italic.woff?v=3.19") format("woff");
|
||||||
url("Inter-Italic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Medium.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Medium.woff2?v=3.19") format("woff2"), url("Inter-Medium.woff?v=3.19") format("woff");
|
||||||
url("Inter-Medium.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-MediumItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-MediumItalic.woff2?v=3.19") format("woff2"), url("Inter-MediumItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-MediumItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-SemiBold.woff2?v=3.19") format("woff2"),
|
src: url("Inter-SemiBold.woff2?v=3.19") format("woff2"), url("Inter-SemiBold.woff?v=3.19") format("woff");
|
||||||
url("Inter-SemiBold.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"), url("Inter-SemiBoldItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-SemiBoldItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Bold.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Bold.woff2?v=3.19") format("woff2"), url("Inter-Bold.woff?v=3.19") format("woff");
|
||||||
url("Inter-Bold.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-BoldItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-BoldItalic.woff2?v=3.19") format("woff2"), url("Inter-BoldItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-BoldItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-ExtraBold.woff2?v=3.19") format("woff2"),
|
src: url("Inter-ExtraBold.woff2?v=3.19") format("woff2"), url("Inter-ExtraBold.woff?v=3.19") format("woff");
|
||||||
url("Inter-ExtraBold.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-ExtraBoldItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-ExtraBoldItalic.woff2?v=3.19") format("woff2"), url("Inter-ExtraBoldItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-ExtraBoldItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-Black.woff2?v=3.19") format("woff2"),
|
src: url("Inter-Black.woff2?v=3.19") format("woff2"), url("Inter-Black.woff?v=3.19") format("woff");
|
||||||
url("Inter-Black.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter';
|
font-family: "Inter";
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url("Inter-BlackItalic.woff2?v=3.19") format("woff2"),
|
src: url("Inter-BlackItalic.woff2?v=3.19") format("woff2"), url("Inter-BlackItalic.woff?v=3.19") format("woff");
|
||||||
url("Inter-BlackItalic.woff?v=3.19") format("woff");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------
|
/* -------------------------------------------------------
|
||||||
|
@ -161,23 +143,22 @@ Usage:
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter var';
|
font-family: "Inter var";
|
||||||
font-weight: 100 900;
|
font-weight: 100 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-named-instance: 'Regular';
|
font-named-instance: "Regular";
|
||||||
src: url("Inter-roman.var.woff2?v=3.19") format("woff2");
|
src: url("Inter-roman.var.woff2?v=3.19") format("woff2");
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter var';
|
font-family: "Inter var";
|
||||||
font-weight: 100 900;
|
font-weight: 100 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-named-instance: 'Italic';
|
font-named-instance: "Italic";
|
||||||
src: url("Inter-italic.var.woff2?v=3.19") format("woff2");
|
src: url("Inter-italic.var.woff2?v=3.19") format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
[EXPERIMENTAL] Multi-axis, single variable font.
|
[EXPERIMENTAL] Multi-axis, single variable font.
|
||||||
|
|
||||||
|
@ -192,7 +173,7 @@ explicitly, e.g.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Inter var experimental';
|
font-family: "Inter var experimental";
|
||||||
font-weight: 100 900;
|
font-weight: 100 900;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-style: oblique 0deg 10deg;
|
font-style: oblique 0deg 10deg;
|
||||||
|
|
|
@ -8,9 +8,9 @@ http://scripts.sil.org/OFL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Pretendard Variable';
|
font-family: "Pretendard Variable";
|
||||||
font-weight: 45 920;
|
font-weight: 45 920;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: local('Pretendard Variable'), url('./woff2/PretendardVariable.woff2') format('woff2-variations');
|
src: local("Pretendard Variable"), url("./woff2/PretendardVariable.woff2") format("woff2-variations");
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
11874
src/renderer/hlscider.js
11874
src/renderer/hlscider.js
File diff suppressed because it is too large
Load diff
|
@ -57,11 +57,11 @@ Vue.component("animated-number", {
|
||||||
});
|
});
|
||||||
|
|
||||||
function initMusicKit() {
|
function initMusicKit() {
|
||||||
if(!this.responseText) {
|
if (!this.responseText) {
|
||||||
console.log("Using stored token")
|
console.log("Using stored token");
|
||||||
this.responseText = JSON.stringify({
|
this.responseText = JSON.stringify({
|
||||||
token: localStorage.getItem("lastToken")
|
token: localStorage.getItem("lastToken"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
let parsedJson = JSON.parse(this.responseText);
|
let parsedJson = JSON.parse(this.responseText);
|
||||||
localStorage.setItem("lastToken", parsedJson.token);
|
localStorage.setItem("lastToken", parsedJson.token);
|
||||||
|
@ -95,10 +95,10 @@ function capiInit() {
|
||||||
request.addEventListener("load", initMusicKit);
|
request.addEventListener("load", initMusicKit);
|
||||||
request.onreadystatechange = function (aEvt) {
|
request.onreadystatechange = function (aEvt) {
|
||||||
if (request.readyState == 4 && request.status != 200) {
|
if (request.readyState == 4 && request.status != 200) {
|
||||||
if(localStorage.getItem("lastToken") != null) {
|
if (localStorage.getItem("lastToken") != null) {
|
||||||
initMusicKit()
|
initMusicKit();
|
||||||
} else {
|
} else {
|
||||||
console.error(`Failed to load capi, cannot get token [${request.status}]`)
|
console.error(`Failed to load capi, cannot get token [${request.status}]`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -110,7 +110,7 @@ document.addEventListener("musickitloaded", function () {
|
||||||
if (showOobe()) return;
|
if (showOobe()) return;
|
||||||
console.log("MusicKit loaded");
|
console.log("MusicKit loaded");
|
||||||
// MusicKit global is now defined
|
// MusicKit global is now defined
|
||||||
capiInit()
|
capiInit();
|
||||||
});
|
});
|
||||||
window.addEventListener("drmUnsupported", function () {
|
window.addEventListener("drmUnsupported", function () {
|
||||||
initMusicKit();
|
initMusicKit();
|
||||||
|
@ -140,12 +140,7 @@ function Clone(obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
|
||||||
(
|
|
||||||
c ^
|
|
||||||
(crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
|
|
||||||
).toString(16)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function xmlToJson(xml) {
|
function xmlToJson(xml) {
|
||||||
|
@ -196,26 +191,19 @@ async function asyncForEach(array, callback) {
|
||||||
|
|
||||||
var checkIfScrollIsStatic = setInterval(() => {
|
var checkIfScrollIsStatic = setInterval(() => {
|
||||||
try {
|
try {
|
||||||
if (
|
if (position === document.getElementsByClassName("lyric-body")[0].scrollTop) {
|
||||||
position === document.getElementsByClassName("lyric-body")[0].scrollTop
|
|
||||||
) {
|
|
||||||
clearInterval(checkIfScrollIsStatic);
|
clearInterval(checkIfScrollIsStatic);
|
||||||
// do something
|
// do something
|
||||||
}
|
}
|
||||||
position = document.getElementsByClassName("lyric-body")[0].scrollTop;
|
position = document.getElementsByClassName("lyric-body")[0].scrollTop;
|
||||||
} catch (e) { }
|
} catch (e) {}
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
// WebGPU Console Notification
|
// WebGPU Console Notification
|
||||||
async function webGPU() {
|
async function webGPU() {
|
||||||
try {
|
try {
|
||||||
const currentGPU = await navigator.gpu.requestAdapter();
|
const currentGPU = await navigator.gpu.requestAdapter();
|
||||||
console.log(
|
console.log("WebGPU enabled on", currentGPU.name, "with feature ID", currentGPU.features.size);
|
||||||
"WebGPU enabled on",
|
|
||||||
currentGPU.name,
|
|
||||||
"with feature ID",
|
|
||||||
currentGPU.features.size
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("WebGPU disabled / WebGPU initialization failed");
|
console.log("WebGPU disabled / WebGPU initialization failed");
|
||||||
}
|
}
|
||||||
|
@ -240,9 +228,9 @@ function isJson(item) {
|
||||||
webGPU().then();
|
webGPU().then();
|
||||||
|
|
||||||
function showOobe() {
|
function showOobe() {
|
||||||
return false
|
return false;
|
||||||
if (localStorage.getItem("music.ampwebplay.media-user-token") && localStorage.getItem("seenOOBE")) {
|
if (localStorage.getItem("music.ampwebplay.media-user-token") && localStorage.getItem("seenOOBE")) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
function waitForApp() {
|
function waitForApp() {
|
||||||
if (typeof app.init !== "undefined") {
|
if (typeof app.init !== "undefined") {
|
||||||
|
@ -252,7 +240,7 @@ function showOobe() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitForApp();
|
waitForApp();
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,13 +254,7 @@ document.addEventListener("DOMContentLoaded", async function () {
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
"contextmenu",
|
"contextmenu",
|
||||||
function (e) {
|
function (e) {
|
||||||
if (
|
if (e.target.tagName.toLowerCase() == "textarea" || (e.target.tagName.toLowerCase() == "input" && e.target.type != "checkbox" && e.target.type != "radio" && e.target.disabled == false)) {
|
||||||
e.target.tagName.toLowerCase() == "textarea" ||
|
|
||||||
(e.target.tagName.toLowerCase() == "input" &&
|
|
||||||
e.target.type != "checkbox" &&
|
|
||||||
e.target.type != "radio" &&
|
|
||||||
e.target.disabled == false)
|
|
||||||
) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const menuPanel = {
|
const menuPanel = {
|
||||||
items: {
|
items: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
:root {
|
:root {
|
||||||
--appleEase: cubic-bezier(.42, 0, .58, 1);
|
--appleEase: cubic-bezier(0.42, 0, 0.58, 1);
|
||||||
--appleTransition: .2s var(--appleEase);
|
--appleTransition: 0.2s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple CSS framework for Apple Music Electron */
|
/* Simple CSS framework for Apple Music Electron */
|
||||||
|
@ -57,7 +57,7 @@ input[type="range"].md-slider::-webkit-slider-thumb {
|
||||||
box-shadow: 0 0 2px 0 #555;
|
box-shadow: 0 0 2px 0 #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range].md-slider::-webkit-slider-runnable-track {
|
input[type="range"].md-slider::-webkit-slider-runnable-track {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -102,9 +102,6 @@ input[type=range].md-slider::-webkit-slider-runnable-track {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.md-transparent {
|
.md-transparent {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
@ -142,19 +139,23 @@ input[type=range].md-slider::-webkit-slider-runnable-track {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Vue transitions */
|
/* Vue transitions */
|
||||||
.fade_simple-enter-active, .fade_simple-leave-active {
|
.fade_simple-enter-active,
|
||||||
transition: all .5s;
|
.fade_simple-leave-active {
|
||||||
|
transition: all 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade_simple-enter, .fade_simple-leave-to {
|
.fade_simple-enter,
|
||||||
|
.fade_simple-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter-active, .fade-leave-active {
|
.fade-enter-active,
|
||||||
transition: all .5s;
|
.fade-leave-active {
|
||||||
|
transition: all 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-enter, .fade-leave-to {
|
.fade-enter,
|
||||||
|
.fade-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.95);
|
transform: scale(0.95);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@colorMixRate: 1%;
|
@colorMixRate: 1%;
|
||||||
@transparencyRate: 50%;
|
@transparencyRate: 50%;
|
||||||
|
|
||||||
@keyColor : #fc3c44;
|
@keyColor: #fc3c44;
|
||||||
@ciderColor: #ff2654;
|
@ciderColor: #ff2654;
|
||||||
@baseColor: #1e1e1e;
|
@baseColor: #1e1e1e;
|
||||||
@baseColorMix: mix(@baseColor, transparent, @transparencyRate);
|
@baseColorMix: mix(@baseColor, transparent, @transparencyRate);
|
||||||
|
|
1988
src/renderer/less/bootstrap.less
vendored
1988
src/renderer/less/bootstrap.less
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
||||||
zoom: 0.95;
|
zoom: 0.95;
|
||||||
}
|
}
|
||||||
.app-sidebar-content {
|
.app-sidebar-content {
|
||||||
padding:0px;
|
padding: 0px;
|
||||||
|
|
||||||
.app-sidebar-header-text {
|
.app-sidebar-header-text {
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
|
|
|
@ -5,36 +5,35 @@
|
||||||
#app.twopanel {
|
#app.twopanel {
|
||||||
--chromeHeight1: 46px;
|
--chromeHeight1: 46px;
|
||||||
--chromeHeight2: 90px;
|
--chromeHeight2: 90px;
|
||||||
--chromeHeight : calc(var(--chromeHeight1) + var(--chromeHeight2));
|
--chromeHeight: calc(var(--chromeHeight1) + var(--chromeHeight2));
|
||||||
|
|
||||||
.modular-fs .app-drawer .lyric-footer {
|
.modular-fs .app-drawer .lyric-footer {
|
||||||
bottom: var(--chromeHeight2);
|
bottom: var(--chromeHeight2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-chrome {
|
.app-chrome {
|
||||||
|
|
||||||
&:not(.chrome-bottom) {
|
&:not(.chrome-bottom) {
|
||||||
.app-chrome--center {
|
.app-chrome--center {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
.top-nav-group {
|
.top-nav-group {
|
||||||
background : #1e1e1e99;
|
background: #1e1e1e99;
|
||||||
border : 1px solid lighten(@baseColor, 8);
|
border: 1px solid lighten(@baseColor, 8);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
display : flex;
|
display: flex;
|
||||||
height : 32px;
|
height: 32px;
|
||||||
|
|
||||||
.app-sidebar-item {
|
.app-sidebar-item {
|
||||||
background-color: #1e1e1e00;
|
background-color: #1e1e1e00;
|
||||||
border-radius : 10px !important;
|
border-radius: 10px !important;
|
||||||
border : 0px;
|
border: 0px;
|
||||||
min-width : 120px;
|
min-width: 120px;
|
||||||
padding : 6px;
|
padding: 6px;
|
||||||
justify-content : center;
|
justify-content: center;
|
||||||
align-items : center;
|
align-items: center;
|
||||||
margin : 0px;
|
margin: 0px;
|
||||||
height : 100%;
|
height: 100%;
|
||||||
position : relative;
|
position: relative;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
._svg-icon {
|
._svg-icon {
|
||||||
|
@ -42,18 +41,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
--dist : 1px;
|
--dist: 1px;
|
||||||
content : '';
|
content: "";
|
||||||
position : absolute;
|
position: absolute;
|
||||||
top : var(--dist);
|
top: var(--dist);
|
||||||
left : var(--dist);
|
left: var(--dist);
|
||||||
right : var(--dist);
|
right: var(--dist);
|
||||||
bottom : var(--dist);
|
bottom: var(--dist);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
border-radius : 10px;
|
border-radius: 10px;
|
||||||
transform : scale(0.5);
|
transform: scale(0.5);
|
||||||
transition : transform 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
transition: transform 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
|
@ -65,8 +64,8 @@
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
|
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
|
||||||
opacity : .1;
|
opacity: 0.1;
|
||||||
transform : scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,15 +73,15 @@
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
opacity : .2;
|
opacity: 0.2;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.md-btn-primary {
|
&.md-btn-primary {
|
||||||
box-shadow : 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8);
|
box-shadow: 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8);
|
||||||
background-color: lighten(@baseColor, @colorMixRate * 5);
|
background-color: lighten(@baseColor, @colorMixRate * 5);
|
||||||
z-index : 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +89,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-mainmenu {
|
.app-mainmenu {
|
||||||
width : 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +100,10 @@
|
||||||
height: var(--chromeHeight1);
|
height: var(--chromeHeight1);
|
||||||
|
|
||||||
&.chrome-bottom {
|
&.chrome-bottom {
|
||||||
background : var(--color2);
|
background: var(--color2);
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
height : var(--chromeHeight2);
|
height: var(--chromeHeight2);
|
||||||
box-shadow : 0px -2px 6px rgb(20 20 20 / 12%),
|
box-shadow: 0px -2px 6px rgb(20 20 20 / 12%), 0px -1px 0px 0px rgb(200 200 200 / 12%);
|
||||||
0px -1px 0px 0px rgb(200 200 200 / 12%);
|
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
|
|
||||||
.app-chrome-playback-duration-bottom {
|
.app-chrome-playback-duration-bottom {
|
||||||
|
@ -116,33 +114,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-sm-auto {
|
.col-sm-auto {
|
||||||
width : 4em;
|
width: 4em;
|
||||||
display : flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items : center;
|
align-items: center;
|
||||||
font-size : 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
appearance : none;
|
appearance: none;
|
||||||
width : 100%;
|
width: 100%;
|
||||||
height : 5px;
|
height: 5px;
|
||||||
background-color: rgb(200 200 200 / 10%);
|
background-color: rgb(200 200 200 / 10%);
|
||||||
border-radius : 6px;
|
border-radius: 6px;
|
||||||
box-shadow : 0px 0px 0px 1px rgba(0 0 0 / 10%);
|
box-shadow: 0px 0px 0px 1px rgba(0 0 0 / 10%);
|
||||||
align-self : center;
|
align-self: center;
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : scale(1);
|
transform: scale(1);
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance : none;
|
appearance: none;
|
||||||
width : 16px;
|
width: 16px;
|
||||||
height : 16px;
|
height: 16px;
|
||||||
border-radius : 100%;
|
border-radius: 100%;
|
||||||
background : var(--keyColor);
|
background: var(--keyColor);
|
||||||
cursor : default;
|
cursor: default;
|
||||||
transition : opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -169,38 +167,37 @@
|
||||||
.playback-button.play,
|
.playback-button.play,
|
||||||
.playback-button.pause,
|
.playback-button.pause,
|
||||||
.playback-button.stop {
|
.playback-button.stop {
|
||||||
width : 42px;
|
width: 42px;
|
||||||
height : 42px;
|
height: 42px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin : 6px;
|
margin: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-chrome--center {
|
.app-chrome--center {
|
||||||
display : flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.app-chrome-playback-controls {
|
.app-chrome-playback-controls {
|
||||||
display : flex;
|
display: flex;
|
||||||
z-index : 1;
|
z-index: 1;
|
||||||
// margin-bottom: 12px;
|
// margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-chrome-playback-duration {
|
.app-chrome-playback-duration {
|
||||||
position : relative;
|
position: relative;
|
||||||
width : 80%;
|
width: 80%;
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
height : 16px;
|
height: 16px;
|
||||||
|
|
||||||
.song-progress {
|
.song-progress {
|
||||||
@bgColor : transparent;
|
@bgColor: transparent;
|
||||||
height : 16px;
|
height: 16px;
|
||||||
position : absolute;
|
position: absolute;
|
||||||
bottom : 4px;
|
bottom: 4px;
|
||||||
left : 0px;
|
left: 0px;
|
||||||
right : 4px;
|
right: 4px;
|
||||||
background: @bgColor;
|
background: @bgColor;
|
||||||
z-index : 0;
|
z-index: 0;
|
||||||
|
|
||||||
|
|
||||||
.song-duration {
|
.song-duration {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -208,64 +205,63 @@
|
||||||
|
|
||||||
.song-duration p {
|
.song-duration p {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size : 10px;
|
font-size: 10px;
|
||||||
height : 1.2em;
|
height: 1.2em;
|
||||||
line-height: 1.3em;
|
line-height: 1.3em;
|
||||||
overflow : hidden;
|
overflow: hidden;
|
||||||
margin : 0 0 0 0.25em;
|
margin: 0 0 0 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
>input[type=range] {
|
> input[type="range"] {
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
opacity : 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
z-index : 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
appearance : none;
|
appearance: none;
|
||||||
width : 100%;
|
width: 100%;
|
||||||
height : 4px;
|
height: 4px;
|
||||||
background-color: rgb(200 200 200 / 10%);
|
background-color: rgb(200 200 200 / 10%);
|
||||||
border-radius : 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : scale(0.5);
|
transform: scale(0.5);
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance : none;
|
appearance: none;
|
||||||
width : 12px;
|
width: 12px;
|
||||||
height : 12px;
|
height: 12px;
|
||||||
border-radius : 100%;
|
border-radius: 100%;
|
||||||
background : var(--keyColor);
|
background: var(--keyColor);
|
||||||
cursor : default;
|
cursor: default;
|
||||||
transition : opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-chrome--left {
|
.app-chrome--left {
|
||||||
width : 30%;
|
width: 30%;
|
||||||
justify-content : flex-start;
|
justify-content: flex-start;
|
||||||
align-items : flex-start;
|
align-items: flex-start;
|
||||||
-webkit-app-region: no-drag !important;
|
-webkit-app-region: no-drag !important;
|
||||||
|
|
||||||
.playback-controls {
|
.playback-controls {
|
||||||
-webkit-app-region: no-drag !important;
|
-webkit-app-region: no-drag !important;
|
||||||
|
|
||||||
.artwork {
|
.artwork {
|
||||||
--offset : 20px;
|
--offset: 20px;
|
||||||
--marginOffset: 2;
|
--marginOffset: 2;
|
||||||
--size : calc(var(--chromeHeight2) - var(--offset));
|
--size: calc(var(--chromeHeight2) - var(--offset));
|
||||||
width : var(--size);
|
width: var(--size);
|
||||||
height : var(--size);
|
height: var(--size);
|
||||||
margin : 0 calc(var(--offset) / var(--marginOffset)) 0 calc(var(--offset) / var(--marginOffset));
|
margin: 0 calc(var(--offset) / var(--marginOffset)) 0 calc(var(--offset) / var(--marginOffset));
|
||||||
|
|
||||||
.mediaitem-artwork,
|
.mediaitem-artwork,
|
||||||
img {
|
img {
|
||||||
|
@ -275,13 +271,13 @@
|
||||||
|
|
||||||
.playback-info {
|
.playback-info {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
margin : 6px;
|
margin: 6px;
|
||||||
|
|
||||||
.song-name {
|
.song-name {
|
||||||
text-align : left;
|
text-align: left;
|
||||||
font-size : 0.8em;
|
font-size: 0.8em;
|
||||||
font-weight : 500;
|
font-weight: 500;
|
||||||
width : 100%;
|
width: 100%;
|
||||||
-webkit-mask-image: linear-gradient(-90deg, transparent 0%, transparent 10%, black 20%);
|
-webkit-mask-image: linear-gradient(-90deg, transparent 0%, transparent 10%, black 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,23 +302,22 @@
|
||||||
|
|
||||||
.song-artist-album-content {
|
.song-artist-album-content {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size : 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
width : 100%;
|
height: 100%;
|
||||||
height : 100%;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
border : 0px;
|
border: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-chrome--right {
|
.app-chrome--right {
|
||||||
width : 30%;
|
width: 30%;
|
||||||
flex : 0 0 auto;
|
flex: 0 0 auto;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,7 +329,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// screen width is less than 768px
|
// screen width is less than 768px
|
||||||
@media (max-width: 1100px) {
|
@media (max-width: 1100px) {
|
||||||
#app.twopanel .app-chrome:not(.chrome-bottom) .app-chrome--center {
|
#app.twopanel .app-chrome:not(.chrome-bottom) .app-chrome--center {
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
.md-btn {
|
.md-btn {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
@ -115,7 +114,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.md-close-btn {
|
.md-close-btn {
|
||||||
-webkit-mask-image: url("ameres://icons/webui/close.svg");
|
-webkit-mask-image: url("ameres://icons/webui/close.svg");
|
||||||
-webkit-mask-repeat: no-repeat;
|
-webkit-mask-repeat: no-repeat;
|
||||||
|
@ -165,7 +163,7 @@
|
||||||
.page-btn {
|
.page-btn {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width:max-content;
|
width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-btn img {
|
.page-btn img {
|
||||||
|
@ -174,19 +172,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-ico-first {
|
.md-ico-first {
|
||||||
content: url('./assets/angles-left.svg');
|
content: url("./assets/angles-left.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-ico-prev {
|
.md-ico-prev {
|
||||||
content: url('./assets/chevron-left.svg');
|
content: url("./assets/chevron-left.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-ico-next {
|
.md-ico-next {
|
||||||
content: url('./assets/chevron-right.svg');
|
content: url("./assets/chevron-right.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-ico-last {
|
.md-ico-last {
|
||||||
content: url('./assets/angles-right.svg');
|
content: url("./assets/angles-right.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.reload-btn {
|
.reload-btn {
|
||||||
|
@ -234,7 +232,7 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: rgb(200 200 200 / 10%)
|
background: rgb(200 200 200 / 10%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +313,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#artworkLCD img {
|
#artworkLCD img {
|
||||||
image-rendering: auto;
|
image-rendering: auto;
|
||||||
}
|
}
|
||||||
|
@ -514,7 +511,7 @@
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
font-size: .8em;
|
font-size: 0.8em;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,39 +567,39 @@
|
||||||
*/
|
*/
|
||||||
@keyframes load-bar {
|
@keyframes load-bar {
|
||||||
10% {
|
10% {
|
||||||
box-shadow: inset 0 -4px 0
|
box-shadow: inset 0 -4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
20% {
|
20% {
|
||||||
box-shadow: inset 0 -10px 0
|
box-shadow: inset 0 -10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
30% {
|
30% {
|
||||||
box-shadow: inset 0 -12px 0
|
box-shadow: inset 0 -12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
40% {
|
40% {
|
||||||
box-shadow: inset 0 -8px 0
|
box-shadow: inset 0 -8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
box-shadow: inset 0 -4px 0
|
box-shadow: inset 0 -4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
60% {
|
60% {
|
||||||
box-shadow: inset 0 -6px 0
|
box-shadow: inset 0 -6px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
80% {
|
80% {
|
||||||
box-shadow: inset 0 -12px 0
|
box-shadow: inset 0 -12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
90% {
|
90% {
|
||||||
box-shadow: inset 0 -6px 0
|
box-shadow: inset 0 -6px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
box-shadow: inset 0 -2px 0
|
box-shadow: inset 0 -2px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,17 +626,17 @@
|
||||||
.loadbar-sound::before {
|
.loadbar-sound::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loadbar-sound::before {
|
.loadbar-sound::before {
|
||||||
left: -4.5px;
|
left: -4.5px;
|
||||||
animation-delay: -2.4s
|
animation-delay: -2.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loadbar-sound::after {
|
.loadbar-sound::after {
|
||||||
right: -4.2px;
|
right: -4.2px;
|
||||||
animation-delay: -3.7s
|
animation-delay: -3.7s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.isLibrary {
|
.isLibrary {
|
||||||
|
@ -670,7 +667,6 @@
|
||||||
box-shadow: var(--mediaItemShadow);
|
box-shadow: var(--mediaItemShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background: var(--selected-click);
|
background: var(--selected-click);
|
||||||
box-shadow: var(--mediaItemShadow);
|
box-shadow: var(--mediaItemShadow);
|
||||||
|
@ -805,7 +801,6 @@
|
||||||
|
|
||||||
&:hover + .cd-mediaitem-square-large-overlay {
|
&:hover + .cd-mediaitem-square-large-overlay {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -813,7 +808,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* mediaitem-square-large */
|
/* mediaitem-square-large */
|
||||||
.cd-mediaitem-square-large {
|
.cd-mediaitem-square-large {
|
||||||
width: 190px;
|
width: 190px;
|
||||||
|
@ -855,12 +849,10 @@
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square-large-overlay > * {
|
.cd-mediaitem-square-large-overlay > * {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square-large > .cd-mediaitem-square-large-overlay {
|
.cd-mediaitem-square-large > .cd-mediaitem-square-large-overlay {
|
||||||
|
@ -873,15 +865,12 @@
|
||||||
|
|
||||||
.cd-mediaitem-square-large + .cd-mediaitem-square-large-overlay {
|
.cd-mediaitem-square-large + .cd-mediaitem-square-large-overlay {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square-large:hover + .cd-mediaitem-square-large-overlay {
|
.cd-mediaitem-square-large:hover + .cd-mediaitem-square-large-overlay {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.cd-mediaitem-square-large .artwork.round {
|
.cd-mediaitem-square-large .artwork.round {
|
||||||
border-radius: var(--mediaItemRadiusRound);
|
border-radius: var(--mediaItemRadiusRound);
|
||||||
}
|
}
|
||||||
|
@ -940,12 +929,10 @@
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-mvview-overlay > * {
|
.cd-mediaitem-mvview-overlay > * {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-mvview > .cd-mediaitem-mvview-overlay {
|
.cd-mediaitem-mvview > .cd-mediaitem-mvview-overlay {
|
||||||
|
@ -958,15 +945,12 @@
|
||||||
|
|
||||||
.cd-mediaitem-mvview + .cd-mediaitem-mvview-overlay {
|
.cd-mediaitem-mvview + .cd-mediaitem-mvview-overlay {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-mvview:hover + .cd-mediaitem-mvview-overlay {
|
.cd-mediaitem-mvview:hover + .cd-mediaitem-mvview-overlay {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.cd-mediaitem-mvview .artwork.round {
|
.cd-mediaitem-mvview .artwork.round {
|
||||||
border-radius: var(--mediaItemRadiusRound);
|
border-radius: var(--mediaItemRadiusRound);
|
||||||
}
|
}
|
||||||
|
@ -982,10 +966,9 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* mediaitem-square */
|
/* mediaitem-square */
|
||||||
.cd-mediaitem-square {
|
.cd-mediaitem-square {
|
||||||
--transitionDuration: .5s;
|
--transitionDuration: 0.5s;
|
||||||
--scaleRate: 1.25;
|
--scaleRate: 1.25;
|
||||||
--scaleRateArtwork: 1;
|
--scaleRateArtwork: 1;
|
||||||
width: calc(160px * var(--windowRelativeScale));
|
width: calc(160px * var(--windowRelativeScale));
|
||||||
|
@ -1062,7 +1045,6 @@
|
||||||
bottom: 14px;
|
bottom: 14px;
|
||||||
left: 14px;
|
left: 14px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .menu-btn {
|
> .menu-btn {
|
||||||
|
@ -1110,7 +1092,6 @@
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
.info-rect {
|
.info-rect {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -1119,7 +1100,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -1338,7 +1318,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.artwork{
|
.artwork {
|
||||||
filter: brightness(0.8);
|
filter: brightness(0.8);
|
||||||
}
|
}
|
||||||
.info-rect-card::before {
|
.info-rect-card::before {
|
||||||
|
@ -1430,7 +1410,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
||||||
> .play-btn,
|
> .play-btn,
|
||||||
> .menu-btn {
|
> .menu-btn {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
@ -1438,7 +1417,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -1471,7 +1449,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.listitem-horizontal {
|
.listitem-horizontal {
|
||||||
.cd-mediaitem-list-item {
|
.cd-mediaitem-list-item {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
|
@ -1497,7 +1474,6 @@
|
||||||
|
|
||||||
&:hover::-webkit-scrollbar {
|
&:hover::-webkit-scrollbar {
|
||||||
display: initial;
|
display: initial;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1536,9 +1512,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Switch Checkbox */
|
/* Switch Checkbox */
|
||||||
input[type=checkbox][switch] {
|
input[type="checkbox"][switch] {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
|
@ -1554,12 +1529,12 @@ input[type=checkbox][switch] {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]:focus,
|
input[type="checkbox"][switch]:focus,
|
||||||
input[type=checkbox][switch]:active {
|
input[type="checkbox"][switch]:active {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]:checked {
|
input[type="checkbox"][switch]:checked {
|
||||||
background: var(--keyColor);
|
background: var(--keyColor);
|
||||||
border: 0 solid var(--keyColor);
|
border: 0 solid var(--keyColor);
|
||||||
mix-blend-mode: unset;
|
mix-blend-mode: unset;
|
||||||
|
@ -1573,43 +1548,41 @@ input[type=checkbox][switch]:checked {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]::before {
|
input[type="checkbox"][switch]::before {
|
||||||
background: white;
|
background: white;
|
||||||
width: 26px;
|
width: 26px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: -1px;
|
left: -1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: ' ';
|
content: " ";
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
transition: .10s left var(--appleEase);
|
transition: 0.1s left var(--appleEase);
|
||||||
transform: scale(.75);
|
transform: scale(0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"][switch]:checked::before {
|
||||||
input[type=checkbox][switch]:checked::before {
|
|
||||||
background: white;
|
background: white;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
left: 13px;
|
left: 13px;
|
||||||
transition: .10s left var(--appleEase);
|
transition: 0.1s left var(--appleEase);
|
||||||
transform: scale(.75);
|
transform: scale(0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]:disabled::before {
|
input[type="checkbox"][switch]:disabled::before {
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]:active::before {
|
input[type="checkbox"][switch]:active::before {
|
||||||
left: 13px;
|
left: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=checkbox][switch]:checked:active::before {
|
input[type="checkbox"][switch]:checked:active::before {
|
||||||
left: -1px;
|
left: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End Switch Checkbox */
|
/* End Switch Checkbox */
|
||||||
|
|
||||||
|
|
||||||
.header-text {
|
.header-text {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
@ -1649,7 +1622,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
|
|
||||||
.media-item--small .text {
|
.media-item--small .text {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 0.90em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-item--small .subtext {
|
.media-item--small .subtext {
|
||||||
|
@ -1684,11 +1657,11 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: inset 0px 0px 0px 1px rgb(200 200 200 / 16%), 0 8px 40px rgb(0 0 0 / 0.55);
|
box-shadow: inset 0px 0px 0px 1px rgb(200 200 200 / 16%), 0 8px 40px rgb(0 0 0 / 0.55);
|
||||||
transition: transform .10s var(--appleEase);
|
transition: transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-artwork.paused {
|
.media-artwork.paused {
|
||||||
transition: transform .35s var(--appleEase);
|
transition: transform 0.35s var(--appleEase);
|
||||||
transform: scale(0.85);
|
transform: scale(0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1727,7 +1700,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
background-size: 12px;
|
background-size: 12px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
opacity: 0.70;
|
opacity: 0.7;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -1745,7 +1718,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -1768,7 +1741,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
box-shadow: unset;
|
box-shadow: unset;
|
||||||
opacity: 0.70;
|
opacity: 0.7;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
@ -1785,7 +1758,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -1845,7 +1818,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button.stop {
|
.playback-button.stop {
|
||||||
background-image: url('./assets/cider-icons/stop.svg');
|
background-image: url("./assets/cider-icons/stop.svg");
|
||||||
background-size: 38px;
|
background-size: 38px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
@ -1863,25 +1836,25 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button.pause {
|
.playback-button.pause {
|
||||||
background-image: url('./assets/cider-icons/pause.svg');
|
background-image: url("./assets/cider-icons/pause.svg");
|
||||||
background-size: 38px;
|
background-size: 38px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button.play {
|
.playback-button.play {
|
||||||
background-image: url('./assets/cider-icons/play.svg');
|
background-image: url("./assets/cider-icons/play.svg");
|
||||||
background-size: 38px;
|
background-size: 38px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button.next {
|
.playback-button.next {
|
||||||
background-image: url('./assets/cider-icons/forward.svg');
|
background-image: url("./assets/cider-icons/forward.svg");
|
||||||
background-size: 60%;
|
background-size: 60%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button.previous {
|
.playback-button.previous {
|
||||||
background-image: url('./assets/cider-icons/backward.svg');
|
background-image: url("./assets/cider-icons/backward.svg");
|
||||||
background-size: 60%;
|
background-size: 60%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
@ -1950,7 +1923,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-song-artist {
|
.player-song-artist {
|
||||||
font-size: 1.0em;
|
font-size: 1em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
color: var(--keyColor);
|
color: var(--keyColor);
|
||||||
|
@ -1999,10 +1972,8 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.list-entry-header {
|
.list-entry-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -2206,7 +2177,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
transition: transform .3s var(--appleEase);
|
transition: transform 0.3s var(--appleEase);
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -2216,7 +2187,6 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin: 0px 4px;
|
margin: 0px 4px;
|
||||||
|
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
--dist: 1px;
|
--dist: 1px;
|
||||||
content: "";
|
content: "";
|
||||||
|
@ -2231,10 +2201,9 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: background-color .5s var(--appleEase), opacity 0.25s var(--appleEase), border-radius .32s var(--appleEase);
|
transition: background-color 0.5s var(--appleEase), opacity 0.25s var(--appleEase), border-radius 0.32s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
outline: none;
|
outline: none;
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
|
@ -2245,10 +2214,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
&:after {
|
&:after {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
transition: background-color .25s var(--appleEase),
|
transition: background-color 0.25s var(--appleEase), border-radius 0.25s var(--appleEase), color 0s var(--appleEase), opacity 0s var(--appleEase);
|
||||||
border-radius .25s var(--appleEase),
|
|
||||||
color .0s var(--appleEase),
|
|
||||||
opacity 0.0s var(--appleEase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2265,17 +2231,15 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.nav-link.active {
|
.nav-link.active {
|
||||||
outline: none;
|
outline: none;
|
||||||
transform: scale(1.0);
|
transform: scale(1);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
transform: scale(1.0);
|
transform: scale(1);
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
background: rgb(200 200 200 / 15%);
|
background: rgb(200 200 200 / 15%);
|
||||||
|
@ -2300,7 +2264,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -2399,8 +2363,7 @@ input[type=checkbox][switch]:checked:active::before {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
.md-input-number{
|
.md-input-number {
|
||||||
min-width: 12em;
|
min-width: 12em;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,14 +22,13 @@
|
||||||
--chromeHeight1: 70px;
|
--chromeHeight1: 70px;
|
||||||
|
|
||||||
.app-content-container {
|
.app-content-container {
|
||||||
width:100%;
|
width: 100%;
|
||||||
height:100%;
|
height: 100%;
|
||||||
#app-content {
|
#app-content {
|
||||||
width:100%;
|
width: 100%;
|
||||||
height:100%;
|
height: 100%;
|
||||||
|
|
||||||
.fs-search {
|
.fs-search {
|
||||||
|
|
||||||
.search-input--icon {
|
.search-input--icon {
|
||||||
width: 4em;
|
width: 4em;
|
||||||
background-size: 40%;
|
background-size: 40%;
|
||||||
|
@ -38,7 +37,7 @@
|
||||||
input {
|
input {
|
||||||
padding-left: 2em;
|
padding-left: 2em;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
border-radius: var(--mediaItemRadius)
|
border-radius: var(--mediaItemRadius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,42 +55,41 @@
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|
||||||
.top-nav-group {
|
.top-nav-group {
|
||||||
background : #1e1e1e99;
|
background: #1e1e1e99;
|
||||||
border : 1px solid lighten(@baseColor, 8);
|
border: 1px solid lighten(@baseColor, 8);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
display : flex;
|
display: flex;
|
||||||
height : 55px;
|
height: 55px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
backdrop-filter: var(--glassFilter);
|
backdrop-filter: var(--glassFilter);
|
||||||
|
|
||||||
|
|
||||||
.app-sidebar-item {
|
.app-sidebar-item {
|
||||||
background-color: #1e1e1e00;
|
background-color: #1e1e1e00;
|
||||||
border-radius : 10px !important;
|
border-radius: 10px !important;
|
||||||
border : 0px;
|
border: 0px;
|
||||||
min-width : 120px;
|
min-width: 120px;
|
||||||
padding : 6px;
|
padding: 6px;
|
||||||
justify-content : center;
|
justify-content: center;
|
||||||
align-items : center;
|
align-items: center;
|
||||||
margin : 0px;
|
margin: 0px;
|
||||||
height : 100%;
|
height: 100%;
|
||||||
position : relative;
|
position: relative;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
--dist : 1px;
|
--dist: 1px;
|
||||||
content : '';
|
content: "";
|
||||||
position : absolute;
|
position: absolute;
|
||||||
top : var(--dist);
|
top: var(--dist);
|
||||||
left : var(--dist);
|
left: var(--dist);
|
||||||
right : var(--dist);
|
right: var(--dist);
|
||||||
bottom : var(--dist);
|
bottom: var(--dist);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
border-radius : 10px;
|
border-radius: 10px;
|
||||||
transform : scale(0.5);
|
transform: scale(0.5);
|
||||||
transition : transform 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
transition: transform 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
|
@ -103,8 +101,8 @@
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
|
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
|
||||||
opacity : .1;
|
opacity: 0.1;
|
||||||
transform : scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,15 +110,15 @@
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
opacity : .2;
|
opacity: 0.2;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.md-btn-primary {
|
&.md-btn-primary {
|
||||||
box-shadow : 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8);
|
box-shadow: 0px 0px 0px 1px lighten(@baseColor, @colorMixRate * 8);
|
||||||
background-color: lighten(@baseColor, @colorMixRate * 5);
|
background-color: lighten(@baseColor, @colorMixRate * 5);
|
||||||
z-index : 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +162,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volume-button--small {
|
.volume-button--small {
|
||||||
|
@ -178,7 +176,7 @@
|
||||||
width: 30px;
|
width: 30px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
box-shadow: unset;
|
box-shadow: unset;
|
||||||
opacity: 0.70;
|
opacity: 0.7;
|
||||||
background-image: url("./assets/feather/volume-2.svg");
|
background-image: url("./assets/feather/volume-2.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +188,7 @@
|
||||||
background-image: url("./assets/feather/volume.svg");
|
background-image: url("./assets/feather/volume.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: rgba(255, 255, 255, 0.4);
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
@ -228,7 +226,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
@ -247,13 +244,10 @@
|
||||||
.bg-artwork-container .bg-artwork {
|
.bg-artwork-container .bg-artwork {
|
||||||
filter: brightness(85%) saturate(95%) blur(180px) contrast(0.9) opacity(0.9);
|
filter: brightness(85%) saturate(95%) blur(180px) contrast(0.9) opacity(0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.lyrics-col {
|
.lyrics-col {
|
||||||
|
|
||||||
height: 62vh;
|
height: 62vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -278,11 +272,9 @@
|
||||||
.lyric-line {
|
.lyric-line {
|
||||||
font-size: 35px;
|
font-size: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-col {
|
.queue-col {
|
||||||
|
|
||||||
width: 60vh;
|
width: 60vh;
|
||||||
height: 62vh;
|
height: 62vh;
|
||||||
|
|
||||||
|
@ -361,7 +353,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-playback-controls {
|
.app-playback-controls {
|
||||||
.song-artist, .song-name {
|
.song-artist,
|
||||||
|
.song-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
@ -414,8 +407,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-playback-controls .song-progress {
|
.app-playback-controls .song-progress {
|
||||||
|
@ -436,7 +427,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
> input[type=range] {
|
> input[type="range"] {
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
@ -445,7 +436,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
|
@ -462,7 +453,7 @@
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: var(--songProgressColor);
|
background: var(--songProgressColor);
|
||||||
cursor: default;
|
cursor: default;
|
||||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-thumb {
|
&::-moz-range-thumb {
|
||||||
|
@ -482,7 +473,6 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square {
|
.cd-mediaitem-square {
|
||||||
|
@ -556,18 +546,18 @@
|
||||||
.playlist-page .playlist-display {
|
.playlist-page .playlist-display {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
flex:1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.playlistInfo {
|
.playlistInfo {
|
||||||
>.row {
|
> .row {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-controls {
|
.playlist-controls {
|
||||||
div {
|
div {
|
||||||
width:100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-btn {
|
.close-btn {
|
||||||
.menu-panel.menu-header-text.close-btn
|
.menu-panel.menu-header-text.close-btn;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +179,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-btn {
|
.close-btn {
|
||||||
.menu-panel.menu-header-text.close-btn
|
.menu-panel.menu-header-text.close-btn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +293,6 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
|
|
||||||
.menu-option {
|
.menu-option {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -323,7 +321,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.98);
|
transform: scale(0.98);
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
transition: transform .25s ease-out, opacity .25s ease-out;
|
transition: transform 0.25s ease-out, opacity 0.25s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -336,7 +334,7 @@
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
&::before {
|
&::before {
|
||||||
transition: transform .1s ease-in-out, opacity .1s ease-in-out;
|
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(0.98);
|
transform: scale(0.98);
|
||||||
background: var(--selected-click);
|
background: var(--selected-click);
|
||||||
|
@ -372,7 +370,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgb(196, 43, 28)
|
background-color: rgb(196, 43, 28);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,7 +428,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.moreinfo-modal {
|
.moreinfo-modal {
|
||||||
.modal-window {
|
.modal-window {
|
||||||
height: 70%;
|
height: 70%;
|
||||||
|
@ -496,7 +493,8 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.song-artist, .song-album {
|
.song-artist,
|
||||||
|
.song-album {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
|
@ -6,53 +6,53 @@ body[platform="linux"] {
|
||||||
|
|
||||||
.window-controls {
|
.window-controls {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items : center;
|
align-items: center;
|
||||||
padding-right : 6px;
|
padding-right: 6px;
|
||||||
|
|
||||||
>div {
|
> div {
|
||||||
--iconSize: 16px;
|
--iconSize: 16px;
|
||||||
|
|
||||||
&.close,
|
&.close,
|
||||||
&.minmax,
|
&.minmax,
|
||||||
&.minimize,
|
&.minimize,
|
||||||
&.minmax.restore {
|
&.minmax.restore {
|
||||||
background-image: unset!important;
|
background-image: unset !important;
|
||||||
position : relative;
|
position: relative;
|
||||||
display : grid;
|
display: grid;
|
||||||
align-content : center;
|
align-content: center;
|
||||||
text-align : center;
|
text-align: center;
|
||||||
height : 36px!important;
|
height: 36px !important;
|
||||||
width : 36px!important;
|
width: 36px !important;
|
||||||
border-radius : 50px;
|
border-radius: 50px;
|
||||||
transition: background-color .1s ease-in-out;
|
transition: background-color 0.1s ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgb(200 200 200 / 10%)!important;
|
background: rgb(200 200 200 / 10%) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.close::before {
|
&.close::before {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
font-size : var(--iconSize);
|
font-size: var(--iconSize);
|
||||||
content : "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
&.minmax::before {
|
&.minmax::before {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
font-size : var(--iconSize);
|
font-size: var(--iconSize);
|
||||||
content : "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
&.minimize::before {
|
&.minimize::before {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
font-size : var(--iconSize);
|
font-size: var(--iconSize);
|
||||||
content : "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
&.restore::before {
|
&.restore::before {
|
||||||
font-family: "codicon";
|
font-family: "codicon";
|
||||||
font-size : var(--iconSize);
|
font-size: var(--iconSize);
|
||||||
content : "";
|
content: "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ body[platform="darwin"] {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
box-shadow: inset 0px 0px .5px 1px rgb(200 200 200 / 40%);
|
box-shadow: inset 0px 0px 0.5px 1px rgb(200 200 200 / 40%);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
content: " ";
|
content: " ";
|
||||||
z-index: 999999;
|
z-index: 999999;
|
||||||
|
@ -66,8 +66,8 @@ body[platform="darwin"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-window.maxed {
|
.settings-window.maxed {
|
||||||
.tabs>.col-auto {
|
.tabs > .col-auto {
|
||||||
transition: padding-top .3s linear;
|
transition: padding-top 0.3s linear;
|
||||||
padding-top: var(--chromeHeight1);
|
padding-top: var(--chromeHeight1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#app.macosemu {
|
#app.macosemu {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.app-chrome .app-chrome-item > .window-controls-macos {
|
.app-chrome .app-chrome-item > .window-controls-macos {
|
||||||
@controlSize: 12px;
|
@controlSize: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -42,7 +39,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.usermenu-body{
|
.usermenu-body {
|
||||||
left: calc(100vw - 260px);
|
left: calc(100vw - 260px);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volume-button--small {
|
.volume-button--small {
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
width: 30px;
|
width: 30px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
box-shadow: unset;
|
box-shadow: unset;
|
||||||
opacity: 0.70;
|
opacity: 0.7;
|
||||||
background-image: url("./assets/feather/volume-2.svg");
|
background-image: url("./assets/feather/volume-2.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
background-image: url("./assets/feather/volume.svg");
|
background-image: url("./assets/feather/volume.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background: rgba(255, 255, 255, 0.4);
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
@ -129,7 +129,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.background {
|
.background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
@ -157,9 +156,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.lyrics-col {
|
.lyrics-col {
|
||||||
|
|
||||||
height: 62vh;
|
height: 62vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -184,11 +181,9 @@
|
||||||
.lyric-line {
|
.lyric-line {
|
||||||
font-size: 35px;
|
font-size: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.queue-col {
|
.queue-col {
|
||||||
|
|
||||||
width: 60vh;
|
width: 60vh;
|
||||||
height: 50vh;
|
height: 50vh;
|
||||||
|
|
||||||
|
@ -281,11 +276,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.app-playback-controls {
|
.app-playback-controls {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
|
|
||||||
.song-artist, .song-name {
|
.song-artist,
|
||||||
|
.song-name {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
|
@ -338,8 +333,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-playback-controls .song-progress {
|
.app-playback-controls .song-progress {
|
||||||
|
@ -360,7 +353,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
> input[type=range] {
|
> input[type="range"] {
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
|
@ -369,7 +362,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type="range"] {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
|
@ -386,7 +379,7 @@
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background: var(--songProgressColor);
|
background: var(--songProgressColor);
|
||||||
cursor: default;
|
cursor: default;
|
||||||
transition: opacity .10s var(--appleEase), transform .10s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase), transform 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-thumb {
|
&::-moz-range-thumb {
|
||||||
|
@ -405,6 +398,5 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,116 +1,116 @@
|
||||||
@-webkit-keyframes notyf-fadeinup {
|
@-webkit-keyframes notyf-fadeinup {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(25%)
|
transform: translateY(25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0)
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes notyf-fadeinup {
|
@keyframes notyf-fadeinup {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(25%)
|
transform: translateY(25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0)
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes notyf-fadeinleft {
|
@-webkit-keyframes notyf-fadeinleft {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(25%)
|
transform: translateX(25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0)
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes notyf-fadeinleft {
|
@keyframes notyf-fadeinleft {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(25%)
|
transform: translateX(25%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0)
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes notyf-fadeoutright {
|
@-webkit-keyframes notyf-fadeoutright {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0)
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(25%)
|
transform: translateX(25%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes notyf-fadeoutright {
|
@keyframes notyf-fadeoutright {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0)
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(25%)
|
transform: translateX(25%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes notyf-fadeoutdown {
|
@-webkit-keyframes notyf-fadeoutdown {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0)
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(25%)
|
transform: translateY(25%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes notyf-fadeoutdown {
|
@keyframes notyf-fadeoutdown {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0)
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(25%)
|
transform: translateY(25%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes ripple {
|
@-webkit-keyframes ripple {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(0) translateY(-45%) translateX(13%)
|
transform: scale(0) translateY(-45%) translateX(13%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
transform: scale(1) translateY(-45%) translateX(13%)
|
transform: scale(1) translateY(-45%) translateX(13%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes ripple {
|
@keyframes ripple {
|
||||||
0% {
|
0% {
|
||||||
transform: scale(0) translateY(-45%) translateX(13%)
|
transform: scale(0) translateY(-45%) translateX(13%);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
transform: scale(1) translateY(-45%) translateX(13%)
|
transform: scale(1) translateY(-45%) translateX(13%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 20px
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--error,
|
.notyf__icon--error,
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--error:after,
|
.notyf__icon--error:after,
|
||||||
|
@ -152,15 +152,15 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
left: 9px;
|
left: 9px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
top: 5px
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--error:after {
|
.notyf__icon--error:after {
|
||||||
transform: rotate(-45deg)
|
transform: rotate(-45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--error:before {
|
.notyf__icon--error:before {
|
||||||
transform: rotate(45deg)
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--success:after,
|
.notyf__icon--success:after,
|
||||||
|
@ -170,77 +170,77 @@
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 3px;
|
width: 3px;
|
||||||
border-radius: 3px
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--success:after {
|
.notyf__icon--success:after {
|
||||||
height: 6px;
|
height: 6px;
|
||||||
transform: rotate(-45deg);
|
transform: rotate(-45deg);
|
||||||
top: 9px;
|
top: 9px;
|
||||||
left: 6px
|
left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon--success:before {
|
.notyf__icon--success:before {
|
||||||
height: 11px;
|
height: 11px;
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
top: 5px;
|
top: 5px;
|
||||||
left: 10px
|
left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast {
|
.notyf__toast {
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
-webkit-animation: notyf-fadeinup .3s ease-in forwards;
|
-webkit-animation: notyf-fadeinup 0.3s ease-in forwards;
|
||||||
animation: notyf-fadeinup .3s ease-in forwards;
|
animation: notyf-fadeinup 0.3s ease-in forwards;
|
||||||
box-shadow: 0 3px 7px 0 rgba(0, 0, 0, .25);
|
box-shadow: 0 3px 7px 0 rgba(0, 0, 0, 0.25);
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
transform: translateY(25%);
|
transform: translateY(25%);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex-shrink: 0
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--disappear {
|
.notyf__toast--disappear {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
-webkit-animation: notyf-fadeoutdown .3s forwards;
|
-webkit-animation: notyf-fadeoutdown 0.3s forwards;
|
||||||
animation: notyf-fadeoutdown .3s forwards;
|
animation: notyf-fadeoutdown 0.3s forwards;
|
||||||
-webkit-animation-delay: .25s;
|
-webkit-animation-delay: 0.25s;
|
||||||
animation-delay: .25s
|
animation-delay: 0.25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--disappear .notyf__icon,
|
.notyf__toast--disappear .notyf__icon,
|
||||||
.notyf__toast--disappear .notyf__message {
|
.notyf__toast--disappear .notyf__message {
|
||||||
-webkit-animation: notyf-fadeoutdown .3s forwards;
|
-webkit-animation: notyf-fadeoutdown 0.3s forwards;
|
||||||
animation: notyf-fadeoutdown .3s forwards;
|
animation: notyf-fadeoutdown 0.3s forwards;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0)
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--disappear .notyf__dismiss {
|
.notyf__toast--disappear .notyf__dismiss {
|
||||||
-webkit-animation: notyf-fadeoutright .3s forwards;
|
-webkit-animation: notyf-fadeoutright 0.3s forwards;
|
||||||
animation: notyf-fadeoutright .3s forwards;
|
animation: notyf-fadeoutright 0.3s forwards;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateX(0)
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--disappear .notyf__message {
|
.notyf__toast--disappear .notyf__message {
|
||||||
-webkit-animation-delay: .05s;
|
-webkit-animation-delay: 0.05s;
|
||||||
animation-delay: .05s
|
animation-delay: 0.05s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--upper {
|
.notyf__toast--upper {
|
||||||
margin-bottom: 20px
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--lower {
|
.notyf__toast--lower {
|
||||||
margin-top: 20px
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast--dismissible .notyf__wrapper {
|
.notyf__toast--dismissible .notyf__wrapper {
|
||||||
padding-right: 30px
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__ripple {
|
.notyf__ripple {
|
||||||
|
@ -253,8 +253,8 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transform: scale(0) translateY(-51%) translateX(13%);
|
transform: scale(0) translateY(-51%) translateX(13%);
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
-webkit-animation: ripple .4s ease-out forwards;
|
-webkit-animation: ripple 0.4s ease-out forwards;
|
||||||
animation: ripple .4s ease-out forwards
|
animation: ripple 0.4s ease-out forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__wrapper {
|
.notyf__wrapper {
|
||||||
|
@ -265,7 +265,7 @@
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 10
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__icon {
|
.notyf__icon {
|
||||||
|
@ -273,11 +273,11 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
-webkit-animation: notyf-fadeinup .3s forwards;
|
-webkit-animation: notyf-fadeinup 0.3s forwards;
|
||||||
animation: notyf-fadeinup .3s forwards;
|
animation: notyf-fadeinup 0.3s forwards;
|
||||||
-webkit-animation-delay: .3s;
|
-webkit-animation-delay: 0.3s;
|
||||||
animation-delay: .3s;
|
animation-delay: 0.3s;
|
||||||
margin-right: 13px
|
margin-right: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss {
|
.notyf__dismiss {
|
||||||
|
@ -287,22 +287,22 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 26px;
|
width: 26px;
|
||||||
margin-right: -15px;
|
margin-right: -15px;
|
||||||
-webkit-animation: notyf-fadeinleft .3s forwards;
|
-webkit-animation: notyf-fadeinleft 0.3s forwards;
|
||||||
animation: notyf-fadeinleft .3s forwards;
|
animation: notyf-fadeinleft 0.3s forwards;
|
||||||
-webkit-animation-delay: .35s;
|
-webkit-animation-delay: 0.35s;
|
||||||
animation-delay: .35s;
|
animation-delay: 0.35s;
|
||||||
opacity: 0
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn {
|
.notyf__dismiss-btn {
|
||||||
background-color: rgba(0, 0, 0, .25);
|
background-color: rgba(0, 0, 0, 0.25);
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: opacity .2s ease, background-color .2s ease;
|
transition: opacity 0.2s ease, background-color 0.2s ease;
|
||||||
outline: none;
|
outline: none;
|
||||||
opacity: .35;
|
opacity: 0.35;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn:after,
|
.notyf__dismiss-btn:after,
|
||||||
|
@ -314,57 +314,57 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: calc(50% - 1px);
|
left: calc(50% - 1px);
|
||||||
top: calc(50% - 5px)
|
top: calc(50% - 5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn:after {
|
.notyf__dismiss-btn:after {
|
||||||
transform: rotate(-45deg)
|
transform: rotate(-45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn:before {
|
.notyf__dismiss-btn:before {
|
||||||
transform: rotate(45deg)
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn:hover {
|
.notyf__dismiss-btn:hover {
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
background-color: rgba(0, 0, 0, .15)
|
background-color: rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss-btn:active {
|
.notyf__dismiss-btn:active {
|
||||||
opacity: .8
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__message {
|
.notyf__message {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
position: relative;
|
position: relative;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
-webkit-animation: notyf-fadeinup .3s forwards;
|
-webkit-animation: notyf-fadeinup 0.3s forwards;
|
||||||
animation: notyf-fadeinup .3s forwards;
|
animation: notyf-fadeinup 0.3s forwards;
|
||||||
-webkit-animation-delay: .25s;
|
-webkit-animation-delay: 0.25s;
|
||||||
animation-delay: .25s;
|
animation-delay: 0.25s;
|
||||||
line-height: 1.5em
|
line-height: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width:480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
.notyf {
|
.notyf {
|
||||||
padding: 0
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__ripple {
|
.notyf__ripple {
|
||||||
height: 600px;
|
height: 600px;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
-webkit-animation-duration: .5s;
|
-webkit-animation-duration: 0.5s;
|
||||||
animation-duration: .5s
|
animation-duration: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__toast {
|
.notyf__toast {
|
||||||
max-width: none;
|
max-width: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: 0 -2px 7px 0 rgba(0, 0, 0, .13);
|
box-shadow: 0 -2px 7px 0 rgba(0, 0, 0, 0.13);
|
||||||
width: 100%
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notyf__dismiss {
|
.notyf__dismiss {
|
||||||
width: 56px
|
width: 56px;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1277,7 +1277,7 @@
|
||||||
}
|
}
|
||||||
.audiolabs-page .spprofile-line .spprofile-viewport .spprev:before,
|
.audiolabs-page .spprofile-line .spprofile-viewport .spprev:before,
|
||||||
.audiolabs-page .spprofile-line .spprofile-viewport .nextprev:before {
|
.audiolabs-page .spprofile-line .spprofile-viewport .nextprev:before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -1309,7 +1309,7 @@
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
.audiolabs-page .spprofile-line .spprofile-viewport .spslide > img {
|
.audiolabs-page .spprofile-line .spprofile-viewport .spslide > img {
|
||||||
WIDTH: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-group-item {
|
.list-group-item {
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: grab;
|
cursor: grab;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +293,6 @@
|
||||||
|
|
||||||
// Search Page
|
// Search Page
|
||||||
&.search-page {
|
&.search-page {
|
||||||
|
|
||||||
.searchToggle {
|
.searchToggle {
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
|
@ -302,7 +300,7 @@
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.categories{
|
.categories {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(200px, 1fr));
|
grid-template-columns: repeat(3, minmax(200px, 1fr));
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
@ -316,7 +314,7 @@
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.info-rect{
|
.info-rect {
|
||||||
height: max-content;
|
height: max-content;
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
|
@ -452,7 +450,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgb(196, 43, 28)
|
background-color: rgb(196, 43, 28);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,10 +486,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
line-break: anywhere;
|
line-break: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Podcast Page
|
// Podcast Page
|
||||||
|
@ -622,7 +617,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgb(196, 43, 28)
|
background-color: rgb(196, 43, 28);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,10 +652,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
line-break: anywhere;
|
line-break: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 1230px) {
|
@media only screen and (max-width: 1230px) {
|
||||||
|
@ -828,7 +820,7 @@
|
||||||
margin-bottom: -10px;
|
margin-bottom: -10px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
-webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%);
|
-webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%);
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
animation: playlistArtworkFadeIn 1s var(--appleEase);
|
animation: playlistArtworkFadeIn 1s var(--appleEase);
|
||||||
|
|
||||||
.artworkMaterial img {
|
.artworkMaterial img {
|
||||||
|
@ -898,7 +890,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input::placeholder {
|
.search-input::placeholder {
|
||||||
color: var(--heroplaceholdercolor)
|
color: var(--heroplaceholdercolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nameEdit {
|
.nameEdit {
|
||||||
|
@ -939,7 +931,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-desc {
|
.playlist-desc {
|
||||||
transition: height .2s ease-in-out, opacity .2s ease-in-out;
|
transition: height 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
flex-shrink: unset;
|
flex-shrink: unset;
|
||||||
|
@ -1043,8 +1035,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.friends-info {
|
.friends-info {
|
||||||
|
@ -1061,7 +1051,7 @@
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: var(--mediaItemShadow-ShadowSubtle);
|
box-shadow: var(--mediaItemShadow-ShadowSubtle);
|
||||||
transition: transform .2s var(--appleEase);
|
transition: transform 0.2s var(--appleEase);
|
||||||
margin: 6px;
|
margin: 6px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -1081,7 +1071,7 @@
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin: 6px;
|
margin: 6px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: height .2s ease-in-out, opacity .2s ease-in-out;
|
transition: height 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
height: 0.9em;
|
height: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,13 +1141,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-time {
|
.playlist-time {
|
||||||
transition: height .2s ease-in-out, opacity .2s ease-in-out;
|
transition: height 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
height: 0px;
|
height: 0px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playlist-desc {
|
.playlist-desc {
|
||||||
transition: height .2s ease-in-out, opacity .2s ease-in-out;
|
transition: height 0.2s ease-in-out, opacity 0.2s ease-in-out;
|
||||||
height: 0px !important;
|
height: 0px !important;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
@ -1272,7 +1262,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.artworkContainer {
|
.artworkContainer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -1282,7 +1271,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
-webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%);
|
-webkit-mask-image: radial-gradient(at top left, black, transparent 70%), radial-gradient(at top right, black, transparent 70%), linear-gradient(180deg, rgb(200 200 200), transparent 98%);
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
animation: playlistArtworkFadeIn 1s var(--appleEase);
|
animation: playlistArtworkFadeIn 1s var(--appleEase);
|
||||||
|
|
||||||
.artworkMaterial img {
|
.artworkMaterial img {
|
||||||
|
@ -1412,7 +1401,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.artist-title {
|
.artist-title {
|
||||||
|
|
||||||
.artist-play {
|
.artist-play {
|
||||||
transform: translateY(3px);
|
transform: translateY(3px);
|
||||||
margin: 14px;
|
margin: 14px;
|
||||||
|
@ -1490,7 +1478,6 @@
|
||||||
width: 90%;
|
width: 90%;
|
||||||
margin: 16px auto 0px;
|
margin: 16px auto 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AudioLabs page
|
// AudioLabs page
|
||||||
|
@ -1502,7 +1489,7 @@
|
||||||
border-bottom: unset;
|
border-bottom: unset;
|
||||||
border-top: unset;
|
border-top: unset;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 1.0em;
|
font-size: 1em;
|
||||||
background: rgb(255 255 255 / 3%);
|
background: rgb(255 255 255 / 3%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,7 +1535,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -1568,7 +1555,6 @@
|
||||||
&:before {
|
&:before {
|
||||||
-webkit-mask-image: url("./views/svg/chevron-left.svg");
|
-webkit-mask-image: url("./views/svg/chevron-left.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nextprev {
|
.nextprev {
|
||||||
|
@ -1577,7 +1563,6 @@
|
||||||
&:before {
|
&:before {
|
||||||
-webkit-mask-image: url("./views/svg/chevron-right.svg");
|
-webkit-mask-image: url("./views/svg/chevron-right.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.spslide {
|
.spslide {
|
||||||
|
@ -1588,7 +1573,7 @@
|
||||||
background: black;
|
background: black;
|
||||||
|
|
||||||
> img {
|
> img {
|
||||||
WIDTH: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
@ -1646,7 +1631,6 @@
|
||||||
|
|
||||||
//Home
|
//Home
|
||||||
.home-page {
|
.home-page {
|
||||||
|
|
||||||
.md-btn-replay {
|
.md-btn-replay {
|
||||||
background-image: linear-gradient(-45deg, #2e2173, #925042);
|
background-image: linear-gradient(-45deg, #2e2173, #925042);
|
||||||
animation: gradient-animation 5s ease-in-out infinite;
|
animation: gradient-animation 5s ease-in-out infinite;
|
||||||
|
@ -1738,8 +1722,8 @@
|
||||||
border-radius: var(--mediaItemRadius);
|
border-radius: var(--mediaItemRadius);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform .2s var(--appleEase);
|
transition: transform 0.2s var(--appleEase);
|
||||||
transition-delay: .1s;
|
transition-delay: 0.1s;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -1780,7 +1764,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-genres-container {
|
.top-genres-container {
|
||||||
|
|
||||||
.genre-name {
|
.genre-name {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin: 6px 0px;
|
margin: 6px 0px;
|
||||||
|
@ -1810,11 +1793,11 @@
|
||||||
|
|
||||||
.cd-mediaitem-square {
|
.cd-mediaitem-square {
|
||||||
.mediaitem-artwork {
|
.mediaitem-artwork {
|
||||||
animation: replayFadeIn .5s var(--appleEase);
|
animation: replayFadeIn 0.5s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
transition: transform .2s var(--appleEase);
|
transition: transform 0.2s var(--appleEase);
|
||||||
transition-delay: .1s;
|
transition-delay: 0.1s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
|
@ -1883,7 +1866,6 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|
||||||
.oobe-header {
|
.oobe-header {
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
text-shadow: var(--replayTextShadow);
|
text-shadow: var(--replayTextShadow);
|
||||||
|
@ -1927,7 +1909,7 @@
|
||||||
|
|
||||||
.visualPreview {
|
.visualPreview {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: .25s all;
|
transition: 0.25s all;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1954,9 +1936,8 @@
|
||||||
outline: 4px solid var(--keyColor);
|
outline: 4px solid var(--keyColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.10) translateZ(-1px) translateY(10px);
|
transform: scale(1.1) translateZ(-1px) translateY(10px);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
box-shadow: 0px 12px 16px rgb(0 0 0 / 25%);
|
box-shadow: 0px 12px 16px rgb(0 0 0 / 25%);
|
||||||
}
|
}
|
||||||
|
@ -1981,10 +1962,8 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.oobe-titlebar {
|
.oobe-titlebar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -2125,7 +2104,6 @@
|
||||||
|
|
||||||
.nav-pills {
|
.nav-pills {
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-pills .nav-link {
|
.nav-pills .nav-link {
|
||||||
|
@ -2139,7 +2117,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.md-option-header {
|
.md-option-header {
|
||||||
padding: 0px 26px;
|
padding: 0px 26px;
|
||||||
border-bottom: unset;
|
border-bottom: unset;
|
||||||
|
@ -2192,7 +2169,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgb(196, 43, 28)
|
background-color: rgb(196, 43, 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.back-btn {
|
&.back-btn {
|
||||||
|
@ -2241,35 +2218,36 @@
|
||||||
overflow-y: overlay;
|
overflow-y: overlay;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--panelColor2);
|
background-color: var(--panelColor2);
|
||||||
padding:0px;
|
padding: 0px;
|
||||||
padding-top: 48px;
|
padding-top: 48px;
|
||||||
border-left: 1px solid var(--borderColor);
|
border-left: 1px solid var(--borderColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.github-themes-page, .installed-themes-page {
|
.github-themes-page,
|
||||||
|
.installed-themes-page {
|
||||||
.header-text {
|
.header-text {
|
||||||
font-size: 1.25em;
|
font-size: 1.25em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pane {
|
.tab-pane {
|
||||||
height:100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-tab-content {
|
.settings-tab-content {
|
||||||
height:100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.no-sidebar {
|
&.no-sidebar {
|
||||||
.gh-header {
|
.gh-header {
|
||||||
>.row {
|
> .row {
|
||||||
&:last-child {
|
&:last-child {
|
||||||
padding-right: 90px;
|
padding-right: 90px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tab-content {
|
.tab-content {
|
||||||
padding-top:0px;
|
padding-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
|
@ -2277,10 +2255,10 @@
|
||||||
width: 50px;
|
width: 50px;
|
||||||
:nth-child(2) {
|
:nth-child(2) {
|
||||||
// font-size: 0px;
|
// font-size: 0px;
|
||||||
opacity:0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
>.col-auto {
|
> .col-auto {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,35 @@
|
||||||
import { app } from "./vueapp.js"
|
import { app } from "./vueapp.js";
|
||||||
import {CiderCache} from './cidercache.js'
|
import { CiderCache } from "./cidercache.js";
|
||||||
import {CiderFrontAPI} from './ciderfrontapi.js'
|
import { CiderFrontAPI } from "./ciderfrontapi.js";
|
||||||
import {simulateGamepad} from './gamepad.js'
|
import { simulateGamepad } from "./gamepad.js";
|
||||||
import {CiderAudio} from '../audio/cideraudio.js'
|
import { CiderAudio } from "../audio/cideraudio.js";
|
||||||
import {Events} from './events.js'
|
import { Events } from "./events.js";
|
||||||
import { wsapi } from "./wsapi_interop.js"
|
import { wsapi } from "./wsapi_interop.js";
|
||||||
import { MusicKitTools } from "./musickittools.js"
|
import { MusicKitTools } from "./musickittools.js";
|
||||||
import { spawnMica } from "./mica.js"
|
import { spawnMica } from "./mica.js";
|
||||||
import { svgIcon } from './components/svg-icon.js'
|
import { svgIcon } from "./components/svg-icon.js";
|
||||||
import { sidebarLibraryItem } from './components/sidebar-library-item.js'
|
import { sidebarLibraryItem } from "./components/sidebar-library-item.js";
|
||||||
|
|
||||||
|
|
||||||
// Define window objects
|
// Define window objects
|
||||||
window.app = app
|
window.app = app;
|
||||||
window.MusicKitTools = MusicKitTools
|
window.MusicKitTools = MusicKitTools;
|
||||||
window.CiderAudio = CiderAudio
|
window.CiderAudio = CiderAudio;
|
||||||
window.CiderCache = CiderCache
|
window.CiderCache = CiderCache;
|
||||||
window.CiderFrontAPI = CiderFrontAPI
|
window.CiderFrontAPI = CiderFrontAPI;
|
||||||
window.wsapi = wsapi
|
window.wsapi = wsapi;
|
||||||
|
|
||||||
if (app.cfg.advanced.disableLogging === true) {
|
if (app.cfg.advanced.disableLogging === true) {
|
||||||
window.console = {
|
window.console = {
|
||||||
log: function() {},
|
log: function () {},
|
||||||
error: function() {},
|
error: function () {},
|
||||||
warn: function() {},
|
warn: function () {},
|
||||||
assert: function() {},
|
assert: function () {},
|
||||||
debug: function() {}
|
debug: function () {},
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Mount Vue to #app
|
// Mount Vue to #app
|
||||||
app.$mount("#app")
|
app.$mount("#app");
|
||||||
|
|
||||||
// Init CiderAudio and force audiocontext
|
// Init CiderAudio and force audiocontext
|
||||||
if (app.cfg.advanced.AudioContext != true) {
|
if (app.cfg.advanced.AudioContext != true) {
|
||||||
|
@ -39,10 +37,10 @@ if (app.cfg.advanced.AudioContext != true) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
CiderAudio.init()
|
CiderAudio.init();
|
||||||
|
|
||||||
// Import gamepad support
|
// Import gamepad support
|
||||||
app.simulateGamepad = simulateGamepad
|
app.simulateGamepad = simulateGamepad;
|
||||||
app.spawnMica = spawnMica
|
app.spawnMica = spawnMica;
|
||||||
|
|
||||||
Events.InitEvents()
|
Events.InitEvents();
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
const CiderCache = {
|
const CiderCache = {
|
||||||
async getCache(file) {
|
async getCache(file) {
|
||||||
let cache = await ipcRenderer.sendSync("get-cache", file)
|
let cache = await ipcRenderer.sendSync("get-cache", file);
|
||||||
if (isJson(cache)) {
|
if (isJson(cache)) {
|
||||||
cache = JSON.parse(cache)
|
cache = JSON.parse(cache);
|
||||||
if (Object.keys(cache).length === 0) {
|
if (Object.keys(cache).length === 0) {
|
||||||
cache = false
|
cache = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cache = false
|
cache = false;
|
||||||
}
|
}
|
||||||
return cache
|
return cache;
|
||||||
},
|
},
|
||||||
async putCache(file, data) {
|
async putCache(file, data) {
|
||||||
console.log(`Caching ${file}`)
|
console.log(`Caching ${file}`);
|
||||||
ipcRenderer.invoke("put-cache", {
|
ipcRenderer.invoke("put-cache", {
|
||||||
file: file,
|
file: file,
|
||||||
data: JSON.stringify(data)
|
data: JSON.stringify(data),
|
||||||
})
|
});
|
||||||
return true
|
return true;
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export {CiderCache}
|
export { CiderCache };
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
const CiderFrontAPI = {
|
const CiderFrontAPI = {
|
||||||
Objects: {
|
Objects: {
|
||||||
MenuEntry: function () {
|
MenuEntry: function () {
|
||||||
this.id = ""
|
this.id = "";
|
||||||
this.name = ""
|
this.name = "";
|
||||||
this.onClick = () => {
|
this.onClick = () => {};
|
||||||
}
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
AddMenuEntry(entry) {
|
AddMenuEntry(entry) {
|
||||||
app.pluginMenuEntries.push(entry)
|
app.pluginMenuEntries.push(entry);
|
||||||
app.pluginInstalled = true
|
app.pluginInstalled = true;
|
||||||
},
|
},
|
||||||
StyleSheets: {
|
StyleSheets: {
|
||||||
Add(href) {
|
Add(href) {
|
||||||
console.log("Adding stylesheet: " + href)
|
console.log("Adding stylesheet: " + href);
|
||||||
let id = uuidv4()
|
let id = uuidv4();
|
||||||
let link = document.createElement("link")
|
let link = document.createElement("link");
|
||||||
link.rel = "stylesheet/less"
|
link.rel = "stylesheet/less";
|
||||||
link.type = "text/css"
|
link.type = "text/css";
|
||||||
link.href = href
|
link.href = href;
|
||||||
link.setAttribute("css-id", id)
|
link.setAttribute("css-id", id);
|
||||||
// insert the link before document.querySelector("#userTheme") in head
|
// insert the link before document.querySelector("#userTheme") in head
|
||||||
document.querySelector("head").insertBefore(link, document.querySelector("#userTheme"))
|
document.querySelector("head").insertBefore(link, document.querySelector("#userTheme"));
|
||||||
less.registerStylesheetsImmediately()
|
less.registerStylesheetsImmediately();
|
||||||
less.refresh(true, true, true)
|
less.refresh(true, true, true);
|
||||||
return link
|
return link;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export {CiderFrontAPI}
|
export { CiderFrontAPI };
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import {html} from "../html.js"
|
import { html } from "../html.js";
|
||||||
|
|
||||||
export const sidebarLibraryItem = Vue.component("sidebar-library-item", {
|
export const sidebarLibraryItem = Vue.component("sidebar-library-item", {
|
||||||
template: html`
|
template: html`
|
||||||
<button class="app-sidebar-item"
|
<button class="app-sidebar-item" :class="$root.getSidebarItemClass(page)" @click="$root.setWindowHash(page)">
|
||||||
:class="$root.getSidebarItemClass(page)" @click="$root.setWindowHash(page)">
|
<svg-icon :url="svgIconData" :name="'sidebar-' + svgIconName" v-if="svgIconData != ''" />
|
||||||
<svg-icon :url="svgIconData" :name="'sidebar-' + svgIconName" v-if="svgIconData != ''"/>
|
|
||||||
<span class="sidebar-item-text">{{ name }}</span>
|
<span class="sidebar-item-text">{{ name }}</span>
|
||||||
</button>
|
</button>
|
||||||
`,
|
`,
|
||||||
|
@ -24,7 +23,7 @@ export const sidebarLibraryItem = Vue.component("sidebar-library-item", {
|
||||||
},
|
},
|
||||||
svgIconName: {
|
svgIconName: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
cdClick: {
|
cdClick: {
|
||||||
type: Function,
|
type: Function,
|
||||||
|
@ -43,4 +42,4 @@ export const sidebarLibraryItem = Vue.component("sidebar-library-item", {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {},
|
methods: {},
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
import {html} from "../html.js"
|
import { html } from "../html.js";
|
||||||
|
|
||||||
export const svgIcon = Vue.component("svg-icon", {
|
export const svgIcon = Vue.component("svg-icon", {
|
||||||
template: html`
|
template: html` <div class="_svg-icon" :class="classes" :svg-name="name" :style="{'--icon': 'url(' + url + ')'}"></div> `,
|
||||||
<div class="_svg-icon" :class="classes" :svg-name="name" :style="{'--icon': 'url(' + url + ')'}"></div>
|
|
||||||
`,
|
|
||||||
props: {
|
props: {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
classes: {
|
classes: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: "./assets/repeat.svg"
|
default: "./assets/repeat.svg",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,98 +1,94 @@
|
||||||
const Events = {
|
const Events = {
|
||||||
InitEvents() {
|
InitEvents() {
|
||||||
const app = window.app
|
const app = window.app;
|
||||||
|
|
||||||
// add event listener for when window.location.hash changes
|
// add event listener for when window.location.hash changes
|
||||||
window.addEventListener("hashchange", function () {
|
window.addEventListener("hashchange", function () {
|
||||||
app.page = "blank"
|
app.page = "blank";
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
app.appRoute(window.location.hash)
|
app.appRoute(window.location.hash);
|
||||||
}, 100)
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("mouseup", (e) => {
|
window.addEventListener("mouseup", (e) => {
|
||||||
if (e.button === 3) {
|
if (e.button === 3) {
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
app.navigateBack()
|
app.navigateBack();
|
||||||
} else if (e.button === 4) {
|
} else if (e.button === 4) {
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
app.navigateForward()
|
app.navigateForward();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('keydown', async function (event) {
|
document.addEventListener("keydown", async function (event) {
|
||||||
// CTRL + R
|
// CTRL + R
|
||||||
if (event.keyCode === 82 && event.ctrlKey) {
|
if (event.keyCode === 82 && event.ctrlKey) {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
app.confirm(app.getLz('term.reload'), (res)=>{
|
app.confirm(app.getLz("term.reload"), (res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
window.location.reload()
|
window.location.reload();
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
// CTRL + SHIFT + R
|
// CTRL + SHIFT + R
|
||||||
if (event.keyCode === 82 && event.ctrlKey && event.shiftKey) {
|
if (event.keyCode === 82 && event.ctrlKey && event.shiftKey) {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
window.location.reload()
|
window.location.reload();
|
||||||
}
|
}
|
||||||
// CTRL + E
|
// CTRL + E
|
||||||
if (event.keyCode === 69 && event.ctrlKey) {
|
if (event.keyCode === 69 && event.ctrlKey) {
|
||||||
app.invokeDrawer('queue')
|
app.invokeDrawer("queue");
|
||||||
}
|
}
|
||||||
// CTRL+H
|
// CTRL+H
|
||||||
if (event.keyCode === 72 && event.ctrlKey) {
|
if (event.keyCode === 72 && event.ctrlKey) {
|
||||||
app.appRoute("home")
|
app.appRoute("home");
|
||||||
}
|
}
|
||||||
// CTRL+SHIFT+H
|
// CTRL+SHIFT+H
|
||||||
if (event.ctrlKey && event.shiftKey && event.keyCode == 72) {
|
if (event.ctrlKey && event.shiftKey && event.keyCode == 72) {
|
||||||
let hist = await app.mk.api.v3.music(`/v1/me/recent/played/tracks`, {
|
let hist = await app.mk.api.v3.music(`/v1/me/recent/played/tracks`, {
|
||||||
l: app.mklang
|
l: app.mklang,
|
||||||
})
|
});
|
||||||
app.showCollection(hist.data, app.getLz('term.history'))
|
app.showCollection(hist.data, app.getLz("term.history"));
|
||||||
}
|
}
|
||||||
if (event.ctrlKey && event.keyCode == 121) {
|
if (event.ctrlKey && event.keyCode == 121) {
|
||||||
try {
|
try {
|
||||||
app.mk._services.mediaItemPlayback._currentPlayer.stop()
|
app.mk._services.mediaItemPlayback._currentPlayer.stop();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
app.mk._services.mediaItemPlayback._currentPlayer.destroy()
|
app.mk._services.mediaItemPlayback._currentPlayer.destroy();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (event.ctrlKey && event.keyCode == 122) {
|
if (event.ctrlKey && event.keyCode == 122) {
|
||||||
try {
|
try {
|
||||||
ipcRenderer.send('detachDT', '')
|
ipcRenderer.send("detachDT", "");
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Prevent Scrolling on spacebar
|
// Prevent Scrolling on spacebar
|
||||||
if (event.keyCode === 32 && event.target === document.body) {
|
if (event.keyCode === 32 && event.target === document.body) {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
app.SpacePause()
|
app.SpacePause();
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hang Timer
|
// Hang Timer
|
||||||
app.hangtimer = setTimeout(() => {
|
app.hangtimer = setTimeout(() => {
|
||||||
if (confirm("Cider is not responding. Reload the app?")) {
|
if (confirm("Cider is not responding. Reload the app?")) {
|
||||||
window.location.reload()
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}, 10000)
|
}, 10000);
|
||||||
|
|
||||||
// Refresh Focus
|
// Refresh Focus
|
||||||
function refreshFocus() {
|
function refreshFocus() {
|
||||||
if (document.hasFocus() == false) {
|
if (document.hasFocus() == false) {
|
||||||
app.windowFocus(false)
|
app.windowFocus(false);
|
||||||
} else {
|
} else {
|
||||||
app.windowFocus(true)
|
app.windowFocus(true);
|
||||||
}
|
}
|
||||||
setTimeout(refreshFocus, 200);
|
setTimeout(refreshFocus, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshFocus();
|
refreshFocus();
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export {Events}
|
export { Events };
|
||||||
|
|
|
@ -1,35 +1,33 @@
|
||||||
function simulateGamepad () {
|
function simulateGamepad() {
|
||||||
const app = window.app
|
const app = window.app;
|
||||||
app.chrome.showCursor = true
|
app.chrome.showCursor = true;
|
||||||
let cursorPos = [0, 0];
|
let cursorPos = [0, 0];
|
||||||
let intTabIndex = 0
|
let intTabIndex = 0;
|
||||||
const cursorSpeedPvt = 8
|
const cursorSpeedPvt = 8;
|
||||||
const cursorSize = 16
|
const cursorSize = 16;
|
||||||
let scrollSpeed = 8
|
let scrollSpeed = 8;
|
||||||
let buttonPressDelay = 500
|
let buttonPressDelay = 500;
|
||||||
let stickDeadZone = 0.2
|
let stickDeadZone = 0.2;
|
||||||
let scrollGroup = null
|
let scrollGroup = null;
|
||||||
let scrollGroupY = null
|
let scrollGroupY = null;
|
||||||
let elementFocusEnabled = true
|
let elementFocusEnabled = true;
|
||||||
let start;
|
let start;
|
||||||
|
|
||||||
let cursorSpeed = cursorSpeedPvt
|
let cursorSpeed = cursorSpeedPvt;
|
||||||
|
|
||||||
let lastButtonPress = {
|
let lastButtonPress = {};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var sounds = {
|
var sounds = {
|
||||||
Confirm: new Audio("./sounds/confirm.ogg"),
|
Confirm: new Audio("./sounds/confirm.ogg"),
|
||||||
Menu: new Audio("./sounds/btn1.ogg"),
|
Menu: new Audio("./sounds/btn1.ogg"),
|
||||||
Hover: new Audio("./sounds/hover.ogg")
|
Hover: new Audio("./sounds/hover.ogg"),
|
||||||
}
|
};
|
||||||
|
|
||||||
let element = document.elementFromPoint(0, 0)
|
let element = document.elementFromPoint(0, 0);
|
||||||
let elementType = 0
|
let elementType = 0;
|
||||||
|
|
||||||
function appLoop() {
|
function appLoop() {
|
||||||
var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);
|
var gamepads = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : [];
|
||||||
if (!gamepads) {
|
if (!gamepads) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -38,218 +36,207 @@ function simulateGamepad () {
|
||||||
|
|
||||||
// LEFT STICK
|
// LEFT STICK
|
||||||
if (gp.axes[0] > stickDeadZone) {
|
if (gp.axes[0] > stickDeadZone) {
|
||||||
cursorPos[0] += (gp.axes[0] * cursorSpeed)
|
cursorPos[0] += gp.axes[0] * cursorSpeed;
|
||||||
} else if (gp.axes[0] < -stickDeadZone) {
|
} else if (gp.axes[0] < -stickDeadZone) {
|
||||||
cursorPos[0] += (gp.axes[0] * cursorSpeed)
|
cursorPos[0] += gp.axes[0] * cursorSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gp.axes[1] > stickDeadZone) {
|
if (gp.axes[1] > stickDeadZone) {
|
||||||
cursorPos[1] += (gp.axes[1] * cursorSpeed)
|
cursorPos[1] += gp.axes[1] * cursorSpeed;
|
||||||
} else if (gp.axes[1] < -stickDeadZone) {
|
} else if (gp.axes[1] < -stickDeadZone) {
|
||||||
cursorPos[1] += (gp.axes[1] * cursorSpeed)
|
cursorPos[1] += gp.axes[1] * cursorSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursorPos[0] < cursorSize) {
|
if (cursorPos[0] < cursorSize) {
|
||||||
cursorPos[0] = cursorSize
|
cursorPos[0] = cursorSize;
|
||||||
}
|
}
|
||||||
if (cursorPos[1] < cursorSize) {
|
if (cursorPos[1] < cursorSize) {
|
||||||
cursorPos[1] = cursorSize
|
cursorPos[1] = cursorSize;
|
||||||
}
|
}
|
||||||
if (cursorPos[0] > window.innerWidth - cursorSize) {
|
if (cursorPos[0] > window.innerWidth - cursorSize) {
|
||||||
cursorPos[0] = window.innerWidth - cursorSize
|
cursorPos[0] = window.innerWidth - cursorSize;
|
||||||
}
|
}
|
||||||
if (cursorPos[1] > window.innerHeight - cursorSize) {
|
if (cursorPos[1] > window.innerHeight - cursorSize) {
|
||||||
cursorPos[1] = window.innerHeight - cursorSize
|
cursorPos[1] = window.innerHeight - cursorSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// RIGHT STICK.
|
// RIGHT STICK.
|
||||||
if (scrollGroupY) {
|
if (scrollGroupY) {
|
||||||
if (gp.axes[3] > stickDeadZone) {
|
if (gp.axes[3] > stickDeadZone) {
|
||||||
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + (gp.axes[3] * scrollSpeed))
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + gp.axes[3] * scrollSpeed);
|
||||||
elementFocusEnabled = false
|
elementFocusEnabled = false;
|
||||||
} else if (gp.axes[3] < -stickDeadZone) {
|
} else if (gp.axes[3] < -stickDeadZone) {
|
||||||
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + (gp.axes[3] * scrollSpeed))
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + gp.axes[3] * scrollSpeed);
|
||||||
elementFocusEnabled = false
|
elementFocusEnabled = false;
|
||||||
} else {
|
} else {
|
||||||
elementFocusEnabled = true
|
elementFocusEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (scrollGroup) {
|
if (scrollGroup) {
|
||||||
if (gp.axes[2] > stickDeadZone) {
|
if (gp.axes[2] > stickDeadZone) {
|
||||||
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + (gp.axes[2] * scrollSpeed))
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + gp.axes[2] * scrollSpeed);
|
||||||
elementFocusEnabled = false
|
elementFocusEnabled = false;
|
||||||
} else if (gp.axes[2] < -stickDeadZone) {
|
} else if (gp.axes[2] < -stickDeadZone) {
|
||||||
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + (gp.axes[2] * scrollSpeed))
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + gp.axes[2] * scrollSpeed);
|
||||||
elementFocusEnabled = false
|
elementFocusEnabled = false;
|
||||||
} else {
|
} else {
|
||||||
elementFocusEnabled = true
|
elementFocusEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$(".cursor").css({
|
$(".cursor").css({
|
||||||
top: cursorPos[1] + "px",
|
top: cursorPos[1] + "px",
|
||||||
left: cursorPos[0] + "px",
|
left: cursorPos[0] + "px",
|
||||||
display: "block"
|
display: "block",
|
||||||
})
|
});
|
||||||
|
|
||||||
// A BUTTON
|
// A BUTTON
|
||||||
if (gp.buttons[0].pressed) {
|
if (gp.buttons[0].pressed) {
|
||||||
if (!lastButtonPress["A"]) {
|
if (!lastButtonPress["A"]) {
|
||||||
lastButtonPress["A"] = 0
|
lastButtonPress["A"] = 0;
|
||||||
}
|
}
|
||||||
if (Date.now() - lastButtonPress["A"] > buttonPressDelay) {
|
if (Date.now() - lastButtonPress["A"] > buttonPressDelay) {
|
||||||
lastButtonPress["A"] = Date.now()
|
lastButtonPress["A"] = Date.now();
|
||||||
sounds.Confirm.play()
|
sounds.Confirm.play();
|
||||||
if (elementType == 0) {
|
if (elementType == 0) {
|
||||||
document.activeElement.dispatchEvent(new Event("click"))
|
document.activeElement.dispatchEvent(new Event("click"));
|
||||||
document.activeElement.dispatchEvent(new Event("controller-click"))
|
document.activeElement.dispatchEvent(new Event("controller-click"));
|
||||||
} else {
|
} else {
|
||||||
element.dispatchEvent(new Event("click"))
|
element.dispatchEvent(new Event("click"));
|
||||||
element.dispatchEvent(new Event("controller-click"))
|
element.dispatchEvent(new Event("controller-click"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// B BUTTON
|
// B BUTTON
|
||||||
if (gp.buttons[1].pressed) {
|
if (gp.buttons[1].pressed) {
|
||||||
|
|
||||||
if (!lastButtonPress["B"]) {
|
if (!lastButtonPress["B"]) {
|
||||||
lastButtonPress["B"] = 0
|
lastButtonPress["B"] = 0;
|
||||||
}
|
}
|
||||||
if (Date.now() - lastButtonPress["B"] > buttonPressDelay) {
|
if (Date.now() - lastButtonPress["B"] > buttonPressDelay) {
|
||||||
lastButtonPress["B"] = Date.now()
|
lastButtonPress["B"] = Date.now();
|
||||||
if (elementType == 0) {
|
if (elementType == 0) {
|
||||||
document.activeElement.dispatchEvent(new Event("contextmenu"))
|
document.activeElement.dispatchEvent(new Event("contextmenu"));
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if ($(".menu-option").length > 0) {
|
if ($(".menu-option").length > 0) {
|
||||||
let bounds = $(".menu-option")[0].getBoundingClientRect()
|
let bounds = $(".menu-option")[0].getBoundingClientRect();
|
||||||
cursorPos[0] = bounds.left + (bounds.width / 2)
|
cursorPos[0] = bounds.left + bounds.width / 2;
|
||||||
cursorPos[1] = bounds.top + (bounds.height / 2)
|
cursorPos[1] = bounds.top + bounds.height / 2;
|
||||||
}
|
}
|
||||||
}, 100)
|
}, 100);
|
||||||
} else {
|
} else {
|
||||||
element.dispatchEvent(new Event("contextmenu"))
|
element.dispatchEvent(new Event("contextmenu"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// right bumper
|
// right bumper
|
||||||
if (gp.buttons[5].pressed) {
|
if (gp.buttons[5].pressed) {
|
||||||
if (!lastButtonPress["RB"]) {
|
if (!lastButtonPress["RB"]) {
|
||||||
lastButtonPress["RB"] = 0
|
lastButtonPress["RB"] = 0;
|
||||||
}
|
}
|
||||||
if (Date.now() - lastButtonPress["RB"] > buttonPressDelay) {
|
if (Date.now() - lastButtonPress["RB"] > buttonPressDelay) {
|
||||||
lastButtonPress["RB"] = Date.now()
|
lastButtonPress["RB"] = Date.now();
|
||||||
app.navigateForward()
|
app.navigateForward();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// left bumper
|
// left bumper
|
||||||
if (gp.buttons[4].pressed) {
|
if (gp.buttons[4].pressed) {
|
||||||
if (!lastButtonPress["LB"]) {
|
if (!lastButtonPress["LB"]) {
|
||||||
lastButtonPress["LB"] = 0
|
lastButtonPress["LB"] = 0;
|
||||||
}
|
}
|
||||||
if (Date.now() - lastButtonPress["LB"] > buttonPressDelay) {
|
if (Date.now() - lastButtonPress["LB"] > buttonPressDelay) {
|
||||||
lastButtonPress["LB"] = Date.now()
|
lastButtonPress["LB"] = Date.now();
|
||||||
app.navigateBack()
|
app.navigateBack();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// cursor hover
|
// cursor hover
|
||||||
if (elementFocusEnabled) {
|
if (elementFocusEnabled) {
|
||||||
element = document.elementFromPoint(cursorPos[0], cursorPos[1])
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
|
let closest = element.closest("[tabindex], input, button, a");
|
||||||
let closest = element.closest("[tabindex], input, button, a")
|
|
||||||
|
|
||||||
// VERT SCROLL
|
// VERT SCROLL
|
||||||
let scrollGroupCloY = element.closest(`[scrollaxis="y"]`)
|
let scrollGroupCloY = element.closest(`[scrollaxis="y"]`);
|
||||||
if (scrollGroupCloY) {
|
if (scrollGroupCloY) {
|
||||||
scrollGroupY = scrollGroupCloY
|
scrollGroupY = scrollGroupCloY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// HOZ SCROLL
|
// HOZ SCROLL
|
||||||
let scrollGroupClo = element.closest(".v-hl-container")
|
let scrollGroupClo = element.closest(".v-hl-container");
|
||||||
|
|
||||||
if (scrollGroupClo) {
|
if (scrollGroupClo) {
|
||||||
if (scrollGroupClo.classList.contains("v-hl-container")) {
|
if (scrollGroupClo.classList.contains("v-hl-container")) {
|
||||||
scrollGroup = scrollGroupClo
|
scrollGroup = scrollGroupClo;
|
||||||
scrollGroup.style["scroll-snap-type"] = "unset"
|
scrollGroup.style["scroll-snap-type"] = "unset";
|
||||||
} else {
|
} else {
|
||||||
scrollGroup.style["scroll-snap-type"] = ""
|
scrollGroup.style["scroll-snap-type"] = "";
|
||||||
scrollGroup = null
|
scrollGroup = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closest) {
|
if (closest) {
|
||||||
elementType = 0
|
elementType = 0;
|
||||||
closest.focus()
|
closest.focus();
|
||||||
} else {
|
} else {
|
||||||
if (closest) {
|
if (closest) {
|
||||||
closest.blur()
|
closest.blur();
|
||||||
}
|
}
|
||||||
elementType = 1
|
elementType = 1;
|
||||||
element.focus()
|
element.focus();
|
||||||
}
|
}
|
||||||
cursorSpeed = cursorSpeedPvt
|
cursorSpeed = cursorSpeedPvt;
|
||||||
if (!element.classList.contains("app-chrome")
|
if (!element.classList.contains("app-chrome") && !element.classList.contains("app-content")) {
|
||||||
&& !element.classList.contains("app-content")) {
|
cursorSpeed = cursorSpeedPvt;
|
||||||
cursorSpeed = cursorSpeedPvt
|
|
||||||
}
|
}
|
||||||
// console.log($._data($(element), "events"))
|
// console.log($._data($(element), "events"))
|
||||||
} else {
|
} else {
|
||||||
cursorSpeed = 12
|
cursorSpeed = 12;
|
||||||
}
|
}
|
||||||
// console.log(gp.axes[0], gp.axes[1])
|
// console.log(gp.axes[0], gp.axes[1])
|
||||||
start = requestAnimationFrame(appLoop);
|
start = requestAnimationFrame(appLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// controller pairing
|
// controller pairing
|
||||||
notyf.error("Press the button on your controller to pair it to Cider.")
|
notyf.error("Press the button on your controller to pair it to Cider.");
|
||||||
window.addEventListener("gamepadconnected", function (e) {
|
window.addEventListener(
|
||||||
console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.",
|
"gamepadconnected",
|
||||||
e.gamepad.index, e.gamepad.id,
|
function (e) {
|
||||||
e.gamepad.buttons.length, e.gamepad.axes.length);
|
console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", e.gamepad.index, e.gamepad.id, e.gamepad.buttons.length, e.gamepad.axes.length);
|
||||||
notyf.success("Pairing successful!")
|
notyf.success("Pairing successful!");
|
||||||
appLoop()
|
appLoop();
|
||||||
}, { once: true });
|
},
|
||||||
|
{ once: true }
|
||||||
|
);
|
||||||
|
|
||||||
document.addEventListener("keydown", (e) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
sounds.Confirm.currentTime = 0
|
sounds.Confirm.currentTime = 0;
|
||||||
sounds.Menu.currentTime = 0
|
sounds.Menu.currentTime = 0;
|
||||||
sounds.Hover.currentTime = 0
|
sounds.Hover.currentTime = 0;
|
||||||
let tabbable = $("[tabindex]")
|
let tabbable = $("[tabindex]");
|
||||||
console.log(e.key)
|
console.log(e.key);
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case "ArrowLeft":
|
case "ArrowLeft":
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
cursorPos[0] -= cursorSpeed
|
cursorPos[0] -= cursorSpeed;
|
||||||
break;
|
break;
|
||||||
case "ArrowRight":
|
case "ArrowRight":
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
cursorPos[0] += cursorSpeed
|
cursorPos[0] += cursorSpeed;
|
||||||
break;
|
break;
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
cursorPos[1] -= cursorSpeed
|
cursorPos[1] -= cursorSpeed;
|
||||||
// sounds.Hover.play()
|
// sounds.Hover.play()
|
||||||
// if (intTabIndex <= 0) {
|
// if (intTabIndex <= 0) {
|
||||||
// intTabIndex = 0
|
// intTabIndex = 0
|
||||||
|
@ -260,9 +247,9 @@ function simulateGamepad () {
|
||||||
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
||||||
break;
|
break;
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
cursorPos[1] += cursorSpeed
|
cursorPos[1] += cursorSpeed;
|
||||||
// if (intTabIndex < tabbable.length) {
|
// if (intTabIndex < tabbable.length) {
|
||||||
// intTabIndex++
|
// intTabIndex++
|
||||||
// } else {
|
// } else {
|
||||||
|
@ -272,56 +259,55 @@ function simulateGamepad () {
|
||||||
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
||||||
break;
|
break;
|
||||||
case "c":
|
case "c":
|
||||||
app.resetState()
|
app.resetState();
|
||||||
break;
|
break;
|
||||||
case "x":
|
case "x":
|
||||||
// set cursorPos to the top right of the screen
|
// set cursorPos to the top right of the screen
|
||||||
// sounds.Menu.play()
|
// sounds.Menu.play()
|
||||||
if (elementType == 0) {
|
if (elementType == 0) {
|
||||||
document.activeElement.dispatchEvent(new Event("contextmenu"))
|
document.activeElement.dispatchEvent(new Event("contextmenu"));
|
||||||
} else {
|
} else {
|
||||||
element.dispatchEvent(new Event("contextmenu"))
|
element.dispatchEvent(new Event("contextmenu"));
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
case "z":
|
case "z":
|
||||||
sounds.Confirm.play()
|
sounds.Confirm.play();
|
||||||
if (elementType == 0) {
|
if (elementType == 0) {
|
||||||
document.activeElement.dispatchEvent(new Event("click"))
|
document.activeElement.dispatchEvent(new Event("click"));
|
||||||
document.activeElement.dispatchEvent(new Event("controller-click"))
|
document.activeElement.dispatchEvent(new Event("controller-click"));
|
||||||
} else {
|
} else {
|
||||||
element.dispatchEvent(new Event("click"))
|
element.dispatchEvent(new Event("click"));
|
||||||
element.dispatchEvent(new Event("controller-click"))
|
element.dispatchEvent(new Event("controller-click"));
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".cursor").css({
|
$(".cursor").css({
|
||||||
top: cursorPos[1] + "px",
|
top: cursorPos[1] + "px",
|
||||||
left: cursorPos[0] + "px"
|
left: cursorPos[0] + "px",
|
||||||
})
|
});
|
||||||
function lerp(a, b, n) {
|
function lerp(a, b, n) {
|
||||||
return (1 - n) * a + n * b
|
return (1 - n) * a + n * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1]);
|
||||||
element = document.elementFromPoint(cursorPos[0], cursorPos[1])
|
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
let closest = element.closest("[tabindex], input, button, a")
|
let closest = element.closest("[tabindex], input, button, a");
|
||||||
if (closest) {
|
if (closest) {
|
||||||
elementType = 0
|
elementType = 0;
|
||||||
closest.focus()
|
closest.focus();
|
||||||
} else {
|
} else {
|
||||||
elementType = 1
|
elementType = 1;
|
||||||
element.focus()
|
element.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(element)
|
console.log(element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export {simulateGamepad}
|
export { simulateGamepad };
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export function html (str) {
|
export function html(str) {
|
||||||
return str[0]
|
return str[0];
|
||||||
}
|
}
|
|
@ -31,9 +31,9 @@ async function spawnMica() {
|
||||||
}
|
}
|
||||||
if (micaCache.path == imgSrc.path) {
|
if (micaCache.path == imgSrc.path) {
|
||||||
imgSrc = micaCache;
|
imgSrc = micaCache;
|
||||||
}else{
|
} else {
|
||||||
imgSrc = await ipcRenderer.sendSync("get-wallpaper", {
|
imgSrc = await ipcRenderer.sendSync("get-wallpaper", {
|
||||||
blurAmount: 256
|
blurAmount: 256,
|
||||||
});
|
});
|
||||||
CiderCache.putCache("mica-cache", imgSrc);
|
CiderCache.putCache("mica-cache", imgSrc);
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,7 @@ async function spawnMica() {
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
// window size change
|
// window size change
|
||||||
if (
|
if (lastScreenWidth !== window.innerWidth || lastScreenHeight !== window.innerHeight) {
|
||||||
lastScreenWidth !== window.innerWidth ||
|
|
||||||
lastScreenHeight !== window.innerHeight
|
|
||||||
) {
|
|
||||||
lastScreenWidth = window.innerWidth;
|
lastScreenWidth = window.innerWidth;
|
||||||
lastScreenHeight = window.innerHeight;
|
lastScreenHeight = window.innerHeight;
|
||||||
cb();
|
cb();
|
||||||
|
|
|
@ -1,56 +1,44 @@
|
||||||
const MusicKitTools = {
|
const MusicKitTools = {
|
||||||
async v3Backend({
|
async v3Backend({ route = "", getBody = {}, options = {} }) {
|
||||||
route = "", getBody = {}, options = {}
|
return await await ipcRenderer.invoke("mkv3", {
|
||||||
}) {
|
|
||||||
return await (await ipcRenderer.invoke("mkv3", {
|
|
||||||
token: MusicKit.getInstance().developerToken,
|
token: MusicKit.getInstance().developerToken,
|
||||||
route: route,
|
route: route,
|
||||||
mediaToken: MusicKit.getInstance().musicUserToken,
|
mediaToken: MusicKit.getInstance().musicUserToken,
|
||||||
GETBody: getBody
|
GETBody: getBody,
|
||||||
}))
|
});
|
||||||
},
|
},
|
||||||
async v3Continuous({
|
async v3Continuous({ href, options = {}, reqOptions = {}, onProgress = () => {}, onError = () => {}, onSuccess = () => {} } = {}) {
|
||||||
href,
|
let returnData = [];
|
||||||
options = {},
|
|
||||||
reqOptions = {},
|
|
||||||
onProgress = () => {
|
|
||||||
},
|
|
||||||
onError = () => {
|
|
||||||
},
|
|
||||||
onSuccess = () => {
|
|
||||||
}
|
|
||||||
} = {}) {
|
|
||||||
let returnData = []
|
|
||||||
|
|
||||||
async function sendReq(href, options) {
|
async function sendReq(href, options) {
|
||||||
const response = await app.mk.api.v3.music(href, options).catch(error => onError)
|
const response = await app.mk.api.v3.music(href, options).catch((error) => onError);
|
||||||
|
|
||||||
returnData = returnData.concat(response.data.data)
|
returnData = returnData.concat(response.data.data);
|
||||||
if (response.data.next) {
|
if (response.data.next) {
|
||||||
onProgress({
|
onProgress({
|
||||||
response: response,
|
response: response,
|
||||||
total: returnData.length
|
total: returnData.length,
|
||||||
})
|
});
|
||||||
try {
|
try {
|
||||||
await sendReq(response.data.next, options)
|
await sendReq(response.data.next, options);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await sendReq(response.data.next, options)
|
await sendReq(response.data.next, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendReq(href, options)
|
await sendReq(href, options);
|
||||||
onSuccess(returnData)
|
onSuccess(returnData);
|
||||||
return returnData
|
return returnData;
|
||||||
},
|
},
|
||||||
getHeader() {
|
getHeader() {
|
||||||
return new Headers({
|
return new Headers({
|
||||||
Authorization: 'Bearer ' + MusicKit.getInstance().developerToken,
|
Authorization: "Bearer " + MusicKit.getInstance().developerToken,
|
||||||
Accept: 'application/json',
|
Accept: "application/json",
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
'Music-User-Token': '' + MusicKit.getInstance().musicUserToken
|
"Music-User-Token": "" + MusicKit.getInstance().musicUserToken,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export {MusicKitTools}
|
export { MusicKitTools };
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,16 +12,16 @@ const store = new Vuex.Store({
|
||||||
loaded: false,
|
loaded: false,
|
||||||
nextUrl: null,
|
nextUrl: null,
|
||||||
items: [],
|
items: [],
|
||||||
size: "normal"
|
size: "normal",
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
currentTabIndex: 0,
|
currentTabIndex: 0,
|
||||||
fullscreen: false
|
fullscreen: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
artwork: {
|
artwork: {
|
||||||
playerLCD: ""
|
playerLCD: "",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
resetRecentlyAdded(state) {
|
resetRecentlyAdded(state) {
|
||||||
|
@ -30,9 +30,9 @@ const store = new Vuex.Store({
|
||||||
state.pageState.recentlyAdded.items = [];
|
state.pageState.recentlyAdded.items = [];
|
||||||
},
|
},
|
||||||
setLCDArtwork(state, artwork) {
|
setLCDArtwork(state, artwork) {
|
||||||
state.artwork.playerLCD = artwork
|
state.artwork.playerLCD = artwork;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
export {store}
|
export { store };
|
||||||
|
|
|
@ -1,41 +1,51 @@
|
||||||
const wsapi = {
|
const wsapi = {
|
||||||
cache: {playParams: {id: 0}, status: null, remainingTime: 0},
|
cache: { playParams: { id: 0 }, status: null, remainingTime: 0 },
|
||||||
playbackCache: {status: null, time: Date.now()},
|
playbackCache: { status: null, time: Date.now() },
|
||||||
async v3(encoded = "") {
|
async v3(encoded = "") {
|
||||||
let decoded = atob(encoded);
|
let decoded = atob(encoded);
|
||||||
let json = JSON.parse(decoded);
|
let json = JSON.parse(decoded);
|
||||||
console.log(json)
|
console.log(json);
|
||||||
let response = await (await MusicKit.getInstance().api.v3.music(json.route, json.body, json.options))
|
let response = await await MusicKit.getInstance().api.v3.music(json.route, json.body, json.options);
|
||||||
let ret = response.data
|
let ret = response.data;
|
||||||
return JSON.stringify(ret)
|
return JSON.stringify(ret);
|
||||||
},
|
},
|
||||||
search(term, limit) {
|
search(term, limit) {
|
||||||
MusicKit.getInstance().api.search(term, {limit: limit, types: 'songs,artists,albums,playlists'}).then((results)=>{
|
MusicKit.getInstance()
|
||||||
ipcRenderer.send('wsapi-returnSearch', JSON.stringify(results))
|
.api.search(term, {
|
||||||
|
limit: limit,
|
||||||
|
types: "songs,artists,albums,playlists",
|
||||||
})
|
})
|
||||||
|
.then((results) => {
|
||||||
|
ipcRenderer.send("wsapi-returnSearch", JSON.stringify(results));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
searchLibrary(term, limit) {
|
searchLibrary(term, limit) {
|
||||||
MusicKit.getInstance().api.library.search(term, {limit: limit, types: 'library-songs,library-artists,library-albums,library-playlists'}).then((results)=>{
|
MusicKit.getInstance()
|
||||||
ipcRenderer.send('wsapi-returnSearchLibrary', JSON.stringify(results))
|
.api.library.search(term, {
|
||||||
|
limit: limit,
|
||||||
|
types: "library-songs,library-artists,library-albums,library-playlists",
|
||||||
})
|
})
|
||||||
|
.then((results) => {
|
||||||
|
ipcRenderer.send("wsapi-returnSearchLibrary", JSON.stringify(results));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getAttributes: function () {
|
getAttributes: function () {
|
||||||
const mk = MusicKit.getInstance();
|
const mk = MusicKit.getInstance();
|
||||||
const nowPlayingItem = mk.nowPlayingItem;
|
const nowPlayingItem = mk.nowPlayingItem;
|
||||||
const isPlayingExport = mk.isPlaying;
|
const isPlayingExport = mk.isPlaying;
|
||||||
const remainingTimeExport = mk.currentPlaybackTimeRemaining;
|
const remainingTimeExport = mk.currentPlaybackTimeRemaining;
|
||||||
const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {});
|
const attributes = nowPlayingItem != null ? nowPlayingItem.attributes : {};
|
||||||
|
|
||||||
attributes.status = isPlayingExport ? isPlayingExport : false;
|
attributes.status = isPlayingExport ? isPlayingExport : false;
|
||||||
attributes.name = attributes.name ? attributes.name : 'No Title Found';
|
attributes.name = attributes.name ? attributes.name : "No Title Found";
|
||||||
attributes.artwork = attributes.artwork ? attributes.artwork : {url: ''};
|
attributes.artwork = attributes.artwork ? attributes.artwork : { url: "" };
|
||||||
attributes.artwork.url = attributes.artwork.url ? attributes.artwork.url : '';
|
attributes.artwork.url = attributes.artwork.url ? attributes.artwork.url : "";
|
||||||
attributes.playParams = attributes.playParams ? attributes.playParams : {id: 'no-id-found'};
|
attributes.playParams = attributes.playParams ? attributes.playParams : { id: "no-id-found" };
|
||||||
attributes.playParams.id = attributes.playParams.id ? attributes.playParams.id : 'no-id-found';
|
attributes.playParams.id = attributes.playParams.id ? attributes.playParams.id : "no-id-found";
|
||||||
attributes.albumName = attributes.albumName ? attributes.albumName : '';
|
attributes.albumName = attributes.albumName ? attributes.albumName : "";
|
||||||
attributes.artistName = attributes.artistName ? attributes.artistName : '';
|
attributes.artistName = attributes.artistName ? attributes.artistName : "";
|
||||||
attributes.genreNames = attributes.genreNames ? attributes.genreNames : [];
|
attributes.genreNames = attributes.genreNames ? attributes.genreNames : [];
|
||||||
attributes.remainingTime = remainingTimeExport ? (remainingTimeExport * 1000) : 0;
|
attributes.remainingTime = remainingTimeExport ? remainingTimeExport * 1000 : 0;
|
||||||
attributes.durationInMillis = attributes.durationInMillis ? attributes.durationInMillis : 0;
|
attributes.durationInMillis = attributes.durationInMillis ? attributes.durationInMillis : 0;
|
||||||
attributes.startTime = Date.now();
|
attributes.startTime = Date.now();
|
||||||
attributes.endTime = attributes.endTime ? attributes.endTime : Date.now();
|
attributes.endTime = attributes.endTime ? attributes.endTime : Date.now();
|
||||||
|
@ -43,152 +53,178 @@ const wsapi = {
|
||||||
attributes.shuffleMode = mk.shuffleMode;
|
attributes.shuffleMode = mk.shuffleMode;
|
||||||
attributes.repeatMode = mk.repeatMode;
|
attributes.repeatMode = mk.repeatMode;
|
||||||
attributes.autoplayEnabled = mk.autoplayEnabled;
|
attributes.autoplayEnabled = mk.autoplayEnabled;
|
||||||
return attributes
|
return attributes;
|
||||||
},
|
},
|
||||||
moveQueueItem(oldPosition, newPosition) {
|
moveQueueItem(oldPosition, newPosition) {
|
||||||
MusicKit.getInstance().queue._queueItems.splice(newPosition,0,MusicKit.getInstance().queue._queueItems.splice(oldPosition,1)[0])
|
MusicKit.getInstance().queue._queueItems.splice(newPosition, 0, MusicKit.getInstance().queue._queueItems.splice(oldPosition, 1)[0]);
|
||||||
MusicKit.getInstance().queue._reindex()
|
MusicKit.getInstance().queue._reindex();
|
||||||
},
|
},
|
||||||
setAutoplay(value) {
|
setAutoplay(value) {
|
||||||
MusicKit.getInstance().autoplayEnabled = value
|
MusicKit.getInstance().autoplayEnabled = value;
|
||||||
},
|
},
|
||||||
returnDynamic(data, type) {
|
returnDynamic(data, type) {
|
||||||
ipcRenderer.send('wsapi-returnDynamic', JSON.stringify(data), type)
|
ipcRenderer.send("wsapi-returnDynamic", JSON.stringify(data), type);
|
||||||
},
|
},
|
||||||
musickitApi(method, id, params, library = false) {
|
musickitApi(method, id, params, library = false) {
|
||||||
if (library) {
|
if (library) {
|
||||||
MusicKit.getInstance().api.library[method](id, params).then((results)=>{
|
MusicKit.getInstance()
|
||||||
ipcRenderer.send('wsapi-returnMusicKitApi', JSON.stringify(results), method)
|
.api.library[method](id, params)
|
||||||
})
|
.then((results) => {
|
||||||
|
ipcRenderer.send("wsapi-returnMusicKitApi", JSON.stringify(results), method);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
MusicKit.getInstance().api[method](id, params).then((results)=>{
|
MusicKit.getInstance()
|
||||||
ipcRenderer.send('wsapi-returnMusicKitApi', JSON.stringify(results), method)
|
.api[method](id, params)
|
||||||
})
|
.then((results) => {
|
||||||
|
ipcRenderer.send("wsapi-returnMusicKitApi", JSON.stringify(results), method);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPlaybackState () {
|
getPlaybackState() {
|
||||||
ipcRenderer.send('wsapi-updatePlaybackState', MusicKitInterop.getAttributes());
|
ipcRenderer.send("wsapi-updatePlaybackState", MusicKitInterop.getAttributes());
|
||||||
},
|
},
|
||||||
getLyrics() {
|
getLyrics() {
|
||||||
ipcRenderer.send('wsapi-returnLyrics',JSON.stringify(app.lyrics));
|
ipcRenderer.send("wsapi-returnLyrics", JSON.stringify(app.lyrics));
|
||||||
},
|
},
|
||||||
getQueue() {
|
getQueue() {
|
||||||
ipcRenderer.send('wsapi-returnQueue', JSON.stringify(MusicKit.getInstance().queue))
|
ipcRenderer.send("wsapi-returnQueue", JSON.stringify(MusicKit.getInstance().queue));
|
||||||
},
|
},
|
||||||
playNext(type, id) {
|
playNext(type, id) {
|
||||||
var request = {}
|
var request = {};
|
||||||
request[type] = id
|
request[type] = id;
|
||||||
MusicKit.getInstance().playNext(request)
|
MusicKit.getInstance().playNext(request);
|
||||||
},
|
},
|
||||||
playLater(type, id) {
|
playLater(type, id) {
|
||||||
var request = {}
|
var request = {};
|
||||||
request[type] = id
|
request[type] = id;
|
||||||
MusicKit.getInstance().playLater(request)
|
MusicKit.getInstance().playLater(request);
|
||||||
},
|
|
||||||
love() {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
love() {},
|
||||||
playTrackById(id, kind = "song") {
|
playTrackById(id, kind = "song") {
|
||||||
MusicKit.getInstance().setQueue({ [kind]: id , parameters : {l : app.mklang}}).then(function (queue) {
|
MusicKit.getInstance()
|
||||||
MusicKit.getInstance().play()
|
.setQueue({ [kind]: id, parameters: { l: app.mklang } })
|
||||||
})
|
.then(function (queue) {
|
||||||
|
MusicKit.getInstance().play();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
quickPlay(term) {
|
quickPlay(term) {
|
||||||
// Quick play by song name
|
// Quick play by song name
|
||||||
MusicKit.getInstance().api.search(term, { limit: 2, types: 'songs' }).then(function (data) {
|
MusicKit.getInstance()
|
||||||
MusicKit.getInstance().setQueue({ song: data["songs"][0]["id"],parameters : {l : app.mklang} }).then(function (queue) {
|
.api.search(term, { limit: 2, types: "songs" })
|
||||||
MusicKit.getInstance().play()
|
.then(function (data) {
|
||||||
})
|
MusicKit.getInstance()
|
||||||
|
.setQueue({
|
||||||
|
song: data["songs"][0]["id"],
|
||||||
|
parameters: { l: app.mklang },
|
||||||
})
|
})
|
||||||
|
.then(function (queue) {
|
||||||
|
MusicKit.getInstance().play();
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
toggleShuffle() {
|
toggleShuffle() {
|
||||||
MusicKit.getInstance().shuffleMode = MusicKit.getInstance().shuffleMode === 0 ? 1 : 0
|
MusicKit.getInstance().shuffleMode = MusicKit.getInstance().shuffleMode === 0 ? 1 : 0;
|
||||||
},
|
},
|
||||||
togglePlayPause() {
|
togglePlayPause() {
|
||||||
app.mk.isPlaying ? app.mk.pause() : app.mk.play()
|
app.mk.isPlaying ? app.mk.pause() : app.mk.play();
|
||||||
},
|
},
|
||||||
toggleRepeat() {
|
toggleRepeat() {
|
||||||
if (MusicKit.getInstance().repeatMode == 0) {
|
if (MusicKit.getInstance().repeatMode == 0) {
|
||||||
MusicKit.getInstance().repeatMode = 1
|
MusicKit.getInstance().repeatMode = 1;
|
||||||
} else if (MusicKit.getInstance().repeatMode == 1){
|
} else if (MusicKit.getInstance().repeatMode == 1) {
|
||||||
MusicKit.getInstance().repeatMode = 2
|
MusicKit.getInstance().repeatMode = 2;
|
||||||
} else {
|
} else {
|
||||||
MusicKit.getInstance().repeatMode = 0
|
MusicKit.getInstance().repeatMode = 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getmaxVolume() {
|
getmaxVolume() {
|
||||||
ipcRenderer.send('wsapi-returnvolumeMax',JSON.stringify(app.cfg.audio.maxVolume));
|
ipcRenderer.send("wsapi-returnvolumeMax", JSON.stringify(app.cfg.audio.maxVolume));
|
||||||
},
|
},
|
||||||
getLibraryStatus(kind, id) {
|
getLibraryStatus(kind, id) {
|
||||||
if (kind === undefined || id === "no-id-found") return;
|
if (kind === undefined || id === "no-id-found") return;
|
||||||
|
|
||||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
let truekind = !kind.endsWith("s") ? kind + "s" : kind;
|
||||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
app.mk.api.v3
|
||||||
|
.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
||||||
relate: "library",
|
relate: "library",
|
||||||
fields: "inLibrary"
|
fields: "inLibrary",
|
||||||
}).then(data => {
|
})
|
||||||
|
.then((data) => {
|
||||||
const res = data.data.data[0];
|
const res = data.data.data[0];
|
||||||
const inLibrary = res && res.attributes && res.attributes.inLibrary;
|
const inLibrary = res && res.attributes && res.attributes.inLibrary;
|
||||||
|
|
||||||
app.getRating({ type: truekind, id: id }).then(rating => {
|
app.getRating({ type: truekind, id: id }).then((rating) => {
|
||||||
ipcRenderer.send('wsapi-libraryStatus', inLibrary, rating);
|
ipcRenderer.send("wsapi-libraryStatus", inLibrary, rating);
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
rate(kind, id, rating) {
|
rate(kind, id, rating) {
|
||||||
if (kind === undefined || id === "no-id-found") return;
|
if (kind === undefined || id === "no-id-found") return;
|
||||||
|
|
||||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
let truekind = !kind.endsWith("s") ? kind + "s" : kind;
|
||||||
|
|
||||||
if (rating === 0) {
|
if (rating === 0) {
|
||||||
app.mk.api.v3.music(`/v1/me/ratings/${truekind}/${id}`, {}, {
|
app.mk.api.v3
|
||||||
|
.music(
|
||||||
|
`/v1/me/ratings/${truekind}/${id}`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}).then(function () {
|
)
|
||||||
ipcRenderer.send('wsapi-rate', kind, id, rating);
|
.then(function () {
|
||||||
})
|
ipcRenderer.send("wsapi-rate", kind, id, rating);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
app.mk.api.v3.music(`/v1/me/ratings/${truekind}/${id}`, {}, {
|
app.mk.api.v3
|
||||||
|
.music(
|
||||||
|
`/v1/me/ratings/${truekind}/${id}`,
|
||||||
|
{},
|
||||||
|
{
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
"type": "rating",
|
type: "rating",
|
||||||
"attributes": {
|
attributes: {
|
||||||
"value": rating
|
value: rating,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
.then(function () {
|
||||||
}).then(function () {
|
ipcRenderer.send("wsapi-rate", kind, id, rating);
|
||||||
ipcRenderer.send('wsapi-rate', kind, id, rating);
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeLibrary(kind, id, shouldAdd) {
|
changeLibrary(kind, id, shouldAdd) {
|
||||||
if (shouldAdd) {
|
if (shouldAdd) {
|
||||||
app.addToLibrary(id);
|
app.addToLibrary(id);
|
||||||
ipcRenderer.send('wsapi-change-library', kind, id, shouldAdd);
|
ipcRenderer.send("wsapi-change-library", kind, id, shouldAdd);
|
||||||
} else {
|
} else {
|
||||||
let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind;
|
let truekind = !kind.endsWith("s") ? kind + "s" : kind;
|
||||||
|
|
||||||
app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
app.mk.api.v3
|
||||||
|
.music(`/v1/catalog/${app.mk.storefrontId}/?ids[${truekind}]=${id}`, {
|
||||||
relate: "library",
|
relate: "library",
|
||||||
fields: "inLibrary"
|
fields: "inLibrary",
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
res = res.data.data[0]
|
res = res.data.data[0];
|
||||||
if (res && res.relationships && res.relationships.library && res.relationships.library.data) {
|
if (res && res.relationships && res.relationships.library && res.relationships.library.data) {
|
||||||
const item = res.relationships.library.data[0];
|
const item = res.relationships.library.data[0];
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
app.removeFromLibrary(kind, item.id)
|
app.removeFromLibrary(kind, item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcRenderer.send('wsapi-change-library', kind, id, shouldAdd);
|
ipcRenderer.send("wsapi-change-library", kind, id, shouldAdd);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export {wsapi}
|
export { wsapi };
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,2 +1,68 @@
|
||||||
if(!self.define){let e,i={};const s=(s,r)=>(s=new URL(s+".js",r).href,i[s]||new Promise((i=>{if("document"in self){const e=document.createElement("script");e.src=s,e.onload=i,document.head.appendChild(e)}else e=s,importScripts(s),i()})).then((()=>{let e=i[s];if(!e)throw new Error(`Module ${s} didn’t register its module`);return e})));self.define=(r,c)=>{const n=e||("document"in self?document.currentScript.src:"")||location.href;if(i[n])return;let o={};const t=e=>s(e,n),a={module:{uri:n},exports:o,require:t};i[n]=Promise.all(r.map((e=>a[e]||t(e)))).then((e=>(c(...e),o)))}}define(["./workbox-962786f2"],(function(e){"use strict";self.addEventListener("message",(e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()})),e.precacheAndRoute([{url:"ameframework.css",revision:"4bcc8646bb5742638fad52b94e231601"},{url:"apple-hls.js",revision:"2b74055662676b0fcc2d4a4bf994a9dc"},{url:"hlscider.js",revision:"cf7f512e83e32694f2c94f904714fe4c"},{url:"index_old.html",revision:"c21f3e9c5b015599d3ab07639f64a7a8"},{url:"index.js",revision:"8591a69fc9c975a063eb264b7447f173"},{url:"less.js",revision:"b6e574e4d680686786a28e7e71a17bbc"},{url:"musickit.js",revision:"211d80891c3336c1795cb83df58d4b63"},{url:"sortable.min.js",revision:"5cbc31ebec32adf60e27b76418e79d93"},{url:"style-old.css",revision:"aea9ea49df13f2deee42b68654aeea06"},{url:"todo.js",revision:"18d49fabcb96de8bd11455877d8eacb6"},{url:"vue-observe-visibility.min.js",revision:"5a52e761f6aa71b4f65a7b458f698b95"},{url:"vue.js",revision:"0a9a4681294d8c5f476687eea6e74842"},{url:"vuedraggable.umd.min.js",revision:"9a84fec5263bb510cee88e1c3b9583cc"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/,/^X-Amz-Algorithm/,/^X-Amz-Date/,/^X-Amz-SignedHeaders/,/^X-Amz-Expires/,/^X-Amz-Credential/,/^X-Amz-Signature/]}),e.registerRoute(/\.(?:png|jpg|jpeg|svg|webp)$/,new e.CacheFirst({cacheName:"imageinternet",plugins:[]}),"GET"),e.registerRoute(/https:\/\/is[0-9]-ssl\.mzstatic\.com\/image+/,new e.CacheFirst,"GET"),e.registerRoute(/^https:\/\/store-\d{3}\.blobstore\.apple\.com\/.{65}\/image+/,new e.CacheFirst,"GET")}));
|
if (!self.define) {
|
||||||
|
let e,
|
||||||
|
i = {};
|
||||||
|
const s = (s, r) => (
|
||||||
|
(s = new URL(s + ".js", r).href),
|
||||||
|
i[s] ||
|
||||||
|
new Promise((i) => {
|
||||||
|
if ("document" in self) {
|
||||||
|
const e = document.createElement("script");
|
||||||
|
(e.src = s), (e.onload = i), document.head.appendChild(e);
|
||||||
|
} else (e = s), importScripts(s), i();
|
||||||
|
}).then(() => {
|
||||||
|
let e = i[s];
|
||||||
|
if (!e) throw new Error(`Module ${s} didn’t register its module`);
|
||||||
|
return e;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
self.define = (r, c) => {
|
||||||
|
const n = e || ("document" in self ? document.currentScript.src : "") || location.href;
|
||||||
|
if (i[n]) return;
|
||||||
|
let o = {};
|
||||||
|
const t = (e) => s(e, n),
|
||||||
|
a = { module: { uri: n }, exports: o, require: t };
|
||||||
|
i[n] = Promise.all(r.map((e) => a[e] || t(e))).then((e) => (c(...e), o));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
define(["./workbox-962786f2"], function (e) {
|
||||||
|
"use strict";
|
||||||
|
self.addEventListener("message", (e) => {
|
||||||
|
e.data && "SKIP_WAITING" === e.data.type && self.skipWaiting();
|
||||||
|
}),
|
||||||
|
e.precacheAndRoute(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
url: "ameframework.css",
|
||||||
|
revision: "4bcc8646bb5742638fad52b94e231601",
|
||||||
|
},
|
||||||
|
{ url: "apple-hls.js", revision: "2b74055662676b0fcc2d4a4bf994a9dc" },
|
||||||
|
{ url: "hlscider.js", revision: "cf7f512e83e32694f2c94f904714fe4c" },
|
||||||
|
{ url: "index_old.html", revision: "c21f3e9c5b015599d3ab07639f64a7a8" },
|
||||||
|
{ url: "index.js", revision: "8591a69fc9c975a063eb264b7447f173" },
|
||||||
|
{ url: "less.js", revision: "b6e574e4d680686786a28e7e71a17bbc" },
|
||||||
|
{ url: "musickit.js", revision: "211d80891c3336c1795cb83df58d4b63" },
|
||||||
|
{
|
||||||
|
url: "sortable.min.js",
|
||||||
|
revision: "5cbc31ebec32adf60e27b76418e79d93",
|
||||||
|
},
|
||||||
|
{ url: "style-old.css", revision: "aea9ea49df13f2deee42b68654aeea06" },
|
||||||
|
{ url: "todo.js", revision: "18d49fabcb96de8bd11455877d8eacb6" },
|
||||||
|
{
|
||||||
|
url: "vue-observe-visibility.min.js",
|
||||||
|
revision: "5a52e761f6aa71b4f65a7b458f698b95",
|
||||||
|
},
|
||||||
|
{ url: "vue.js", revision: "0a9a4681294d8c5f476687eea6e74842" },
|
||||||
|
{
|
||||||
|
url: "vuedraggable.umd.min.js",
|
||||||
|
revision: "9a84fec5263bb510cee88e1c3b9583cc",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
ignoreURLParametersMatching: [/^utm_/, /^fbclid$/, /^X-Amz-Algorithm/, /^X-Amz-Date/, /^X-Amz-SignedHeaders/, /^X-Amz-Expires/, /^X-Amz-Credential/, /^X-Amz-Signature/],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
e.registerRoute(/\.(?:png|jpg|jpeg|svg|webp)$/, new e.CacheFirst({ cacheName: "imageinternet", plugins: [] }), "GET"),
|
||||||
|
e.registerRoute(/https:\/\/is[0-9]-ssl\.mzstatic\.com\/image+/, new e.CacheFirst(), "GET"),
|
||||||
|
e.registerRoute(/^https:\/\/store-\d{3}\.blobstore\.apple\.com\/.{65}\/image+/, new e.CacheFirst(), "GET");
|
||||||
|
});
|
||||||
//# sourceMappingURL=sw.js.map
|
//# sourceMappingURL=sw.js.map
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
&:not(.modular-fs) {
|
&:not(.modular-fs) {
|
||||||
.app-drawer {
|
.app-drawer {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
top : 0;
|
top: 0;
|
||||||
right : 0;
|
right: 0;
|
||||||
height : 100%;
|
height: 100%;
|
||||||
box-shadow : unset;
|
box-shadow: unset;
|
||||||
border-left : 1px solid var(--color2);
|
border-left: 1px solid var(--color2);
|
||||||
background : var(--color1);
|
background: var(--color1);
|
||||||
margin-right : 0px;
|
margin-right: 0px;
|
||||||
position : relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawertransition-enter-active,
|
.drawertransition-enter-active,
|
||||||
.drawertransition-leave-active {
|
.drawertransition-leave-active {
|
||||||
transition: margin .25s var(--appleEase), opacity .25s var(--appleEase);
|
transition: margin 0.25s var(--appleEase), opacity 0.25s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawertransition-enter,
|
.drawertransition-enter,
|
||||||
|
@ -24,12 +24,12 @@
|
||||||
@media screen and (max-width: 1120px) {
|
@media screen and (max-width: 1120px) {
|
||||||
.app-drawer {
|
.app-drawer {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
position : absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawertransition-enter-active,
|
.drawertransition-enter-active,
|
||||||
.drawertransition-leave-active {
|
.drawertransition-leave-active {
|
||||||
transition: right .25s var(--appleEase), opacity .25s var(--appleEase);
|
transition: right 0.25s var(--appleEase), opacity 0.25s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawertransition-enter,
|
.drawertransition-enter,
|
||||||
|
@ -37,5 +37,4 @@
|
||||||
right: -300px;
|
right: -300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
body {
|
body {
|
||||||
--ciderShadow-Generic : var(--mediaItemShadow);
|
--ciderShadow-Generic: var(--mediaItemShadow);
|
||||||
--mediaItemShadow-Shadow : var(--mediaItemShadow);
|
--mediaItemShadow-Shadow: var(--mediaItemShadow);
|
||||||
--mediaItemShadow-ShadowSubtle: var(--mediaItemShadow);
|
--mediaItemShadow-ShadowSubtle: var(--mediaItemShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-artwork-container {
|
.bg-artwork-container {
|
||||||
display : none;
|
display: none;
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
|
|
||||||
.bg-artwork {
|
.bg-artwork {
|
||||||
|
@ -13,7 +13,6 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.app-chrome:not(.chrome-bottom) {
|
.app-chrome:not(.chrome-bottom) {
|
||||||
backdrop-filter: unset;
|
backdrop-filter: unset;
|
||||||
background-color: var(--baseColor);
|
background-color: var(--baseColor);
|
||||||
|
@ -23,20 +22,21 @@ body {
|
||||||
background: rgb(30 30 30);
|
background: rgb(30 30 30);
|
||||||
}
|
}
|
||||||
.menu-panel .menu-panel-body .menu-option::before {
|
.menu-panel .menu-panel-body .menu-option::before {
|
||||||
transition: unset!important;
|
transition: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app.twopanel .app-chrome:not(.chrome-bottom) .app-chrome--center .top-nav-group .app-sidebar-item:before {
|
#app.twopanel .app-chrome:not(.chrome-bottom) .app-chrome--center .top-nav-group .app-sidebar-item:before {
|
||||||
transition: unset!important;
|
transition: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playback-button:before, .playback-button--small:before {
|
.playback-button:before,
|
||||||
transition: unset!important;
|
.playback-button--small:before {
|
||||||
|
transition: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-header {
|
.floating-header {
|
||||||
backdrop-filter: unset!important;
|
backdrop-filter: unset !important;
|
||||||
background: rgb(0 0 0 / 80%)!important;
|
background: rgb(0 0 0 / 80%) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.replaycard-enter-active,
|
.replaycard-enter-active,
|
||||||
|
@ -46,7 +46,7 @@ body {
|
||||||
|
|
||||||
.replaycard-enter,
|
.replaycard-enter,
|
||||||
.replaycard-leave-to {
|
.replaycard-leave-to {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform: translateY(20px);
|
transform: translateY(20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,13 +57,13 @@ body {
|
||||||
|
|
||||||
.modal-enter,
|
.modal-enter,
|
||||||
.modal-leave-to {
|
.modal-leave-to {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform: scale(1.10);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade-enter-active,
|
.wpfade-enter-active,
|
||||||
.wpfade-leave-active {
|
.wpfade-leave-active {
|
||||||
transition: opacity .1s var(--appleEase);
|
transition: opacity 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade-enter,
|
.wpfade-enter,
|
||||||
|
@ -73,37 +73,36 @@ body {
|
||||||
|
|
||||||
.wpfade_transform-enter-active,
|
.wpfade_transform-enter-active,
|
||||||
.wpfade_transform-leave-active {
|
.wpfade_transform-leave-active {
|
||||||
transition : unset;
|
transition: unset;
|
||||||
will-change: unset;
|
will-change: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade_transform-enter {
|
.wpfade_transform-enter {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : unset;
|
transform: unset;
|
||||||
will-change: unset;
|
will-change: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade_transform-leave-to {
|
.wpfade_transform-leave-to {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : unset;
|
transform: unset;
|
||||||
will-change: unset;
|
will-change: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.wpfade_transform_backwards-enter-active,
|
.wpfade_transform_backwards-enter-active,
|
||||||
.wpfade_transform_backwards-leave-active {
|
.wpfade_transform_backwards-leave-active {
|
||||||
transition: unset;
|
transition: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade_transform_backwards-enter {
|
.wpfade_transform_backwards-enter {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : unset;
|
transform: unset;
|
||||||
will-change: unset;
|
will-change: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wpfade_transform_backwards-leave-to {
|
.wpfade_transform_backwards-leave-to {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : unset;
|
transform: unset;
|
||||||
will-change: unset;
|
will-change: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ body {
|
||||||
|
|
||||||
.fabfade-enter,
|
.fabfade-enter,
|
||||||
.fabfade-leave-to {
|
.fabfade-leave-to {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform: scale(0.5);
|
transform: scale(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +124,10 @@ body {
|
||||||
|
|
||||||
.fsModeSwitch-enter,
|
.fsModeSwitch-enter,
|
||||||
.fsModeSwitch-leave-to {
|
.fsModeSwitch-leave-to {
|
||||||
transform: scale(1.10);
|
transform: scale(1.1);
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.drawertransition-enter-active,
|
.drawertransition-enter-active,
|
||||||
.drawertransition-leave-active {
|
.drawertransition-leave-active {
|
||||||
transition: unset;
|
transition: unset;
|
||||||
|
|
|
@ -1,49 +1,47 @@
|
||||||
@panelColorsFallback: rgb(30 30 30);
|
@panelColorsFallback: rgb(30 30 30);
|
||||||
@panelColors : rgb(30 30 30 / 45%);
|
@panelColors: rgb(30 30 30 / 45%);
|
||||||
|
|
||||||
.menu-panel {
|
.menu-panel {
|
||||||
.menu-panel-body {
|
.menu-panel-body {
|
||||||
background-color: @panelColors;
|
background-color: @panelColors;
|
||||||
backdrop-filter : blur(32px) saturate(180%);
|
backdrop-filter: blur(32px) saturate(180%);
|
||||||
|
|
||||||
&.menu-panel-body-down {
|
&.menu-panel-body-down {
|
||||||
animation: menuInDown .10s var(--appleEase);
|
animation: menuInDown 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.menu-panel-body-up {
|
&.menu-panel-body-up {
|
||||||
animation: menuInUp .10s var(--appleEase);
|
animation: menuInUp 0.1s var(--appleEase);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes menuInUp {
|
@keyframes menuInUp {
|
||||||
0% {
|
0% {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : translateY(-10px) translate3d(0,0,0);
|
transform: translateY(-10px) translate3d(0, 0, 0);
|
||||||
background: @panelColorsFallback;
|
background: @panelColorsFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity : 1;
|
opacity: 1;
|
||||||
transform : translateY(0);
|
transform: translateY(0);
|
||||||
background: @panelColors;
|
background: @panelColors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes menuInDown {
|
@keyframes menuInDown {
|
||||||
0% {
|
0% {
|
||||||
opacity : 0;
|
opacity: 0;
|
||||||
transform : translateY(10px) translate3d(0,0,0);
|
transform: translateY(10px) translate3d(0, 0, 0);
|
||||||
background: @panelColorsFallback;
|
background: @panelColorsFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity : 1;
|
opacity: 1;
|
||||||
transform : translateY(0);
|
transform: translateY(0);
|
||||||
background: @panelColors;
|
background: @panelColors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square {
|
.cd-mediaitem-square {
|
||||||
|
@ -55,46 +53,45 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cd-mediaitem-square:not(.mediaitem-card) {
|
.cd-mediaitem-square:not(.mediaitem-card) {
|
||||||
transition : transform .2s var(--appleEase);
|
transition: transform 0.2s var(--appleEase);
|
||||||
transition-delay: .1s;
|
transition-delay: 0.1s;
|
||||||
|
|
||||||
|
.artwork-container {
|
||||||
|
}
|
||||||
|
|
||||||
.artwork-container {}
|
.info-rect {
|
||||||
|
}
|
||||||
.info-rect {}
|
|
||||||
|
|
||||||
.artwork-container,
|
.artwork-container,
|
||||||
.info-rect {
|
.info-rect {
|
||||||
transition : transform .22s var(--appleEase);
|
transition: transform 0.22s var(--appleEase);
|
||||||
transition-delay: .05s;
|
transition-delay: 0.05s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.artwork-container {
|
.artwork-container {
|
||||||
transform : scale(0.962) translateZ(0);
|
transform: scale(0.962) translateZ(0);
|
||||||
transition : transform .1s var(--appleEase);
|
transition: transform 0.1s var(--appleEase);
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.artwork-container {
|
.artwork-container {
|
||||||
transform : scale(1.0);
|
transform: scale(1);
|
||||||
transition : transform .1s var(--appleEase);
|
transition: transform 0.1s var(--appleEase);
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.info-rect {
|
.info-rect {
|
||||||
z-index : 1;
|
z-index: 1;
|
||||||
transition : transform .1s var(--appleEase);
|
transition: transform 0.1s var(--appleEase);
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
transform : translateY(8px) translate3d(0,0,0);
|
transform: translateY(8px) translate3d(0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,16 +104,15 @@
|
||||||
|
|
||||||
.wpfade_transform-enter {
|
.wpfade_transform-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(50%) translate3d(0,0,0);
|
transform: translateX(50%) translate3d(0, 0, 0);
|
||||||
will-change: opacity, transform;
|
will-change: opacity, transform;
|
||||||
}
|
}
|
||||||
.wpfade_transform-leave-to {
|
.wpfade_transform-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-50%) translate3d(0,0,0);
|
transform: translateX(-50%) translate3d(0, 0, 0);
|
||||||
will-change: opacity, transform;
|
will-change: opacity, transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.wpfade_transform_backwards-enter-active,
|
.wpfade_transform_backwards-enter-active,
|
||||||
.wpfade_transform_backwards-leave-active {
|
.wpfade_transform_backwards-leave-active {
|
||||||
--transitionTime: 0.2s;
|
--transitionTime: 0.2s;
|
||||||
|
@ -125,11 +121,11 @@
|
||||||
|
|
||||||
.wpfade_transform_backwards-enter {
|
.wpfade_transform_backwards-enter {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-50%) translate3d(0,0,0);
|
transform: translateX(-50%) translate3d(0, 0, 0);
|
||||||
will-change: opacity, transform;
|
will-change: opacity, transform;
|
||||||
}
|
}
|
||||||
.wpfade_transform_backwards-leave-to {
|
.wpfade_transform_backwards-leave-to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(50%) translate3d(0,0,0);
|
transform: translateX(50%) translate3d(0, 0, 0);
|
||||||
will-change: opacity, transform;
|
will-change: opacity, transform;
|
||||||
}
|
}
|
|
@ -1,25 +1,26 @@
|
||||||
// Apple Music Listen Now Page
|
// Apple Music Listen Now Page
|
||||||
// URL : https://amp-api.music.apple.com/v1/me/recommendations?timezone=+00:00
|
// URL : https://amp-api.music.apple.com/v1/me/recommendations?timezone=+00:00
|
||||||
// &with=friendsMix,library,social&art[social-profiles:url]=c
|
// &with=friendsMix,library,social&art[social-profiles:url]=c
|
||||||
// &name=listen-now&art[url]=c,f&omit[resource]=autos
|
// &name=listen-now&art[url]=c,f&omit[resource]=autos
|
||||||
// &relate[editorial-items]=contents
|
// &relate[editorial-items]=contents
|
||||||
// &extend=editorialCard,editorialVideo
|
// &extend=editorialCard,editorialVideo
|
||||||
// &extend[albums]=artistUrl
|
// &extend[albums]=artistUrl
|
||||||
// &extend[library-albums]=artistUrl
|
// &extend[library-albums]=artistUrl
|
||||||
// &extend[playlists]=artistNames,editorialArtwork
|
// &extend[playlists]=artistNames,editorialArtwork
|
||||||
// &extend[library-playlists]=artistNames,editorialArtwork
|
// &extend[library-playlists]=artistNames,editorialArtwork
|
||||||
// &extend[social-profiles]=topGenreNames&include[albums]=artists
|
// &extend[social-profiles]=topGenreNames&include[albums]=artists
|
||||||
// &include[songs]=artists&include[music-videos]=artists
|
// &include[songs]=artists&include[music-videos]=artists
|
||||||
// &fields[albums]=artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url
|
// &fields[albums]=artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url
|
||||||
// &fields[artists]=name,url&extend[stations]=airDate,supportsAirTimeUpdates&meta[stations]=inflectionPoints
|
// &fields[artists]=name,url&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-profiles,social-upsells
|
// &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-profiles,social-upsells
|
||||||
// &l=en-gb&platform=web
|
// &l=en-gb&platform=web
|
||||||
|
|
||||||
await app.mk.api.personalRecommendations("",
|
await app.mk.api.personalRecommendations(
|
||||||
|
"",
|
||||||
{
|
{
|
||||||
name: "listen-now",
|
name: "listen-now",
|
||||||
with: "friendsMix,library,social",
|
with: "friendsMix,library,social",
|
||||||
"art[social-profiles:url]":"c",
|
"art[social-profiles:url]": "c",
|
||||||
"art[url]": "c,f",
|
"art[url]": "c,f",
|
||||||
"omit[resource]": "autos",
|
"omit[resource]": "autos",
|
||||||
"relate[editorial-items]": "contents",
|
"relate[editorial-items]": "contents",
|
||||||
|
@ -37,17 +38,17 @@ await app.mk.api.personalRecommendations("",
|
||||||
"extend[stations]": ["airDate", "supportsAirTimeUpdates"],
|
"extend[stations]": ["airDate", "supportsAirTimeUpdates"],
|
||||||
"meta[stations]": "inflectionPoints",
|
"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-profiles,social-upsells",
|
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-profiles,social-upsells",
|
||||||
l:"en-gb",
|
l: "en-gb",
|
||||||
platform:"web"
|
platform: "web",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
includeResponseMeta: !0,
|
includeResponseMeta: !0,
|
||||||
reload: !0
|
reload: !0,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Browse page
|
// Browse page
|
||||||
await app.mk.api.groupings("",
|
await app.mk.api.groupings("", {
|
||||||
{
|
|
||||||
platform: "web",
|
platform: "web",
|
||||||
name: "music",
|
name: "music",
|
||||||
l: "en-gb",
|
l: "en-gb",
|
||||||
|
@ -57,100 +58,112 @@ await app.mk.api.groupings("",
|
||||||
"include[music-videos]": "artists",
|
"include[music-videos]": "artists",
|
||||||
extend: "editorialArtwork,artistUrl",
|
extend: "editorialArtwork,artistUrl",
|
||||||
"fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes",
|
"fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes",
|
||||||
"art[url]": "f"
|
"art[url]": "f",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Radio page
|
// Radio page
|
||||||
await app.mk.api.recentRadioStations("",
|
await app.mk.api.recentRadioStations("", {
|
||||||
{l: "en-gb",
|
l: "en-gb",
|
||||||
"platform": "web",
|
platform: "web",
|
||||||
"art[url]": "f"});
|
"art[url]": "f",
|
||||||
|
});
|
||||||
|
|
||||||
// Recently Added
|
// Recently Added
|
||||||
await app.mk.api.library.recentlyAdded({
|
await app.mk.api.library.recentlyAdded(
|
||||||
"platform": "web",
|
{
|
||||||
|
platform: "web",
|
||||||
include: {
|
include: {
|
||||||
"library-albums": ["artists"],
|
"library-albums": ["artists"],
|
||||||
"library-artists": ["catalog"]
|
"library-artists": ["catalog"],
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
artists: ["url"],
|
artists: ["url"],
|
||||||
albums: "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url"
|
albums: "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url",
|
||||||
},
|
},
|
||||||
includeOnly: ["catalog", "artists"],
|
includeOnly: ["catalog", "artists"],
|
||||||
limit: 25
|
limit: 25,
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
reload: !0,
|
reload: !0,
|
||||||
includePagination: !0
|
includePagination: !0,
|
||||||
})
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Songs
|
// Songs
|
||||||
await app.mk.api.library.songs({limit: 100}).then((data)=>{
|
await app.mk.api.library.songs({ limit: 100 }).then((data) => {
|
||||||
console.log(data)
|
console.log(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Artists
|
// Artists
|
||||||
await app.mk.api.library.artists({limit: 100}).then((data)=>{
|
await app.mk.api.library.artists({ limit: 100 }).then((data) => {
|
||||||
console.log(data)
|
console.log(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Artists
|
// Artists
|
||||||
await app.mk.api.library.albums({limit: 100}).then((data)=>{
|
await app.mk.api.library.albums({ limit: 100 }).then((data) => {
|
||||||
console.log(data)
|
console.log(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Albums
|
// Albums
|
||||||
// does not like limit = 100 for some reason
|
// does not like limit = 100 for some reason
|
||||||
await app.mk.api.library.albums({limit: 50}).then((data)=>{
|
await app.mk.api.library.albums({ limit: 50 }).then((data) => {
|
||||||
console.log(data)
|
console.log(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Made For You
|
// Made For You
|
||||||
app.mk.api.recommendations("",{extend: "editorialArtwork,artistUrl"})
|
app.mk.api.recommendations("", { extend: "editorialArtwork,artistUrl" });
|
||||||
|
|
||||||
// Library with library length
|
// Library with library length
|
||||||
await app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((data)=>{
|
await app.mk.api.library.songs("", { limit: 100 }, { includeResponseMeta: !0 }).then((data) => {
|
||||||
console.log(data)
|
console.log(data);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Artist View Top Songs
|
// Artist View Top Songs
|
||||||
app.mk.api.artistView("325096253", "top-songs", {}, {view: "top-songs", includeResponseMeta: !0})
|
app.mk.api.artistView("325096253", "top-songs", {}, { view: "top-songs", includeResponseMeta: !0 });
|
||||||
|
|
||||||
// Artist Page Data
|
// Artist Page Data
|
||||||
app.mkapi("artists", false, "412778295", {
|
app
|
||||||
"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",
|
.mkapi(
|
||||||
"extend": "artistBio,bornOrFormed,editorialArtwork,editorialVideo,isGroup,origin,hero",
|
"artists",
|
||||||
|
false,
|
||||||
|
"412778295",
|
||||||
|
{
|
||||||
|
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[playlists]": "trackCount",
|
"extend[playlists]": "trackCount",
|
||||||
"omit[resource:songs]": "relationships",
|
"omit[resource:songs]": "relationships",
|
||||||
"fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url,trackCount",
|
"fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url,trackCount",
|
||||||
"limit[artists:top-songs]": 20,
|
"limit[artists:top-songs]": 20,
|
||||||
"art[url]": "f"
|
"art[url]": "f",
|
||||||
}, {includeResponseMeta: !0}).then((data)=>{
|
},
|
||||||
console.log(data)
|
{ includeResponseMeta: !0 }
|
||||||
})
|
)
|
||||||
|
.then((data) => {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
// download entire library
|
// download entire library
|
||||||
var library = []
|
var library = [];
|
||||||
var downloaded = null;
|
var downloaded = null;
|
||||||
function downloadChunk () {
|
function downloadChunk() {
|
||||||
if (downloaded == null) {
|
if (downloaded == null) {
|
||||||
app.mk.api.library.songs("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
app.mk.api.library.songs("", { limit: 100 }, { includeResponseMeta: !0 }).then((response) => {
|
||||||
processChunk(response)
|
processChunk(response);
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
downloaded.next("", {limit: 100}, {includeResponseMeta: !0}).then((response)=>{
|
downloaded.next("", { limit: 100 }, { includeResponseMeta: !0 }).then((response) => {
|
||||||
processChunk(response)
|
processChunk(response);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function processChunk (response) {
|
function processChunk(response) {
|
||||||
downloaded = response
|
downloaded = response;
|
||||||
library = library.concat(downloaded.data)
|
library = library.concat(downloaded.data);
|
||||||
if (downloaded.meta.total > library.length) {
|
if (downloaded.meta.total > library.length) {
|
||||||
console.log(`downloading next chunk - ${library.length} songs so far`)
|
console.log(`downloading next chunk - ${library.length} songs so far`);
|
||||||
downloadChunk()
|
downloadChunk();
|
||||||
} else {
|
} else {
|
||||||
console.log(library)
|
console.log(library);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,23 +171,23 @@ function processChunk (response) {
|
||||||
// recentPlayed() -> recently played songs ?
|
// recentPlayed() -> recently played songs ?
|
||||||
|
|
||||||
// create Artist / Song/ Album stations:
|
// create Artist / Song/ Album stations:
|
||||||
app.mk.setStationQueue({artist:"1258279972"})
|
app.mk.setStationQueue({ artist: "1258279972" });
|
||||||
app.mk.setStationQueue({song:"1437308307"}) // yes the song id here can be the albumId, but just keep using the song:
|
app.mk.setStationQueue({ song: "1437308307" }); // yes the song id here can be the albumId, but just keep using the song:
|
||||||
|
|
||||||
// Sorting Playlists, send an array of tracks in the format below
|
// Sorting Playlists, send an array of tracks in the format below
|
||||||
// playlist must be fully recursively downloaded first before sorting
|
// playlist must be fully recursively downloaded first before sorting
|
||||||
|
|
||||||
app.mk.api.library.putPlaylistTracklisting(app.showingPlaylist.attributes.playParams.id, [
|
app.mk.api.library.putPlaylistTracklisting(app.showingPlaylist.attributes.playParams.id, [
|
||||||
{
|
{
|
||||||
"id": relationships.tracks.data[X].id,
|
id: relationships.tracks.data[X].id,
|
||||||
"type": relationships.tracks.data[X].type
|
type: relationships.tracks.data[X].type,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": relationships.tracks.data[X].id,
|
id: relationships.tracks.data[X].id,
|
||||||
"type": relationships.tracks.data[X].type
|
type: relationships.tracks.data[X].type,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": relationships.tracks.data[X].id,
|
id: relationships.tracks.data[X].id,
|
||||||
"type": relationships.tracks.data[X].type
|
type: relationships.tracks.data[X].type,
|
||||||
},
|
},
|
||||||
])
|
]);
|
||||||
|
|
|
@ -141,9 +141,12 @@
|
||||||
v-if="drawer.open && drawer.panel == 'lyrics' && lyrics && lyrics != [] && lyrics.length > 0">
|
v-if="drawer.open && drawer.panel == 'lyrics' && lyrics && lyrics != [] && lyrics.length > 0">
|
||||||
<div class="bgArtworkMaterial">
|
<div class="bgArtworkMaterial">
|
||||||
<div class="bg-artwork-container">
|
<div class="bg-artwork-container">
|
||||||
<img v-if="(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork a" :src="$store.state.artwork.playerLCD">
|
<img v-if="(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork a"
|
||||||
<img v-if="(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork b" :src="$store.state.artwork.playerLCD">
|
:src="$store.state.artwork.playerLCD">
|
||||||
<img v-if="!(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork no-animation" :src="$store.state.artwork.playerLCD">
|
<img v-if="(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork b"
|
||||||
|
:src="$store.state.artwork.playerLCD">
|
||||||
|
<img v-if="!(cfg.visual.bg_artwork_rotation && animateBackground)" class="bg-artwork no-animation"
|
||||||
|
:src="$store.state.artwork.playerLCD">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="mk.currentPlaybackTime - lyricOffset" :lyrics="lyrics"
|
<lyrics-view v-if="drawer.panel == 'lyrics'" :time="mk.currentPlaybackTime - lyricOffset" :lyrics="lyrics"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<div class="app-chrome chrome-bottom" v-if="getThemeDirective('windowLayout') == 'twopanel'" :style="{'display': chrome.topChromeVisible ? '' : 'none'}">
|
<div class="app-chrome chrome-bottom" v-if="getThemeDirective('windowLayout') == 'twopanel'"
|
||||||
|
:style="{'display': chrome.topChromeVisible ? '' : 'none'}">
|
||||||
<div class="app-chrome--left">
|
<div class="app-chrome--left">
|
||||||
<div class="app-chrome-item playback-controls">
|
<div class="app-chrome-item playback-controls">
|
||||||
<template v-if="mkReady()">
|
<template v-if="mkReady()">
|
||||||
|
@ -16,15 +17,23 @@
|
||||||
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
<mediaitem-artwork :url="currentArtUrl"></mediaitem-artwork>
|
||||||
</div>
|
</div>
|
||||||
<div class="song-name">{{ mk.nowPlayingItem["attributes"]["name"] }}</div>
|
<div class="song-name">{{ mk.nowPlayingItem["attributes"]["name"] }}</div>
|
||||||
<div class="song-artist" @click="getNowPlayingItemDetailed(`artist`)">{{ mk.nowPlayingItem["attributes"]["artistName"] }}</div>
|
<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>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="btn-group" style="width:100%;">
|
<div class="btn-group" style="width:100%;">
|
||||||
<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%;"
|
||||||
<button class="md-btn md-btn-small" style="width: 100%;" @click="drawer.open = false; fullscreen(true)">{{ $root.getLz("term.fullscreenView") }}</button>
|
@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)">{{
|
||||||
|
$root.getLz("term.fullscreenView") }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</b-popover>
|
</b-popover>
|
||||||
|
@ -39,20 +48,26 @@
|
||||||
<div class="song-artist" @click="getNowPlayingItemDetailed(`artist`)">
|
<div class="song-artist" @click="getNowPlayingItemDetailed(`artist`)">
|
||||||
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
{{ mk.nowPlayingItem["attributes"]["artistName"] }}
|
||||||
</div>
|
</div>
|
||||||
<div class="song-album" @click="getNowPlayingItemDetailed('album')" v-if='mk.nowPlayingItem["attributes"]["albumName"]'>
|
<div class="song-album" @click="getNowPlayingItemDetailed('album')"
|
||||||
|
v-if='mk.nowPlayingItem["attributes"]["albumName"]'>
|
||||||
{{(mk.nowPlayingItem["attributes"]["albumName"]) ?
|
{{(mk.nowPlayingItem["attributes"]["albumName"]) ?
|
||||||
(mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
|
(mk.nowPlayingItem["attributes"]["albumName"]) : "" }}
|
||||||
</div>
|
</div>
|
||||||
<div class="chrome-icon-container">
|
<div class="chrome-icon-container">
|
||||||
<div class="audio-type private-icon" v-if="cfg.general.privateEnabled === true"></div>
|
<div class="audio-type private-icon" v-if="cfg.general.privateEnabled === true"></div>
|
||||||
<div class="audio-type spatial-icon" v-if="cfg.audio.maikiwiAudio.spatial === true"
|
<div class="audio-type spatial-icon" v-if="cfg.audio.maikiwiAudio.spatial === true"
|
||||||
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization') + ' (' + getProfileLz('CTS', cfg.audio.maikiwiAudio.spatialProfile) + ')'" v-b-tooltip.hover
|
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization') + ' (' + getProfileLz('CTS', cfg.audio.maikiwiAudio.spatialProfile) + ')'"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
<div class="audio-type lossless-icon" v-if="(mk.nowPlayingItem?.localFilesMetadata?.lossless ?? false) === true"
|
<div class="audio-type lossless-icon"
|
||||||
:title="mk.nowPlayingItem?.localFilesMetadata?.bitDepth +'-bit / '+ mk.nowPlayingItem?.localFilesMetadata?.sampleRate/1000 + ' kHz ' + mk.nowPlayingItem.localFilesMetadata.container" v-b-tooltip.hover
|
v-if="(mk.nowPlayingItem?.localFilesMetadata?.lossless ?? false) === true"
|
||||||
|
:title="mk.nowPlayingItem?.localFilesMetadata?.bitDepth +'-bit / '+ mk.nowPlayingItem?.localFilesMetadata?.sampleRate/1000 + ' kHz ' + mk.nowPlayingItem.localFilesMetadata.container"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
<div class="audio-type ppe-icon" v-if="mk.nowPlayingItem.localFilesMetadata == null && cfg.audio.maikiwiAudio.ciderPPE === true"
|
<div class="audio-type ppe-icon"
|
||||||
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE')" v-b-tooltip.hover
|
v-if="mk.nowPlayingItem.localFilesMetadata == null && cfg.audio.maikiwiAudio.ciderPPE === true"
|
||||||
|
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE')"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -87,7 +102,8 @@
|
||||||
<div class="app-chrome--center">
|
<div class="app-chrome--center">
|
||||||
<div class="app-chrome-playback-duration-bottom">
|
<div class="app-chrome-playback-duration-bottom">
|
||||||
<b-row v-if="mkReady()">
|
<b-row v-if="mkReady()">
|
||||||
<b-col sm="auto" v-if="!mk.nowPlayingItem?.isLiveRadioStation">{{ convertTime(getSongProgress()) }}</b-col>
|
<b-col sm="auto" v-if="!mk.nowPlayingItem?.isLiveRadioStation">{{ convertTime(getSongProgress()) }}
|
||||||
|
</b-col>
|
||||||
<b-col sm="auto" v-else>--:--</b-col>
|
<b-col sm="auto" v-else>--:--</b-col>
|
||||||
<b-col>
|
<b-col>
|
||||||
<input type="range" step="0.01" min="0" :style="progressBarStyle()"
|
<input type="range" step="0.01" min="0" :style="progressBarStyle()"
|
||||||
|
@ -96,13 +112,16 @@
|
||||||
@touchend="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()">
|
||||||
</b-col>
|
</b-col>
|
||||||
<b-col sm="auto" v-if="!mk.nowPlayingItem?.isLiveRadioStation">{{ 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-col sm="auto" v-else>{{ getLz("term.live") }}</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-playback-controls">
|
<div class="app-chrome-playback-controls">
|
||||||
<div class="app-chrome-item">
|
<div class="app-chrome-item">
|
||||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0" :class="isDisabled() && 'disabled'"
|
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||||
|
:class="isDisabled() && 'disabled'"
|
||||||
@click="mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')"
|
@click="mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
<button class="playback-button--small shuffle active" v-else :class="isDisabled() && 'disabled'"
|
<button class="playback-button--small shuffle active" v-else :class="isDisabled() && 'disabled'"
|
||||||
|
@ -114,7 +133,8 @@
|
||||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item">
|
<div class="app-chrome-item">
|
||||||
<button class="playback-button stop" @click="mk.stop()" v-if="mk.isPlaying && mk.nowPlayingItem.attributes.playParams.kind == 'radioStation'"
|
<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>
|
:title="$root.getLz('term.stop')" v-b-tooltip.hover></button>
|
||||||
<button class="playback-button pause" @click="mk.pause()" v-else-if="mk.isPlaying"
|
<button class="playback-button pause" @click="mk.pause()" v-else-if="mk.isPlaying"
|
||||||
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.pause')" v-b-tooltip.hover></button>
|
||||||
|
@ -126,13 +146,16 @@
|
||||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item">
|
<div class="app-chrome-item">
|
||||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0" :class="isDisabled() && 'disabled'"
|
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||||
|
:class="isDisabled() && 'disabled'"
|
||||||
@click="mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')"
|
@click="mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2" :class="isDisabled() && 'disabled'"
|
<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-else-if="mk.repeatMode == 1" :title="$root.getLz('term.disableRepeatOne')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 0" :class="isDisabled() && 'disabled'"
|
<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-else-if="mk.repeatMode == 2" :title="$root.getLz('term.disableRepeat')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<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--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="window-controls-macos">
|
||||||
<div class="close" @click="ipcRenderer.send('close')"></div>
|
<div class="close" @click="ipcRenderer.send('close')"></div>
|
||||||
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
<div class="minimize" @click="ipcRenderer.send('minimize')"></div>
|
||||||
|
@ -16,7 +17,8 @@
|
||||||
<template v-if="getThemeDirective('appNavigation') != 'seperate'">
|
<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">
|
<div class="app-chrome-item">
|
||||||
<button class="playback-button navigation" @click="navigateBack()" :title="$root.getLz('term.navigateBack')"
|
<button class="playback-button navigation" @click="navigateBack()"
|
||||||
|
:title="$root.getLz('term.navigateBack')"
|
||||||
v-b-tooltip.hover>
|
v-b-tooltip.hover>
|
||||||
<svg-icon url="./views/svg/chevron-left.svg"></svg-icon>
|
<svg-icon url="./views/svg/chevron-left.svg"></svg-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -45,13 +47,17 @@
|
||||||
<template v-if="getThemeDirective('windowLayout') != 'twopanel'">
|
<template v-if="getThemeDirective('windowLayout') != 'twopanel'">
|
||||||
<div class="app-chrome-item playback-control-buttons">
|
<div class="app-chrome-item playback-control-buttons">
|
||||||
<div class="app-chrome-item display--large">
|
<div class="app-chrome-item display--large">
|
||||||
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0" :class="isDisabled() && 'disabled'"
|
<button class="playback-button--small shuffle" v-if="mk.shuffleMode == 0"
|
||||||
@click="mk.shuffleMode = 1" :title="$root.getLz('term.enableShuffle')" v-b-tooltip.hover></button>
|
: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'"
|
<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>
|
@click="mk.shuffleMode = 0" :title="$root.getLz('term.disableShuffle')"
|
||||||
|
v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item display--large">
|
<div class="app-chrome-item display--large">
|
||||||
<button class="playback-button previous" @click="prevButton()" :class="isPrevDisabled() && 'disabled'"
|
<button class="playback-button previous" @click="prevButton()"
|
||||||
|
:class="isPrevDisabled() && 'disabled'"
|
||||||
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.previous')" v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item display--large">
|
<div class="app-chrome-item display--large">
|
||||||
|
@ -64,17 +70,21 @@
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item display--large">
|
<div class="app-chrome-item display--large">
|
||||||
<button class="playback-button next" @click="skipToNextItem()" :class="isNextDisabled() && 'disabled'"
|
<button class="playback-button next" @click="skipToNextItem()"
|
||||||
|
:class="isNextDisabled() && 'disabled'"
|
||||||
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.next')" v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item display--large">
|
<div class="app-chrome-item display--large">
|
||||||
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0" :class="isDisabled() && 'disabled'"
|
<button class="playback-button--small repeat" v-if="mk.repeatMode == 0"
|
||||||
@click="mk.repeatMode = 1" :title="$root.getLz('term.enableRepeatOne')" v-b-tooltip.hover></button>
|
: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"
|
<button class="playback-button--small repeat repeatOne" @click="mk.repeatMode = 2"
|
||||||
:class="isDisabled() && 'disabled'" v-else-if="mk.repeatMode == 1"
|
:class="isDisabled() && 'disabled'" v-else-if="mk.repeatMode == 1"
|
||||||
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
|
:title="$root.getLz('term.disableRepeatOne')" v-b-tooltip.hover></button>
|
||||||
<button class="playback-button--small repeat active" @click="mk.repeatMode = 0"
|
<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')"
|
:class="isDisabled() && 'disabled'" v-else-if="mk.repeatMode == 2"
|
||||||
|
:title="$root.getLz('term.disableRepeat')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,10 +121,12 @@
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="btn-group" style="width: 100%">
|
<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") }}
|
{{ $root.getLz("term.miniplayer") }}
|
||||||
</button>
|
</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") }}
|
{{ $root.getLz("term.fullscreenView") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -124,20 +136,26 @@
|
||||||
<div class="chrome-icon-container">
|
<div class="chrome-icon-container">
|
||||||
<div class="audio-type private-icon" v-if="cfg.general.privateEnabled === true"></div>
|
<div class="audio-type private-icon" v-if="cfg.general.privateEnabled === true"></div>
|
||||||
<div class="audio-type spatial-icon" v-if="cfg.audio.maikiwiAudio.spatial === true"
|
<div class="audio-type spatial-icon" v-if="cfg.audio.maikiwiAudio.spatial === true"
|
||||||
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization') + ' (' + getProfileLz('CTS', cfg.audio.maikiwiAudio.spatialProfile) + ')'" v-b-tooltip.hover
|
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization') + ' (' + getProfileLz('CTS', cfg.audio.maikiwiAudio.spatialProfile) + ')'"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
<div class="audio-type lossless-icon" v-if="(mk.nowPlayingItem?.localFilesMetadata?.lossless ?? false) === true"
|
<div class="audio-type lossless-icon"
|
||||||
:title="mk.nowPlayingItem?.localFilesMetadata?.bitDepth +'-bit / '+ mk.nowPlayingItem?.localFilesMetadata?.sampleRate/1000 + ' kHz ' + mk.nowPlayingItem.localFilesMetadata.container" v-b-tooltip.hover
|
v-if="(mk.nowPlayingItem?.localFilesMetadata?.lossless ?? false) === true"
|
||||||
|
:title="mk.nowPlayingItem?.localFilesMetadata?.bitDepth +'-bit / '+ mk.nowPlayingItem?.localFilesMetadata?.sampleRate/1000 + ' kHz ' + mk.nowPlayingItem.localFilesMetadata.container"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
<div class="audio-type ppe-icon" v-if="mk.nowPlayingItem.localFilesMetadata == null && cfg.audio.maikiwiAudio.ciderPPE === true"
|
<div class="audio-type ppe-icon"
|
||||||
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE')" v-b-tooltip.hover
|
v-if="mk.nowPlayingItem.localFilesMetadata == null && cfg.audio.maikiwiAudio.ciderPPE === true"
|
||||||
|
:title="$root.getLz('settings.option.audio.enableAdvancedFunctionality.ciderPPE')"
|
||||||
|
v-b-tooltip.hover
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-rect">
|
<div class="info-rect">
|
||||||
<div class="song-name"
|
<div class="song-name"
|
||||||
:class="[isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-name') ? 'marquee' : '']">
|
:class="[isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-name') ? 'marquee' : '']">
|
||||||
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
{{ mk.nowPlayingItem["attributes"]["name"] }}
|
||||||
<div class="explicit-icon" v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
|
<div class="explicit-icon"
|
||||||
|
v-if="mk.nowPlayingItem['attributes']['contentRating'] == 'explicit'"
|
||||||
style="display: inline-block"></div>
|
style="display: inline-block"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="song-artist-album">
|
<div class="song-artist-album">
|
||||||
|
@ -208,13 +226,17 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item" v-else>
|
<div class="app-chrome-item" v-else>
|
||||||
<div class="top-nav-group">
|
<div class="top-nav-group">
|
||||||
<sidebar-library-item :name="$root.getLz('home.title')" svg-icon="./assets/feather/home.svg" svg-icon-name="home" page="home">
|
<sidebar-library-item :name="$root.getLz('home.title')" svg-icon="./assets/feather/home.svg"
|
||||||
|
svg-icon-name="home" page="home">
|
||||||
</sidebar-library-item>
|
</sidebar-library-item>
|
||||||
<sidebar-library-item :name="$root.getLz('term.listenNow')" svg-icon="./assets/feather/play-circle.svg" svg-icon-name="listenNow"
|
<sidebar-library-item :name="$root.getLz('term.listenNow')" svg-icon="./assets/feather/play-circle.svg"
|
||||||
|
svg-icon-name="listenNow"
|
||||||
page="listen_now"></sidebar-library-item>
|
page="listen_now"></sidebar-library-item>
|
||||||
<sidebar-library-item :name="$root.getLz('term.browse')" svg-icon="./assets/feather/globe.svg" svg-icon-name="browse" page="browse">
|
<sidebar-library-item :name="$root.getLz('term.browse')" svg-icon="./assets/feather/globe.svg"
|
||||||
|
svg-icon-name="browse" page="browse">
|
||||||
</sidebar-library-item>
|
</sidebar-library-item>
|
||||||
<sidebar-library-item :name="$root.getLz('term.radio')" svg-icon="./assets/feather/radio.svg" svg-icon-name="radio" page="radio">
|
<sidebar-library-item :name="$root.getLz('term.radio')" svg-icon="./assets/feather/radio.svg"
|
||||||
|
svg-icon-name="radio" page="radio">
|
||||||
</sidebar-library-item>
|
</sidebar-library-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -224,9 +246,11 @@
|
||||||
<div class="app-chrome-item volume display--large">
|
<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}"
|
:class="{'active': this.cfg.audio.volume == 0}"
|
||||||
:title="cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')" v-b-tooltip.hover></button>
|
: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"
|
<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
|
v-model="mk.volume" v-if="typeof mk.volume != 'undefined'" @change="checkMuteChange()"
|
||||||
|
v-b-tooltip.hover
|
||||||
:title="formatVolumeTooltip()" />
|
:title="formatVolumeTooltip()" />
|
||||||
</div>
|
</div>
|
||||||
<div class="app-chrome-item generic">
|
<div class="app-chrome-item generic">
|
||||||
|
@ -244,7 +268,8 @@
|
||||||
:class="{'active': drawer.panel == 'lyrics'}" @click="invokeDrawer('lyrics')"></button>
|
:class="{'active': drawer.panel == 'lyrics'}" @click="invokeDrawer('lyrics')"></button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<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>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -252,9 +277,11 @@
|
||||||
<div class="app-chrome-item search">
|
<div class="app-chrome-item search">
|
||||||
<div class="search-input-container">
|
<div class="search-input-container">
|
||||||
<div class="search-input--icon"></div>
|
<div class="search-input--icon"></div>
|
||||||
<input type="search" spellcheck="false" @click="$root.appRoute('search');" @focus="search.showHints = true"
|
<input type="search" spellcheck="false" @click="$root.appRoute('search');"
|
||||||
|
@focus="search.showHints = true"
|
||||||
@blur="setTimeout(()=>{search.showHints = false}, 300)"
|
@blur="setTimeout(()=>{search.showHints = false}, 300)"
|
||||||
v-on:keyup.enter="searchQuery();search.showHints = false" @change="$root.appRoute('search');" @input="getSearchHints()"
|
v-on:keyup.enter="searchQuery();search.showHints = false" @change="$root.appRoute('search');"
|
||||||
|
@input="getSearchHints()"
|
||||||
:placeholder="$root.getLz('term.search') + '...'" v-model="search.term" ref="searchInput"
|
:placeholder="$root.getLz('term.search') + '...'" v-model="search.term" ref="searchInput"
|
||||||
class="search-input" />
|
class="search-input" />
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
aria-role="presentation" focusable="false" @click="exitMV();fullscreen(false);">
|
aria-role="presentation" focusable="false" @click="exitMV();fullscreen(false);">
|
||||||
<path
|
<path
|
||||||
d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
d="M10.5 21C4.724 21 0 16.275 0 10.5S4.724 0 10.5 0 21 4.725 21 10.5 16.276 21 10.5 21zm-3.543-5.967a.96.96 0 00.693-.295l2.837-2.842 2.85 2.842c.167.167.41.295.693.295.552 0 1.001-.461 1.001-1.012 0-.281-.115-.512-.295-.704L11.899 10.5l2.85-2.855a.875.875 0 00.295-.68c0-.55-.45-.998-1.001-.998a.871.871 0 00-.668.295l-2.888 2.855-2.862-2.843a.891.891 0 00-.668-.281.99.99 0 00-1.001.986c0 .269.116.512.295.678L9.088 10.5l-2.837 2.843a.926.926 0 00-.295.678c0 .551.45 1.012 1.001 1.012z"
|
||||||
fill-rule="nonzero"/>
|
fill-rule="nonzero" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div id="captions" v-if="lyricon">{{((lyricon) ? ((lyrics.length > 0 && lyrics[currentLyricsLine] &&
|
<div id="captions" v-if="lyricon">{{((lyricon) ? ((lyrics.length > 0 && lyrics[currentLyricsLine] &&
|
||||||
|
@ -93,7 +93,8 @@
|
||||||
:class="{'active': this.cfg.audio.volume == 0}"
|
:class="{'active': this.cfg.audio.volume == 0}"
|
||||||
:title="cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')"
|
:title="cfg.audio.muted ? $root.getLz('term.unmute') : $root.getLz('term.mute')"
|
||||||
v-b-tooltip.hover></button>
|
v-b-tooltip.hover></button>
|
||||||
<input type="range" @wheel="volumeWheel" :step="cfg.audio.volumeStep" min="0" :max="cfg.audio.maxVolume"
|
<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-model="mk.volume" v-if="typeof mk.volume != 'undefined'" @change="checkMuteChange()"
|
||||||
v-b-tooltip.hover :title="formatVolumeTooltip()">
|
v-b-tooltip.hover :title="formatVolumeTooltip()">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script type="text/x-template" id="add-to-playlist">
|
<script type="text/x-template" id="add-to-playlist">
|
||||||
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.resetState()" @contextmenu.self="app.resetState()">
|
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.resetState()"
|
||||||
|
@contextmenu.self="app.resetState()">
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{app.getLz('action.addToPlaylist')}}</div>
|
<div class="modal-title">{{app.getLz('action.addToPlaylist')}}</div>
|
||||||
|
@ -11,7 +12,8 @@
|
||||||
<div class="icon"><%- include("../svg/plus.svg") %></div>
|
<div class="icon"><%- include("../svg/plus.svg") %></div>
|
||||||
<div class="name">{{app.getLz('action.createPlaylist')}}</div>
|
<div class="name">{{app.getLz('action.createPlaylist')}}</div>
|
||||||
</button>
|
</button>
|
||||||
<sidebar-playlist :playlist-select="playlistSelect" :relate-media-items="relateItems" v-for="item in $root.getPlaylistFolderChildren('p.playlistsroot')" :item="item">
|
<sidebar-playlist :playlist-select="playlistSelect" :relate-media-items="relateItems"
|
||||||
|
v-for="item in $root.getPlaylistFolderChildren('p.playlistsroot')" :item="item">
|
||||||
</sidebar-playlist>
|
</sidebar-playlist>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-search">
|
<div class="modal-search">
|
||||||
|
@ -34,7 +36,7 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('add-to-playlist', {
|
Vue.component('add-to-playlist', {
|
||||||
template: '#add-to-playlist',
|
template: '#add-to-playlist',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
playlistSorted: [],
|
playlistSorted: [],
|
||||||
searchQuery: "",
|
searchQuery: "",
|
||||||
|
|
|
@ -1,27 +1,30 @@
|
||||||
<script type="text/x-template" id="airplay-modal">
|
<script type="text/x-template" id="airplay-modal">
|
||||||
<div class="spatialproperties-panel castmenu modal-fullscreen airplay-modal" @click.self="close()" @contextmenu.self="close()">
|
<div class="spatialproperties-panel castmenu modal-fullscreen airplay-modal" @click.self="close()"
|
||||||
|
@contextmenu.self="close()">
|
||||||
<div class="modal-window airplay-modal">
|
<div class="modal-window airplay-modal">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{'Enter password'}}</div>
|
<div class="modal-title">{{'Enter password'}}</div>
|
||||||
<button class="close-btn" @click="close()" :aria-label="this.$root.getLz('action.close')"></button>
|
<button class="close-btn" @click="close()" :aria-label="this.$root.getLz('action.close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content" style="overflow-y: overlay; padding: 3%">
|
<div class="modal-content" style="overflow-y: overlay; padding: 3%">
|
||||||
<input type="text" v-model="passcode"/>
|
<input type="text" v-model="passcode" />
|
||||||
</div>
|
</div>
|
||||||
<div class="md-footer">
|
<div class="md-footer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col" >
|
<div class="col">
|
||||||
<button style="width:100%" @click="enterPassword()" class="md-btn md-btn-block md-btn-primary">{{'OK'}}</button>
|
<button style="width:100%" @click="enterPassword()" class="md-btn md-btn-block md-btn-primary">
|
||||||
|
{{'OK'}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
Vue.component('airplay-modal', {
|
Vue.component('airplay-modal', {
|
||||||
template: '#airplay-modal',
|
template: '#airplay-modal',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
passcode: '',
|
passcode: '',
|
||||||
}
|
}
|
||||||
|
@ -34,7 +37,7 @@
|
||||||
},
|
},
|
||||||
enterPassword() {
|
enterPassword() {
|
||||||
console.log('Entered passCode: ', this.passcode)
|
console.log('Entered passCode: ', this.passcode)
|
||||||
ipcRenderer.send("setAirPlayPasscode",this.passcode)
|
ipcRenderer.send("setAirPlayPasscode", this.passcode)
|
||||||
this.close()
|
this.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('animatedartwork-view', {
|
Vue.component('animatedartwork-view', {
|
||||||
template: '#animatedartwork-view',
|
template: '#animatedartwork-view',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
app: this.$root,
|
app: this.$root,
|
||||||
hls: null,
|
hls: null,
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.video) {
|
if (this.video) {
|
||||||
this.$nextTick(function () {
|
this.$nextTick(function() {
|
||||||
var config = {
|
var config = {
|
||||||
backBufferLength: 0,
|
backBufferLength: 0,
|
||||||
enableWebVTT: false,
|
enableWebVTT: false,
|
||||||
|
@ -54,8 +54,8 @@
|
||||||
persistentState: "required"
|
persistentState: "required"
|
||||||
}
|
}
|
||||||
let p = {
|
let p = {
|
||||||
platformInfo: {requiresCDMAttachOnStart: !0, maxSecurityLevel: d, keySystemConfig: h},
|
platformInfo: { requiresCDMAttachOnStart: !0, maxSecurityLevel: d, keySystemConfig: h },
|
||||||
appData: {serviceName: "Apple Music"}
|
appData: { serviceName: "Apple Music" }
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hls.attachMedia(this.$refs.video);
|
this.hls.attachMedia(this.$refs.video);
|
||||||
|
@ -63,26 +63,31 @@
|
||||||
let u = this.hls;
|
let u = this.hls;
|
||||||
var quality = app.cfg.visual.animated_artwork_qualityLevel;
|
var quality = app.cfg.visual.animated_artwork_qualityLevel;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let levelsnum = u.levels.map((level)=>{return level.width})
|
let levelsnum = u.levels.map((level) => {
|
||||||
|
return level.width
|
||||||
|
})
|
||||||
if (levelsnum.length > 0) {
|
if (levelsnum.length > 0) {
|
||||||
let qualities = []
|
let qualities = []
|
||||||
let qualities2 = []
|
let qualities2 = []
|
||||||
for (let i = 0; i < levelsnum.length; i++) {
|
for (let i = 0; i < levelsnum.length; i++) {
|
||||||
if (qualities2.indexOf(levelsnum[i]) == -1) {
|
if (qualities2.indexOf(levelsnum[i]) == -1) {
|
||||||
qualities.push({level: i, quality: levelsnum[i]})
|
qualities.push({ level: i, quality: levelsnum[i] })
|
||||||
qualities2.push(levelsnum[i])
|
qualities2.push(levelsnum[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let actualnum = Math.floor(qualities[qualities.length -1 ].level * (quality / 4))
|
let actualnum = Math.floor(qualities[qualities.length - 1].level * (quality / 4))
|
||||||
if (quality != 0 ){
|
if (quality != 0) {
|
||||||
quality = qualities[Math.min(actualnum,qualities.length -1 )].level
|
quality = qualities[Math.min(actualnum, qualities.length - 1)].level
|
||||||
}
|
}
|
||||||
if (quality == 4 ){
|
if (quality == 4) {
|
||||||
quality = qualities[qualities.length - 1].level
|
quality = qualities[qualities.length - 1].level
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try{
|
try {
|
||||||
this.hls.loadLevel = parseInt( quality || 1);} catch(e){}},200)
|
this.hls.loadLevel = parseInt(quality || 1);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
<transition
|
<transition
|
||||||
<% if(env.appRoutes[i].onEnter) {
|
<% if(env.appRoutes[i].onEnter) {
|
||||||
%>
|
%>
|
||||||
v-on:enter="<%- env.appRoutes[i].onEnter %>"
|
v-on:enter="<%- env.appRoutes[i].onEnter; %>"
|
||||||
<%
|
<%
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
:name="$root.chrome.desiredPageTransition">
|
:name="$root.chrome.desiredPageTransition">
|
||||||
<template
|
<template
|
||||||
v-if="<%- env.appRoutes[i].condition %>">
|
v-if="<%- env.appRoutes[i].condition; %>">
|
||||||
<%- env.appRoutes[i].component %>
|
<%- env.appRoutes[i].component; %>
|
||||||
</template>
|
</template>
|
||||||
</transition>
|
</transition>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -40,12 +40,11 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('app-content-area', {
|
Vue.component('app-content-area', {
|
||||||
template: '#app-content-area',
|
template: '#app-content-area',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
scrollPos: 0
|
scrollPos: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
|
@ -1,15 +1,19 @@
|
||||||
<script type="text/x-template" id="artist-chip">
|
<script type="text/x-template" id="artist-chip">
|
||||||
<div class="artist-chip" @click.self="route" tabindex="0">
|
<div class="artist-chip" @click.self="route" tabindex="0">
|
||||||
<div class="artist-chip__image" v-if="image" :style="{backgroundColor: '#' + (artist.attributes.artwork?.bgColor ?? '000')}">
|
<div class="artist-chip__image" v-if="image"
|
||||||
<mediaitem-artwork v-if="artist.id != null" :url="artist.attributes.artwork.url" :size="80"></mediaitem-artwork>
|
: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>
|
||||||
<div class="artist-chip__image" v-else>
|
<div class="artist-chip__image" v-else>
|
||||||
</div>
|
</div>
|
||||||
<div class="artist-chip__name">
|
<div class="artist-chip__name">
|
||||||
<span>{{ item.attributes.name }}</span>
|
<span>{{ item.attributes.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<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, true)" title="Follow"
|
||||||
<button @click="$root.setArtistFavorite(artist.id, false)" title="Following" v-else class="artist-chip__follow codicon codicon-check"></button>
|
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>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script type="text/x-template" id="artwork-material">
|
<script type="text/x-template" id="artwork-material">
|
||||||
<div class="artworkMaterial">
|
<div class="artworkMaterial">
|
||||||
<mediaitem-artwork :url="src" :size="500" v-for="image in images"/>
|
<mediaitem-artwork :url="src" :size="500" v-for="image in images" />
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
Vue.component('artwork-material', {
|
Vue.component('artwork-material', {
|
||||||
template: '#artwork-material',
|
template: '#artwork-material',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
src: ""
|
src: ""
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@
|
||||||
default: '2'
|
default: '2'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
|
@ -4,7 +4,8 @@
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{app.getLz('term.audioControls')}}</div>
|
<div class="modal-title">{{app.getLz('term.audioControls')}}</div>
|
||||||
<button class="close-btn" @click="app.modals.audioControls = false" :aria-label="app.getLz('action.close')"></button>
|
<button class="close-btn" @click="app.modals.audioControls = false"
|
||||||
|
:aria-label="app.getLz('action.close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
|
@ -14,7 +15,7 @@
|
||||||
<div class="md-option-segment md-option-segment_auto percent">
|
<div class="md-option-segment md-option-segment_auto percent">
|
||||||
<input type="number"
|
<input type="number"
|
||||||
style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||||
step="2" v-model="volume"/>
|
step="2" v-model="volume" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto percent">
|
<div class="md-option-segment md-option-segment_auto percent">
|
||||||
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||||
v-model="volumeStep"/>
|
v-model="volumeStep" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto percent">
|
<div class="md-option-segment md-option-segment_auto percent">
|
||||||
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
<input type="number" style="width: 100%; text-align: center; margin-right: 5px;" min="0"
|
||||||
v-model="maxVolume"/>
|
v-model="maxVolume" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
|
@ -41,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" v-model="app.cfg.audio.advanced" switch/>
|
<input type="checkbox" v-model="app.cfg.audio.advanced" switch />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('audio-controls', {
|
Vue.component('audio-controls', {
|
||||||
template: '#audio-controls',
|
template: '#audio-controls',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
app: this.$root,
|
app: this.$root,
|
||||||
maxVolume: this.$root.cfg.audio.maxVolume * 100,
|
maxVolume: this.$root.cfg.audio.maxVolume * 100,
|
||||||
|
@ -62,7 +63,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
maxVolume: function (newValue, _oldValue) {
|
maxVolume: function(newValue, _oldValue) {
|
||||||
if (newValue > 100) {
|
if (newValue > 100) {
|
||||||
newValue = 100
|
newValue = 100
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,7 +73,7 @@
|
||||||
this.maxVolume = newValue
|
this.maxVolume = newValue
|
||||||
console.log(newValue, _oldValue)
|
console.log(newValue, _oldValue)
|
||||||
},
|
},
|
||||||
volume: function (newValue, _oldValue) {
|
volume: function(newValue, _oldValue) {
|
||||||
if (newValue > this.maxVolume) {
|
if (newValue > this.maxVolume) {
|
||||||
newValue = 100
|
newValue = 100
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +83,7 @@
|
||||||
this.volume = newValue
|
this.volume = newValue
|
||||||
console.log(newValue, _oldValue)
|
console.log(newValue, _oldValue)
|
||||||
},
|
},
|
||||||
volumeStep: function (newValue, _oldValue) {
|
volumeStep: function(newValue, _oldValue) {
|
||||||
if (newValue > this.maxVolume) {
|
if (newValue > this.maxVolume) {
|
||||||
newValue = 100
|
newValue = 100
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{app.getLz('settings.option.audio.changePlaybackRate')}}</div>
|
<div class="modal-title">{{app.getLz('settings.option.audio.changePlaybackRate')}}</div>
|
||||||
<button class="close-btn" @click="app.modals.audioPlaybackRate = false" :aria-label="app.getLz('action.close')"></button>
|
<button class="close-btn" @click="app.modals.audioPlaybackRate = false"
|
||||||
|
:aria-label="app.getLz('action.close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
|
@ -15,7 +16,8 @@
|
||||||
{{playbackRate}} ×
|
{{playbackRate}} ×
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<input type="range" :step="0.05" min="0.25" :max="2" @wheel="playbackRateWheel" v-model="playbackRate">
|
<input type="range" :step="0.05" min="0.25" :max="2" @wheel="playbackRateWheel"
|
||||||
|
v-model="playbackRate">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,14 +28,14 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('audio-playbackrate', {
|
Vue.component('audio-playbackrate', {
|
||||||
template: '#audio-playbackrate',
|
template: '#audio-playbackrate',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
app: this.$root,
|
app: this.$root,
|
||||||
playbackRate: this.$root.cfg.audio.playbackRate
|
playbackRate: this.$root.cfg.audio.playbackRate
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
playbackRate: function (newValue, _oldValue) {
|
playbackRate: function(newValue, _oldValue) {
|
||||||
this.saveValue(newValue);
|
this.saveValue(newValue);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<script type="text/x-template" id="audio-settings">
|
<script type="text/x-template" id="audio-settings">
|
||||||
<template>
|
<template>
|
||||||
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.modals.audioSettings = false" @contextmenu.self="app.modals.audioSettings = false">
|
<div class="modal-fullscreen addtoplaylist-panel" @click.self="app.modals.audioSettings = false"
|
||||||
|
@contextmenu.self="app.modals.audioSettings = false">
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{app.getLz('term.audioSettings')}}</div>
|
<div class="modal-title">{{app.getLz('term.audioSettings')}}</div>
|
||||||
<button class="close-btn" @click="app.modals.audioSettings = false" :aria-label="app.getLz('action.close')"></button>
|
<button class="close-btn" @click="app.modals.audioSettings = false"
|
||||||
|
:aria-label="app.getLz('action.close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<button class="playlist-item"
|
<button class="playlist-item"
|
||||||
|
@ -36,13 +38,14 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('audio-settings', {
|
Vue.component('audio-settings', {
|
||||||
template: '#audio-settings',
|
template: '#audio-settings',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
app: this.$root,
|
app: this.$root,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {},
|
props: {},
|
||||||
mounted() {},
|
mounted() {
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openEqualizer() {
|
openEqualizer() {
|
||||||
app.modals.equalizer = true
|
app.modals.equalizer = true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script type="text/x-template" id="castmenu">
|
<script type="text/x-template" id="castmenu">
|
||||||
<div class="spatialproperties-panel castmenu modal-fullscreen" @click.self="close()" @contextmenu.self="close()">
|
<div class="spatialproperties-panel castmenu modal-fullscreen" @click.self="close()" @contextmenu.self="close()">
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{$root.getLz('action.cast.todevices')}}</div>
|
<div class="modal-title">{{$root.getLz('action.cast.todevices')}}</div>
|
||||||
|
@ -16,11 +16,18 @@
|
||||||
<br>
|
<br>
|
||||||
<small>{{ device.host }}</small>
|
<small>{{ device.host }}</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment_auto" style="display: flex;justify-content: center;align-items: center" v-if="activeCasts.includes(device)">
|
<div class="md-option-segment_auto"
|
||||||
|
style="display: flex;justify-content: center;align-items: center"
|
||||||
|
v-if="activeCasts.includes(device)">
|
||||||
Connected
|
Connected
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment_auto" v-else style="display: flex;justify-content: center;align-items: center">
|
<div class="md-option-segment_auto" v-else
|
||||||
<svg width="20" height="20" viewBox="0 0 34 34" fill="#fff" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" class="castPlayIndicator"><path d="M28.228,18.327l-16.023,8.983c-0.99,0.555 -2.205,-0.17 -2.205,-1.318l0,-17.984c0,-1.146 1.215,-1.873 2.205,-1.317l16.023,8.982c1.029,0.577 1.029,2.077 0,2.654Z" style="fill-rule:nonzero"></path></svg>
|
style="display: flex;justify-content: center;align-items: center">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 34 34" fill="#fff" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xml:space="preserve" class="castPlayIndicator"><path
|
||||||
|
d="M28.228,18.327l-16.023,8.983c-0.99,0.555 -2.205,-0.17 -2.205,-1.318l0,-17.984c0,-1.146 1.215,-1.873 2.205,-1.317l16.023,8.982c1.029,0.577 1.029,2.077 0,2.654Z"
|
||||||
|
style="fill-rule:nonzero"></path></svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -33,11 +40,12 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-labeltext" >{{$root.getLz('action.cast.airplay')}}</div>
|
<div class="md-labeltext">{{$root.getLz('action.cast.airplay')}}</div>
|
||||||
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;overflow-y: scroll;">
|
<div class="md-option-container" style="margin-top: 12px;margin-bottom: 12px;overflow-y: scroll;">
|
||||||
<div class="md-option-line">
|
<div class="md-option-line">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{'EXPERIMENTAL!!! Supports Homepods / Apple TVs / Shairport for now, AirPlay on Samsung/LG/Sony devices will be added later'}}
|
{{'EXPERIMENTAL!!! Supports Homepods / Apple TVs / Shairport for now, AirPlay on
|
||||||
|
Samsung/LG/Sony devices will be added later'}}
|
||||||
<!-- {{$root.getLz('action.cast.airplay.underdevelopment')}} -->
|
<!-- {{$root.getLz('action.cast.airplay.underdevelopment')}} -->
|
||||||
<template v-if="true" v-for="(device) in devices.airplay">
|
<template v-if="true" v-for="(device) in devices.airplay">
|
||||||
<div class="md-option-line" style="cursor: pointer" @click="setAirPlayCast(device)">
|
<div class="md-option-line" style="cursor: pointer" @click="setAirPlayCast(device)">
|
||||||
|
@ -46,11 +54,19 @@
|
||||||
<br>
|
<br>
|
||||||
<small>{{ device.host }}</small>
|
<small>{{ device.host }}</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment_auto" style="display: flex;justify-content: center;align-items: center" v-if="activeCasts.includes(device)">
|
<div class="md-option-segment_auto"
|
||||||
|
style="display: flex;justify-content: center;align-items: center"
|
||||||
|
v-if="activeCasts.includes(device)">
|
||||||
Connected
|
Connected
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment_auto" v-else style="display: flex;justify-content: center;align-items: center">
|
<div class="md-option-segment_auto" v-else
|
||||||
<svg width="20" height="20" viewBox="0 0 34 34" fill="#fff" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" class="castPlayIndicator"><path d="M28.228,18.327l-16.023,8.983c-0.99,0.555 -2.205,-0.17 -2.205,-1.318l0,-17.984c0,-1.146 1.215,-1.873 2.205,-1.317l16.023,8.982c1.029,0.577 1.029,2.077 0,2.654Z" style="fill-rule:nonzero"></path></svg>
|
style="display: flex;justify-content: center;align-items: center">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 34 34" fill="#fff" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xml:space="preserve"
|
||||||
|
class="castPlayIndicator"><path
|
||||||
|
d="M28.228,18.327l-16.023,8.983c-0.99,0.555 -2.205,-0.17 -2.205,-1.318l0,-17.984c0,-1.146 1.215,-1.873 2.205,-1.317l16.023,8.982c1.029,0.577 1.029,2.077 0,2.654Z"
|
||||||
|
style="fill-rule:nonzero"></path></svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -61,20 +77,24 @@
|
||||||
<div class="md-footer">
|
<div class="md-footer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col" v-if="activeCasts.length != 0">
|
<div class="col" v-if="activeCasts.length != 0">
|
||||||
<button style="width:100%" @click="stopCasting()" class="md-btn md-btn-block md-btn-primary">{{$root.getLz('action.cast.stop')}}</button>
|
<button style="width:100%" @click="stopCasting()" class="md-btn md-btn-block md-btn-primary">
|
||||||
|
{{$root.getLz('action.cast.stop')}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<button style="width:100%" class="md-btn md-btn-block" @click="scan()">{{$root.getLz('action.cast.scan')}}</button>
|
<button style="width:100%" class="md-btn md-btn-block" @click="scan()">
|
||||||
|
{{$root.getLz('action.cast.scan')}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
Vue.component('castmenu', {
|
Vue.component('castmenu', {
|
||||||
template: '#castmenu',
|
template: '#castmenu',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
devices: {
|
devices: {
|
||||||
cast: [],
|
cast: [],
|
||||||
|
@ -88,10 +108,11 @@
|
||||||
mounted() {
|
mounted() {
|
||||||
this.scan();
|
this.scan();
|
||||||
},
|
},
|
||||||
watch:{
|
watch: {
|
||||||
activeCasts: function (newVal, oldVal) {
|
activeCasts: function(newVal, oldVal) {
|
||||||
this.$root.activeCasts = this.activeCasts;
|
this.$root.activeCasts = this.activeCasts;
|
||||||
}},
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close() {
|
||||||
this.$root.modals.castMenu = false
|
this.$root.modals.castMenu = false
|
||||||
|
@ -100,7 +121,7 @@
|
||||||
let self = this;
|
let self = this;
|
||||||
this.scanning = true;
|
this.scanning = true;
|
||||||
ipcRenderer.send('getChromeCastDevices', '');
|
ipcRenderer.send('getChromeCastDevices', '');
|
||||||
ipcRenderer.send("getAirplayDevice","")
|
ipcRenderer.send("getAirplayDevice", "")
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
self.devices.cast = ipcRenderer.sendSync("getKnownCastDevices");
|
self.devices.cast = ipcRenderer.sendSync("getKnownCastDevices");
|
||||||
self.devices.airplay = ipcRenderer.sendSync("getKnownAirplayDevices");
|
self.devices.airplay = ipcRenderer.sendSync("getKnownAirplayDevices");
|
||||||
|
@ -116,7 +137,7 @@
|
||||||
},
|
},
|
||||||
setAirPlayCast(device) {
|
setAirPlayCast(device) {
|
||||||
this.activeCasts.push(device);
|
this.activeCasts.push(device);
|
||||||
ipcRenderer.send("performAirplayPCM",device.host,device.port,null,"","","","",device.txt,device.airplay2)
|
ipcRenderer.send("performAirplayPCM", device.host, device.port, null, "", "", "", "", device.txt, device.airplay2)
|
||||||
},
|
},
|
||||||
stopCasting() {
|
stopCasting() {
|
||||||
CiderAudio.stopAudio();
|
CiderAudio.stopAudio();
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
<div class="modal-window">
|
<div class="modal-window">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">{{app.getLz('action.addToLibrary')}}</div>
|
<div class="modal-title">{{app.getLz('action.addToLibrary')}}</div>
|
||||||
<button class="close-btn" @click="app.resetState()" :aria-label="app.getLz('action.close')"></button>
|
<button class="close-btn" @click="app.resetState()"
|
||||||
|
:aria-label="app.getLz('action.close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<button class="playlist-item"
|
<button class="playlist-item"
|
||||||
:class="{ focused: playlist.id == focused }"
|
:class="{ focused: playlist.id == focused }"
|
||||||
@click="addToPlaylist(playlist.id)" style="width:100%;" v-for="playlist in playlistSorted" v-if="playlist.attributes.canEdit && playlist.type != 'library-playlist-folders'">
|
@click="addToPlaylist(playlist.id)" style="width:100%;" v-for="playlist in playlistSorted"
|
||||||
|
v-if="playlist.attributes.canEdit && playlist.type != 'library-playlist-folders'">
|
||||||
<div class="icon"><%- include("../svg/playlist.svg") %></div>
|
<div class="icon"><%- include("../svg/playlist.svg") %></div>
|
||||||
<div class="name">{{ playlist.attributes.name }}</div>
|
<div class="name">{{ playlist.attributes.name }}</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -35,7 +37,7 @@
|
||||||
<script>
|
<script>
|
||||||
Vue.component('add-to-playlist', {
|
Vue.component('add-to-playlist', {
|
||||||
template: '#add-to-playlist',
|
template: '#add-to-playlist',
|
||||||
data: function () {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
playlistSorted: [],
|
playlistSorted: [],
|
||||||
searchQuery: "",
|
searchQuery: "",
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue