fix: plugin load

This commit is contained in:
JellyBrick
2023-11-11 19:23:17 +09:00
parent de0b228ae8
commit 1f96b6b44d
10 changed files with 69 additions and 99 deletions

View File

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

View File

@ -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<DefaultPluginsConfig>).filter(([, options]) =>
(options as Plugin).enabled,
);
export function getPlugins() {
return store.get('plugins') as Record<string, PluginBaseConfig>;
}
export function isEnabled(plugin: string) {
const pluginConfig = (store.get('plugins') as Record<string, Plugin>)[plugin];
const pluginConfig = (store.get('plugins') as Record<string, PluginBaseConfig>)[plugin];
return pluginConfig !== undefined && pluginConfig.enabled;
}
@ -69,7 +58,7 @@ export function disable(plugin: string) {
export default {
isEnabled,
getEnabled,
getPlugins,
enable,
disable,
setOptions,

View File

@ -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<string, MainPluginFactory<PluginBaseConfig>>)[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<PluginBaseConfig>)(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);
// }
}
}

View File

@ -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');

View File

@ -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();
});

View File

@ -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);
});

View File

@ -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 () => {

View File

@ -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 });
},

View File

@ -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<string, PreloadPluginFactory<PluginBaseConfig>>)[id];
try {
const context = createContext(id);
const context = createContext(id as keyof PluginBuilderList);
const plugin = await factory(context);
plugin.onLoad?.();
preloadedPluginList.push(plugin);

View File

@ -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<string, RendererPluginFactory<PluginBaseConfig>>)[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<PluginBaseConfig>)(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);