Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/improsocial/impro
An extensible Bluesky client for web impro.social
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156import { Signal, ReactiveStore, ComputedMap } from "/js/signals.js";import { Permissions } from "/js/plugins/pluginPermissions.js";import { unique } from "/js/utils.js";
// Sanitizes stored user-granted origins into canonical fetch patterns. The// installed-plugins list lives in the user's preferences record, we need to// sanitize before using it.function parseGrantedOrigins(origins) { if (!Array.isArray(origins)) return []; return unique(origins.map(Permissions.normalizeFetchOrigin).filter(Boolean));}
// Handles persisting plugin settings in user preferencesexport class PluginPreferencesManager extends ReactiveStore { constructor(preferencesProvider) { super("pluginPreferencesManager"); this.preferencesProvider = preferencesProvider; this.$installedPlugins = new Signal.Computed( () => preferencesProvider.$preferences.get()?.getInstalledPlugins() ?? [], ); this.$enabledPlugins = new Signal.Computed(() => this.$installedPlugins.get().filter((entry) => entry.enabled), ); this.$installedPlugin = new ComputedMap( (pluginId) => this.$installedPlugins.get().find((entry) => entry.id === pluginId) ?? null, ); }
// The signals above remain empty until preferences load, which is correct for // reactive consumers (they re-run when necessary) but silently wrong for // non-reactive consumers. These methods make sure preferences are loaded first. async getInstalledPlugins() { await this.preferencesProvider.requirePreferences(); return this.$installedPlugins.get(); }
async getEnabledPlugins() { await this.preferencesProvider.requirePreferences(); return this.$enabledPlugins.get(); }
async getInstalledPlugin(pluginId) { await this.preferencesProvider.requirePreferences(); return this.$installedPlugin.get(pluginId); }
async setInstalledPlugins(plugins) { const preferences = await this.preferencesProvider.requirePreferences(); await this.preferencesProvider.updatePreferences( preferences.setInstalledPlugins(plugins), ); }
async addInstalledPlugin(plugin) { const installedPlugins = await this.getInstalledPlugins(); await this.setInstalledPlugins([...installedPlugins, plugin]); }
async removeInstalledPlugin(pluginId) { const installedPlugins = await this.getInstalledPlugins(); await this.setInstalledPlugins( installedPlugins.filter((plugin) => plugin.id !== pluginId), ); }
async updateInstalledPlugin(pluginId, updateFunc) { const installedPlugins = await this.getInstalledPlugins(); if (!installedPlugins.some((plugin) => plugin.id === pluginId)) { throw new Error( `Tried to update preference for uninstalled plugin: ${pluginId}`, ); } const updated = installedPlugins.map((plugin) => plugin.id === pluginId ? updateFunc(plugin) : plugin, ); await this.setInstalledPlugins(updated); }
async setPluginDisabled(pluginId) { await this.updateInstalledPlugin(pluginId, (entry) => ({ ...entry, enabled: false, })); }
async setPluginsDisabled(pluginIds) { const ids = new Set(pluginIds); if (ids.size === 0) return; const installedPlugins = await this.getInstalledPlugins(); for (const pluginId of ids) { if (!installedPlugins.some((plugin) => plugin.id === pluginId)) { throw new Error( `Tried to update preference for uninstalled plugin: ${pluginId}`, ); } } const updated = installedPlugins.map((plugin) => ids.has(plugin.id) ? { ...plugin, enabled: false } : plugin, ); await this.setInstalledPlugins(updated); }
async setPluginEnabled(pluginId) { await this.updateInstalledPlugin(pluginId, (entry) => ({ ...entry, enabled: true, })); }
// User-granted fetch origins are kept apart from the manifest permissions. getUserGrantedFetchOrigins(pluginId) { const entry = this.$installedPlugin.get(pluginId); return parseGrantedOrigins(entry?.userGrantedFetchOrigins); }
async addUserGrantedFetchOrigin(pluginId, origin) { await this.updateInstalledPlugin(pluginId, (entry) => { const granted = parseGrantedOrigins(entry.userGrantedFetchOrigins); if (granted.includes(origin)) { return { ...entry, userGrantedFetchOrigins: granted }; } return { ...entry, userGrantedFetchOrigins: [...granted, origin] }; }); }
async removeUserGrantedFetchOrigin(pluginId, origin) { await this.updateInstalledPlugin(pluginId, (entry) => ({ ...entry, userGrantedFetchOrigins: parseGrantedOrigins( entry.userGrantedFetchOrigins, ).filter((granted) => granted !== origin), })); }
async readSettingsForPlugin(pluginId) { const preferences = await this.preferencesProvider.requirePreferences(); return preferences.getPluginSettings(pluginId); }
async writeSettingsForPlugin(pluginId, data) { const preferences = await this.preferencesProvider.requirePreferences(); await this.preferencesProvider.updatePreferences( preferences.setPluginSettings(pluginId, data), ); }
async clearSettingsForPlugin(pluginId) { const preferences = await this.preferencesProvider.requirePreferences(); await this.preferencesProvider.updatePreferences( preferences.clearPluginSettings(pluginId), ); }}