Merge branch 'ciderapp:develop' into develop

This commit is contained in:
Amaru8 2022-04-19 19:39:54 +02:00 committed by GitHub
commit 95972ecf7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 317 additions and 125 deletions

View file

@ -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",

View file

@ -246,3 +246,15 @@ 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`
Update 16/04/2022 9:30 UTC
* `settings.header.connect`: Added for `en_US`

View file

@ -10,6 +10,7 @@
"notification.updatingLibrarySongs": "Updating wibwawy songs...",
"notification.updatingLibraryAlbums": "Updating wibwawy awbums...",
"notification.updatingLibraryArtists": "Updating wibwawy awtists...",
"term.variables": "Vawiabwes",
"term.appleInc": "Appwe Inc.",
"term.appleMusic": "Appwe Music",
"term.applePodcasts": "Appwe Podcasts",
@ -23,6 +24,7 @@
"term.cast": "Cast",
"term.about": "About",
"term.privateSession": "Pwivate Session",
"term.disablePrivateSession": "Disabwe Pwivate Session",
"term.queue": "Queue",
"term.lyrics": "Wywics",
"term.miniplayer": "MinyiPwayew",
@ -256,6 +258,8 @@
"action.cast.airplay.underdevelopment": "AiwPway is stiww undew devewopment",
"action.cast.scan": "Scan",
"action.cast.scanning": "Scannying...",
"action.createNew": "Cweate Nyew...",
"action.openArtworkInBrowser": "Open awtwowk in bwowsew",
"settings.header.general": "Genyewaw",
"settings.header.general.description": "Adjust the genyewaw settings fow Cidew.",
"settings.option.general.language": "Wanguage",
@ -298,6 +302,7 @@
"settings.warn.audio.enableAdvancedFunctionality.lowcores": "Cidew thinks youw PC can't handwe these featuwes. Awe you suwe you want to continyue?",
"settings.option.audio.audioLab": "Cidew Audio Wab",
"settings.option.audio.audioLab.description": "An assowtment of in-house devewoped audio effects fow Cidew.",
"settings.option.audio.audioLab.subheader": "Designyed by Cidew Acoustic Technyowogies in Cawifownyia",
"settings.warn.audioLab.withoutAF": "AudioContext (Advanced Functionyawity) is wequiwed to enyabwe Cidew Audio Wabowatowy.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "Anyawog Wawmth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "Simuwates the anyawog wawmth modewwed aftew the Kowg Nyutube 6P1",
@ -305,6 +310,13 @@
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "Changes the intensity of the Anyawog Wawmth Moduwe pwocessing.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "Smooth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "Wawm",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer": "Cidew Atmosphewe Weawizew™",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer.description": "Weawizes a diffewent musicaw atmosphewe modewwed aftew the state of the awt audio setups.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode": "Cidew Atmosphewe Weawizew™ Mode",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.description": "Changes the mode of opewation of the Atmosphewe Weawizew moduwe.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural1": "Nyatuwaw (Standawd)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural2": "Nyatuwaw (High)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural3": "Nyatuwaw (Pwus)",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cidew Adwenyawinye Pwocessow™",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the pewceived audio quawity of 256 kbps AAC audio by using a weaw-time awgowithm that takes advantage of both psychoacoustic modews of human heawing and AAC encoding chawactewistics.",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "CAP is nyot compatibwe with Spatiawization. Pwease disabwe Spatiawization to continyue.",
@ -320,7 +332,7 @@
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization": "Cidew Tunyed Spatiawization",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.description": "Pwe-tunyed Spatiawizing Effect, disabwes the customizabwe settings of Audio Spatiawization. Spatiawization must be enyabwed as a pwewequisite.",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile": "Cidew Spatiawization Pwofiwe",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.description": "Changes the Tunying Pwofiwe of the Spatiawization. (Wequiwes App Westawt)",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.description": "Changes the Tunying Pwofiwe of the Spatiawization.",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.standard": "Standawd",
"settings.option.audio.enableAdvancedFunctionality.tunedAudioSpatialization.profile.audiophile": "Audiophiwe",
"settings.warn.audio.enableAdvancedFunctionality.audioSpatialization.compatibility": "Spatiawization is nyot compatibwe with CAP. Pwease disabwe CAP to continyue.",
@ -346,6 +358,7 @@
"settings.option.visual.hardwareAcceleration.description": "Wequiwes wewaunch",
"settings.header.visual.hardwareAcceleration.default": "Defauwt",
"settings.header.visual.hardwareAcceleration.webGPU": "WebGPU",
"settings.option.visual.uiscale": "UI Scawe",
"settings.header.visual.theme": "Theme",
"settings.option.visual.theme.github.download": "Instaww fwom GitHub UWW",
"settings.option.visual.theme.github.explore": "Expwowe GitHub Themes",
@ -382,12 +395,13 @@
"settings.option.lyrics.enableYoutubeLyrics": "Enyabwe Youtube Wywics fow Music Videos",
"settings.header.connectivity": "Connyectivity",
"settings.header.connectivity.description": "Adjust the connyectivity settings fow Cidew.",
"settings.option.connectivity.discordRPC": "Discowd Wich Pwesence",
"settings.option.connectivity.playbackNotifications": "Pwayback Nyotifications",
"settings.header.connectivity.discordRPC.cider": "Dispway as 'Cidew'",
"settings.header.connectivity.discordRPC.appleMusic": "Dispway as 'Appwe Music'",
"settings.option.connectivity.discordRPC": "Discowd Wich Pwesence",
"settings.option.connectivity.discordRPC.clientName": "Cwient Nyame",
"settings.option.connectivity.discordRPC.clearOnPause": "Cweaw Discowd Wich Pwesence on Pause",
"settings.option.connectivity.discordRPC.hideButtons": "Hide buttons on Discowd Wich Pwesence",
"settings.option.connectivity.discordRPC.detailsFormat": "Detaiws Fowmat",
"settings.option.connectivity.discordRPC.stateFormat": "State Fowmat",
"settings.option.connectivity.lastfmScrobble": "Wast.fm Scwobbwing",
"settings.option.connectivity.lastfmScrobble.delay": "Wast.fm Scwobbwe Deway (%)",
"settings.option.connectivity.lastfmScrobble.nowPlaying": "Enyabwe Wast.fm Nyow Pwaying",
@ -410,6 +424,7 @@
"settings.option.visual.transparent": "Twanspawent fwame",
"settings.option.visual.transparent.description": "Twanspawent fwame (nyeeds Theme Suppowt , wequiwes wewaunch)",
"settings.header.advanced": "Advanced",
"settings.header.connect": "Connyect",
"spatial.notTurnedOn": "Audio Spatiawization is disabwed. To use, pwease enyabwe it fiwst.",
"spatial.spatialProperties": "Spatiaw Pwopewties",
"spatial.width": "Width",

View file

@ -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",
@ -301,6 +302,7 @@
"settings.warn.audio.enableAdvancedFunctionality.lowcores": "Cider thinks your PC can't handle these features. Are you sure you want to continue?",
"settings.option.audio.audioLab": "Cider Audio Lab",
"settings.option.audio.audioLab.description": "An assortment of in-house developed audio effects for Cider.",
"settings.option.audio.audioLab.subheader": "Designed by Cider Acoustic Technologies in California",
"settings.warn.audioLab.withoutAF": "AudioContext (Advanced Functionality) is required to enable Cider Audio Laboratory.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "Analog Warmth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "Simulates the analog warmth modelled after the Korg Nutube 6P1",
@ -308,6 +310,13 @@
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "Changes the intensity of the Analog Warmth Module processing.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "Smooth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "Warm",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer": "Cider Atmosphere Realizer™",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer.description": "Realizes a different musical atmosphere modelled after the state of the art audio setups.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode": "Cider Atmosphere Realizer™ Mode",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.description": "Changes the mode of operation of the Atmosphere Realizer module.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural1": "Natural (Standard)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural2": "Natural (High)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural3": "Natural (Plus)",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of 256 kbps AAC audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "CAP is not compatible with Spatialization. Please disable Spatialization to continue.",
@ -386,12 +395,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",
@ -414,6 +424,9 @@
"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": "Sync",
"settings.option.connect.link_account": "Enable Sync with Cider Connect",
"settings.option.connect.link_account.description": "Linking your Discord account with Cider Connect allows you to store userdata including Settings, EQ's, and eventually more once finished. (Work In Progress)",
"spatial.notTurnedOn": "Audio Spatialization is disabled. To use, please enable it first.",
"spatial.spatialProperties": "Spatial Properties",
"spatial.width": "Width",

View file

@ -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",
@ -301,6 +302,7 @@
"settings.warn.audio.enableAdvancedFunctionality.lowcores": "Cider thinks your PC can't handle these features. Are you sure you want to continue?",
"settings.option.audio.audioLab": "Cider Audio Lab",
"settings.option.audio.audioLab.description": "An assortment of in-house developed audio effects for Cider.",
"settings.option.audio.audioLab.subheader": "Designed by Cider Acoustic Technologies in California",
"settings.warn.audioLab.withoutAF": "AudioContext (Advanced Functionality) is required to enable Cider Audio Laboratory.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth": "Analog Warmth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmth.description": "Simulates the analog warmth modelled after the Korg Nutube 6P1",
@ -308,6 +310,13 @@
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.description": "Changes the intensity of the Analog Warmth Module processing.",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.smooth": "Smooth",
"settings.option.audio.enableAdvancedFunctionality.analogWarmthIntensity.warm": "Warm",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer": "Cider Atmosphere Realizer™",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer.description": "Realizes a different musical atmosphere modelled after the state of the art audio setups.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode": "Cider Atmosphere Realizer™ Mode",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.description": "Changes the mode of operation of the Atmosphere Realizer module.",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural1": "Natural (Standard)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural2": "Natural (High)",
"settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural3": "Natural (Plus)",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE": "Cider Adrenaline Processor™",
"settings.option.audio.enableAdvancedFunctionality.ciderPPE.description": "Enhances the perceived audio quality of 256 kbps AAC audio by using a real-time algorithm that takes advantage of both psychoacoustic models of human hearing and AAC encoding characteristics.",
"settings.warn.audio.enableAdvancedFunctionality.ciderPPE.compatibility": "CAP is not compatible with Spatialization. Please disable Spatialization to continue.",
@ -386,12 +395,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",
@ -414,6 +424,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",

View file

@ -203,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]}')`)
}
}

View file

@ -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
@ -413,7 +414,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,12 +527,23 @@ export class BrowserWindow {
console.log(ex);
}
});
//app.use(express.static())
//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`)
});
// [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
@ -1088,12 +1100,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 +1115,9 @@ 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}`);
@ -1156,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
* **********************************************************************************************/

View file

@ -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

View file

@ -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,21 @@ export class Store {
"playlistTrackMapping": true
}
}
private migrations: any = {}
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)
}
},
}
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))

View file

@ -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';
// Add the timestamp if its playing
if (attributes.status) {
this._activity.startTimestamp = Date.now() - (attributes?.durationInMillis - attributes?.remainingTime)
this._activity.endTimestamp = attributes.endTime
}
this._client.setActivity(this._activity)
.catch((e: any) => console.error(`[DiscordRichPresence][updateActivity] ${e}`));
this._activityCache = this._activity;
// 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 ? 'play' : 'pause';
this._activity.smallImageText = attributes.status ? 'Playing' : 'Paused';
}
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)
}
}
/**
@ -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)
}
}
}

View file

@ -82,10 +82,10 @@ const app = new Vue({
},
albums: {
sortingOptions: {
"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 +349,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 = {
@ -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);
@ -4258,6 +4256,9 @@ const app = new Vue({
document.getElementById('settings.option.general.updateCider.check').innerHTML = app.getLz('term.check')
})
},
authCC(){
ipcRenderer.send('cc-auth')
}
}
})

View file

@ -11626,7 +11626,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
filter: none !important;
}
.lyricWaiting {
margin-top: 8px;
margin-bottom: 10px;
display: none;
}
.lyric-line.active .lyricWaiting {

View file

@ -1261,7 +1261,7 @@ body[platform="darwin"] .app-chrome .app-chrome-item > .window-controls > div.cl
.marquee {
animation: marquee 15s linear infinite;
animation: marquee 15s linear 2s infinite;
&.song-artist {
overflow: unset;
@ -1630,7 +1630,7 @@ input[type="range"].web-slider.display--small::-webkit-slider-thumb {
}
.lyricWaiting {
margin-top: 8px;
margin-bottom:10px;
display: none;
}

View file

@ -122,7 +122,7 @@
},
multiple: {
items: [{
"name": app.getLz('action.removeTracks'),
"name": app.getLz('action.removeTracks').replace('${self.selectedItems.length}', self.selectedItems.length.toString()),
"action": function () {
// add property to items to be removed
self.selectedItems.forEach(function (item) {

View file

@ -5,7 +5,7 @@
<div class="settings-option-body">
<div class="md-option-line">
<b-jumbotron :header="$root.getLz('settings.option.audio.audioLab')"
lead="Designed by Cider Acoustic Technologies in California"></b-jumbotron>
lead="$root.getLz('settings.option.audio.audioLab.subheader')"></b-jumbotron>
</div>
<div class="md-option-line" v-show="app.cfg.advanced.AudioContext === false">
<div class="md-option-segment">
@ -79,9 +79,9 @@
</div>
<div class="md-option-line" v-show="app.cfg.advanced.AudioContext === true">
<div class="md-option-segment">
Cider Atmosphere Realizer™
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer')}}
<br>
<small>Realizes a different musical atmosphere modelled after the state of the art audio setups.</small>
<small>{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizer.description')}}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.audio.maikiwiAudio.atmosphereRealizer"
@ -90,17 +90,17 @@
</div>
<div class="md-option-line" v-show="app.cfg.audio.maikiwiAudio.atmosphereRealizer === true">
<div class="md-option-segment">
Cider Atmosphere Realizer™ Mode
{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode')}}
<br>
<small>Changes the mode of operation of the Atmosphere Realizer module.</small>
<small>{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.description')}}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<select class="md-select" style="width:180px;"
v-model="app.cfg.audio.maikiwiAudio.atmosphereRealizer_value"
v-on:change="CiderAudio.hierarchical_loading()">
<option value="NATURAL_STANDARD">Natural (Standard)</option>
<option value="NATURAL_HIGH">Natural (High)</option>
<option value="NATURAL_PLUS">Natural (Plus)</option>
<option value="NATURAL_STANDARD">{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural1')}}</option>
<option value="NATURAL_HIGH">{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural2')}}</option>
<option value="NATURAL_PLUS">{{$root.getLz('settings.option.audio.enableAdvancedFunctionality.atmosphereRealizerMode.natural3')}}</option>
</select>
</div>
</div>

View file

@ -0,0 +1,21 @@
<script type="text/x-template" id="connected">
<div style="display:flex;width:100%;height:100%;padding-top: var(--navigationBarHeight);position:absolute;top:0;left:0;">
<webview id="foo" src="https://cider.sh" style="display:inline-flex; width:100%;"></webview>
</div>
</script>
<script>
Vue.component('connected', {
template: '#connected',
async mounted() {
ipcRenderer.send('get-connected-url')
ipcRenderer.on('send-connected-url', (event, url) => {
this.url = url
app.webview.src = url
document.getElementById('foo').src = url;
})
},
methods: {
}
});
</script>

View file

@ -710,36 +710,68 @@
</div>
</div>
<!-- DiscordRPC -->
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<select class="md-select" v-model="app.cfg.general.discord_rpc">
<option value="0">{{$root.getLz('term.disabled')}}</option>
<option value="1">{{$root.getLz('settings.header.connectivity.discordRPC.cider')}}</option>
<option value="2">{{$root.getLz('settings.header.connectivity.discordRPC.appleMusic')}}
<input type="checkbox" v-model="app.cfg.general.discord_rpc.enabled" switch/>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.general.discord_rpc.enabled != false">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC.clientName')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<select class="md-select" v-model="app.cfg.general.discord_rpc.client">
<option value="Cider">{{$root.getLz('app.name')}}</option>
<option value="AppleMusic">{{$root.getLz('term.appleMusic')}}
</option>
</select>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.general.discord_rpc != 0">
<div class="md-option-line" v-show="app.cfg.general.discord_rpc.enabled != false">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC.clearOnPause')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.general.discord_rpc_clear_on_pause" switch/>
<input type="checkbox" v-model="app.cfg.general.discord_rpc.clear_on_pause" switch/>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.general.discord_rpc != 0">
<div class="md-option-line" v-show="app.cfg.general.discord_rpc.enabled != false">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}<br>
<small>({{$root.getLz('settings.option.visual.hardwareAcceleration.description')}})</small>
{{$root.getLz('settings.option.connectivity.discordRPC.hideButtons')}}
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="checkbox" v-model="app.cfg.general.discord_rpc_hide_buttons" switch/>
<input type="checkbox" v-model="app.cfg.general.discord_rpc.hide_buttons" switch/>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.general.discord_rpc.enabled != false">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC.detailsFormat')}}<br/>
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album}, {trackNumber}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="text" v-model="app.cfg.general.discord_rpc.details_format"/>
</div>
</div>
<div class="md-option-line" v-show="app.cfg.general.discord_rpc.enabled != false">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.discordRPC.stateFormat')}}
<small>{{$root.getLz('term.variables')}}: {artist}, {composer}, {title}, {album}, {trackNumber}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<input type="text" v-model="app.cfg.general.discord_rpc.state_format"/>
</div>
</div>
<!-- LastFM -->
<div class="md-option-line">
<div class="md-option-segment">
{{$root.getLz('settings.option.connectivity.lastfmScrobble')}}
@ -944,6 +976,30 @@
</div>
</div>
</b-tab>
<b-tab :title="$root.getLz('settings.header.connect')">
<div class="md-option-container">
<!-- Cider Connect / Linking Settings -->
<div class="md-option-header">
<span>{{$root.getLz('settings.header.connect')}}</span>
</div>
<div class="settings-option-body">
<div class="md-option-line update-check">
<div class="md-option-segment">
{{$root.getLz('settings.option.connect.link_account')}}
<small>{{$root.getLz('settings.option.connect.link_account.description')}}</small>
<br>
<small>Debug Status: {{ app.cfg.connectUser }}</small>
</div>
<div class="md-option-segment md-option-segment_auto">
<button class="md-btn" id='settings.option.general.updateCider.check' @click="authCC()">
{{$root.getLz('term.connect')}}
</button>
</div>
</div>
</div>
</div>
</div>
</b-tab>
</b-tabs>
</div>
</script>
@ -1180,7 +1236,10 @@
ipcRenderer.send('relaunchApp', '');
}
});
}
},
authCC() {
ipcRenderer.send('cc-auth')
},
}
})
</script>

View file

@ -1,6 +1,5 @@
<template v-if="page == 'webview'">
<div style="display:flex;width:100%;height:100%">
<<webview id="foo" :src="webview.url" nodeintegration="true" style="display:inline-flex; width:100%;"></webview>
<webview id="foo" :src="webview.url" nodeintegration="true" style="display:inline-flex; width:100%;"></webview>
</div>
</template>