diff --git a/src/components/layout/MainLayout.tsx b/src/components/layout/MainLayout.tsx index bb002d8..b47ff72 100644 --- a/src/components/layout/MainLayout.tsx +++ b/src/components/layout/MainLayout.tsx @@ -37,6 +37,7 @@ import { } from '@/stores'; import { collectPluginResourceEntries, + PLUGIN_RESOURCES_REFRESH_EVENT, resolvePluginAssetURL, type PluginResourceEntry, } from '@/features/plugins/pluginResources'; @@ -449,7 +450,12 @@ export function MainLayout() { void loadPluginResources(); }, 0); - return () => window.clearTimeout(timer); + window.addEventListener(PLUGIN_RESOURCES_REFRESH_EVENT, loadPluginResources); + + return () => { + window.clearTimeout(timer); + window.removeEventListener(PLUGIN_RESOURCES_REFRESH_EVENT, loadPluginResources); + }; }, [apiBase, loadPluginResources]); const pluginResourceGroups = pluginResources.reduce< diff --git a/src/features/plugins/PluginResourcePage.tsx b/src/features/plugins/PluginResourcePage.tsx index ab6e885..3831caa 100644 --- a/src/features/plugins/PluginResourcePage.tsx +++ b/src/features/plugins/PluginResourcePage.tsx @@ -9,6 +9,7 @@ import { getErrorMessage, isRecord } from '@/utils/helpers'; import type { PluginListResponse } from '@/types'; import { collectPluginResourceEntries, + PLUGIN_RESOURCES_REFRESH_EVENT, resolvePluginAssetURL, } from './pluginResources'; import styles from './PluginResourcePage.module.scss'; @@ -78,6 +79,14 @@ export function PluginResourcePage() { void loadResource(); }, [loadResource]); + useEffect(() => { + window.addEventListener(PLUGIN_RESOURCES_REFRESH_EVENT, loadResource); + + return () => { + window.removeEventListener(PLUGIN_RESOURCES_REFRESH_EVENT, loadResource); + }; + }, [loadResource]); + const resource = useMemo(() => { const entries = collectPluginResourceEntries(data?.plugins ?? []); return entries.find((entry) => entry.pluginID === pluginID && entry.menuIndex === menuIndex); diff --git a/src/features/plugins/PluginsPage.tsx b/src/features/plugins/PluginsPage.tsx index 676636c..ebf372c 100644 --- a/src/features/plugins/PluginsPage.tsx +++ b/src/features/plugins/PluginsPage.tsx @@ -27,7 +27,11 @@ import type { PluginListEntry, PluginListResponse, } from '@/types'; -import { getPluginTitle, resolvePluginAssetURL } from './pluginResources'; +import { + getPluginTitle, + notifyPluginResourcesChanged, + resolvePluginAssetURL, +} from './pluginResources'; import styles from './PluginsPage.module.scss'; type PluginDraftValue = string | boolean | string[]; @@ -376,6 +380,7 @@ export function PluginsPage() { await pluginsApi.updateEnabled(plugin.id, enabled); clearConfigCache(); await loadPluginsAfterMutation(enabled); + notifyPluginResourcesChanged(); showNotification(t('plugin_management.toggle_success'), 'success'); } catch (err: unknown) { showNotification( @@ -412,6 +417,7 @@ export function PluginsPage() { await loadPluginsAfterMutation( nextConfig.enabled === true && editingPlugin.enabled !== true ); + notifyPluginResourcesChanged(); setEditingPlugin(null); setEditingConfig({}); setDraft(null); diff --git a/src/features/plugins/pluginResources.ts b/src/features/plugins/pluginResources.ts index 75a0383..a271448 100644 --- a/src/features/plugins/pluginResources.ts +++ b/src/features/plugins/pluginResources.ts @@ -1,6 +1,12 @@ import type { PluginListEntry, PluginMenu } from '@/types'; import { normalizeApiBase } from '@/utils/connection'; +export const PLUGIN_RESOURCES_REFRESH_EVENT = 'plugin-resources-refresh'; + +export const notifyPluginResourcesChanged = () => { + window.dispatchEvent(new Event(PLUGIN_RESOURCES_REFRESH_EVENT)); +}; + export interface PluginResourceEntry { pluginID: string; pluginTitle: string; @@ -39,6 +45,8 @@ export const collectPluginResourceEntries = ( plugins: PluginListEntry[] ): PluginResourceEntry[] => plugins.flatMap((plugin) => { + if (!plugin.effectiveEnabled) return []; + const pluginTitle = getPluginTitle(plugin); const pluginLogo = plugin.logo || plugin.metadata?.logo || '';