Merge branch 'main' into enhancement/search-bar
This commit is contained in:
commit
13f12121ba
22 changed files with 569 additions and 593 deletions
|
@ -3,7 +3,6 @@
|
||||||
LATEST_SHA=$(curl -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep sha | cut -d '"' -f 4 | sed 's/v//' | xargs)
|
LATEST_SHA=$(curl -s https://api.github.com/repos/ciderapp/Cider/branches/stable | grep sha | cut -d '"' -f 4 | sed 's/v//' | xargs)
|
||||||
COMMITSINCESTABLE=$(git rev-list $LATEST_SHA..HEAD --count)
|
COMMITSINCESTABLE=$(git rev-list $LATEST_SHA..HEAD --count)
|
||||||
CURRENT_VERSION=$(node -p -e "require('./package.json').version")
|
CURRENT_VERSION=$(node -p -e "require('./package.json').version")
|
||||||
CIRCLE_BRANCH="main"
|
|
||||||
if [[ $CIRCLE_BRANCH == "main" && $COMMITSINCESTABLE -gt 0 ]]; then
|
if [[ $CIRCLE_BRANCH == "main" && $COMMITSINCESTABLE -gt 0 ]]; then
|
||||||
NEW_VERSION="${CURRENT_VERSION}-beta.${COMMITSINCESTABLE}"
|
NEW_VERSION="${CURRENT_VERSION}-beta.${COMMITSINCESTABLE}"
|
||||||
else
|
else
|
||||||
|
|
|
@ -497,7 +497,21 @@ Update 14/06/2022 14:10 UTC
|
||||||
|
|
||||||
* `term.themeManaged`: Added to `en_US`
|
* `term.themeManaged`: Added to `en_US`
|
||||||
|
|
||||||
|
Update 15/06/2022 20:00 UTC
|
||||||
|
|
||||||
|
* `settings.notyf.connectivity.lastfmScrobble.connectError`: Added to `en_US`
|
||||||
|
* `settings.notyf.connectivity.lastfmScrobble.connectSuccess`: Added to `en_US`
|
||||||
|
* `settings.notyf.connectivity.lastfmScrobble.connecting`: Added to `en_US`
|
||||||
|
|
||||||
|
Update 19/06/2022 12:00 UTC
|
||||||
|
|
||||||
|
* `settings.option.connectivity.lastfmScrobble.filterLoop.description`: Added to `en_US`
|
||||||
|
|
||||||
Update 21/06/2022 20:39 UTC
|
Update 21/06/2022 20:39 UTC
|
||||||
|
|
||||||
* `term.showSearch`: Added to `en_US`
|
* `term.showSearch`: Added to `en_US`
|
||||||
* `term.hideSearch`: Added to `en_US`
|
* `term.hideSearch`: Added to `en_US`
|
||||||
|
|
||||||
|
Update 23/06/2022 04:00 UTC
|
||||||
|
|
||||||
|
* `settings.option.connectivity.lastfmScrobble.filterTypes`: Added to `en_US`
|
||||||
|
|
|
@ -239,6 +239,7 @@
|
||||||
"action.delete": "Delete",
|
"action.delete": "Delete",
|
||||||
"action.edit": "Edit",
|
"action.edit": "Edit",
|
||||||
"action.done": "Done",
|
"action.done": "Done",
|
||||||
|
"action.submit": "Submit",
|
||||||
"action.editTracklist": "Edit Tracklist",
|
"action.editTracklist": "Edit Tracklist",
|
||||||
"action.addToLibrary": "Add to Library",
|
"action.addToLibrary": "Add to Library",
|
||||||
"action.addToLibrary.success": "Added to Library",
|
"action.addToLibrary.success": "Added to Library",
|
||||||
|
@ -535,6 +536,12 @@
|
||||||
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing",
|
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing",
|
||||||
"settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)",
|
"settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)",
|
||||||
"settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)",
|
"settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "Prevent looped tracks from being scrobbled or displayed in the Now Playing list on Last.fm.",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.filterTypes": "Filter Media Types (Last.fm)",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.manualToken": "Enter Last.fm Token Manually",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connectSuccess": "Last.fm Connection Successful",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connecting": "Connecting to Last.fm...",
|
||||||
"settings.header.debug": "Debug",
|
"settings.header.debug": "Debug",
|
||||||
"settings.option.debug.copy_log": "Copy logs to clipboard",
|
"settings.option.debug.copy_log": "Copy logs to clipboard",
|
||||||
"settings.option.debug.openAppData": "Open Cider Folder",
|
"settings.option.debug.openAppData": "Open Cider Folder",
|
||||||
|
|
|
@ -234,6 +234,7 @@
|
||||||
"action.delete": "Delete",
|
"action.delete": "Delete",
|
||||||
"action.edit": "Edit",
|
"action.edit": "Edit",
|
||||||
"action.done": "Done",
|
"action.done": "Done",
|
||||||
|
"action.submit": "Submit",
|
||||||
"action.editTracklist": "Edit Tracklist",
|
"action.editTracklist": "Edit Tracklist",
|
||||||
"action.addToLibrary": "Add to Library",
|
"action.addToLibrary": "Add to Library",
|
||||||
"action.addToLibrary.success": "Added to Library",
|
"action.addToLibrary.success": "Added to Library",
|
||||||
|
@ -522,6 +523,12 @@
|
||||||
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing",
|
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing",
|
||||||
"settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)",
|
"settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (Last.fm)",
|
||||||
"settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)",
|
"settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (Last.fm)",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.filterLoop.description": "Prevent looped tracks from being scrobbled or displayed in the Now Playing list on Last.fm.",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.filterTypes": "Filter Media Types (Last.fm)",
|
||||||
|
"settings.option.connectivity.lastfmScrobble.manualToken": "Enter Last.fm Token Manually",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connectError": "Last.fm Connection Timed Out",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connectSuccess": "Last.fm Connection Successful",
|
||||||
|
"settings.notyf.connectivity.lastfmScrobble.connecting": "Connecting to Last.fm...",
|
||||||
"settings.header.debug": "Debug",
|
"settings.header.debug": "Debug",
|
||||||
"settings.option.debug.copy_log": "Copy logs to clipboard",
|
"settings.option.debug.copy_log": "Copy logs to clipboard",
|
||||||
"settings.option.debug.openAppData": "Open Cider Folder",
|
"settings.option.debug.openAppData": "Open Cider Folder",
|
||||||
|
|
|
@ -162,13 +162,10 @@ export class AppEvents {
|
||||||
|
|
||||||
// LastFM Auth URL
|
// LastFM Auth URL
|
||||||
if (arg.includes('auth')) {
|
if (arg.includes('auth')) {
|
||||||
let 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')) { // If we wanted more auth options
|
||||||
const authKey = authURI.split('lastfm?token=')[1];
|
console.log('token: ', authURI.split('lastfm?token=')[1])
|
||||||
utils.setStoreValue('lastfm.enabled', true);
|
utils.getWindow().webContents.executeJavaScript(`ipcRenderer.send('lastfm:auth', "${authURI.split('lastfm?token=')[1]}")`).catch(console.error)
|
||||||
utils.setStoreValue('lastfm.auth_token', authKey);
|
|
||||||
utils.getWindow().webContents.send('LastfmAuthenticated', authKey);
|
|
||||||
this.plugin.callPlugin('lastfm', 'authenticate', authKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Play
|
// Play
|
||||||
|
|
|
@ -618,8 +618,7 @@ export class BrowserWindow {
|
||||||
//region Connect Integration
|
//region Connect Integration
|
||||||
app.get("/connect/set-cc-user/:data", (req, res) => {
|
app.get("/connect/set-cc-user/:data", (req, res) => {
|
||||||
//utils.getStoreValue('connectUser', JSON.parse()) // [Connect] Save user in store
|
//utils.getStoreValue('connectUser', JSON.parse()) // [Connect] Save user in store
|
||||||
utils.setStoreValue('connectUser', JSON.parse(req.params.data))
|
utils.getWindow().webContents.send('setStoreValue', 'connectUser', JSON.parse(req.params.data))
|
||||||
utils.getWindow().reload()
|
|
||||||
res.redirect(`https://connect.cidercollective.dev/linked.html`)
|
res.redirect(`https://connect.cidercollective.dev/linked.html`)
|
||||||
});
|
});
|
||||||
// [Connect] Set auth URL in store for `shell.openExternal`
|
// [Connect] Set auth URL in store for `shell.openExternal`
|
||||||
|
|
|
@ -107,7 +107,8 @@ export class Plugins {
|
||||||
try{
|
try{
|
||||||
this.pluginsList[plugin][event](...args);
|
this.pluginsList[plugin][event](...args);
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
console.log(`[${plugin}] Plugin error: ${e}`);
|
console.error(`[${plugin}] An error was encountered: ${e}`);
|
||||||
|
console.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ 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;
|
||||||
|
|
||||||
|
@ -12,16 +13,6 @@ export class Store {
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"close_button_hide": false,
|
"close_button_hide": false,
|
||||||
"discordrpc": {
|
|
||||||
"enabled": true,
|
|
||||||
"client": "Cider",
|
|
||||||
"clear_on_pause": true,
|
|
||||||
"hide_buttons": false,
|
|
||||||
"hide_timestamp": false,
|
|
||||||
"state_format": "by {artist}",
|
|
||||||
"details_format": "{title}",
|
|
||||||
},
|
|
||||||
"refreshInterval": 120000,
|
|
||||||
"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",
|
||||||
|
@ -67,7 +58,7 @@ export class Store {
|
||||||
"CommandOrControl",
|
"CommandOrControl",
|
||||||
"G"
|
"G"
|
||||||
],
|
],
|
||||||
"songs" : [
|
"songs": [
|
||||||
"CommandOrControl",
|
"CommandOrControl",
|
||||||
"J"
|
"J"
|
||||||
],
|
],
|
||||||
|
@ -90,17 +81,17 @@ export class Store {
|
||||||
],
|
],
|
||||||
"audioSettings": [
|
"audioSettings": [
|
||||||
"CommandOrControl",
|
"CommandOrControl",
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift": "Alt"),
|
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
||||||
"A"
|
"A"
|
||||||
],
|
],
|
||||||
"pluginMenu": [
|
"pluginMenu": [
|
||||||
"CommandOrControl",
|
"CommandOrControl",
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift": "Alt"),
|
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
||||||
"P"
|
"P"
|
||||||
],
|
],
|
||||||
"castToDevices": [
|
"castToDevices": [
|
||||||
"CommandOrControl",
|
"CommandOrControl",
|
||||||
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift": "Alt"),
|
process.platform == "darwin" ? "Option" : (process.platform == "linux" ? "Shift" : "Alt"),
|
||||||
"C"
|
"C"
|
||||||
],
|
],
|
||||||
"settings": [
|
"settings": [
|
||||||
|
@ -127,6 +118,28 @@ export class Store {
|
||||||
},
|
},
|
||||||
"showLovedTracksInline": true
|
"showLovedTracksInline": true
|
||||||
},
|
},
|
||||||
|
"connectivity": {
|
||||||
|
"discord_rpc": {
|
||||||
|
"enabled": true,
|
||||||
|
"client": "Cider",
|
||||||
|
"clear_on_pause": true,
|
||||||
|
"hide_buttons": false,
|
||||||
|
"hide_timestamp": false,
|
||||||
|
"state_format": "by {artist}",
|
||||||
|
"details_format": "{title}",
|
||||||
|
},
|
||||||
|
"lastfm": {
|
||||||
|
"enabled": false,
|
||||||
|
"scrobble_after": 50,
|
||||||
|
"filter_loop": false,
|
||||||
|
"filter_types": {},
|
||||||
|
"secrets": {
|
||||||
|
"username": "",
|
||||||
|
"key": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"followedArtists": [],
|
"followedArtists": [],
|
||||||
"favoriteItems": []
|
"favoriteItems": []
|
||||||
|
@ -231,14 +244,6 @@ export class Store {
|
||||||
"enable_qq": false,
|
"enable_qq": false,
|
||||||
"enable_yt": false,
|
"enable_yt": false,
|
||||||
},
|
},
|
||||||
"lastfm": {
|
|
||||||
"enabled": false,
|
|
||||||
"scrobble_after": 30,
|
|
||||||
"auth_token": "",
|
|
||||||
"enabledRemoveFeaturingArtists": true,
|
|
||||||
"filterLoop": true,
|
|
||||||
"NowPlaying": "true"
|
|
||||||
},
|
|
||||||
"advanced": {
|
"advanced": {
|
||||||
"AudioContext": true,
|
"AudioContext": true,
|
||||||
"experiments": [],
|
"experiments": [],
|
||||||
|
@ -255,15 +260,9 @@ export class Store {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
private migrations: any = {
|
private migrations: any = {}
|
||||||
'>=1.4.3': (store: ElectronStore) => {
|
|
||||||
if (typeof store.get('general.discordrpc') == 'number' || typeof store.get('general.discordrpc') == 'string') {
|
|
||||||
store.delete('general.discordrpc');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
private schema: ElectronStore.Schema<any> = {
|
private schema: ElectronStore.Schema<any> = {
|
||||||
"general.discordrpc": {
|
"connectivity.discord_rpc": {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -274,57 +273,13 @@ export class Store {
|
||||||
defaults: this.defaults,
|
defaults: this.defaults,
|
||||||
schema: this.schema,
|
schema: this.schema,
|
||||||
migrations: this.migrations,
|
migrations: this.migrations,
|
||||||
clearInvalidConfig: true
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge Configurations
|
|
||||||
* @param target The target configuration
|
|
||||||
* @param source The source configuration
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
for (const key of Object.keys(source)) {
|
|
||||||
if (key.includes('migrations')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (source[key] instanceof Array) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key]))
|
|
||||||
}
|
|
||||||
// Join `target` and modified `source`
|
|
||||||
Object.assign(target || {}, source)
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IPC Handler
|
|
||||||
*/
|
|
||||||
private ipcHandler(): void {
|
|
||||||
electron.ipcMain.handle('getStoreValue', (_event, key, defaultValue) => {
|
|
||||||
return (defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key));
|
|
||||||
});
|
|
||||||
|
|
||||||
electron.ipcMain.handle('setStoreValue', (_event, key, value) => {
|
|
||||||
Store.cfg.set(key, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
electron.ipcMain.on('getStore', (event) => {
|
|
||||||
event.returnValue = Store.cfg.store
|
|
||||||
})
|
|
||||||
|
|
||||||
electron.ipcMain.on('setStore', (_event, store) => {
|
|
||||||
Store.cfg.store = store
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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();
|
||||||
|
@ -338,7 +293,7 @@ export class Store {
|
||||||
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'),
|
||||||
|
@ -362,4 +317,46 @@ export class Store {
|
||||||
body: JSON.stringify(postBody)
|
body: JSON.stringify(postBody)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge Configurations
|
||||||
|
* @param target The target configuration
|
||||||
|
* @param source The source configuration
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
for (const key of Object.keys(source)) {
|
||||||
|
if (key.includes('migrations')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (source[key] instanceof Array) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key]))
|
||||||
|
}
|
||||||
|
// Join `target` and modified `source`
|
||||||
|
Object.assign(target || {}, source)
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPC Handler
|
||||||
|
*/
|
||||||
|
private ipcHandler(): void {
|
||||||
|
electron.ipcMain.handle('getStoreValue', (_event, key, defaultValue) => {
|
||||||
|
return (defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.handle('setStoreValue', (_event, key, value) => {
|
||||||
|
Store.cfg.set(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
electron.ipcMain.on('getStore', (event) => {
|
||||||
|
event.returnValue = Store.cfg.store
|
||||||
|
})
|
||||||
|
|
||||||
|
electron.ipcMain.on('setStore', (_event, store) => {
|
||||||
|
Store.cfg.store = store
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,36 @@ 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, dialog, ipcMain, Notification, shell, BrowserWindow} from "electron";
|
import {app, BrowserWindow, ipcMain} from "electron";
|
||||||
import fetch from "electron-fetch";
|
import fetch from "electron-fetch";
|
||||||
import {AppImageUpdater, NsisUpdater} from "electron-updater";
|
|
||||||
import * as log from "electron-log";
|
|
||||||
import ElectronStore from "electron-store";
|
import ElectronStore from "electron-store";
|
||||||
|
|
||||||
export class utils {
|
export class utils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Playback Functions
|
||||||
|
*/
|
||||||
|
static playback = {
|
||||||
|
pause: () => {
|
||||||
|
bw.win.webContents.executeJavaScript("MusicKitInterop.pause()")
|
||||||
|
},
|
||||||
|
play: () => {
|
||||||
|
bw.win.webContents.executeJavaScript("MusicKitInterop.play()")
|
||||||
|
},
|
||||||
|
playPause: () => {
|
||||||
|
bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()")
|
||||||
|
},
|
||||||
|
next: () => {
|
||||||
|
bw.win.webContents.executeJavaScript("MusicKitInterop.next()")
|
||||||
|
},
|
||||||
|
previous: () => {
|
||||||
|
bw.win.webContents.executeJavaScript("MusicKitInterop.previous()")
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Paths for the application to use
|
* Paths for the application to use
|
||||||
*/
|
*/
|
||||||
private static paths: any = {
|
static paths: any = {
|
||||||
srcPath: path.join(__dirname, "../../src"),
|
srcPath: path.join(__dirname, "../../src"),
|
||||||
rendererPath: path.join(__dirname, "../../src/renderer"),
|
rendererPath: path.join(__dirname, "../../src/renderer"),
|
||||||
mainPath: path.join(__dirname, "../../src/main"),
|
mainPath: path.join(__dirname, "../../src/main"),
|
||||||
|
@ -43,6 +61,13 @@ export class utils {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IPCMain
|
||||||
|
*/
|
||||||
|
static getIPCMain(): Electron.IpcMain {
|
||||||
|
return ipcMain
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the i18n locale for the given language.
|
* Fetches the i18n locale for the given language.
|
||||||
* @param language {string} The language to fetch the locale for.
|
* @param language {string} The language to fetch the locale for.
|
||||||
|
@ -64,7 +89,7 @@ export class utils {
|
||||||
} else {
|
} else {
|
||||||
i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `en_US.json`), "utf8")));
|
i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `en_US.json`), "utf8")));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (key) {
|
if (key) {
|
||||||
return i18n[key]
|
return i18n[key]
|
||||||
|
@ -90,7 +115,6 @@ export class utils {
|
||||||
return Store.cfg.store
|
return Store.cfg.store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the store instance
|
* Get the store instance
|
||||||
* @returns {Store}
|
* @returns {Store}
|
||||||
|
@ -116,10 +140,6 @@ export class utils {
|
||||||
return Store.pushToCloud
|
return Store.pushToCloud
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the browser window
|
* Gets the browser window
|
||||||
*/
|
*/
|
||||||
|
@ -138,25 +158,4 @@ export class utils {
|
||||||
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Playback Functions
|
|
||||||
*/
|
|
||||||
static playback = {
|
|
||||||
pause: () => {
|
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.pause()")
|
|
||||||
},
|
|
||||||
play: () => {
|
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.play()")
|
|
||||||
},
|
|
||||||
playPause: () => {
|
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.playPause()")
|
|
||||||
},
|
|
||||||
next: () => {
|
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.next()")
|
|
||||||
},
|
|
||||||
previous: () => {
|
|
||||||
bw.win.webContents.executeJavaScript("MusicKitInterop.previous()")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
require('v8-compile-cache');
|
require("v8-compile-cache");
|
||||||
|
|
||||||
const {app, components, ipcMain} = require('electron');
|
|
||||||
import {join} from 'path';
|
|
||||||
|
|
||||||
|
import {join} from "path";
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
// Analytics for debugging fun yeah.
|
// Analytics for debugging fun yeah.
|
||||||
Sentry({
|
Sentry({
|
||||||
|
@ -32,13 +33,13 @@ const CiderPlug = new Plugins();
|
||||||
* App Event Handlers
|
* App Event Handlers
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
||||||
|
|
||||||
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 () => {
|
||||||
|
@ -49,11 +50,11 @@ app.on('ready', () => {
|
||||||
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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -68,20 +69,20 @@ 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);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('nowPlayingItemDidChange', (_event, attributes) => {
|
ipcMain.on("nowPlayingItemDidChange", (_event, attributes) => {
|
||||||
CiderPlug.callPlugins('onNowPlayingItemDidChange', attributes);
|
CiderPlug.callPlugins("onNowPlayingItemDidChange", attributes);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('nowPlayingItemDidChangeLastFM', (_event, attributes) => {
|
ipcMain.on("nowPlayingItemDidChangeLastFM", (_event, attributes) => {
|
||||||
CiderPlug.callPlugin('lastfm.js', 'nowPlayingItemDidChangeLastFM', attributes);
|
CiderPlug.callPlugin("lastfm.js", "nowPlayingItemDidChangeLastFM", attributes);
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('before-quit', () => {
|
app.on("before-quit", () => {
|
||||||
CiderPlug.callPlugins('onBeforeQuit');
|
CiderPlug.callPlugins("onBeforeQuit");
|
||||||
console.warn(`${app.getName()} exited.`);
|
console.warn(`${app.getName()} exited.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -90,21 +91,21 @@ 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()
|
||||||
})
|
})
|
||||||
|
|
|
@ -74,7 +74,7 @@ export default class DiscordRPC {
|
||||||
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("general.discordrpc.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)
|
||||||
|
@ -125,7 +125,7 @@ export default class DiscordRPC {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private connect() {
|
private connect() {
|
||||||
if (!this._utils.getStoreValue("general.discordrpc.enabled")) {
|
if (!this._utils.getStoreValue("connectivity.discord_rpc.enabled")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ export default class DiscordRPC {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Login to Discord
|
// Login to Discord
|
||||||
this._client.endlessLogin({clientId: this._utils.getStoreValue("general.discordrpc.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
|
||||||
})
|
})
|
||||||
|
@ -161,8 +161,8 @@ export default class DiscordRPC {
|
||||||
|
|
||||||
// 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("general.discordrpc.details_format"),
|
details: this._utils.getStoreValue("connectivity.discord_rpc.details_format"),
|
||||||
state: this._utils.getStoreValue("general.discordrpc.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
|
||||||
|
@ -177,7 +177,7 @@ export default class DiscordRPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the activity
|
// Set the activity
|
||||||
if (!attributes.status && this._utils.getStoreValue("general.discordrpc.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)
|
||||||
|
@ -191,7 +191,7 @@ export default class DiscordRPC {
|
||||||
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("general.discordrpc.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}
|
||||||
|
@ -199,13 +199,13 @@ export default class DiscordRPC {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the timestamp if its playing and people want them
|
// Add the timestamp if its playing and people want them
|
||||||
if (!this._utils.getStoreValue("general.discordrpc.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("general.discordrpc.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';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,278 +1,233 @@
|
||||||
import * as electron from 'electron';
|
export default class lastfm {
|
||||||
import * as fs from 'fs';
|
|
||||||
import {resolve} from 'path';
|
|
||||||
|
|
||||||
export default class LastFMPlugin {
|
/**
|
||||||
private sessionPath = resolve(electron.app.getPath('userData'), 'session.json');
|
* Base Plugin Information
|
||||||
private apiCredentials = {
|
*/
|
||||||
|
public name: string = 'LastFM Plugin';
|
||||||
|
public version: string = '2.0.0';
|
||||||
|
public author: string = 'Core (Cider Collective)';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private variables for interaction in plugins
|
||||||
|
*/
|
||||||
|
private _attributes: any;
|
||||||
|
private _apiCredentials = {
|
||||||
key: "f9986d12aab5a0fe66193c559435ede3",
|
key: "f9986d12aab5a0fe66193c559435ede3",
|
||||||
secret: "acba3c29bd5973efa38cc2f0b63cc625"
|
secret: "acba3c29bd5973efa38cc2f0b63cc625"
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Private variables for interaction in plugins
|
* Plugin Initialization
|
||||||
*/
|
*/
|
||||||
private _win: any;
|
private _lfm: any = null;
|
||||||
private _app: any;
|
private _authenticated: boolean = false;
|
||||||
private _lastfm: any;
|
private _scrobbleDelay: any = null;
|
||||||
private _store: any;
|
private _utils: any = null;
|
||||||
private _timer: any;
|
private _scrobbleCache: any = {};
|
||||||
|
private _nowPlayingCache: any = {};
|
||||||
private authenticateFromFile() {
|
|
||||||
let sessionData = require(this.sessionPath)
|
|
||||||
console.log("[LastFM][authenticateFromFile] Logging in with Session Info.")
|
|
||||||
this._lastfm.setSessionCredentials(sessionData.username, sessionData.key)
|
|
||||||
console.log("[LastFM][authenticateFromFile] Logged in.", sessionData.username, sessionData.key)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
authenticate() {
|
|
||||||
try {
|
|
||||||
if (this._store.lastfm.auth_token) {
|
|
||||||
this._store.lastfm.enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._store.lastfm.enabled || !this._store.lastfm.auth_token) {
|
|
||||||
this._store.lastfm.enabled = false;
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/// dont move this require to top , app wont load
|
|
||||||
const LastfmAPI = require('lastfmapi');
|
|
||||||
const lfmAPI = new LastfmAPI({
|
|
||||||
'api_key': this.apiCredentials.key,
|
|
||||||
'secret': this.apiCredentials.secret
|
|
||||||
});
|
|
||||||
|
|
||||||
this._lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false});
|
|
||||||
|
|
||||||
fs.stat(this.sessionPath, (err: any) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("[LastFM][Session] Session file couldn't be opened or doesn't exist,", err)
|
|
||||||
console.log("[LastFM][Auth] Beginning authentication from configuration")
|
|
||||||
console.log("[LastFM][tk]", this._store.lastfm.auth_token)
|
|
||||||
this._lastfm.authenticate(this._store.lastfm.auth_token, (err: any, session: any) => {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
console.log("[LastFM] Successfully obtained LastFM session info,", session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"}
|
|
||||||
console.log("[LastFM] Saving session info to disk.")
|
|
||||||
let tempData = JSON.stringify(session)
|
|
||||||
fs.writeFile(this.sessionPath, tempData, (err: any) => {
|
|
||||||
if (err)
|
|
||||||
console.log("[LastFM][fs]", err)
|
|
||||||
else {
|
|
||||||
console.log("[LastFM][fs] File was written successfully.")
|
|
||||||
this.authenticateFromFile()
|
|
||||||
new electron.Notification({
|
|
||||||
title: electron.app.getName(),
|
|
||||||
body: "Successfully logged into LastFM using Authentication Key."
|
|
||||||
}).show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.authenticateFromFile()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private scrobbleSong(attributes: any) {
|
|
||||||
if (this._timer) clearTimeout(this._timer);
|
|
||||||
var self = this;
|
|
||||||
this._timer = setTimeout(async () => {
|
|
||||||
const currentAttributes = attributes;
|
|
||||||
|
|
||||||
if (!self._lastfm || self._lastfm.cachedAttributes === attributes) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self._lastfm.cachedAttributes) {
|
|
||||||
if (self._lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const artist = await this.getPrimaryArtist(attributes)
|
|
||||||
const album = this.getAlbumName(attributes)
|
|
||||||
|
|
||||||
if (currentAttributes.status && currentAttributes === attributes) {
|
|
||||||
if (fs.existsSync(this.sessionPath)) {
|
|
||||||
// Scrobble playing song.
|
|
||||||
if (attributes.status === true) {
|
|
||||||
self._lastfm.track.scrobble({
|
|
||||||
'artist': artist,
|
|
||||||
'track': attributes.name,
|
|
||||||
'album': album,
|
|
||||||
'albumArtist': artist,
|
|
||||||
'timestamp': new Date().getTime() / 1000
|
|
||||||
}, function (err: any, scrobbled: any) {
|
|
||||||
if (err) {
|
|
||||||
return console.error('[LastFM] An error occurred while scrobbling', err);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[LastFM] Successfully scrobbled: ', scrobbled);
|
|
||||||
});
|
|
||||||
self._lastfm.cachedAttributes = attributes
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.authenticate();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return console.log('[LastFM] Did not add ', attributes.name, '—', artist, 'because now playing a other song.');
|
|
||||||
}
|
|
||||||
}, Math.round(attributes.durationInMillis * Math.min((self._store.lastfm.scrobble_after / 100), 0.8)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async updateNowPlayingSong(attributes: any) {
|
|
||||||
if (!this._lastfm || this._lastfm.cachedNowPlayingAttributes === attributes || !this._store.lastfm.NowPlaying) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._lastfm.cachedNowPlayingAttributes) {
|
|
||||||
if (this._lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fs.existsSync(this.sessionPath)) {
|
|
||||||
const artist = await this.getPrimaryArtist(attributes)
|
|
||||||
const album = this.getAlbumName(attributes)
|
|
||||||
|
|
||||||
// update Now Playing
|
|
||||||
if (attributes.status === true) {
|
|
||||||
this._lastfm.track.updateNowPlaying({
|
|
||||||
'artist': artist,
|
|
||||||
'track': attributes.name,
|
|
||||||
'album': album,
|
|
||||||
'albumArtist': artist
|
|
||||||
}, function (err: any, nowPlaying: any) {
|
|
||||||
if (err) {
|
|
||||||
return console.error('[LastFM] An error occurred while updating nowPlayingSong', err);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying);
|
|
||||||
});
|
|
||||||
this._lastfm.cachedNowPlayingAttributes = attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.authenticate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getAlbumName(attributes: any): string {
|
|
||||||
return attributes.albumName.replace(/ - Single| - EP/g, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getPrimaryArtist(attributes: any) {
|
|
||||||
const songId = attributes.playParams.catalogId || attributes.playParams.id
|
|
||||||
|
|
||||||
if (!this._store.lastfm.enabledRemoveFeaturingArtists || !songId) return attributes.artistName;
|
|
||||||
|
|
||||||
const res = await this._win.webContents.executeJavaScript(`
|
|
||||||
(async () => {
|
|
||||||
const subMk = await MusicKit.getInstance().api.v3.music("/v1/catalog/" + MusicKit.getInstance().storefrontId + "/songs/${songId}", {
|
|
||||||
include: {
|
|
||||||
songs: ["artists"]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (!subMk) console.error('[LastFM] Request failed: /v1/catalog/us/songs/${songId}')
|
|
||||||
return subMk.data
|
|
||||||
})()
|
|
||||||
`).catch(console.error)
|
|
||||||
if (!res) return attributes.artistName
|
|
||||||
|
|
||||||
const data = res.data
|
|
||||||
if (!data.length) {
|
|
||||||
console.error(`[LastFM] Unable to locate song with id of ${songId}`)
|
|
||||||
return attributes.artistName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const artists = res.data[0].relationships.artists.data
|
|
||||||
if (!artists.length) {
|
|
||||||
console.error(`[LastFM] Unable to find artists related to the song with id of ${songId}`)
|
|
||||||
return attributes.artistName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const primaryArtist = artists[0]
|
|
||||||
return primaryArtist.attributes.name
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Plugin Details (Eventually implemented into a GUI in settings)
|
* Public Methods
|
||||||
*/
|
*/
|
||||||
public name: string = 'LastFMPlugin';
|
|
||||||
public description: string = 'LastFM plugin for Cider';
|
|
||||||
public version: string = '0.0.1';
|
|
||||||
public author: string = 'vapormusic / Cider Collective';
|
|
||||||
|
|
||||||
/**
|
constructor(utils: any) {
|
||||||
* Runs on plugin load (Currently run on application start)
|
this._utils = utils;
|
||||||
*/
|
this.initializeLastFM("", this._apiCredentials)
|
||||||
constructor(utils: { getApp: () => any; getStore: () => any; }) {
|
}
|
||||||
this._app = utils.getApp();
|
|
||||||
this._store = utils.getStore()
|
onReady(_win: Electron.BrowserWindow): void {
|
||||||
utils.getApp().on('second-instance', (_e: any, argv: any) => {
|
|
||||||
// Checks if first instance is authorized and if second instance has protocol args
|
// Register the ipcMain handlers
|
||||||
argv.forEach((value: any) => {
|
this._utils.getIPCMain().handle('lastfm:url', (event: any) => {
|
||||||
if (value.includes('auth')) {
|
console.debug(`${lastfm.name}:url`)
|
||||||
console.log('[LastFMPlugin ok]')
|
return this._lfm.getAuthenticationUrl({"cb": "cider://auth/lastfm"})
|
||||||
let authURI = String(argv).split('/auth/')[1];
|
|
||||||
if (authURI.startsWith('lastfm')) { // If we wanted more auth options
|
|
||||||
const authKey = authURI.split('lastfm?token=')[1];
|
|
||||||
this._store.lastfm.enabled = true;
|
|
||||||
this._store.lastfm.auth_token = authKey;
|
|
||||||
console.log(authKey);
|
|
||||||
this._win.webContents.send('LastfmAuthenticated', authKey);
|
|
||||||
this.authenticate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
electron.app.on('open-url', (event: any, arg: any) => {
|
|
||||||
console.log('[LastFMPlugin] yes')
|
this._utils.getIPCMain().on('lastfm:auth', (event: any, token: string) => {
|
||||||
event.preventDefault();
|
console.debug(`${lastfm.name}:auth`, token)
|
||||||
if (arg.includes('auth')) {
|
this.authenticateLastFM(token)
|
||||||
let authURI = String(arg).split('/auth/')[1];
|
})
|
||||||
if (authURI.startsWith('lastfm')) { // If we wanted more auth options
|
|
||||||
const authKey = authURI.split('lastfm?token=')[1];
|
this._utils.getIPCMain().on('lastfm:disconnect', (_event: any) => {
|
||||||
this._store.lastfm.enabled = true;
|
this._lfm.setSessionCredentials(null, null);
|
||||||
this._store.lastfm.auth_token = authKey;
|
this._authenticated = false;
|
||||||
this._win.webContents.send('LastfmAuthenticated', authKey);
|
console.debug(`${lastfm.name}:disconnect`)
|
||||||
console.log(authKey);
|
})
|
||||||
this.authenticate();
|
|
||||||
}
|
this._utils.getIPCMain().on('lastfm:nowPlayingChange', (event: any, attributes: any) => {
|
||||||
}
|
if (this._utils.getStoreValue("connectivity.lastfm.filter_loop")) return;
|
||||||
|
this.onNowPlayingItemDidChange(attributes)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on app ready
|
* Runs on playback State Change
|
||||||
|
* @param attributes Music Attributes (attributes.status = current state)
|
||||||
*/
|
*/
|
||||||
onReady(win: any): void {
|
onPlaybackStateDidChange(attributes: object): void {
|
||||||
this._win = win;
|
this._attributes = attributes
|
||||||
this.authenticate();
|
// this.scrobbleTrack(attributes)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs on app stop
|
|
||||||
*/
|
|
||||||
onBeforeQuit(): void {
|
|
||||||
console.log('Example plugin stopped');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on song change
|
* Runs on song change
|
||||||
* @param attributes Music Attributes
|
* @param attributes Music Attributes
|
||||||
*/
|
*/
|
||||||
nowPlayingItemDidChangeLastFM(attributes: any): void {
|
onNowPlayingItemDidChange(attributes: any): void {
|
||||||
if (!this._store.general.privateEnabled) {
|
if (this._utils.getStoreValue("general.privateEnabled")) return;
|
||||||
attributes.status = true
|
this._attributes = attributes
|
||||||
if (!this._store.lastfm.filterLoop) {
|
if (!attributes?.lfmTrack || !attributes?.lfmAlbum) {
|
||||||
this._lastfm.cachedNowPlayingAttributes = false;
|
this.verifyTrack(attributes)
|
||||||
this._lastfm.cachedAttributes = false
|
return
|
||||||
}
|
}
|
||||||
this.updateNowPlayingSong(attributes)
|
this.scrobbleTrack(attributes)
|
||||||
this.scrobbleSong(attributes)
|
this.updateNowPlayingTrack(attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize LastFM
|
||||||
|
* @param token
|
||||||
|
* @param api
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private initializeLastFM(token: string, api: { key: string, secret: string }): void {
|
||||||
|
const LastfmAPI = require("lastfmapi")
|
||||||
|
this._lfm = new LastfmAPI({
|
||||||
|
'api_key': api.key,
|
||||||
|
'secret': api.secret,
|
||||||
|
});
|
||||||
|
|
||||||
|
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._authenticated = true;
|
||||||
|
} else {
|
||||||
|
this.authenticateLastFM(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Authenticate the user with the given token
|
||||||
|
* @param token
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private authenticateLastFM(token: string): void {
|
||||||
|
if (!token) return;
|
||||||
|
this._lfm.authenticate(token, (err: any, session: any) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
this._utils.getWindow().webContents.executeJavaScript(`app.notyf.error("${err.message}");`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._utils.getWindow().webContents.send('lastfm:authenticated', session)
|
||||||
|
this._authenticated = true;
|
||||||
|
console.debug(`[${lastfm.name}:authenticate] Authenticated as ${session.username}`)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the track information with lastfm
|
||||||
|
* @param attributes
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private verifyTrack(attributes: any): object {
|
||||||
|
if (!attributes) return attributes;
|
||||||
|
|
||||||
|
if (!attributes.lfmAlbum) {
|
||||||
|
return this._lfm.album.getInfo({
|
||||||
|
"artist": attributes.artistName,
|
||||||
|
"album": attributes.albumName
|
||||||
|
}, (err: any, data: any) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`[${lastfm.name}] [album.getInfo] Error: ${typeof err === "string" ? err : err.message}`)
|
||||||
|
console.error(err)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
attributes.lfmAlbum = data
|
||||||
|
}
|
||||||
|
this.onNowPlayingItemDidChange(attributes)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return this._lfm.track.getCorrection(attributes.artistName, attributes.name, (err: any, data: any) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`[${lastfm.name}] [track.getCorrection] Error: ${typeof err === "string" ? err : err.message}`)
|
||||||
|
console.error(err)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (data) {
|
||||||
|
attributes.lfmTrack = data.correction.track
|
||||||
|
}
|
||||||
|
this.onNowPlayingItemDidChange(attributes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scrobbles the track to lastfm
|
||||||
|
* @param attributes
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private scrobbleTrack(attributes: any): void {
|
||||||
|
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._scrobbleDelay) {
|
||||||
|
clearTimeout(this._scrobbleDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrobble delay
|
||||||
|
this._scrobbleDelay = setTimeout(() => {
|
||||||
|
|
||||||
|
// Scrobble
|
||||||
|
const scrobble = {
|
||||||
|
'artist': attributes.lfmTrack.artist.name,
|
||||||
|
'track': attributes.lfmTrack.name,
|
||||||
|
'album': attributes.lfmAlbum.name,
|
||||||
|
'albumArtist': attributes.lfmAlbum.artist,
|
||||||
|
'timestamp': new Date().getTime() / 1000,
|
||||||
|
'trackNumber': attributes.trackNumber,
|
||||||
|
'duration': attributes.durationInMillis / 1000,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Easy Debugging
|
||||||
|
if (!this._utils.getApp().isPackaged) {
|
||||||
|
console.debug(scrobble)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrobble the track
|
||||||
|
this._lfm.track.scrobble(scrobble, (err: any, _res: any) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`[${lastfm.name}:scrobble] Scrobble failed: ${err.message}`);
|
||||||
|
} else {
|
||||||
|
console.debug(`[${lastfm.name}:scrobble] Track scrobbled: ${scrobble.artist} - ${scrobble.track}`);
|
||||||
|
this._scrobbleCache = scrobble
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, Math.round(attributes.durationInMillis * Math.min((this._utils.getStoreValue("connectivity.lastfm.scrobble_after") / 100), 0.8)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateNowPlayingTrack(attributes: any): void {
|
||||||
|
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 = {
|
||||||
|
'artist': attributes.lfmTrack.artist.name,
|
||||||
|
'track': attributes.lfmTrack.name,
|
||||||
|
'album': attributes.lfmAlbum.name,
|
||||||
|
'trackNumber': attributes.trackNumber,
|
||||||
|
'duration': attributes.durationInMillis / 1000,
|
||||||
|
'albumArtist': attributes.lfmAlbum.artist,
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lfm.track.updateNowPlaying(nowPlaying, (err: any, res: any) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`[${lastfm.name}:updateNowPlaying] Now Playing Update failed: ${err.message}`);
|
||||||
|
} else {
|
||||||
|
console.log(res)
|
||||||
|
console.debug(`[${lastfm.name}:updateNowPlaying] Now Playing Updated: ${nowPlaying.artist} - ${nowPlaying.track}`);
|
||||||
|
this._nowPlayingCache = nowPlaying
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ export default class mpris {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private static runMediaEvent(type: string) {
|
private static runMediaEvent(type: string) {
|
||||||
console.debug(`[Plugin][${this.name}] ${type}.`);
|
// console.debug(`[Plugin][${this.name}] ${type}.`);
|
||||||
mpris.utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.${type}()`).catch(console.error)
|
mpris.utils.getWindow().webContents.executeJavaScript(`MusicKitInterop.${type}()`).catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ export default class mpris {
|
||||||
*/
|
*/
|
||||||
@mpris.linuxOnly
|
@mpris.linuxOnly
|
||||||
onPlaybackStateDidChange(attributes: object): void {
|
onPlaybackStateDidChange(attributes: object): void {
|
||||||
console.debug(`[Plugin][${mpris.name}] onPlaybackStateDidChange.`);
|
// console.debug(`[Plugin][${mpris.name}] onPlaybackStateDidChange.`);
|
||||||
mpris.updatePlayerState(attributes)
|
mpris.updatePlayerState(attributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ export default class mpris {
|
||||||
*/
|
*/
|
||||||
@mpris.linuxOnly
|
@mpris.linuxOnly
|
||||||
onNowPlayingItemDidChange(attributes: object): void {
|
onNowPlayingItemDidChange(attributes: object): void {
|
||||||
console.debug(`[Plugin][${mpris.name}] onMetadataDidChange.`);
|
// console.debug(`[Plugin][${mpris.name}] onMetadataDidChange.`);
|
||||||
mpris.updatePlayer(attributes);
|
mpris.updatePlayer(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,6 @@ const MusicKitInterop = {
|
||||||
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);
|
||||||
// if (typeof _plugins != "undefined") {
|
|
||||||
// _plugins.execute("OnPlaybackStateChanged", {Attributes: MusicKitInterop.getAttributes()})
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,18 +21,13 @@ const MusicKitInterop = {
|
||||||
/** wsapi */
|
/** wsapi */
|
||||||
|
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, async () => {
|
||||||
console.debug('nowPlayingItemDidChange')
|
console.debug('[cider:preload] nowPlayingItemDidChange')
|
||||||
const attributes = MusicKitInterop.getAttributes()
|
const attributes = MusicKitInterop.getAttributes()
|
||||||
const trackFilter = MusicKitInterop.filterTrack(attributes, false, true)
|
|
||||||
|
|
||||||
if (trackFilter) {
|
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") {
|
||||||
|
global.ipcRenderer.send('lastfm:nowPlayingChange', attributes);
|
||||||
// LastFM's Custom Call
|
|
||||||
await MusicKitInterop.modifyNamesOnLocale();
|
|
||||||
if (trackFilter || !app.cfg.lastfm.filterLoop) {
|
|
||||||
global.ipcRenderer.send('nowPlayingItemDidChangeLastFM', attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MusicKit.getInstance().nowPlayingItem) {
|
if (MusicKit.getInstance().nowPlayingItem) {
|
||||||
|
@ -49,38 +41,16 @@ const MusicKitInterop = {
|
||||||
})
|
})
|
||||||
|
|
||||||
MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => {
|
MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => {
|
||||||
console.warn(`[mediaPlaybackError] ${e}`);
|
console.warn(`[cider:preload] mediaPlaybackError] ${e}`);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
sleep(ms) {
|
sleep(ms) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async modifyNamesOnLocale() {
|
|
||||||
if (app.mklang === '' || app.mklang == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const mk = MusicKit.getInstance()
|
|
||||||
const nowPlayingItem = mk.nowPlayingItem;
|
|
||||||
if ((nowPlayingItem?._songId ?? nowPlayingItem?.songId) == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const id = nowPlayingItem?._songId ?? (nowPlayingItem?.songId ?? nowPlayingItem?.id)
|
|
||||||
if (id != null && id !== -1) {
|
|
||||||
try{
|
|
||||||
const query = await mk.api.v3.music(`/v1${(((nowPlayingItem?._songId ?? nowPlayingItem?.songId) != null) && ((nowPlayingItem?._songId ?? nowPlayingItem?.songId) !== -1)) ? `/catalog/${mk.storefrontId}/` : `/me/library/`}songs/${id}?l=${app.mklang}`);
|
|
||||||
if (query?.data?.data[0]){
|
|
||||||
let attrs = query?.data?.data[0]?.attributes;
|
|
||||||
if (attrs?.name) { nowPlayingItem.attributes.name = attrs?.name ?? ''}
|
|
||||||
if (attrs?.albumName) { nowPlayingItem.attributes.albumName = attrs?.albumName ?? ''}
|
|
||||||
if (attrs?.artistName) { nowPlayingItem.attributes.artistName = attrs?.artistName ?? ''}
|
|
||||||
|
|
||||||
}} catch (e) { }
|
|
||||||
} else {}
|
|
||||||
},
|
|
||||||
getAttributes: function () {
|
getAttributes: function () {
|
||||||
const mk = MusicKit.getInstance()
|
const mk = MusicKit.getInstance()
|
||||||
const nowPlayingItem = mk.nowPlayingItem;
|
const nowPlayingItem = mk.nowPlayingItem;
|
||||||
|
@ -96,8 +66,8 @@ const MusicKitInterop = {
|
||||||
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') {
|
if (attributes.playParams.id === 'no-id-found') {
|
||||||
attributes.playParams.id = nowPlayingItem?.id ?? 'no-id-found';
|
attributes.playParams.id = nowPlayingItem?.id ?? 'no-id-found';
|
||||||
|
@ -115,7 +85,7 @@ const MusicKitInterop = {
|
||||||
attributes?.playParams?.id === cache.playParams.id
|
attributes?.playParams?.id === cache.playParams.id
|
||||||
? Date.now() + attributes?.remainingTime
|
? Date.now() + attributes?.remainingTime
|
||||||
: attributes?.startTime + attributes?.durationInMillis
|
: attributes?.startTime + attributes?.durationInMillis
|
||||||
);
|
);
|
||||||
return attributes;
|
return attributes;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -156,19 +126,19 @@ 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(`[MusicKitInterop.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(`[MusicKitInterop.previous] Skipping to Previous ${r}`));
|
MusicKit.getInstance().skipToPreviousItem().then(r => console.debug(`[cider:preload] [previous] Skipping to Previous ${r}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
process.once('loaded', () => {
|
process.once('loaded', () => {
|
||||||
console.debug("Setting ipcRenderer")
|
console.debug("[cider:preload] IPC Listeners Created!")
|
||||||
global.MusicKitInterop = MusicKitInterop;
|
global.MusicKitInterop = MusicKitInterop;
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,6 +68,10 @@ Vue.component("sidebar-library-item", {
|
||||||
required: false,
|
required: false,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
|
svgIconName: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
cdClick: {
|
cdClick: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: false,
|
required: false,
|
||||||
|
|
|
@ -832,6 +832,10 @@ const app = new Vue({
|
||||||
|
|
||||||
MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player")
|
MusicKit.getInstance().videoContainerElement = document.getElementById("apple-music-video-player")
|
||||||
|
|
||||||
|
ipcRenderer.on('setStoreValue', (e, key, value) => {
|
||||||
|
app.cfg[key] = value
|
||||||
|
})
|
||||||
|
|
||||||
ipcRenderer.on('theme-update', async (event, arg) => {
|
ipcRenderer.on('theme-update', async (event, arg) => {
|
||||||
await less.refresh(true, true, true)
|
await less.refresh(true, true, true)
|
||||||
self.setTheme(self.cfg.visual.theme, true)
|
self.setTheme(self.cfg.visual.theme, true)
|
||||||
|
@ -4423,37 +4427,6 @@ const app = new Vue({
|
||||||
}
|
}
|
||||||
app.modals.settings = true
|
app.modals.settings = true
|
||||||
},
|
},
|
||||||
LastFMDeauthorize() {
|
|
||||||
ipcRenderer.invoke('setStoreValue', 'lastfm.enabled', false).catch((e) => console.error(e));
|
|
||||||
ipcRenderer.invoke('setStoreValue', 'lastfm.auth_token', '').catch((e) => console.error(e));
|
|
||||||
app.cfg.lastfm.auth_token = "";
|
|
||||||
app.cfg.lastfm.enabled = false;
|
|
||||||
const element = document.getElementById('lfmConnect');
|
|
||||||
element.innerHTML = app.getLz('term.connect');
|
|
||||||
element.onclick = app.LastFMAuthenticate;
|
|
||||||
},
|
|
||||||
LastFMAuthenticate() {
|
|
||||||
console.log("[LastFM] Received LastFM authentication callback")
|
|
||||||
const element = document.getElementById('lfmConnect');
|
|
||||||
// new key : f9986d12aab5a0fe66193c559435ede3
|
|
||||||
window.open('https://www.last.fm/api/auth?api_key=f9986d12aab5a0fe66193c559435ede3&cb=cider://auth/lastfm');
|
|
||||||
element.innerText = app.getLz('term.connecting') + '...';
|
|
||||||
|
|
||||||
/* Just a timeout for the button */
|
|
||||||
setTimeout(() => {
|
|
||||||
if (element.innerText === app.getLz('term.connecting') + '...') {
|
|
||||||
element.innerText = app.getLz('term.connect');
|
|
||||||
console.warn('[LastFM] Attempted connection timed out.');
|
|
||||||
}
|
|
||||||
}, 20000);
|
|
||||||
|
|
||||||
ipcRenderer.on('LastfmAuthenticated', function (_event, lfmAuthKey) {
|
|
||||||
app.cfg.lastfm.auth_token = lfmAuthKey;
|
|
||||||
app.cfg.lastfm.enabled = true;
|
|
||||||
element.innerHTML = `${app.getLz('term.disconnect')}\n<p style="font-size: 8px"><i>(${app.getLz('term.authed')}: ${lfmAuthKey})</i></p>`;
|
|
||||||
element.onclick = app.LastFMDeauthorize;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
fullscreen(flag) {
|
fullscreen(flag) {
|
||||||
this.fullscreenState = flag;
|
this.fullscreenState = flag;
|
||||||
if (flag) {
|
if (flag) {
|
||||||
|
|
|
@ -198,13 +198,13 @@
|
||||||
</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" 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"
|
<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" 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" 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>
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('home.title')"
|
:name="$root.getLz('home.title')"
|
||||||
svg-icon="./assets/feather/home.svg"
|
svg-icon="./assets/feather/home.svg"
|
||||||
|
svg-icon-name="home"
|
||||||
page="home"
|
page="home"
|
||||||
>
|
>
|
||||||
</sidebar-library-item>
|
</sidebar-library-item>
|
||||||
|
@ -67,17 +68,20 @@
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.listenNow')"
|
:name="$root.getLz('term.listenNow')"
|
||||||
svg-icon="./assets/feather/play-circle.svg"
|
svg-icon="./assets/feather/play-circle.svg"
|
||||||
|
svg-icon-name="listenNow"
|
||||||
page="listen_now"
|
page="listen_now"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.browse')"
|
:name="$root.getLz('term.browse')"
|
||||||
svg-icon="./assets/feather/globe.svg"
|
svg-icon="./assets/feather/globe.svg"
|
||||||
|
svg-icon-name="browse"
|
||||||
page="browse"
|
page="browse"
|
||||||
>
|
>
|
||||||
</sidebar-library-item>
|
</sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.radio')"
|
:name="$root.getLz('term.radio')"
|
||||||
svg-icon="./assets/feather/radio.svg"
|
svg-icon="./assets/feather/radio.svg"
|
||||||
|
svg-icon-name="radio"
|
||||||
page="radio"
|
page="radio"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
</template>
|
</template>
|
||||||
|
@ -94,36 +98,42 @@
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.recentlyAdded')"
|
:name="$root.getLz('term.recentlyAdded')"
|
||||||
svg-icon="./assets/feather/plus-circle.svg"
|
svg-icon="./assets/feather/plus-circle.svg"
|
||||||
|
svg-icon-name="recentlyAdded"
|
||||||
v-if="cfg.general.sidebarItems.recentlyAdded"
|
v-if="cfg.general.sidebarItems.recentlyAdded"
|
||||||
page="library-recentlyadded"
|
page="library-recentlyadded"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.songs')"
|
:name="$root.getLz('term.songs')"
|
||||||
svg-icon="./assets/feather/music.svg"
|
svg-icon="./assets/feather/music.svg"
|
||||||
|
svg-icon-name="songs"
|
||||||
v-if="cfg.general.sidebarItems.songs"
|
v-if="cfg.general.sidebarItems.songs"
|
||||||
page="library-songs"
|
page="library-songs"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.albums')"
|
:name="$root.getLz('term.albums')"
|
||||||
svg-icon="./assets/feather/disc.svg"
|
svg-icon="./assets/feather/disc.svg"
|
||||||
|
svg-icon-name="albums"
|
||||||
v-if="cfg.general.sidebarItems.albums"
|
v-if="cfg.general.sidebarItems.albums"
|
||||||
page="library-albums"
|
page="library-albums"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.artists')"
|
:name="$root.getLz('term.artists')"
|
||||||
svg-icon="./assets/feather/user.svg"
|
svg-icon="./assets/feather/user.svg"
|
||||||
|
svg-icon-name="artists"
|
||||||
v-if="cfg.general.sidebarItems.artists"
|
v-if="cfg.general.sidebarItems.artists"
|
||||||
page="library-artists"
|
page="library-artists"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.videos')"
|
:name="$root.getLz('term.videos')"
|
||||||
svg-icon="./assets/feather/video.svg"
|
svg-icon="./assets/feather/video.svg"
|
||||||
|
svg-icon-name="videos"
|
||||||
v-if="cfg.general.sidebarItems.videos"
|
v-if="cfg.general.sidebarItems.videos"
|
||||||
page="library-videos"
|
page="library-videos"
|
||||||
></sidebar-library-item>
|
></sidebar-library-item>
|
||||||
<sidebar-library-item
|
<sidebar-library-item
|
||||||
:name="$root.getLz('term.podcasts')"
|
:name="$root.getLz('term.podcasts')"
|
||||||
svg-icon="./assets/feather/mic.svg"
|
svg-icon="./assets/feather/mic.svg"
|
||||||
|
svg-icon-name="podcasts"
|
||||||
v-if="cfg.general.sidebarItems.podcasts"
|
v-if="cfg.general.sidebarItems.podcasts"
|
||||||
page="podcasts"
|
page="podcasts"
|
||||||
>
|
>
|
||||||
|
|
|
@ -994,18 +994,18 @@
|
||||||
</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.general.discordrpc.enabled" switch />
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.enabled" switch />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.clientName')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.clientName')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<select class="md-select" v-model="app.cfg.general.discordrpc.client">
|
<select class="md-select" v-model="app.cfg.connectivity.discord_rpc.client">
|
||||||
<option value="Cider">{{$root.getLz('app.name')}}</option>
|
<option value="Cider">{{$root.getLz('app.name')}}</option>
|
||||||
<option value="AppleMusic">{{$root.getLz('term.appleMusic')}}
|
<option value="AppleMusic">{{$root.getLz('term.appleMusic')}}
|
||||||
</option>
|
</option>
|
||||||
|
@ -1014,40 +1014,40 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
|
||||||
</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.general.discordrpc.clear_on_pause" switch />
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.clear_on_pause" switch />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
|
||||||
</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.general.discordrpc.hide_buttons" switch />
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.hide_buttons" switch />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.hideTimestamp')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.hideTimestamp')}}
|
||||||
</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.general.discordrpc.hide_timestamp" switch />
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.hide_timestamp" switch />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}<br />
|
{{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}<br />
|
||||||
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
||||||
|
@ -1055,12 +1055,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="text" v-model="app.cfg.general.discordrpc.details_format" />
|
<input type="text" v-model="app.cfg.connectivity.discord_rpc.details_format" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}}
|
||||||
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
||||||
|
@ -1068,12 +1068,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="text" v-model="app.cfg.general.discordrpc.state_format" />
|
<input type="text" v-model="app.cfg.connectivity.discord_rpc.state_format" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.reload')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.reload')}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1089,51 +1089,55 @@
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto" >
|
||||||
<button class="md-btn" id="lfmConnect" ref="lfmConnect"
|
<button class="md-btn" id="lfmConnect" @click="app.cfg.connectivity.lastfm.enabled ? lfmDisconnect() : lfmAuthorize()">
|
||||||
@click="app.LastFMAuthenticate()">
|
{{$root.getLz(`term.${$root.cfg.connectivity.lastfm.enabled ? "disconnect" : "connect"}`)}}<br>
|
||||||
{{$root.getLz('term.connect')}}
|
<small>{{app.cfg.connectivity.lastfm.enabled ? `${$root.getLz('term.authed')}: ${$root.cfg.connectivity.lastfm.secrets.username}` : '' }}</small>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
<div class="md-option-line" v-show="lastfmConnecting">
|
||||||
|
<div class="md-option-segment">
|
||||||
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.manualToken')}}
|
||||||
|
</div>
|
||||||
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
|
<label>
|
||||||
|
<form @submit.prevent="submitToken">
|
||||||
|
<input type="text" autofocus id="lfmToken" />
|
||||||
|
<input type="submit" class="md-btn" @value="$root.getLz('action.submit')" />
|
||||||
|
</form>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.delay')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.delay')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="number" min="50" max="100" v-model="app.cfg.lastfm.scrobble_after" />
|
<input type="number" min="50" max="100" v-model="app.cfg.connectivity.lastfm.scrobble_after"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
<div class="md-option-segment">
|
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.nowPlaying')}}
|
|
||||||
</div>
|
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" v-model="app.cfg.lastfm.NowPlaying" switch />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
|
||||||
<div class="md-option-segment">
|
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.removeFeatured')}}
|
|
||||||
</div>
|
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" v-model="app.cfg.lastfm.enabledRemoveFeaturingArtists"
|
|
||||||
switch />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}}
|
||||||
|
<small>{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop.description')}}</small>
|
||||||
</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.lastfm.filterLoop" switch />
|
<input type="checkbox" v-model="app.cfg.connectivity.lastfm.filter_loop" switch/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
|
<div class="md-option-segment">
|
||||||
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterTypes')}}
|
||||||
|
</div>
|
||||||
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" @change="filterChange" value="song">{{$root.getLz('term.songs')}}<br>
|
||||||
|
<input type="checkbox" @change="filterChange" value="musicVideo">{{$root.getLz('term.musicVideos')}}<br>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1421,7 +1425,8 @@
|
||||||
app: this.$root,
|
app: this.$root,
|
||||||
themes: ipcRenderer.sendSync("get-themes"),
|
themes: ipcRenderer.sendSync("get-themes"),
|
||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
canChangeHash: false
|
canChangeHash: false,
|
||||||
|
lastfmConnecting: false
|
||||||
}
|
}
|
||||||
}, watch: {
|
}, watch: {
|
||||||
tabIndex: function (val) {
|
tabIndex: function (val) {
|
||||||
|
@ -1430,15 +1435,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted: function () {
|
|
||||||
if (app.cfg.lastfm.enabled) {
|
|
||||||
const element = document.getElementById('lfmConnect');
|
|
||||||
if (element) {
|
|
||||||
element.innerHTML = `Disconnect\n<p style="font-size: 8px"><i>(Authed: ${app.cfg.lastfm.auth_token})</i></p>`;
|
|
||||||
element.onclick = app.LastFMDeauthorize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close() {
|
||||||
this.$root.modals.settings = false
|
this.$root.modals.settings = false
|
||||||
|
@ -1554,6 +1550,41 @@
|
||||||
},
|
},
|
||||||
reloadDiscordRPC() {
|
reloadDiscordRPC() {
|
||||||
ipcRenderer.send('reloadRPC')
|
ipcRenderer.send('reloadRPC')
|
||||||
|
},
|
||||||
|
lfmDisconnect() {
|
||||||
|
this.$root.cfg.connectivity.lastfm.enabled = false;
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.username = "";
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.key = "";
|
||||||
|
ipcRenderer.send('lastfm:disconnect');
|
||||||
|
},
|
||||||
|
async lfmAuthorize() {
|
||||||
|
this.lastfmConnecting = true;
|
||||||
|
window.open(await ipcRenderer.invoke('lastfm:url'));
|
||||||
|
app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connecting'));
|
||||||
|
|
||||||
|
/* Just a timeout for the button */
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.$root.cfg.connectivity.lastfm.enabled) {
|
||||||
|
app.notyf.error(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectError'));
|
||||||
|
console.warn('[lastfm:authorize] Last.fm authorization timed out.');
|
||||||
|
this.lastfmConnecting = false;
|
||||||
|
}
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
ipcRenderer.once('lastfm:authenticated', (_e, session) => {
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.username = session.username
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.key = session.key
|
||||||
|
this.$root.cfg.connectivity.lastfm.enabled = true
|
||||||
|
this.lastfmConnecting = false;
|
||||||
|
app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectSuccess'));
|
||||||
|
})
|
||||||
|
},
|
||||||
|
filterChange(e) {
|
||||||
|
this.$root.cfg.connectivity.lastfm.filter_types[e.target.value] = e.target.checked;
|
||||||
|
},
|
||||||
|
submitToken() {
|
||||||
|
const token = document.getElementById('lfmToken').value;
|
||||||
|
ipcRenderer.send('lastfm:auth', token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
:href="item.href"
|
:href="item.href"
|
||||||
@click='clickEvent()'>
|
@click='clickEvent()'>
|
||||||
<template v-if="!renaming">
|
<template v-if="!renaming">
|
||||||
<svg-icon :url="icon"/> {{ item.attributes.name }}
|
<svg-icon :url="icon" name="sidebar-playlist"/> {{ item.attributes.name }}
|
||||||
<small class="presentNotice" v-if="hasRelatedMediaItems">(Track present)</small>
|
<small class="presentNotice" v-if="hasRelatedMediaItems">(Track present)</small>
|
||||||
</template>
|
</template>
|
||||||
<input type="text" v-model="item.attributes.name" class="pl-rename-field" @blur="rename()" @keydown.enter="rename()" v-else>
|
<input type="text" v-model="item.attributes.name" class="pl-rename-field" @blur="rename()" @keydown.enter="rename()" v-else>
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
<script type="text/x-template" id="sidebar-library-item">
|
<script type="text/x-template" id="sidebar-library-item">
|
||||||
<button class="app-sidebar-item"
|
<button class="app-sidebar-item"
|
||||||
:class="$parent.getSidebarItemClass(page)" @click="$root.setWindowHash(page)">
|
:class="$parent.getSidebarItemClass(page)" @click="$root.setWindowHash(page)">
|
||||||
<svg-icon :url="svgIconData" 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>
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -954,18 +954,18 @@
|
||||||
</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.general.discordrpc.enabled" switch/>
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.enabled" switch/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.clientName')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.clientName')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<select class="md-select" v-model="app.cfg.general.discordrpc.client">
|
<select class="md-select" v-model="app.cfg.connectivity.discord_rpc.client">
|
||||||
<option value="Cider">{{$root.getLz('app.name')}}</option>
|
<option value="Cider">{{$root.getLz('app.name')}}</option>
|
||||||
<option value="AppleMusic">{{$root.getLz('term.appleMusic')}}
|
<option value="AppleMusic">{{$root.getLz('term.appleMusic')}}
|
||||||
</option>
|
</option>
|
||||||
|
@ -974,40 +974,40 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
|
||||||
</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.general.discordrpc.clear_on_pause" switch/>
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.clear_on_pause" switch/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
|
||||||
</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.general.discordrpc.hide_buttons" switch/>
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.hide_buttons" switch/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.hideTimestamp')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.hideTimestamp')}}
|
||||||
</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.general.discordrpc.hide_timestamp" switch/>
|
<input type="checkbox" v-model="app.cfg.connectivity.discord_rpc.hide_timestamp" switch/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}<br/>
|
{{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}<br/>
|
||||||
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
||||||
|
@ -1015,12 +1015,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="text" v-model="app.cfg.general.discordrpc.details_format"/>
|
<input type="text" v-model="app.cfg.connectivity.discord_rpc.details_format"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}}
|
||||||
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album},
|
||||||
|
@ -1028,12 +1028,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="text" v-model="app.cfg.general.discordrpc.state_format"/>
|
<input type="text" v-model="app.cfg.connectivity.discord_rpc.state_format"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="md-option-line" v-show="app.cfg.general.discordrpc.enabled != false">
|
<div class="md-option-line" v-show="app.cfg.connectivity.discord_rpc.enabled != false">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.discordRPC.reload')}}
|
{{$root.getLz('settings.option.connectivity.discordRPC.reload')}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1050,50 +1050,41 @@
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<button class="md-btn" id="lfmConnect" ref="lfmConnect"
|
<button class="md-btn" id="lfmConnect" @click="app.cfg.connectivity.lastfm.enabled ? lfmDisconnect() : lfmAuthorize()">
|
||||||
@click="app.LastFMAuthenticate()">
|
{{$root.getLz(`term.${$root.cfg.connectivity.lastfm.enabled ? "disconnect" : "connect"}`)}}<br>
|
||||||
{{$root.getLz('term.connect')}}
|
<small>{{app.cfg.connectivity.lastfm.enabled ? `${$root.getLz('term.authed')}: ${$root.cfg.connectivity.lastfm.secrets.username}` : '' }}</small>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.delay')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.delay')}}
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
<label>
|
<label>
|
||||||
<input type="number" min="50" max="100" v-model="app.cfg.lastfm.scrobble_after"/>
|
<input type="number" min="50" max="100" v-model="app.cfg.connectivity.lastfm.scrobble_after"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
<div class="md-option-segment">
|
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.nowPlaying')}}
|
|
||||||
</div>
|
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" v-model="app.cfg.lastfm.NowPlaying" switch/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
|
||||||
<div class="md-option-segment">
|
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.removeFeatured')}}
|
|
||||||
</div>
|
|
||||||
<div class="md-option-segment md-option-segment_auto">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" v-model="app.cfg.lastfm.enabledRemoveFeaturingArtists"
|
|
||||||
switch/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="md-option-line" v-show="app.cfg.lastfm.enabled">
|
|
||||||
<div class="md-option-segment">
|
<div class="md-option-segment">
|
||||||
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}}
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop')}}
|
||||||
|
<small>{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterLoop.description')}}</small>
|
||||||
</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.lastfm.filterLoop" switch/>
|
<input type="checkbox" v-model="app.cfg.connectivity.lastfm.filter_loop" switch/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="md-option-line" v-show="app.cfg.connectivity.lastfm.enabled">
|
||||||
|
<div class="md-option-segment">
|
||||||
|
{{$root.getLz('settings.option.connectivity.lastfmScrobble.filterTypes')}}
|
||||||
|
</div>
|
||||||
|
<div class="md-option-segment md-option-segment_auto">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" @change="filterChange" value="song">{{$root.getLz('term.songs')}}<br>
|
||||||
|
<input type="checkbox" @change="filterChange" value="musicVideo">{{$root.getLz('term.musicVideos')}}<br>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1390,14 +1381,6 @@
|
||||||
this.canChangeHash = true
|
this.canChangeHash = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (app.cfg.lastfm.enabled) {
|
|
||||||
const element = document.getElementById('lfmConnect');
|
|
||||||
if (element) {
|
|
||||||
element.innerHTML = `Disconnect\n<p style="font-size: 8px"><i>(Authed: ${app.cfg.lastfm.auth_token})</i></p>`;
|
|
||||||
element.onclick = app.LastFMDeauthorize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
windowBgStyleChange() {
|
windowBgStyleChange() {
|
||||||
|
@ -1511,6 +1494,35 @@
|
||||||
},
|
},
|
||||||
reloadDiscordRPC() {
|
reloadDiscordRPC() {
|
||||||
ipcRenderer.send('reloadRPC')
|
ipcRenderer.send('reloadRPC')
|
||||||
|
},
|
||||||
|
lfmDisconnect() {
|
||||||
|
this.$root.cfg.connectivity.lastfm.enabled = false;
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.username = "";
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.key = "";
|
||||||
|
ipcRenderer.send('lastfm:disconnect');
|
||||||
|
},
|
||||||
|
async lfmAuthorize() {
|
||||||
|
window.open(await ipcRenderer.invoke('lastfm:url'));
|
||||||
|
app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connecting'));
|
||||||
|
|
||||||
|
/* Just a timeout for the button */
|
||||||
|
setTimeout(() => {
|
||||||
|
if (document.getElementById('lfmConnect').innerText === app.getLz('term.connecting') + '...') {
|
||||||
|
app.notyf.error(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectError'));
|
||||||
|
console.warn('[lastfm:authorize] Last.fm authorization timed out.');
|
||||||
|
}
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
ipcRenderer.once('lastfm:authenticated', (_e, session) => {
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.username = session.username
|
||||||
|
this.$root.cfg.connectivity.lastfm.secrets.key = session.key
|
||||||
|
this.$root.cfg.connectivity.lastfm.enabled = true
|
||||||
|
app.notyf.success(app.getLz('settings.notyf.connectivity.lastfmScrobble.connectSuccess'));
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
filterChange(e) {
|
||||||
|
this.$root.cfg.connectivity.lastfm.filter_types[e.target.value] = e.target.checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue