add subscribe and subscribeAll to config

this primarily allows front.js to have an up to date config without requesting it over ipc every second

for example the crossfade plugin uses its `options.secondsBeforeEnd` every second - so `subscribeAll` would be much more efficient in this case
This commit is contained in:
Araxeus
2023-03-19 23:47:29 +02:00
parent 212009a69b
commit 648d102101

View File

@ -1,7 +1,8 @@
const { ipcRenderer, ipcMain } = require("electron");
const { ipcRenderer, ipcMain } = require('electron');
const defaultConfig = require("./defaults");
const { getOptions, setOptions, setMenuOptions } = require("./plugins");
const defaultConfig = require('./defaults');
const { getOptions, setOptions, setMenuOptions } = require('./plugins');
const { sendToFront } = require('../providers/app-controls');
const activePlugins = {};
/**
@ -9,12 +10,12 @@ const activePlugins = {};
* 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")
process.type === 'renderer'
? async () => ipcRenderer.invoke('get-active-plugins')
: () => activePlugins;
if (process.type === "browser") {
ipcMain.handle("get-active-plugins", this.getActivePlugins);
if (process.type === 'browser') {
ipcMain.handle('get-active-plugins', this.getActivePlugins);
}
/**
@ -22,9 +23,9 @@ if (process.type === "browser") {
* The method is **sync** in the main process and **async** in the renderer process.
*/
module.exports.isActive =
process.type === "renderer"
process.type === 'renderer'
? async (plugin) =>
plugin in (await ipcRenderer.invoke("get-active-plugins"))
plugin in (await ipcRenderer.invoke('get-active-plugins'))
: (plugin) => plugin in activePlugins;
/**
@ -58,6 +59,9 @@ module.exports.PluginConfig = class PluginConfig {
#defaultConfig;
#enableFront;
#subscribers = {};
#allSubscribers = [];
constructor(name, { enableFront = false, initialOptions = undefined } = {}) {
const pluginDefaultConfig = defaultConfig.plugins[name] || {};
const pluginConfig = initialOptions || getOptions(name) || {};
@ -80,11 +84,13 @@ module.exports.PluginConfig = class PluginConfig {
set = (option, value) => {
this.#config[option] = value;
this.#onChange(option);
this.#save();
};
toggle = (option) => {
this.#config[option] = !this.#config[option];
this.#onChange(option);
this.#save();
};
@ -93,7 +99,18 @@ module.exports.PluginConfig = class PluginConfig {
};
setAll = (options) => {
this.#config = { ...this.#config, ...options };
if (!options || typeof options !== 'object')
throw new Error('Options must be an object.');
let changed = false;
for (const [key, val] of Object.entries(options)) {
if (this.#config[key] !== val) {
this.#config[key] = val;
this.#onChange(key, false);
changed = true;
}
}
if (changed) this.#allSubscribers.forEach((fn) => fn(this.#config));
this.#save();
};
@ -109,6 +126,15 @@ module.exports.PluginConfig = class PluginConfig {
setAndMaybeRestart = (option, value) => {
this.#config[option] = value;
setMenuOptions(this.#name, this.#config);
this.#onChange(option);
};
subscribe = (valueName, fn) => {
this.#subscribers[valueName] = fn;
};
subscribeAll = (fn) => {
this.#allSubscribers.push(fn);
};
/** Called only from back */
@ -116,24 +142,64 @@ module.exports.PluginConfig = class PluginConfig {
setOptions(this.#name, this.#config);
}
#onChange(valueName, single = true) {
this.#subscribers[valueName]?.(this.#config[valueName]);
if (single) this.#allSubscribers.forEach((fn) => fn(this.#config));
}
#setupFront() {
if (process.type === "renderer") {
const ignoredMethods = ['subscribe', 'subscribeAll'];
if (process.type === 'renderer') {
for (const [fnName, fn] of Object.entries(this)) {
if (typeof fn !== "function") return;
if (typeof fn !== 'function' || fn.name in ignoredMethods) return;
this[fnName] = async (...args) => {
return await ipcRenderer.invoke(
`${this.name}-config-${fnName}`,
...args,
);
};
this.subscribe = (valueName, fn) => {
if (valueName in this.#subscribers) {
console.error(`Already subscribed to ${valueName}`);
}
this.#subscribers[valueName] = fn;
ipcRenderer.on(
`${this.name}-config-changed-${valueName}`,
(_, value) => {
fn(value);
},
);
ipcRenderer.send(`${this.name}-config-subscribe`, valueName);
};
this.subscribeAll = (fn) => {
ipcRenderer.on(`${this.name}-config-changed`, (_, value) => {
fn(value);
});
ipcRenderer.send(`${this.name}-config-subscribe-all`);
};
}
} else if (process.type === "browser") {
} else if (process.type === 'browser') {
for (const [fnName, fn] of Object.entries(this)) {
if (typeof fn !== "function") return;
if (typeof fn !== 'function' || fn.name in ignoredMethods) return;
ipcMain.handle(`${this.name}-config-${fnName}`, (_, ...args) => {
return fn(...args);
});
}
ipcMain.on(`${this.name}-config-subscribe`, (_, valueName) => {
this.subscribe(valueName, (value) => {
sendToFront(`${this.name}-config-changed-${valueName}`, value);
});
});
ipcMain.on(`${this.name}-config-subscribe-all`, () => {
this.subscribeAll((value) => {
sendToFront(`${this.name}-config-changed`, value);
});
});
}
}
};