enhance(frontend): improve plugin management

This commit is contained in:
syuilo 2025-03-09 21:57:56 +09:00
parent 8e3304344f
commit c76afce9a7
5 changed files with 51 additions and 38 deletions

View File

@ -6,6 +6,7 @@
### Client
- Feat: 設定の管理が強化されました
- 自動でバックアップされるように
- Enhance: プラグインの管理が強化されました
### Server
- Fix: プロフィール追加情報で無効なURLに入力された場合に照会エラーを出るのを修正

View File

@ -27,7 +27,7 @@ import { addCustomEmoji, removeCustomEmojis, updateCustomEmojis } from '@/custom
import { prefer } from '@/preferences.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { deckStore } from '@/ui/deck/deck-store.js';
import { launchPlugin } from '@/plugin.js';
import { launchPlugins } from '@/plugin.js';
export async function mainBoot() {
const { isClientUpdated } = await common(() => {
@ -105,9 +105,7 @@ export async function mainBoot() {
removeCustomEmojis(emojiData.emojis);
});
for (const plugin of prefer.s.plugins.filter(p => p.active)) {
launchPlugin(plugin);
}
launchPlugins();
try {
if (prefer.s.enableSeasonalScreenEffect) {

View File

@ -36,10 +36,6 @@ async function install() {
try {
await installPlugin(code.value);
os.success();
nextTick(() => {
unisonReload();
});
} catch (err) {
os.alert({
type: 'error',

View File

@ -94,7 +94,6 @@ import MkButton from '@/components/MkButton.vue';
import MkCode from '@/components/MkCode.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkKeyValue from '@/components/MkKeyValue.vue';
import { unisonReload } from '@/utility/unison-reload.js';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/utility/page-metadata.js';
import { changePluginActive, configPlugin, pluginLogs, uninstallPlugin, reloadPlugin } from '@/plugin.js';
@ -104,9 +103,6 @@ const plugins = prefer.r.plugins;
async function uninstall(plugin: Plugin) {
await uninstallPlugin(plugin);
nextTick(() => {
unisonReload();
});
}
function reload(plugin: Plugin) {
@ -119,9 +115,6 @@ async function config(plugin: Plugin) {
function changeActive(plugin: Plugin, active: boolean) {
changePluginActive(plugin, active);
nextTick(() => {
location.reload();
});
}
const headerActions = computed(() => []);

View File

@ -144,9 +144,12 @@ export async function installPlugin(code: string, meta?: AiScriptPluginMeta) {
prefer.set('plugins', prefer.s.plugins.concat(plugin));
await authorizePlugin(plugin);
await launchPlugin(installId);
}
export async function uninstallPlugin(plugin: Plugin) {
abortPlugin(plugin);
prefer.set('plugins', prefer.s.plugins.filter(x => x.installId !== plugin.installId));
if (Object.hasOwn(store.state.pluginTokens, plugin.installId)) {
await os.apiWithDialog('i/revoke-token', {
@ -158,26 +161,6 @@ export async function uninstallPlugin(plugin: Plugin) {
}
}
export async function configPlugin(plugin: Plugin) {
if (plugin.config == null) {
throw new Error('This plugin does not have a config');
}
const config = plugin.config;
for (const key in plugin.configData) {
config[key].default = plugin.configData[key];
}
const { canceled, result } = await os.form(plugin.name, config);
if (canceled) return;
prefer.set('plugins', prefer.s.plugins.map(x => x.installId === plugin.installId ? { ...x, configData: result } : x));
}
export function changePluginActive(plugin: Plugin, active: boolean) {
prefer.set('plugins', prefer.s.plugins.map(x => x.installId === plugin.installId ? { ...x, active } : x));
}
const pluginContexts = new Map<string, Interpreter>();
export const pluginLogs = ref(new Map<string, string[]>());
@ -217,7 +200,18 @@ function addPluginHandler<K extends keyof HandlerDef>(installId: Plugin['install
pluginHandlers.push({ pluginInstallId: installId, type, ctx });
}
export async function launchPlugin(plugin: Plugin): Promise<void> {
export function launchPlugins() {
for (const plugin of prefer.s.plugins) {
if (plugin.active) {
launchPlugin(plugin.installId);
}
}
}
async function launchPlugin(id: Plugin['installId']): Promise<void> {
const plugin = prefer.s.plugins.find(x => x.installId === id);
if (!plugin) return;
// 後方互換性のため
if (plugin.src == null) return;
@ -254,7 +248,7 @@ export async function launchPlugin(plugin: Plugin): Promise<void> {
);
}
export function reloadPlugin(plugin: Plugin): void {
export function abortPlugin(plugin: Plugin): void {
const pluginContext = pluginContexts.get(plugin.installId);
if (!pluginContext) return;
@ -262,8 +256,39 @@ export function reloadPlugin(plugin: Plugin): void {
pluginContexts.delete(plugin.installId);
pluginLogs.value.delete(plugin.installId);
pluginHandlers = pluginHandlers.filter(x => x.pluginInstallId !== plugin.installId);
}
launchPlugin(plugin);
export function reloadPlugin(plugin: Plugin): void {
abortPlugin(plugin);
launchPlugin(plugin.installId);
}
export async function configPlugin(plugin: Plugin) {
if (plugin.config == null) {
throw new Error('This plugin does not have a config');
}
const config = plugin.config;
for (const key in plugin.configData) {
config[key].default = plugin.configData[key];
}
const { canceled, result } = await os.form(plugin.name, config);
if (canceled) return;
prefer.set('plugins', prefer.s.plugins.map(x => x.installId === plugin.installId ? { ...x, configData: result } : x));
reloadPlugin(plugin);
}
export function changePluginActive(plugin: Plugin, active: boolean) {
prefer.set('plugins', prefer.s.plugins.map(x => x.installId === plugin.installId ? { ...x, active } : x));
if (active) {
launchPlugin(plugin.installId);
} else {
abortPlugin(plugin);
}
}
function createPluginEnv(opts: { plugin: Plugin; storageKey: string }): Record<string, values.Value> {