Merge branch 'develop'
This commit is contained in:
commit
df2f7b7216
195 changed files with 62285 additions and 12895 deletions
|
@ -1,7 +1,15 @@
|
|||
import {app, Menu, nativeImage, Tray} from 'electron';
|
||||
import {app, Menu, nativeImage, Tray, ipcMain, clipboard, shell} from 'electron';
|
||||
import {readFileSync} from "fs";
|
||||
import * as path from 'path';
|
||||
import {utils} from './utils'
|
||||
import * as log from 'electron-log';
|
||||
import {utils} from './utils';
|
||||
|
||||
/**
|
||||
* @file Creates App instance
|
||||
* @author CiderCollective
|
||||
*/
|
||||
|
||||
/** @namespace */
|
||||
export class AppEvents {
|
||||
private protocols: string[] = [
|
||||
"ame",
|
||||
|
@ -15,6 +23,7 @@ export class AppEvents {
|
|||
private tray: any = undefined;
|
||||
private i18n: any = undefined;
|
||||
|
||||
/** @constructor */
|
||||
constructor() {
|
||||
this.start();
|
||||
}
|
||||
|
@ -24,6 +33,7 @@ export class AppEvents {
|
|||
* @returns {void}
|
||||
*/
|
||||
private start(): void {
|
||||
AppEvents.initLogging()
|
||||
console.info('[AppEvents] App started');
|
||||
|
||||
/**********************************************************************************************************************
|
||||
|
@ -87,6 +97,7 @@ export class AppEvents {
|
|||
/***********************************************************************************************************************
|
||||
* Protocols
|
||||
**********************************************************************************************************************/
|
||||
/** */
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
this.protocols.forEach((protocol: string) => {
|
||||
|
@ -120,6 +131,13 @@ export class AppEvents {
|
|||
}
|
||||
})
|
||||
|
||||
if (process.platform === "darwin") {
|
||||
app.setUserActivity('8R23J2835D.com.ciderapp.webremote.play', {
|
||||
title: 'Web Remote',
|
||||
description: 'Connect to your Web Remote',
|
||||
}, "https://webremote.cider.sh")
|
||||
}
|
||||
|
||||
this.InstanceHandler()
|
||||
this.InitTray()
|
||||
}
|
||||
|
@ -169,6 +187,18 @@ export class AppEvents {
|
|||
let url = arg.split('//')[1]
|
||||
console.warn(`[LinkHandler] Attempting to load url: ${url}`);
|
||||
utils.getWindow().webContents.send('play', 'url', url)
|
||||
} else if (arg.includes('/debug/appdata')) {
|
||||
shell.openPath(app.getPath('userData'))
|
||||
} else if (arg.includes('/debug/logs')) {
|
||||
shell.openPath(app.getPath('logs'))
|
||||
} else if (arg.includes('/discord')) {
|
||||
shell.openExternal('https://discord.gg/applemusic')
|
||||
} else if (arg.includes('/github')) {
|
||||
shell.openExternal('https://github.com/ciderapp/cider')
|
||||
} else if (arg.includes('/donate')) {
|
||||
shell.openExternal('https://opencollective.com/ciderapp')
|
||||
} else if (arg.includes('/beep')) {
|
||||
shell.beep()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,6 +227,7 @@ export class AppEvents {
|
|||
app.quit()
|
||||
} else if (utils.getWindow()) {
|
||||
if (utils.getWindow().isMinimized()) utils.getWindow().restore()
|
||||
utils.getWindow().show()
|
||||
utils.getWindow().focus()
|
||||
}
|
||||
})
|
||||
|
@ -264,7 +295,7 @@ export class AppEvents {
|
|||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: (visible ? this.i18n['action.tray.minimize'] : this.i18n['action.tray.show'].includes("{appName}") ? `${this.i18n['action.tray.show'].replace("{appName}", app.getName())}` : `${this.i18n['action.tray.show']} ${app.getName()}`),
|
||||
label: (visible ? this.i18n['action.tray.minimize'] : `${this.i18n['action.tray.show']} ${app.getName()}`),
|
||||
click: () => {
|
||||
if (utils.getWindow()) {
|
||||
if (visible) {
|
||||
|
@ -284,4 +315,18 @@ export class AppEvents {
|
|||
])
|
||||
this.tray.setContextMenu(menu)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes logging in the application
|
||||
* @private
|
||||
*/
|
||||
private static initLogging() {
|
||||
log.transports.console.format = '[{h}:{i}:{s}.{ms}] [{level}] {text}';
|
||||
Object.assign(console, log.functions);
|
||||
|
||||
ipcMain.on('fetch-log', (_event) => {
|
||||
const data = readFileSync(log.transports.file.getFile().path, {encoding: 'utf8', flag: 'r'});
|
||||
clipboard.writeText(data)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
24
src/main/base/castcontroller.js
Normal file
24
src/main/base/castcontroller.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
var util = require('util');
|
||||
var castv2Cli = require('castv2-client');
|
||||
var RequestResponseController = castv2Cli.RequestResponseController;
|
||||
|
||||
function CiderCastController(client, sourceId, destinationId) {
|
||||
RequestResponseController.call(this, client, sourceId, destinationId, 'urn:x-cast:com.ciderapp.customdata');
|
||||
this.once('close', onclose);
|
||||
var self = this;
|
||||
function onclose() {
|
||||
self.stop();
|
||||
}
|
||||
}
|
||||
|
||||
util.inherits(CiderCastController, RequestResponseController);
|
||||
|
||||
CiderCastController.prototype.sendIp = function(ip) {
|
||||
// TODO: Implement Callback
|
||||
let data = {
|
||||
ip : ip
|
||||
}
|
||||
this.request(data);
|
||||
};
|
||||
|
||||
module.exports = CiderCastController;
|
77
src/main/base/castreceiver.js
Normal file
77
src/main/base/castreceiver.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
//@ts-nocheck
|
||||
var util = require('util');
|
||||
// var debug = require('debug')('castv2-client');
|
||||
var Application = require('castv2-client').Application;
|
||||
var MediaController = require('castv2-client').MediaController;
|
||||
var CiderCastController = require('./castcontroller');
|
||||
|
||||
function CiderReceiver(client, session) {
|
||||
Application.apply(this, arguments);
|
||||
|
||||
this.media = this.createController(MediaController);
|
||||
this.mediaReceiver = this.createController(CiderCastController);
|
||||
|
||||
this.media.on('status', onstatus);
|
||||
|
||||
var self = this;
|
||||
|
||||
function onstatus(status) {
|
||||
self.emit('status', status);
|
||||
}
|
||||
|
||||
}
|
||||
// FE96A351
|
||||
// 27E1334F
|
||||
CiderReceiver.APP_ID = 'FE96A351';
|
||||
|
||||
util.inherits(CiderReceiver, Application);
|
||||
|
||||
CiderReceiver.prototype.getStatus = function(callback) {
|
||||
this.media.getStatus.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.load = function(media, options, callback) {
|
||||
this.media.load.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.play = function(callback) {
|
||||
this.media.play.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.pause = function(callback) {
|
||||
this.media.pause.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.stop = function(callback) {
|
||||
this.media.stop.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.seek = function(currentTime, callback) {
|
||||
this.media.seek.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.queueLoad = function(items, options, callback) {
|
||||
this.media.queueLoad.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.queueInsert = function(items, options, callback) {
|
||||
this.media.queueInsert.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.queueRemove = function(itemIds, options, callback) {
|
||||
this.media.queueRemove.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.queueReorder = function(itemIds, options, callback) {
|
||||
this.media.queueReorder.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.queueUpdate = function(items, callback) {
|
||||
this.media.queueUpdate.apply(this.media, arguments);
|
||||
};
|
||||
|
||||
CiderReceiver.prototype.sendIp = function(opts){
|
||||
this.mediaReceiver.sendIp.apply(this.mediaReceiver, arguments);
|
||||
};
|
||||
|
||||
module.exports = CiderReceiver;
|
|
@ -3,15 +3,36 @@ import * as path from 'path';
|
|||
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
|
||||
// numerous plugins internally and ones made by the community
|
||||
//
|
||||
// To learn how to make your own, visit https://github.com/ciderapp/Cider/wiki/Plugins
|
||||
//
|
||||
/**
|
||||
* @class
|
||||
* Plugin Loading
|
||||
* @author booploops#7139
|
||||
* @see {@link https://github.com/ciderapp/Cider/wiki/Plugins|Documentation}
|
||||
*/
|
||||
export class Plugins {
|
||||
private basePluginsPath = path.join(__dirname, '../plugins');
|
||||
private userPluginsPath = path.join(electron.app.getPath('userData'), 'plugins');
|
||||
private userPluginsPath = path.join(electron.app.getPath('userData'), 'Plugins');
|
||||
private readonly pluginsList: any = {};
|
||||
private static PluginMap: any = {};
|
||||
|
||||
constructor() {
|
||||
this.pluginsList = this.getPlugins();
|
||||
}
|
||||
|
||||
public static getPluginFromMap(plugin: string): any {
|
||||
if(Plugins.PluginMap[plugin]) {
|
||||
return Plugins.PluginMap[plugin];
|
||||
}else{
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
|
||||
public getPlugins(): any {
|
||||
let plugins: any = {};
|
||||
|
||||
|
@ -32,13 +53,46 @@ export class Plugins {
|
|||
|
||||
if (fs.existsSync(this.userPluginsPath)) {
|
||||
fs.readdirSync(this.userPluginsPath).forEach(file => {
|
||||
// Plugins V1
|
||||
if (file.endsWith('.ts') || file.endsWith('.js')) {
|
||||
const plugin = require(path.join(this.userPluginsPath, file)).default;
|
||||
file = file.replace('.ts', '').replace('.js', '');
|
||||
if (plugins[file] || plugin in plugins) {
|
||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||
if (!electron.app.isPackaged) {
|
||||
const plugin = require(path.join(this.userPluginsPath, file)).default;
|
||||
file = file.replace('.ts', '').replace('.js', '');
|
||||
if (plugins[file] || plugin in plugins) {
|
||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||
} else {
|
||||
plugins[file] = new plugin(electron.app, utils.getStore());
|
||||
}
|
||||
} else {
|
||||
plugins[file] = new plugin(electron.app, utils.getStore());
|
||||
const plugin = require(path.join(this.userPluginsPath, file));
|
||||
file = file.replace('.ts', '').replace('.js', '');
|
||||
if (plugins[file] || plugin in plugins) {
|
||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||
} else {
|
||||
plugins[file] = new plugin(electron.app, utils.getStore());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Plugins V2
|
||||
else if (fs.lstatSync(path.join(this.userPluginsPath, file)).isDirectory()) {
|
||||
const pluginPath = path.join(this.userPluginsPath, file);
|
||||
if (fs.existsSync(path.join(pluginPath, 'package.json'))) {
|
||||
const pluginPackage = require(path.join(pluginPath, "package.json"));
|
||||
const plugin = require(path.join(pluginPath, pluginPackage.main));
|
||||
if (plugins[plugin.name] || plugin.name in plugins) {
|
||||
console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`);
|
||||
} else {
|
||||
Plugins.PluginMap[pluginPackage.name] = file;
|
||||
const pluginEnv = {
|
||||
app: electron.app,
|
||||
store: utils.getStore(),
|
||||
utils: utils,
|
||||
win: utils.getWindow(),
|
||||
dir: pluginPath,
|
||||
dirName: file
|
||||
}
|
||||
plugins[plugin.name] = new plugin(pluginEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,12 +6,24 @@ export class Store {
|
|||
|
||||
private defaults: any = {
|
||||
"general": {
|
||||
"close_button_hide": true,
|
||||
"close_button_hide": false,
|
||||
"open_on_startup": false,
|
||||
"discord_rpc": 1, // 0 = disabled, 1 = enabled as Cider, 2 = enabled as Apple Music
|
||||
"discord_rpc_clear_on_pause": true,
|
||||
"language": "en_US", // electron.app.getLocale().replace('-', '_') this can be used in future
|
||||
"playbackNotifications": true
|
||||
"playbackNotifications": true,
|
||||
"update_branch": "main",
|
||||
"resumeOnStartupBehavior": "local",
|
||||
"privateEnabled": false,
|
||||
"themeUpdateNotification": true,
|
||||
"sidebarItems": {
|
||||
"recentlyAdded": true,
|
||||
"songs": true,
|
||||
"albums": true,
|
||||
"artists": true,
|
||||
"videos": true,
|
||||
"podcasts": true
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"followedArtists": [],
|
||||
|
@ -22,20 +34,37 @@ export class Store {
|
|||
"sort": "name",
|
||||
"sortOrder": "asc",
|
||||
"size": "normal"
|
||||
}
|
||||
},
|
||||
"albums": {
|
||||
"sort": "name",
|
||||
"sortOrder": "asc",
|
||||
"viewAs": "covers"
|
||||
},
|
||||
},
|
||||
"audio": {
|
||||
"volume": 1,
|
||||
"volumeStep": 0.1,
|
||||
"maxVolume": 1,
|
||||
"lastVolume": 1,
|
||||
"muted": false,
|
||||
"quality": "256",
|
||||
"quality": "HIGH",
|
||||
"seamless_audio": true,
|
||||
"normalization": false,
|
||||
"maikiwiAudio": {
|
||||
"ciderPPE": false,
|
||||
"ciderPPE_value": 0.5,
|
||||
"analogWarmth": false,
|
||||
"analogWarmth_value": 1.25,
|
||||
"spatial": false,
|
||||
"spatialType": 0,
|
||||
"vibrantBass": { // Hard coded into the app. Don't include any of this config into exporting presets in store.ts
|
||||
'multiplier': 0,
|
||||
'frequencies': [17.182, 42.169, 53.763, 112.69, 119.65, 264.59, 336.57, 400.65, 505.48, 612.7, 838.7, 1155.3, 1175.6, 3406.8, 5158.6, 5968.1, 6999.9, 7468.6, 8862.9, 9666, 10109],
|
||||
'Q': [2.5, 0.388, 5, 5, 2.5, 7.071, 14.14, 10, 7.071, 14.14, 8.409, 0.372, 7.071, 10, 16.82, 7.071, 28.28, 20, 8.409, 40, 40],
|
||||
'gain': [-0.34, 2.49, 0.23, -0.49, 0.23, -0.12, 0.32, -0.29, 0.33, 0.19, -0.18, -1.27, -0.11, 0.25, -0.18, -0.53, 0.34, 1.32, 1.78, 0.41, -0.28]
|
||||
}
|
||||
},
|
||||
"spatial": false,
|
||||
"maxVolume": 1,
|
||||
"volumePrecision": 0.1,
|
||||
"volumeRoundMax": 0.9,
|
||||
"volumeRoundMin": 0.1,
|
||||
"spatial_properties": {
|
||||
"presets": [],
|
||||
"gain": 0.8,
|
||||
|
@ -59,19 +88,12 @@ export class Store {
|
|||
'preset': "default",
|
||||
'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000],
|
||||
'gain': [0,0,0,0,0,0,0,0,0,0],
|
||||
'Q' : [1,1,1,1,1,1,1,1,1,1],
|
||||
'preamp' : 0,
|
||||
'mix' : 1,
|
||||
'vibrantBass' : 0,
|
||||
'Q': [1,1,1,1,1,1,1,1,1,1],
|
||||
'mix': 1,
|
||||
'vibrantBass': 0,
|
||||
'presets': [],
|
||||
'userGenerated': false
|
||||
},
|
||||
"vibrantBass": { // Hard coded into the app. Don't include any of this config into exporting presets in store.ts
|
||||
'multiplier': 0,
|
||||
'frequencies': [17.182, 42.169, 53.763, 112.69, 119.65, 264.59, 336.57, 400.65, 505.48, 612.7, 838.7, 1155.3, 1175.6, 3406.8, 5158.6, 5968.1, 6999.9, 7468.6, 8862.9, 9666, 10109],
|
||||
'Q': [2.5, 0.388, 5, 5, 2.5, 7.071, 14.14, 10, 7.071, 14.14, 8.409, 0.372, 7.071, 10, 16.82, 7.071, 28.28, 20, 8.409, 40, 40],
|
||||
'gain': [-0.34, 2.49, 0.23, -0.49, 0.23, -0.12, 0.32, -0.29, 0.33, 0.19, -0.18, -1.27, -0.11, 0.25, -0.18, -0.53, 0.34, 1.32, 1.78, 0.41, -0.28]
|
||||
}
|
||||
},
|
||||
"visual": {
|
||||
"theme": "",
|
||||
|
@ -83,7 +105,11 @@ export class Store {
|
|||
"bg_artwork_rotation": false,
|
||||
"hw_acceleration": "default", // default, webgpu, disabled
|
||||
"showuserinfo": true,
|
||||
"miniplayer_top_toggle": true
|
||||
"transparent": false,
|
||||
"miniplayer_top_toggle": true,
|
||||
"directives": {
|
||||
"windowLayout": "default"
|
||||
}
|
||||
},
|
||||
"lyrics": {
|
||||
"enable_mxm": false,
|
||||
|
@ -101,7 +127,8 @@ export class Store {
|
|||
},
|
||||
"advanced": {
|
||||
"AudioContext": false,
|
||||
"experiments": []
|
||||
"experiments": [],
|
||||
"playlistTrackMapping": true
|
||||
}
|
||||
}
|
||||
private migrations: any = {}
|
||||
|
@ -142,11 +169,11 @@ export class Store {
|
|||
* IPC Handler
|
||||
*/
|
||||
private ipcHandler(): void {
|
||||
electron.ipcMain.handle('getStoreValue', (event, key, defaultValue) => {
|
||||
electron.ipcMain.handle('getStoreValue', (_event, key, defaultValue) => {
|
||||
return (defaultValue ? Store.cfg.get(key, true) : Store.cfg.get(key));
|
||||
});
|
||||
|
||||
electron.ipcMain.handle('setStoreValue', (event, key, value) => {
|
||||
electron.ipcMain.handle('setStoreValue', (_event, key, value) => {
|
||||
Store.cfg.set(key, value);
|
||||
});
|
||||
|
||||
|
@ -154,7 +181,7 @@ export class Store {
|
|||
event.returnValue = Store.cfg.store
|
||||
})
|
||||
|
||||
electron.ipcMain.on('setStore', (event, store) => {
|
||||
electron.ipcMain.on('setStore', (_event, store) => {
|
||||
Store.cfg.store = store
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,11 +1,38 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import {jsonc} from "jsonc";
|
||||
import {Store} from "./store";
|
||||
import {BrowserWindow as bw} from "./browserwindow";
|
||||
import {app, dialog, ipcMain, Notification, shell } from "electron";
|
||||
import fetch from "electron-fetch";
|
||||
import {AppImageUpdater, NsisUpdater} from "electron-updater";
|
||||
import * as log from "electron-log";
|
||||
|
||||
export class utils {
|
||||
|
||||
/**
|
||||
* Paths for the application to use
|
||||
*/
|
||||
private static paths: any = {
|
||||
srcPath: path.join(__dirname, "../../src"),
|
||||
rendererPath: path.join(__dirname, "../../src/renderer"),
|
||||
mainPath: path.join(__dirname, "../../src/main"),
|
||||
resourcePath: path.join(__dirname, "../../resources"),
|
||||
i18nPath: path.join(__dirname, "../../src/i18n"),
|
||||
i18nPathSrc: path.join(__dirname, "../../src/il8n/source"),
|
||||
ciderCache: path.resolve(app.getPath("userData"), "CiderCache"),
|
||||
themes: path.resolve(app.getPath("userData"), "Themes"),
|
||||
plugins: path.resolve(app.getPath("userData"), "Plugins"),
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the path
|
||||
* @returns {string}
|
||||
* @param name
|
||||
*/
|
||||
static getPath(name: string): string {
|
||||
return this.paths[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the i18n locale for the given language.
|
||||
* @param language {string} The language to fetch the locale for.
|
||||
|
@ -13,10 +40,10 @@ export class utils {
|
|||
* @returns {string | Object} The locale value.
|
||||
*/
|
||||
static getLocale(language: string, key?: string): string | object {
|
||||
let i18n: { [index: string]: Object } = jsonc.parse(fs.readFileSync(path.join(__dirname, "../../src/i18n/en_US.jsonc"), "utf8"));
|
||||
let i18n: { [index: string]: Object } = JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, "en_US.json"), "utf8"));
|
||||
|
||||
if (language !== "en_US" && fs.existsSync(path.join(__dirname, `../../src/i18n/${language}.jsonc`))) {
|
||||
i18n = Object.assign(i18n, jsonc.parse(fs.readFileSync(path.join(__dirname, `../../src/i18n/${language}.jsonc`), "utf8")));
|
||||
if (language !== "en_US" && fs.existsSync(path.join(this.paths.i18nPath, `${language}.json`))) {
|
||||
i18n = Object.assign(i18n, JSON.parse(fs.readFileSync(path.join(this.paths.i18nPath, `${language}.json`), "utf8")));
|
||||
}
|
||||
|
||||
if (key) {
|
||||
|
@ -58,4 +85,110 @@ export class utils {
|
|||
static getWindow(): Electron.BrowserWindow {
|
||||
return bw.win
|
||||
}
|
||||
}
|
||||
|
||||
static loadPluginFrontend(path: string): void {
|
||||
|
||||
}
|
||||
|
||||
static loadJSFrontend(path: string): void {
|
||||
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()")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the application for updates
|
||||
*/
|
||||
static async checkForUpdate(): Promise<void> {
|
||||
if (!app.isPackaged) {
|
||||
new Notification({ title: "Application Update", body: "Can't update as app is in DEV mode. Please build or grab a copy by clicking me"})
|
||||
.on('click', () => {shell.openExternal('https://download.cider.sh/?utm_source=app&utm_medium=dev-mode-warning')})
|
||||
.show()
|
||||
bw.win.webContents.send('update-response', "update-error")
|
||||
return;
|
||||
}
|
||||
// Get the artifacts
|
||||
const response = await fetch(`https://circleci.com/api/v1.1/project/gh/ciderapp/Cider/latest/artifacts?branch=${utils.getStoreValue('general.update_branch')}&filter=successful`)
|
||||
if (response.status != 200) {
|
||||
bw.win.webContents.send('update-response', 'update-timeout')
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the urls
|
||||
const jsonResponse = await response.json()
|
||||
let base_url = jsonResponse[0].url
|
||||
base_url = base_url.substring(0, base_url.lastIndexOf('/'))
|
||||
|
||||
const options: any = {
|
||||
provider: 'generic',
|
||||
url: base_url,
|
||||
allowDowngrade: true,
|
||||
}
|
||||
|
||||
let autoUpdater: any = null
|
||||
if (process.platform === 'win32') { //Windows
|
||||
autoUpdater = await new NsisUpdater(options)
|
||||
} else {
|
||||
autoUpdater = await new AppImageUpdater(options) //Linux and Mac (AppImages work on macOS btw)
|
||||
}
|
||||
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
new Notification({ title: "Cider Update", body: "Cider is currently checking for updates."}).show()
|
||||
})
|
||||
|
||||
autoUpdater.on('error', (error: any) => {
|
||||
console.error(`[AutoUpdater] Error: ${error}`)
|
||||
bw.win.webContents.send('update-response', "update-error")
|
||||
})
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
console.log('[AutoUpdater] Update not available.')
|
||||
bw.win.webContents.send('update-response', "update-not-available");
|
||||
})
|
||||
autoUpdater.on('download-progress', (event: any, progress: any) => {
|
||||
bw.win.setProgressBar(progress.percent / 100)
|
||||
})
|
||||
|
||||
autoUpdater.on('update-downloaded', (info: any) => {
|
||||
console.log('[AutoUpdater] Update downloaded.')
|
||||
bw.win.webContents.send('update-response', "update-downloaded");
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Restart', 'Later'],
|
||||
title: 'Application Update',
|
||||
message: info,
|
||||
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
|
||||
}
|
||||
|
||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
||||
if (returnValue.response === 0) autoUpdater.quitAndInstall()
|
||||
})
|
||||
new Notification({ title: "Application Update", body: info}).on('click', () => {
|
||||
bw.win.show()
|
||||
}).show()
|
||||
})
|
||||
|
||||
log.transports.file.level = "debug"
|
||||
autoUpdater.logger = log
|
||||
await autoUpdater.checkForUpdatesAndNotify()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ export class wsapi {
|
|||
electron.ipcMain.on('wsapi-returnLyrics', (event :any, arg :any) => {
|
||||
this.returnLyrics(JSON.parse(arg));
|
||||
});
|
||||
electron.ipcMain.on('wsapi-returnvolumeMax', (_event: any, arg: any) => {
|
||||
this.returnmaxVolume(JSON.parse(arg));
|
||||
});
|
||||
this.wss = new WebSocketServer({
|
||||
port: this.port,
|
||||
perMessageDeflate: {
|
||||
|
@ -165,6 +168,10 @@ export class wsapi {
|
|||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().stop()`);
|
||||
response.message = "Stopped";
|
||||
break;
|
||||
case "volumeMax":
|
||||
this._win.webContents.executeJavaScript(`wsapi.getmaxVolume()`);
|
||||
response.message = "maxVolume";
|
||||
break;
|
||||
case "volume":
|
||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(data.volume)}`);
|
||||
response.message = "Volume";
|
||||
|
@ -178,11 +185,15 @@ export class wsapi {
|
|||
response.message = "Unmuted";
|
||||
break;
|
||||
case "next":
|
||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToNextItem()`);
|
||||
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.nextPlayableItemIndex != -1 && MusicKit.getInstance().queue.nextPlayableItemIndex != null) {
|
||||
try {
|
||||
app.prevButtonBackIndicator = false;
|
||||
} catch (e) { }
|
||||
MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.nextPlayableItemIndex);}`);
|
||||
response.message = "Next";
|
||||
break;
|
||||
case "previous":
|
||||
this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToPreviousItem()`);
|
||||
this._win.webContents.executeJavaScript(`if (MusicKit.getInstance().queue.previousPlayableItemIndex != -1 && MusicKit.getInstance().queue.previousPlayableItemIndex != null) {MusicKit.getInstance().changeToMediaAtIndex(MusicKit.getInstance().queue.previousPlayableItemIndex)}`);
|
||||
response.message = "Previous";
|
||||
break;
|
||||
case "musickit-api":
|
||||
|
@ -290,4 +301,11 @@ export class wsapi {
|
|||
client.send(JSON.stringify(response));
|
||||
});
|
||||
}
|
||||
|
||||
returnmaxVolume(vol: any) {
|
||||
const response: standardResponse = {status: 0, data: vol, message: "OK", type: "maxVolume"};
|
||||
this.clients.forEach(function each(client: any) {
|
||||
client.send(JSON.stringify(response));
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue