From 99b4c2960c7dff5aca3fa29e913a5f9e4dfadb4f Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:37:06 +0100 Subject: [PATCH 01/26] DiscordRPC customisation --- src/main/plugins/discordrpc.ts | 155 +++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 64 deletions(-) diff --git a/src/main/plugins/discordrpc.ts b/src/main/plugins/discordrpc.ts index 90b06809..0fa1540e 100644 --- a/src/main/plugins/discordrpc.ts +++ b/src/main/plugins/discordrpc.ts @@ -2,15 +2,15 @@ import * as RPC from 'discord-rpc' import {ipcMain} from "electron"; import fetch from 'electron-fetch' -export default class DiscordRichPresence { +export default class DiscordRPC { /** * Private variables for interaction in plugins */ - private static _store: any; + private _utils: any; private _app: any; private _attributes: any; - private static _connection: boolean = false; + private _connection: boolean = false; /** * Base Plugin Details (Eventually implemented into a GUI in settings) @@ -33,7 +33,6 @@ export default class DiscordRichPresence { smallImageText: '', instance: false }; - private _clientId: number = 0; private _activityCache: RPC.Presence = { details: '', @@ -50,21 +49,21 @@ export default class DiscordRichPresence { * ****************************************************************************************/ /** - * Connect to Discord - * @param clientId + * Connect to Discord RPC * @private */ - private connect(clientId: any) { - this._clientId = clientId; - if (DiscordRichPresence._store.general.discord_rpc == 0) { - return + private connect() { + if (!this._utils.getStoreValue("general.discord_rpc.enabled")) { + return; } + const clientId = this._utils.getStoreValue("general.discord_rpc.client") === "Cider" ? '911790844204437504' : '886578863147192350'; // Apparently needed for ask to join, join, spectate etc. RPC.register(clientId) // Create the client this._client = new RPC.Client({transport: "ipc"}); + // Runs on Ready this._client.on('ready', () => { console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`); @@ -72,22 +71,22 @@ export default class DiscordRichPresence { // Handles Errors this._client.on('error', (err: any) => { - console.error(`[DiscordRichPresence] ${err}`); + console.error(`[DiscordRPC] ${err}`); this.disconnect() }); // If Discord is closed, allow reconnecting this._client.transport.once('close', () => { - console.info(`[DiscordRichPresence] Connection closed`); + console.info(`[DiscordRPC] Connection closed`); this.disconnect() }); // Login to Discord this._client.login({clientId}) .then(() => { - DiscordRichPresence._connection = true; + this._connection = true; }) - .catch((e: any) => console.error(`[DiscordRichPresence][connect] ${e}`)); + .catch((e: any) => console.error(`[DiscordRPC][connect] ${e}`)); } /** @@ -99,7 +98,7 @@ export default class DiscordRichPresence { } this._client.destroy().then(() => { - DiscordRichPresence._connection = false; + this._connection = false; console.log('[DiscordRPC][disconnect] Disconnected from discord.') }).catch((e: any) => console.error(`[DiscordRPC][disconnect] ${e}`)); @@ -112,6 +111,32 @@ export default class DiscordRichPresence { */ private static filterActivity(activity: any, attributes: any): Object { + /** + * Works with: + * {artist} + * {composer} + * {title} + * {album} + * {trackNumber} + */ + const rpcVars: any = { + "artist": attributes.artistName, + "composer": attributes.composerName, + "title": attributes.name, + "album": attributes.albumName, + "trackNumber": attributes.trackNumber + } + + // Replace the variables + Object.keys(rpcVars).forEach((key) => { + if (activity.details.includes(`{${key}}`)) { + activity.details = activity.details.replace(`{${key}}`, rpcVars[key]) + } + if (activity.state.includes(`{${key}}`)) { + activity.state = activity.state.replace(`{${key}}`, rpcVars[key]) + } + }) + // Checks if the name is greater than 128 because some songs can be that long if (activity.details && activity.details.length > 128) { activity.details = activity.details.substring(0, 125) + '...' @@ -139,67 +164,68 @@ export default class DiscordRichPresence { return activity } + /** + * Sets the activity + * @param {activity} activity + */ + private setActivity(activity: any) { + if (!this._connection || !this._client || !activity) { + return + } + + // Filter the activity + activity = DiscordRPC.filterActivity(activity, this._attributes) + + // Set the activity + if (!this._attributes.status && this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) { + this._client.clearActivity() + } else { + this._client.setActivity(activity) + this._activityCache = this._activity; + } + } + /** * Sets the activity of the client * @param {object} attributes */ private updateActivity(attributes: any) { - if (DiscordRichPresence._store.general.discord_rpc == 0) { + if (!this._utils.getStoreValue("general.discord_rpc.enabled") || this._utils.getStoreValue("general.privateEnabled")) { return - } else if (!DiscordRichPresence._connection || !this._client) { - this.connect(this._clientId) - } - - if (!DiscordRichPresence._connection) { - this._client.clearActivity().catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`)); - return; + } else if (!this._client || !this._connection) { + this.connect() } // Check if show buttons is (true) or (false) this._activity = { - details: attributes.name, - state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`, - startTimestamp: Date.now() - (attributes?.durationInMillis - attributes?.remainingTime), - endTimestamp: attributes.endTime, + details: this._utils.getStoreValue("general.discord_rpc.details_format"), + state: this._utils.getStoreValue("general.discord_rpc.state_format"), largeImageKey: attributes?.artwork?.url?.replace('{w}', '1024').replace('{h}', '1024'), largeImageText: attributes.albumName, instance: false // Whether the activity is in a game session } - if (!DiscordRichPresence._store.general.discord_rpc_hide_buttons) { + // Add the buttons if people want them + if (!this._utils.getStoreValue("general.discord_rpc.hide_buttons")) { this._activity.buttons = [ {label: 'Listen on Cider', url: attributes.url.cider}, {label: 'View on Apple Music', url: attributes.url.appleMusic} ] //To change attributes.url => preload/cider-preload.js } - - this._activity = DiscordRichPresence.filterActivity(this._activity, attributes) - - // Check if its pausing (false) or playing (true) - if (!attributes.status) { - if (DiscordRichPresence._store.general.discord_rpc_clear_on_pause) { - this._client.clearActivity() - .catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`)); - } else { - this._activity.smallImageKey = 'pause'; - this._activity.smallImageText = 'Paused'; - delete this._activity.endTimestamp; - delete this._activity.startTimestamp; - this._client.setActivity(this._activity) - .catch((e: any) => console.error(`[DiscordRichPresence][setActivity] ${e}`)); - } - } else if (this._activity && this._activityCache !== this._activity && this._activity.details) { - if (!DiscordRichPresence._store.general.discord_rpc_clear_on_pause) { - this._activity.smallImageKey = 'play'; - this._activity.smallImageText = 'Playing'; - } - - this._client.setActivity(this._activity) - .catch((e: any) => console.error(`[DiscordRichPresence][updateActivity] ${e}`)); - this._activityCache = this._activity; + // Add the timestamp if its playing + if (attributes.status) { + this._activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime) + this._activity.endTimestamp = attributes.endTime } + // If the user wants to keep the activity when paused + if (!this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) { + this._activity.smallImageKey = attributes.status ? 'pause' : 'play'; + this._activity.smallImageText = attributes.status ? 'Paused' : 'Playing'; + } + + this.setActivity(this._activity) } /******************************************************************************************* @@ -210,7 +236,7 @@ export default class DiscordRichPresence { * Runs on plugin load (Currently run on application start) */ constructor(utils: { getStore: () => any; getApp: () => any; }) { - DiscordRichPresence._store = utils.getStore(); + this._utils = utils; console.debug(`[Plugin][${this.name}] Loading Complete.`); this._app = utils.getApp(); } @@ -220,10 +246,10 @@ export default class DiscordRichPresence { */ onReady(_win: any): void { let self = this - this.connect((DiscordRichPresence._store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350'); + this.connect(); console.debug(`[Plugin][${this.name}] Ready.`); ipcMain.on('updateRPCImage', (_event, imageurl) => { - if (!DiscordRichPresence._store.general.privateEnabled) { + if (!this._utils.getStoreValue("general.privateEnabled")) { fetch('https://api.cider.sh/v1/images', { method: 'POST', @@ -246,6 +272,9 @@ export default class DiscordRichPresence { * Runs on app stop */ onBeforeQuit(): void { + if (this._client) { + this.disconnect() + } console.debug(`[Plugin][${this.name}] Stopped.`); } @@ -254,10 +283,9 @@ export default class DiscordRichPresence { * @param attributes Music Attributes (attributes.status = current state) */ onPlaybackStateDidChange(attributes: object): void { - if (!DiscordRichPresence._store.general.privateEnabled) { - this._attributes = attributes - this.updateActivity(attributes) - } + this._attributes = attributes + this.updateActivity(attributes) + } /** @@ -265,9 +293,8 @@ export default class DiscordRichPresence { * @param attributes Music Attributes */ onNowPlayingItemDidChange(attributes: object): void { - if (!DiscordRichPresence._store.general.privateEnabled) { - this._attributes = attributes - this.updateActivity(attributes) - } + this._attributes = attributes + this.updateActivity(attributes) + } } From 5a2229cf67914f7a0e3367d28b51ebb4be5b92be Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:37:21 +0100 Subject: [PATCH 02/26] rpc customisation settings page --- src/renderer/main/vueapp.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index d988dcd3..422a6b31 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -1507,10 +1507,9 @@ const app = new Vue({ */ convertTime(seconds, format = "short") { - if (isNaN(seconds) || seconds == Infinity) { + if (isNaN(seconds) || seconds === Infinity) { seconds = 0 } - seconds = parseInt(seconds); const datetime = new Date(seconds * 1000) @@ -1520,12 +1519,11 @@ const app = new Vue({ const m = Math.floor(seconds % 3600 / 60); const s = Math.floor(seconds % 60); - const dDisplay = d > 0 ? `${d} ${app.getLz("term.time.day", { "count": d })}, ` : ""; - const hDisplay = h > 0 ? `${h} ${app.getLz("term.time.hour", { "count": h })}, ` : ""; - const mDisplay = m > 0 ? `${m} ${app.getLz("term.time.minute", { "count": m })}, ` : ""; - const sDisplay = s > 0 ? `${s} ${app.getLz("term.time.second", { "count": s })}` : ""; + const dDisplay = d > 0 ? `${d} ${app.getLz("term.time.day", { "count": d })}` : ""; + const hDisplay = h > 0 ? `${h} ${app.getLz("term.time.hour", { "count": h })}` : ""; + const mDisplay = m > 0 ? `${m} ${app.getLz("term.time.minute", { "count": m })}` : ""; - return dDisplay + hDisplay + mDisplay + sDisplay; + return dDisplay + (dDisplay && hDisplay ? ", " : "") + hDisplay + (hDisplay && mDisplay ? ", " : "") + mDisplay; } else { let returnTime = datetime.toISOString().substring(11, 19); From d47c784bad4ead22961fa88ce017e47793965d3f Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:37:39 +0100 Subject: [PATCH 03/26] store update with new options and migration to prevent errors --- src/main/base/store.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index da524ae9..9a5fab0b 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -12,9 +12,14 @@ export class Store { }, "general": { "close_button_hide": false, - "discord_rpc": 1, // 0 = disabled, 1 = enabled as Cider, 2 = enabled as Apple Music - "discord_rpc_clear_on_pause": true, - "discord_rpc_hide_buttons": false, + "discord_rpc": { + "enabled": false, + "client": "Cider", + "clear_on_pause": true, + "hide_buttons": false, + "state_format": "by {artist}", + "details_format": "{title}", + }, "language": "en_US", // electron.app.getLocale().replace('-', '_') this can be used in future "playbackNotifications": true, "update_branch": "main", @@ -152,13 +157,20 @@ export class Store { "playlistTrackMapping": true } } - private migrations: any = {} + private migrations: any = { + '1.4.3': (store: ElectronStore) => { + if (typeof(store.get('general.discord_rpc')) == 'number') { + store.set('general.discord_rpc', this.defaults.general.discord_rpc) + } + }, + } constructor() { Store.cfg = new ElectronStore({ name: 'cider-config', defaults: this.defaults, migrations: this.migrations, + clearInvalidConfig: true }); Store.cfg.set(this.mergeStore(this.defaults, Store.cfg.store)) From 16e41a61433c97c348e65e998d88ffe46a368f6f Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:38:43 +0100 Subject: [PATCH 04/26] settings page again --- src/renderer/views/pages/settings.ejs | 58 +++++++++++++++++++++------ 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 7a45c317..97ff6405 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -204,7 +204,7 @@ {{app.cfg.audio.equalizer.vibrantBass != 0 || app.cfg.audio.maikiwiAudio.spatial === true || app.cfg.audio.maikiwiAudio.ciderPPE === true ? `${$root.getLz('settings.option.audio.enableAdvancedFunctionality.audioNormalization.description')}\n${$root.getLz('settings.option.audio.enableAdvancedFunctionality.audioNormalization.disabled')}` : $root.getLz('settings.option.audio.enableAdvancedFunctionality.audioNormalization.description')}}
-
@@ -394,7 +394,7 @@
- +
@@ -710,36 +710,68 @@ +
{{$root.getLz('settings.option.connectivity.discordRPC')}}
- +
+
+ +
+
+ {{$root.getLz('settings.option.connectivity.discordRPC.clientName')}} +
+
+
-
+ +
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
- +
-
+ +
- {{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
- ({{$root.getLz('settings.option.visual.hardwareAcceleration.description')}}) + {{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
- +
+ +
+
+ {{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}
+ {{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album}, {trackNumber} +
+
+ +
+
+ +
+
+ {{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}} + {{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album}, {trackNumber} +
+
+ +
+
+ +
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}} @@ -1010,7 +1042,7 @@ }, getThemeName(filename) { try { - return this.themes.find(theme => theme.file === filename).name; + return this.themes.find(theme => theme.file === filename).name; }catch(e) { return filename; } From 9f4d689f2ebfb8e5af714dd2b48876dac99158be Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 14:39:03 +0100 Subject: [PATCH 05/26] DiscordRPC Customisation: - Redone logic in discordrpc.ts plugin - Implemented user variables for rpc state and format - Added settings in app to configure this - Bumped version to 1.4.3 to use migrations to ensure config wont fail - Enabled clear invalid config on electron store - i18n updated --- package.json | 2 +- src/i18n/README.md | 7 +++++++ src/i18n/en_US.json | 8 +++++--- src/i18n/source/en_US.json | 8 +++++--- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 2f43ab69..edd5b3af 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "cider", "applicationId": "Cider", "productName": "Cider", - "version": "1.4.2", + "version": "1.4.3", "description": "A new cross-platform Apple Music experience based on Electron and Vue.js written from scratch with performance in mind.", "license": "AGPL-3.0", "main": "./build/index.js", diff --git a/src/i18n/README.md b/src/i18n/README.md index d1a57fdb..5fa695c9 100644 --- a/src/i18n/README.md +++ b/src/i18n/README.md @@ -246,3 +246,10 @@ Update 09/04/2022 13:45 UTC * `action.tray.show`: Changed for `en_US` (Deleted for all language files) +Update 14/04/2022 14:30 UTC +* `term.variables`: Added for `en_US` +* `settings.option.connectivity.discordRPC.clientName`: Added for `en_US` +* `settings.option.connectivity.discordRPC.detailsFormat`: Added for `en_US` +* `settings.option.connectivity.discordRPC.stateFormat`: Added for `en_US` +* `settings.header.connectivity.discordRPC.cider`: Removed from `en_US` +* `settings.header.connectivity.discordRPC.appleMusic`: Removed from `en_US` diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 8b9f8cc8..a84f3f9e 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -10,6 +10,7 @@ "notification.updatingLibrarySongs": "Updating library songs...", "notification.updatingLibraryAlbums": "Updating library albums...", "notification.updatingLibraryArtists": "Updating library artists...", + "term.variables": "Variables", "term.appleInc": "Apple Inc.", "term.appleMusic": "Apple Music", "term.applePodcasts": "Apple Podcasts", @@ -386,12 +387,13 @@ "settings.option.lyrics.enableYoutubeLyrics": "Enable Youtube Lyrics for Music Videos", "settings.header.connectivity": "Connectivity", "settings.header.connectivity.description": "Adjust the connectivity settings for Cider.", - "settings.option.connectivity.discordRPC": "Discord Rich Presence", "settings.option.connectivity.playbackNotifications": "Playback Notifications", - "settings.header.connectivity.discordRPC.cider": "Display as 'Cider'", - "settings.header.connectivity.discordRPC.appleMusic": "Display as 'Apple Music'", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", + "settings.option.connectivity.discordRPC.clientName": "Client Name", "settings.option.connectivity.discordRPC.clearOnPause": "Clear Discord Rich Presence on Pause", "settings.option.connectivity.discordRPC.hideButtons": "Hide buttons on Discord Rich Presence", + "settings.option.connectivity.discordRPC.detailsFormat": "Details Format", + "settings.option.connectivity.discordRPC.stateFormat": "State Format", "settings.option.connectivity.lastfmScrobble": "Last.fm Scrobbling", "settings.option.connectivity.lastfmScrobble.delay": "Last.fm Scrobble Delay (%)", "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index 8b9f8cc8..a84f3f9e 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -10,6 +10,7 @@ "notification.updatingLibrarySongs": "Updating library songs...", "notification.updatingLibraryAlbums": "Updating library albums...", "notification.updatingLibraryArtists": "Updating library artists...", + "term.variables": "Variables", "term.appleInc": "Apple Inc.", "term.appleMusic": "Apple Music", "term.applePodcasts": "Apple Podcasts", @@ -386,12 +387,13 @@ "settings.option.lyrics.enableYoutubeLyrics": "Enable Youtube Lyrics for Music Videos", "settings.header.connectivity": "Connectivity", "settings.header.connectivity.description": "Adjust the connectivity settings for Cider.", - "settings.option.connectivity.discordRPC": "Discord Rich Presence", "settings.option.connectivity.playbackNotifications": "Playback Notifications", - "settings.header.connectivity.discordRPC.cider": "Display as 'Cider'", - "settings.header.connectivity.discordRPC.appleMusic": "Display as 'Apple Music'", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", + "settings.option.connectivity.discordRPC.clientName": "Client Name", "settings.option.connectivity.discordRPC.clearOnPause": "Clear Discord Rich Presence on Pause", "settings.option.connectivity.discordRPC.hideButtons": "Hide buttons on Discord Rich Presence", + "settings.option.connectivity.discordRPC.detailsFormat": "Details Format", + "settings.option.connectivity.discordRPC.stateFormat": "State Format", "settings.option.connectivity.lastfmScrobble": "Last.fm Scrobbling", "settings.option.connectivity.lastfmScrobble.delay": "Last.fm Scrobble Delay (%)", "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable Last.fm Now Playing", From c1b5743b143b9970ea2afa33d605483e189083b2 Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 15:00:51 +0100 Subject: [PATCH 06/26] Small fix, hardcoded each line to set config value to what its supposed to be --- src/main/base/store.ts | 18 +++++++++++------- src/main/plugins/discordrpc.ts | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 9a5fab0b..f28f2a94 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -157,13 +157,7 @@ export class Store { "playlistTrackMapping": true } } - private migrations: any = { - '1.4.3': (store: ElectronStore) => { - if (typeof(store.get('general.discord_rpc')) == 'number') { - store.set('general.discord_rpc', this.defaults.general.discord_rpc) - } - }, - } + private migrations: any = {} constructor() { Store.cfg = new ElectronStore({ @@ -175,6 +169,16 @@ export class Store { Store.cfg.set(this.mergeStore(this.defaults, Store.cfg.store)) this.ipcHandler(); + + if (typeof(Store.cfg.get('general.discord_rpc')) != 'object') { + Store.cfg.set('general.discord_rpc', this.defaults.general.discord_rpc) + Store.cfg.set('general.discord_rpc.enabled', this.defaults.general.discord_rpc.enabled) + Store.cfg.set('general.discord_rpc.client', this.defaults.general.discord_rpc.client) + Store.cfg.set('general.discord_rpc.clear_on_pause', this.defaults.general.discord_rpc.clear_on_pause) + Store.cfg.set('general.discord_rpc.hide_buttons', this.defaults.general.discord_rpc.hide_buttons) + Store.cfg.set('general.discord_rpc.state_format', this.defaults.general.discord_rpc.state_format) + Store.cfg.set('general.discord_rpc.details_format', this.defaults.general.discord_rpc.details_format) + } } /** diff --git a/src/main/plugins/discordrpc.ts b/src/main/plugins/discordrpc.ts index 0fa1540e..33593c0c 100644 --- a/src/main/plugins/discordrpc.ts +++ b/src/main/plugins/discordrpc.ts @@ -221,8 +221,8 @@ export default class DiscordRPC { // If the user wants to keep the activity when paused if (!this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) { - this._activity.smallImageKey = attributes.status ? 'pause' : 'play'; - this._activity.smallImageText = attributes.status ? 'Paused' : 'Playing'; + this._activity.smallImageKey = attributes.status ? 'play' : 'pause'; + this._activity.smallImageText = attributes.status ? 'Playing' : 'Paused'; } this.setActivity(this._activity) From 803e5f3f96a7010ac4dbc7a69c68c5b5c73af417 Mon Sep 17 00:00:00 2001 From: vapormusic Date: Thu, 14 Apr 2022 23:45:37 +0700 Subject: [PATCH 07/26] tempfix --- src/main/base/store.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index f28f2a94..d12b168f 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -171,6 +171,7 @@ export class Store { this.ipcHandler(); if (typeof(Store.cfg.get('general.discord_rpc')) != 'object') { + Store.cfg.delete('general.discord_rpc') Store.cfg.set('general.discord_rpc', this.defaults.general.discord_rpc) Store.cfg.set('general.discord_rpc.enabled', this.defaults.general.discord_rpc.enabled) Store.cfg.set('general.discord_rpc.client', this.defaults.general.discord_rpc.client) From 87bb0c425d7210d0dc8b86909811ad9c2b59511b Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 15:00:51 +0100 Subject: [PATCH 08/26] Changed it --- src/main/base/store.ts | 4 ++-- src/main/plugins/discordrpc.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index 9a5fab0b..a0cf6325 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -158,8 +158,8 @@ export class Store { } } private migrations: any = { - '1.4.3': (store: ElectronStore) => { - if (typeof(store.get('general.discord_rpc')) == 'number') { + '>=1.4.3': (store: ElectronStore) => { + if (typeof(store.get('general.discord_rpc')) == 'number' || typeof(store.get('general.discord_rpc')) == 'string') { store.set('general.discord_rpc', this.defaults.general.discord_rpc) } }, diff --git a/src/main/plugins/discordrpc.ts b/src/main/plugins/discordrpc.ts index 0fa1540e..33593c0c 100644 --- a/src/main/plugins/discordrpc.ts +++ b/src/main/plugins/discordrpc.ts @@ -221,8 +221,8 @@ export default class DiscordRPC { // If the user wants to keep the activity when paused if (!this._utils.getStoreValue("general.discord_rpc.clear_on_pause")) { - this._activity.smallImageKey = attributes.status ? 'pause' : 'play'; - this._activity.smallImageText = attributes.status ? 'Paused' : 'Playing'; + this._activity.smallImageKey = attributes.status ? 'play' : 'pause'; + this._activity.smallImageText = attributes.status ? 'Playing' : 'Paused'; } this.setActivity(this._activity) From 37fd3ecb4780af7e51f3a0e292e067104dd7ad1a Mon Sep 17 00:00:00 2001 From: Core <64542347+coredev-uk@users.noreply.github.com> Date: Thu, 14 Apr 2022 18:48:02 +0100 Subject: [PATCH 09/26] Lets try this --- src/main/base/store.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/base/store.ts b/src/main/base/store.ts index a0cf6325..cbd474d2 100644 --- a/src/main/base/store.ts +++ b/src/main/base/store.ts @@ -160,6 +160,7 @@ export class Store { private migrations: any = { '>=1.4.3': (store: ElectronStore) => { if (typeof(store.get('general.discord_rpc')) == 'number' || typeof(store.get('general.discord_rpc')) == 'string') { + store.delete('general.discord_rpc'); store.set('general.discord_rpc', this.defaults.general.discord_rpc) } }, From 320778b9b7b405594ea7f5783de409c69c1ac1f8 Mon Sep 17 00:00:00 2001 From: child_duckling <19170969+quacksire@users.noreply.github.com> Date: Sat, 16 Apr 2022 01:23:09 -0700 Subject: [PATCH 10/26] [connect] Initial Implementation --- src/main/base/app.ts | 3 +++ src/main/base/browserwindow.ts | 15 ++++++++++----- src/renderer/views/pages/connect-linked.ejs | 18 ++++++++++++++++++ src/renderer/views/pages/settings.ejs | 12 ++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/renderer/views/pages/connect-linked.ejs diff --git a/src/main/base/app.ts b/src/main/base/app.ts index c24ed6e5..b036d95d 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -167,6 +167,9 @@ export class AppEvents { utils.getWindow().webContents.send('LastfmAuthenticated', authKey); this.plugin.callPlugin('lastfm', 'authenticate', authKey); } + } else if (arg.includes("callback/discord?oauth=")){ // Discord OAuth [Connect] + utils.setStoreValue('connectUser', JSON.parse(arg.split("callback/discord?oauth=")[1])); + utils.getWindow().webContents.executeJavaScript("$root.appRoute('connect-linked')") } // Play else if (arg.includes('/play/')) { //Steer away from protocol:// specific conditionals diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index cc04aa15..38bb0eae 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -413,7 +413,7 @@ export class BrowserWindow { console.error('Req not defined') return } - if (req.url.includes("api") || req.url.includes("audio.wav") || (req.headers.host.includes("localhost") && (this.devMode || req.headers["user-agent"].includes("Electron")))) { + if (req.url.includes("api") || req.url.includes("audio.wav") || (req.headers.host.includes("localhost") && (this.devMode || req.headers["user-agent"].includes("Electron")) || req.url.includes("/connect"))) { next(); } else { res.redirect("https://discord.gg/applemusic"); @@ -526,6 +526,10 @@ export class BrowserWindow { console.log(ex); } }); + + app.get("/connect/get-user", (req, res) => { + res.send(utils.getStoreValue('connectUser')); // [Connect] Session redirect for webview + }); //app.use(express.static()) app.listen(this.clientPort, () => { @@ -1088,12 +1092,13 @@ export class BrowserWindow { }); //QR Code - ipcMain.handle('showQR', async (_event, _) => { + ipcMain.handle('showQR', async (_event, _) => { //macOS let url = `http://${BrowserWindow.getIP()}:${this.remotePort}`; - shell.openExternal(`https://cider.sh/remote/pair?url=${Buffer.from(encodeURI(url)).toString('base64')}`).catch(console.error); + BrowserWindow.win.webContents.send('send-remote-pair-url', (`https://cider.sh/remote/pair?url=${Buffer.from(encodeURI(url)).toString('base64')}`).toString()); + }); - ipcMain.on('get-remote-pair-url', (_event, _) => { + ipcMain.on('get-remote-pair-url', (_event, _) => { // Linux and Windows let url = `http://${BrowserWindow.getIP()}:${this.remotePort}`; //if (app.isPackaged) { BrowserWindow.win.webContents.send('send-remote-pair-url', (`https://cider.sh/remote/pair?url=${Buffer.from(encodeURI(url)).toString('base64')}`).toString()); @@ -1102,7 +1107,7 @@ export class BrowserWindow { //} }); - if (process.platform === "darwin") { + if (process.platform === "darwin") { //macOS app.setUserActivity('com.CiderCollective.remote.pair', { ip: `${BrowserWindow.getIP()}` }, `http://${BrowserWindow.getIP()}:${this.remotePort}`); diff --git a/src/renderer/views/pages/connect-linked.ejs b/src/renderer/views/pages/connect-linked.ejs new file mode 100644 index 00000000..306e11d6 --- /dev/null +++ b/src/renderer/views/pages/connect-linked.ejs @@ -0,0 +1,18 @@ + + \ No newline at end of file diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 97ff6405..846382bf 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -976,6 +976,18 @@
+ +
+ +
+ {{$root.getLz('settings.header.connect')}} +
+
+ +
+
+
+
From 27364c5507d68ffba072f9a3d5df371999a33fc9 Mon Sep 17 00:00:00 2001 From: child_duckling <19170969+quacksire@users.noreply.github.com> Date: Sat, 16 Apr 2022 01:42:21 -0700 Subject: [PATCH 11/26] [connect] Wrong web view. Eeeeeee --- src/renderer/views/pages/settings.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/views/pages/settings.ejs b/src/renderer/views/pages/settings.ejs index 846382bf..771d8da3 100644 --- a/src/renderer/views/pages/settings.ejs +++ b/src/renderer/views/pages/settings.ejs @@ -983,7 +983,7 @@ {{$root.getLz('settings.header.connect')}}
- +
From 4e8a160600b4db6e4a70044c1fd7826fa92d78fa Mon Sep 17 00:00:00 2001 From: Amaru8 <52407090+Amaru8@users.noreply.github.com> Date: Sat, 16 Apr 2022 11:32:19 +0200 Subject: [PATCH 12/26] Added Connect string (#880) * Added for en_US * added for source * added to readme --- src/i18n/README.md | 5 +++++ src/i18n/en_US.json | 1 + src/i18n/source/en_US.json | 1 + 3 files changed, 7 insertions(+) diff --git a/src/i18n/README.md b/src/i18n/README.md index 5fa695c9..c4220aa0 100644 --- a/src/i18n/README.md +++ b/src/i18n/README.md @@ -253,3 +253,8 @@ Update 14/04/2022 14:30 UTC * `settings.option.connectivity.discordRPC.stateFormat`: Added for `en_US` * `settings.header.connectivity.discordRPC.cider`: Removed from `en_US` * `settings.header.connectivity.discordRPC.appleMusic`: Removed from `en_US` + +Update 16/04/2022 9:30 UTC + +* `settings.header.connect`: Added for `en_US` + diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index a84f3f9e..d4b0784a 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -416,6 +416,7 @@ "settings.option.visual.transparent": "Transparent frame", "settings.option.visual.transparent.description": "Transparent frame (needs Theme Support , requires relaunch)", "settings.header.advanced": "Advanced", + "settings.header.connect": "Connect", "spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.", "spatial.spatialProperties": "Spatial Properties", "spatial.width": "Width", diff --git a/src/i18n/source/en_US.json b/src/i18n/source/en_US.json index a84f3f9e..d4b0784a 100644 --- a/src/i18n/source/en_US.json +++ b/src/i18n/source/en_US.json @@ -416,6 +416,7 @@ "settings.option.visual.transparent": "Transparent frame", "settings.option.visual.transparent.description": "Transparent frame (needs Theme Support , requires relaunch)", "settings.header.advanced": "Advanced", + "settings.header.connect": "Connect", "spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.", "spatial.spatialProperties": "Spatial Properties", "spatial.width": "Width", From 23ff24bda28f966bcd1a54e0183f78e6db29eba7 Mon Sep 17 00:00:00 2001 From: GGrandma Date: Sat, 16 Apr 2022 19:50:38 -0500 Subject: [PATCH 13/26] add release date option --- src/renderer/main/vueapp.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 422a6b31..9c0f9515 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -85,7 +85,8 @@ const app = new Vue({ "albumName": "0", "artistName": "0", "name": "0", - "genre": "0" + "genre": "0", + "releaseDate": "0" }, viewAs: 'covers', sorting: ["dateAdded", "name"], // [0] = recentlyadded page, [1] = albums page @@ -349,10 +350,10 @@ const app = new Vue({ } app.$data.library.albums.sortingOptions = { - "albumName": app.getLz('term.sortBy.album'), "artistName": app.getLz('term.sortBy.artist'), "name": app.getLz('term.sortBy.name'), - "genre": app.getLz('term.sortBy.genre') + "genre": app.getLz('term.sortBy.genre'), + "releaseDate": app.getLz('term.sortBy.releaseDate') } app.$data.library.artists.sortingOptions = { From 83073d9509ab34301fd951bc59321142d50480fc Mon Sep 17 00:00:00 2001 From: GGrandma Date: Sat, 16 Apr 2022 19:51:43 -0500 Subject: [PATCH 14/26] remove useless option --- src/renderer/main/vueapp.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 9c0f9515..25dfa76a 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -82,7 +82,6 @@ const app = new Vue({ }, albums: { sortingOptions: { - "albumName": "0", "artistName": "0", "name": "0", "genre": "0", From a844903dff0385a9cbb11e2b4d3145527427cad0 Mon Sep 17 00:00:00 2001 From: child_duckling <19170969+child-duckling@users.noreply.github.com> Date: Sat, 16 Apr 2022 23:59:30 -0700 Subject: [PATCH 15/26] connect auth works, now for settings sync --- src/main/base/app.ts | 5 ++--- src/main/base/browserwindow.ts | 22 +++++++++++++++++---- src/main/base/plugins.ts | 2 +- src/renderer/main/vueapp.js | 3 +++ src/renderer/views/pages/connect-linked.ejs | 21 +++++++++++--------- src/renderer/views/pages/settings.ejs | 17 +++++++++++++--- src/renderer/views/pages/webview.ejs | 3 +-- 7 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/main/base/app.ts b/src/main/base/app.ts index b036d95d..3ab49a66 100644 --- a/src/main/base/app.ts +++ b/src/main/base/app.ts @@ -167,9 +167,6 @@ export class AppEvents { utils.getWindow().webContents.send('LastfmAuthenticated', authKey); this.plugin.callPlugin('lastfm', 'authenticate', authKey); } - } else if (arg.includes("callback/discord?oauth=")){ // Discord OAuth [Connect] - utils.setStoreValue('connectUser', JSON.parse(arg.split("callback/discord?oauth=")[1])); - utils.getWindow().webContents.executeJavaScript("$root.appRoute('connect-linked')") } // Play else if (arg.includes('/play/')) { //Steer away from protocol:// specific conditionals @@ -206,6 +203,8 @@ export class AppEvents { shell.openExternal('https://opencollective.com/ciderapp') } else if (arg.includes('/beep')) { shell.beep() + } else { + utils.getWindow().webContents.executeJavaScript(`app.appRoute('${arg.split('//')[1]}')`) } } diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts index 38bb0eae..082d1677 100644 --- a/src/main/base/browserwindow.ts +++ b/src/main/base/browserwindow.ts @@ -18,6 +18,7 @@ const wallpaper = require('wallpaper'); // @ts-ignore import * as AdmZip from "adm-zip"; +import * as util from "util"; /** * @file Creates the BrowserWindow @@ -526,16 +527,23 @@ export class BrowserWindow { console.log(ex); } }); - - app.get("/connect/get-user", (req, res) => { - res.send(utils.getStoreValue('connectUser')); // [Connect] Session redirect for webview + //region Connect Integration + app.get("/connect/set-cc-user/:data", (req, res) => { + //utils.getStoreValue('connectUser', JSON.parse()) // [Connect] Save user in store + utils.setStoreValue('connectUser', JSON.parse(req.params.data)) + res.redirect(`https://connect.cidercollective.dev/linked.html`) }); - //app.use(express.static()) + // [Connect] Set auth URL in store for `shell.openExternal` + utils.setStoreValue('cc_authURL', `https://connect.cidercollective.dev/callback/discord?app=cider&appPort=${this.clientPort}`) + console.log(`[Connect] Auth URL: ${utils.getStoreValue('cc_authURL')}`) + //endregion + app.listen(this.clientPort, () => { console.log(`Cider client port: ${this.clientPort}`); }); + /* * Remote Client -@quacksire * https://github.com/ciderapp/Apple-Music-Electron/blob/818189ed40ff600d76eb59d22016723a75885cd5/resources/functions/handler.js#L1173 @@ -1107,6 +1115,8 @@ export class BrowserWindow { //} }); + + if (process.platform === "darwin") { //macOS app.setUserActivity('com.CiderCollective.remote.pair', { ip: `${BrowserWindow.getIP()}` @@ -1161,6 +1171,10 @@ export class BrowserWindow { ipcMain.on('open-appdata', (_event) => { shell.openPath(app.getPath('userData')); }); + + ipcMain.on('cc-auth', (_event) => { + shell.openExternal(String(utils.getStoreValue('cc_authURL'))); + }); /* ********************************************************************************************* * Window Events * **********************************************************************************************/ diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts index 1f501cd2..a09ee3e9 100644 --- a/src/main/base/plugins.ts +++ b/src/main/base/plugins.ts @@ -4,7 +4,7 @@ import * as electron from 'electron' import {utils} from './utils'; // -// Hello, this our loader for the various plugins that the Cider Development Team built for our +// Hello, this is our loader for the various plugins that the Cider Development Team built for our // numerous plugins internally and ones made by the community // // To learn how to make your own, visit https://github.com/ciderapp/Cider/wiki/Plugins diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js index 422a6b31..0b08fdb8 100644 --- a/src/renderer/main/vueapp.js +++ b/src/renderer/main/vueapp.js @@ -4256,6 +4256,9 @@ const app = new Vue({ document.getElementById('settings.option.general.updateCider.check').innerHTML = app.getLz('term.check') }) }, + authCC(){ + ipcRenderer.send('cc-auth') + } } }) diff --git a/src/renderer/views/pages/connect-linked.ejs b/src/renderer/views/pages/connect-linked.ejs index 306e11d6..1d83dff1 100644 --- a/src/renderer/views/pages/connect-linked.ejs +++ b/src/renderer/views/pages/connect-linked.ejs @@ -1,14 +1,17 @@ -