From 1f96b6b44d8549cfcb03b0393f8e8c84c2bc072a Mon Sep 17 00:00:00 2001 From: JellyBrick Date: Sat, 11 Nov 2023 19:23:17 +0900 Subject: [PATCH] fix: plugin load --- electron.vite.config.ts | 2 + src/config/plugins.ts | 21 +++------ src/index.ts | 59 +++++++++++-------------- src/plugins/ambient-mode/renderer.ts | 1 - src/plugins/in-app-menu/main.ts | 4 +- src/plugins/lyrics-genius/main.ts | 2 +- src/plugins/lyrics-genius/renderer.ts | 2 +- src/plugins/precise-volume/renderer.ts | 4 +- src/preload.ts | 13 ++++-- src/renderer.ts | 60 +++++++++----------------- 10 files changed, 69 insertions(+), 99 deletions(-) diff --git a/electron.vite.config.ts b/electron.vite.config.ts index a9ecee02..5d8dafae 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -50,6 +50,7 @@ export default defineConfig({ const commonConfig: UserConfig = { plugins: [ viteResolve({ + 'virtual:PluginBuilders': pluginVirtualModuleGenerator('index'), 'virtual:PreloadPlugins': pluginVirtualModuleGenerator('preload'), }), ], @@ -86,6 +87,7 @@ export default defineConfig({ const commonConfig: UserConfig = { plugins: [ viteResolve({ + 'virtual:PluginBuilders': pluginVirtualModuleGenerator('index'), 'virtual:RendererPlugins': pluginVirtualModuleGenerator('renderer'), }), ], diff --git a/src/config/plugins.ts b/src/config/plugins.ts index 3092b1d2..32b516ae 100644 --- a/src/config/plugins.ts +++ b/src/config/plugins.ts @@ -1,27 +1,16 @@ -import { deepmerge } from '@fastify/deepmerge'; import store from './store'; -import defaultConfig from './defaults'; import { restart } from '../providers/app-controls'; -import { Entries } from '../utils/type-utils'; -interface Plugin { - enabled: boolean; -} +import type { PluginBaseConfig } from '../plugins/utils/builder'; -type DefaultPluginsConfig = typeof defaultConfig.plugins; -const deepmergeFn = deepmerge(); - -export function getEnabled() { - const plugins = deepmergeFn(defaultConfig.plugins, (store.get('plugins') as DefaultPluginsConfig)); - return (Object.entries(plugins) as Entries).filter(([, options]) => - (options as Plugin).enabled, - ); +export function getPlugins() { + return store.get('plugins') as Record; } export function isEnabled(plugin: string) { - const pluginConfig = (store.get('plugins') as Record)[plugin]; + const pluginConfig = (store.get('plugins') as Record)[plugin]; return pluginConfig !== undefined && pluginConfig.enabled; } @@ -69,7 +58,7 @@ export function disable(plugin: string) { export default { isEnabled, - getEnabled, + getPlugins, enable, disable, setOptions, diff --git a/src/index.ts b/src/index.ts index e126d11b..edbc2d10 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,8 @@ import { autoUpdater } from 'electron-updater'; import electronDebug from 'electron-debug'; import { parse } from 'node-html-parser'; +import { deepmerge as createDeepmerge } from '@fastify/deepmerge'; + import config from './config'; import { refreshMenu, setApplicationMenu } from './menu'; @@ -26,7 +28,10 @@ import { pluginBuilders } from 'virtual:PluginBuilders'; /* eslint-enable import/order */ import youtubeMusicCSS from './youtube-music.css?inline'; -import { MainPlugin, PluginBaseConfig, MainPluginContext, MainPluginFactory } from './plugins/utils/builder'; + +import type { MainPlugin, PluginBaseConfig, MainPluginContext, MainPluginFactory } from './plugins/utils/builder'; + +const deepmerge = createDeepmerge(); // Catch errors and log them unhandled({ @@ -159,42 +164,30 @@ async function loadPlugins(win: BrowserWindow) { }, }); + const pluginConfigs = config.plugins.getPlugins(); + for (const [pluginId, factory] of Object.entries(mainPlugins)) { + if (Object.hasOwn(pluginBuilders, pluginId)) { + const builder = pluginBuilders[pluginId as keyof PluginBuilderList]; + const config = deepmerge(builder.config, pluginConfigs[pluginId as keyof PluginBuilderList]); - for (const [pluginId, options] of config.plugins.getEnabled()) { - const builder = pluginBuilders[pluginId as keyof PluginBuilderList]; - const factory = (mainPlugins as Record>)[pluginId]; + if (config?.enabled) { + builder.styles?.forEach((style) => { + injectCSS(win.webContents, style); + console.log('[YTMusic]', `"${pluginId}" plugin meta data is loaded`); + }); - if (builder) { - builder.styles?.forEach((style) => { - injectCSS(win.webContents, style); - console.log('[YTMusic]', `"${pluginId}" plugin meta data is loaded`); - }); - } - - if (factory) { - try { - const context = createContext(pluginId as keyof PluginBuilderList); - const plugin = await factory(context); - loadedPluginList.push([pluginId, plugin]); - plugin.onLoad?.(win); - console.log('[YTMusic]', `"${pluginId}" plugin is loaded`); - } catch (error) { - console.error('[YTMusic]', `Cannot load plugin "${pluginId}"`); - console.trace(error); + try { + const context = createContext(pluginId as keyof PluginBuilderList); + const plugin = await (factory as MainPluginFactory)(context); + loadedPluginList.push([pluginId, plugin]); + plugin.onLoad?.(win); + console.log('[YTMusic]', `"${pluginId}" plugin is loaded`); + } catch (error) { + console.error('[YTMusic]', `Cannot load plugin "${pluginId}"`); + console.trace(error); + } } } - - // try { - // if (Object.hasOwn(mainPlugins, plugin)) { - // console.log('Loaded plugin - ' + plugin); - // const handler = mainPlugins[plugin as keyof typeof mainPlugins]; - // if (handler) { - // await handler(win, options as never); - // } - // } - // } catch (e) { - // console.error(`Failed to load plugin "${plugin}"`, e); - // } } } diff --git a/src/plugins/ambient-mode/renderer.ts b/src/plugins/ambient-mode/renderer.ts index 91a92fc1..d1c3728a 100644 --- a/src/plugins/ambient-mode/renderer.ts +++ b/src/plugins/ambient-mode/renderer.ts @@ -26,7 +26,6 @@ export default builder.createRenderer(async ({ getConfig }) => { if (!video) return null; if (!wrapper) return null; - console.log('injectBlurVideo', songVideo, video, wrapper); const blurCanvas = document.createElement('canvas'); blurCanvas.classList.add('html5-blur-canvas'); diff --git a/src/plugins/in-app-menu/main.ts b/src/plugins/in-app-menu/main.ts index d0058ce3..5510b015 100644 --- a/src/plugins/in-app-menu/main.ts +++ b/src/plugins/in-app-menu/main.ts @@ -49,7 +49,7 @@ export default builder.createMain(({ handle, send }) => { if (target) target.click(undefined, BrowserWindow.fromWebContents(event.sender), event.sender); }); - handle('get-menu-by-id', (_, commandId: number) => { + handle('get-menu-by-id', (commandId: number) => { const result = getMenuItemById(commandId); return JSON.parse(JSON.stringify( @@ -67,7 +67,7 @@ export default builder.createMain(({ handle, send }) => { handle('window-unmaximize', () => win.unmaximize()); win.on('unmaximize', () => send('window-unmaximize')); - handle('image-path-to-data-url', (_, imagePath: string) => { + handle('image-path-to-data-url', (imagePath: string) => { const nativeImageIcon = nativeImage.createFromPath(imagePath); return nativeImageIcon?.toDataURL(); }); diff --git a/src/plugins/lyrics-genius/main.ts b/src/plugins/lyrics-genius/main.ts index 3b20b69a..0c43877c 100644 --- a/src/plugins/lyrics-genius/main.ts +++ b/src/plugins/lyrics-genius/main.ts @@ -20,7 +20,7 @@ export default builder.createMain(({ handle, getConfig }) =>{ revRomanized = true; } - handle('search-genius-lyrics', async (_, extractedSongInfo: SongInfo) => { + handle('search-genius-lyrics', async (extractedSongInfo: SongInfo) => { const metadata = extractedSongInfo; return await fetchFromGenius(metadata); }); diff --git a/src/plugins/lyrics-genius/renderer.ts b/src/plugins/lyrics-genius/renderer.ts index ea13334c..d9c8f4ce 100644 --- a/src/plugins/lyrics-genius/renderer.ts +++ b/src/plugins/lyrics-genius/renderer.ts @@ -24,7 +24,7 @@ export default builder.createRenderer(({ on, invoke }) => ({ let unregister: (() => void) | null = null; - on('update-song-info', (_, extractedSongInfo: SongInfo) => { + on('update-song-info', (extractedSongInfo: SongInfo) => { unregister?.(); setTimeout(async () => { diff --git a/src/plugins/precise-volume/renderer.ts b/src/plugins/precise-volume/renderer.ts index 9dce69da..c878c1fe 100644 --- a/src/plugins/precise-volume/renderer.ts +++ b/src/plugins/precise-volume/renderer.ts @@ -261,8 +261,8 @@ export default builder.createRenderer(async ({ on, getConfig, setConfig }) => { document.addEventListener('apiLoaded', (e) => { api = e.detail; - on('changeVolume', (_, toIncrease: boolean) => changeVolume(toIncrease)); - on('setVolume', (_, value: number) => setVolume(value)); + on('changeVolume', (toIncrease: boolean) => changeVolume(toIncrease)); + on('setVolume', (value: number) => setVolume(value)); firstRun(); }, { once: true, passive: true }); }, diff --git a/src/preload.ts b/src/preload.ts index 0d0faf39..861dabe5 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -1,13 +1,17 @@ import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'; import is from 'electron-is'; +import { pluginBuilders } from 'virtual:PluginBuilders'; + +import { deepmerge as createDeepmerge } from '@fastify/deepmerge'; + import config from './config'; // eslint-disable-next-line import/order import { preloadPlugins } from 'virtual:PreloadPlugins'; import { PluginBaseConfig, PluginContext, PreloadPluginFactory } from './plugins/utils/builder'; -const enabledPluginNameAndOptions = config.plugins.getEnabled(); +const deepmerge = createDeepmerge(); const createContext = < Key extends keyof PluginBuilderList, @@ -22,12 +26,15 @@ const createContext = < const preloadedPluginList = []; -enabledPluginNameAndOptions.forEach(async ([id]) => { +const pluginConfig = config.plugins.getPlugins(); +Object.entries(preloadPlugins) + .filter(([id]) => deepmerge(pluginBuilders[id as keyof PluginBuilderList].config, pluginConfig[id as keyof PluginBuilderList])?.enabled) + .forEach(async ([id]) => { if (Object.hasOwn(preloadPlugins, id)) { const factory = (preloadPlugins as Record>)[id]; try { - const context = createContext(id); + const context = createContext(id as keyof PluginBuilderList); const plugin = await factory(context); plugin.onLoad?.(); preloadedPluginList.push(plugin); diff --git a/src/renderer.ts b/src/renderer.ts index dcb326a0..64b22f9a 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -2,13 +2,17 @@ // eslint-disable-next-line import/order import { rendererPlugins } from 'virtual:RendererPlugins'; +import { deepmerge as createDeepmerge } from '@fastify/deepmerge'; + import { PluginBaseConfig, RendererPluginContext, RendererPluginFactory } from './plugins/utils/builder'; import { startingPages } from './providers/extracted-data'; import { setupSongControls } from './providers/song-controls-front'; import setupSongInfo from './providers/song-info-front'; +import {mainPlugins} from "virtual:MainPlugins"; +import {pluginBuilders} from "virtual:PluginBuilders"; -const enabledPluginNameAndOptions = window.mainConfig.plugins.getEnabled(); +const deepmerge = createDeepmerge(); let api: Element | null = null; @@ -116,55 +120,31 @@ const createContext = < }); (async () => { - // enabledPluginNameAndOptions.forEach(async ([pluginName, options]) => { - // if (pluginName === 'ambient-mode') { - // const builder = rendererPlugins[pluginName]; - - // try { - // const context = createContext(pluginName); - // const plugin = await builder?.(context); - // console.log(plugin); - // plugin.onLoad?.(); - // } catch (error) { - // console.error(`Error in plugin "${pluginName}"`); - // console.trace(error); - // } - // } - - // if (Object.hasOwn(rendererPlugins, pluginName)) { - // const handler = rendererPlugins[pluginName]; - // try { - // await handler?.(options as never); - // } catch (error) { - // console.error(`Error in plugin "${pluginName}"`); - // console.trace(error); - // } - // } - // }); + const pluginConfig = window.mainConfig.plugins.getPlugins(); + const rendererPluginList = Object.entries(rendererPlugins); const rendererPluginResult = await Promise.allSettled( - enabledPluginNameAndOptions.map(async ([id]) => { - // HACK: eslint has a bug detects the type of rendererPlugins as "any" - const builder = (rendererPlugins as Record>)[id]; - - const context = createContext(id as keyof PluginBuilderList); - return [id, await builder(context)] as const; - }), + rendererPluginList + .filter(([id]) => deepmerge(pluginBuilders[id as keyof PluginBuilderList].config, pluginConfig[id as keyof PluginBuilderList])?.enabled) + .map(async ([id, builder]) => { + const context = createContext(id as keyof PluginBuilderList); + return [id, await (builder as RendererPluginFactory)(context)] as const; + }), ); - const rendererPluginList = rendererPluginResult - .map((it) => it.status === 'fulfilled' ? it.value : null) - .filter(Boolean); - rendererPluginResult.forEach((it, index) => { if (it.status === 'rejected') { - const id = enabledPluginNameAndOptions[index][0]; + const id = rendererPluginList[index][0]; console.error('[YTMusic]', `Cannot load plugin "${id}"`); console.trace(it.reason); } }); - rendererPluginList.forEach(([id, plugin]) => { + const loadedRendererPluginList = rendererPluginResult + .map((it) => it.status === 'fulfilled' ? it.value : null) + .filter(Boolean); + + loadedRendererPluginList.forEach(([id, plugin]) => { try { plugin.onLoad?.(); console.log('[YTMusic]', `"${id}" plugin is loaded`); @@ -175,7 +155,7 @@ const createContext = < }); window.ipcRenderer.on('config-changed', (_event, id: string, newConfig: PluginBaseConfig) => { - const plugin = rendererPluginList.find(([pluginId]) => pluginId === id); + const plugin = loadedRendererPluginList.find(([pluginId]) => pluginId === id); if (plugin) { plugin[1].onConfigChange?.(newConfig);