From 96e6b5d01802ad389b83f6159791a6a2e735f41d Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:23:37 +0200 Subject: [PATCH 1/9] Add dynamic synced plugin config provider --- config/dynamic.js | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 config/dynamic.js diff --git a/config/dynamic.js b/config/dynamic.js new file mode 100644 index 00000000..2e995f21 --- /dev/null +++ b/config/dynamic.js @@ -0,0 +1,112 @@ +const { ipcRenderer, ipcMain } = require("electron"); + +const defaultConfig = require("./defaults"); +const { getOptions, setOptions, setMenuOptions } = require("./plugins"); + +/** + * This class is used to create a dynamic synced config for plugins. + * + * [!IMPORTANT!] + * The methods are **sync** in the main process and **async** in the renderer process. + * + * @param {string} name - The name of the plugin. + * @param {boolean} [options.enableFront] - Whether the config should be available in front.js. Default: false. + * @param {object} [options.initialOptions] - The initial options for the plugin. Default: loaded from store. + * + * @example + * const { PluginConfig } = require("../../config/dynamic"); + * const config = new PluginConfig("plugin-name", { enableFront: true }); + * module.exports = { ...config }; + * + * // or + * + * module.exports = (win, options) => { + * const config = new PluginConfig("plugin-name", { + * enableFront: true, + * initialOptions: options, + * }); + * setupMyPlugin(win, config); + * }; + */ +module.exports.PluginConfig = class PluginConfig { + #name; + #config; + #defaultConfig; + #enableFront; + + constructor(name, { enableFront = false, initialOptions = undefined } = {}) { + const pluginDefaultConfig = defaultConfig.plugins[name] || {}; + const pluginConfig = initialOptions || getOptions(name) || {}; + + this.#name = name; + this.#enableFront = enableFront; + this.#defaultConfig = pluginDefaultConfig; + this.#config = { ...pluginDefaultConfig, ...pluginConfig }; + + if (this.#enableFront) { + this.#setupFront(); + } + } + + get = (option) => { + return this.#config[option]; + }; + + set = (option, value) => { + this.#config[option] = value; + this.#save(); + }; + + toggle = (option) => { + this.#config[option] = !this.#config[option]; + this.#save(); + }; + + getAll = () => { + return { ...this.#config }; + }; + + setAll = (options) => { + this.#config = { ...options }; + this.#save(); + }; + + getDefaultConfig = () => { + return this.#defaultConfig; + }; + + /** + * Use this method to set an option and restart the app if `appConfig.restartOnConfigChange === true` + * + * Used for options that require a restart to take effect. + */ + setAndMaybeRestart = (option, value) => { + this.#config[option] = value; + setMenuOptions(this.#name, this.#config); + }; + + #save() { + setOptions(this.#name, this.#config); + } + + #setupFront() { + if (process.type === "renderer") { + for (const [fnName, fn] of Object.entries(this)) { + if (typeof fn !== "function") return; + this[fnName] = async (...args) => { + return await ipcRenderer.invoke( + `${this.name}-config-${fnName}`, + ...args, + ); + }; + } + } else if (process.type === "browser") { + for (const [fnName, fn] of Object.entries(this)) { + if (typeof fn !== "function") return; + ipcMain.handle(`${this.name}-config-${fnName}`, (_, ...args) => { + return fn(...args); + }); + } + } + } +}; From bdfdf83c246ae2f15c8895690542f0743e0b35be Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:24:41 +0200 Subject: [PATCH 2/9] [notifications] use dynamic config --- plugins/notifications/back.js | 1 - plugins/notifications/config.js | 24 +++--------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index 419e27d3..385ecca7 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -39,7 +39,6 @@ const setup = () => { /** @param {Electron.BrowserWindow} win */ module.exports = (win, options) => { - config.init(options); // Register the callback for new song information is.windows() && options.interactive ? require("./interactive")(win) : diff --git a/plugins/notifications/config.js b/plugins/notifications/config.js index 38d8100e..d0898dc3 100644 --- a/plugins/notifications/config.js +++ b/plugins/notifications/config.js @@ -1,23 +1,5 @@ -const { setOptions, setMenuOptions } = require("../../config/plugins"); -const defaultConfig = require("../../config/defaults"); +const { PluginConfig } = require("../../config/dynamic"); -let config = defaultConfig.plugins["notifications"]; +const config = new PluginConfig("notifications"); -module.exports.init = (options) => { - config = { ...config, ...options }; -}; - -module.exports.setAndMaybeRestart = (option, value) => { - config[option] = value; - setMenuOptions("notifications", config); -}; - -module.exports.set = (option, value) => { - config[option] = value; - setOptions("notifications", config); -}; - -module.exports.get = (option) => { - let res = config[option]; - return res; -}; +module.exports = { ...config }; From 7d93e9f031407be72ffcf76e57c112c9f5f92073 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 12 Mar 2023 02:04:29 +0200 Subject: [PATCH 3/9] fix `config.setAll()` --- config/dynamic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/dynamic.js b/config/dynamic.js index 2e995f21..713379e6 100644 --- a/config/dynamic.js +++ b/config/dynamic.js @@ -67,7 +67,7 @@ module.exports.PluginConfig = class PluginConfig { }; setAll = (options) => { - this.#config = { ...options }; + this.#config = { ...this.#config, ...options }; this.#save(); }; From af2b6782e8262329f6e02ef586d8546faeea870a Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 11 Mar 2023 14:52:09 +0200 Subject: [PATCH 4/9] bump custom-electron-prompt --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index e989a1dd..fef4f42f 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "butterchurn": "^2.6.7", "butterchurn-presets": "^2.4.7", "chokidar": "^3.5.3", - "custom-electron-prompt": "^1.5.1", + "custom-electron-prompt": "^1.5.4", "custom-electron-titlebar": "^4.1.6", "electron-better-web-request": "^1.0.1", "electron-debug": "^3.2.0", diff --git a/yarn.lock b/yarn.lock index da6c5954..05338cf0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2425,12 +2425,12 @@ __metadata: languageName: node linkType: hard -"custom-electron-prompt@npm:^1.5.1": - version: 1.5.1 - resolution: "custom-electron-prompt@npm:1.5.1" +"custom-electron-prompt@npm:^1.5.4": + version: 1.5.4 + resolution: "custom-electron-prompt@npm:1.5.4" peerDependencies: electron: ">=10.0.0" - checksum: 43a0d72a7a3471135822cb210d580285f70080d9d3a7b03f82cd4be403059fe20ea05ebdd1f9534928c386ab25a353e678f2cfb3f4ca016b41f3366bff700767 + checksum: 93995b5f0e9d14401a8c4fdd358af32d8b7585b59b111667cfa55f9505109c08914f3140953125b854e5d09e811de8c76c7fec718934c13e8a1ad09fe1b85270 languageName: node linkType: hard @@ -8981,7 +8981,7 @@ __metadata: butterchurn: ^2.6.7 butterchurn-presets: ^2.4.7 chokidar: ^3.5.3 - custom-electron-prompt: ^1.5.1 + custom-electron-prompt: ^1.5.4 custom-electron-titlebar: ^4.1.6 del-cli: ^5.0.0 electron: ^22.0.2 From 108c778f6da37e75d332ad9b54b83392625f668c Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:07:41 +0200 Subject: [PATCH 5/9] fix caption selector showing when unavailable --- plugins/captions-selector/front.js | 36 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/plugins/captions-selector/front.js b/plugins/captions-selector/front.js index 6ed83d90..bd5203bb 100644 --- a/plugins/captions-selector/front.js +++ b/plugins/captions-selector/front.js @@ -11,28 +11,32 @@ module.exports = (options) => { document.addEventListener('apiLoaded', (event) => setup(event, options), { once: true, passive: true }); } -/** - * If captions are disabled by default, - * unload "captions" module when video changes. - */ -const videoChanged = (api, options) => { - if (options.disableCaptions) { - setTimeout(() => api.unloadModule("captions"), 100); - } -} - function setup(event, options) { const api = event.detail; - $("video").addEventListener("srcChanged", () => videoChanged(api, options)); - $(".right-controls-buttons").append(captionsSettingsButton); + let captionTrackList = api.getOption("captions", "tracklist"); + + $("video").addEventListener("srcChanged", () => { + if (options.disableCaptions) { + setTimeout(() => api.unloadModule("captions"), 100); + captionsSettingsButton.style.display = "none"; + return; + } + + api.loadModule("captions"); + + setTimeout(() => { + captionTrackList = api.getOption("captions", "tracklist"); + + captionsSettingsButton.style.display = captionTrackList?.length + ? "inline-block" + : "none"; + }, 250); + }); + captionsSettingsButton.onclick = async () => { - api.loadModule("captions"); - - const captionTrackList = api.getOption("captions", "tracklist"); - if (captionTrackList?.length) { const currentCaptionTrack = api.getOption("captions", "track"); let currentIndex = !currentCaptionTrack ? From 3abef7cb8af859b98923cc62b2d46c274a5f9ec3 Mon Sep 17 00:00:00 2001 From: Daniel Chalmers Date: Fri, 17 Mar 2023 11:49:22 -0500 Subject: [PATCH 6/9] Nitpick: Fix name casing in tray icon tooltip --- tray.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tray.js b/tray.js index d8712d7e..46b76f83 100644 --- a/tray.js +++ b/tray.js @@ -40,7 +40,7 @@ module.exports.setUpTray = (app, win) => { tray = new Tray(trayIcon); - tray.setToolTip("Youtube Music"); + tray.setToolTip("YouTube Music"); // macOS only tray.setIgnoreDoubleClickEvents(true); From d5c2ad2115131798845edaa1267e65813407a828 Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Fri, 17 Mar 2023 18:02:48 -0500 Subject: [PATCH 7/9] Romanization update --- plugins/lyrics-genius/back.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lyrics-genius/back.js b/plugins/lyrics-genius/back.js index ad626d14..134f66d8 100644 --- a/plugins/lyrics-genius/back.js +++ b/plugins/lyrics-genius/back.js @@ -7,7 +7,7 @@ const fetch = require("node-fetch"); const { cleanupName } = require("../../providers/song-info"); const { injectCSS } = require("../utils"); -let eastAsianChars = new RegExp("[\u{3040}-\u{30ff}\u{3400}-\u{4dbf}\u{4e00}-\u{9fff}\u{f900}-\u{faff}\u{ff66}-\u{ff9f}]"); +let eastAsianChars = new RegExp("[\uac00-\ud7af]|[\u1100-\u11ff]|[\u3130-\u318f]|[\ua960-\ua97f]|[\ud7b0-\ud7ff]|[\u3040-\u309F]|[\u3000-\u303F\u3400-\u4DBF\u4E00-\u9FFF]"); let revRomanized = false; module.exports = async (win, options) => { From bc2a1f7f71ced5f271d271f9a6bb12012fb1babc Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Sat, 18 Mar 2023 13:15:25 -0500 Subject: [PATCH 8/9] Updated Regex to be cleaner --- plugins/lyrics-genius/back.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lyrics-genius/back.js b/plugins/lyrics-genius/back.js index 134f66d8..cb781ca8 100644 --- a/plugins/lyrics-genius/back.js +++ b/plugins/lyrics-genius/back.js @@ -7,7 +7,7 @@ const fetch = require("node-fetch"); const { cleanupName } = require("../../providers/song-info"); const { injectCSS } = require("../utils"); -let eastAsianChars = new RegExp("[\uac00-\ud7af]|[\u1100-\u11ff]|[\u3130-\u318f]|[\ua960-\ua97f]|[\ud7b0-\ud7ff]|[\u3040-\u309F]|[\u3000-\u303F\u3400-\u4DBF\u4E00-\u9FFF]"); +let eastAsianChars = /\p{Script=Han}|\p{Script=Katakana}|\p{Script=Hiragana}|\p{Script=Hangul}|\p{Script=Han}/u; let revRomanized = false; module.exports = async (win, options) => { From a6242d13aecca8b9b6148a0f4bf8b1a504d2b66a Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 19 Mar 2023 03:00:17 +0200 Subject: [PATCH 9/9] add `getActivePlugins` and `isActive` --- config/dynamic.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/config/dynamic.js b/config/dynamic.js index 713379e6..34cb0ac3 100644 --- a/config/dynamic.js +++ b/config/dynamic.js @@ -3,6 +3,30 @@ const { ipcRenderer, ipcMain } = require("electron"); const defaultConfig = require("./defaults"); const { getOptions, setOptions, setMenuOptions } = require("./plugins"); +const activePlugins = {}; +/** + * [!IMPORTANT!] + * The method is **sync** in the main process and **async** in the renderer process. + */ +module.exports.getActivePlugins = + process.type === "renderer" + ? async () => ipcRenderer.invoke("get-active-plugins") + : () => activePlugins; + +if (process.type === "browser") { + ipcMain.handle("get-active-plugins", this.getActivePlugins); +} + +/** + * [!IMPORTANT!] + * The method is **sync** in the main process and **async** in the renderer process. + */ +module.exports.isActive = + process.type === "renderer" + ? async (plugin) => + plugin in (await ipcRenderer.invoke("get-active-plugins")) + : (plugin) => plugin in activePlugins; + /** * This class is used to create a dynamic synced config for plugins. * @@ -17,9 +41,9 @@ const { getOptions, setOptions, setMenuOptions } = require("./plugins"); * const { PluginConfig } = require("../../config/dynamic"); * const config = new PluginConfig("plugin-name", { enableFront: true }); * module.exports = { ...config }; - * + * * // or - * + * * module.exports = (win, options) => { * const config = new PluginConfig("plugin-name", { * enableFront: true, @@ -46,6 +70,8 @@ module.exports.PluginConfig = class PluginConfig { if (this.#enableFront) { this.#setupFront(); } + + activePlugins[name] = this; } get = (option) => { @@ -85,6 +111,7 @@ module.exports.PluginConfig = class PluginConfig { setMenuOptions(this.#name, this.#config); }; + /** Called only from back */ #save() { setOptions(this.#name, this.#config); }