feat(ui): add enable/disable toggle to the plugin-list tab
Each expanded plugin card gains an enable/disable button wired to pluginInventory.setEnabled; the tab re-lists after toggling. Adds zh/en copy for the toggle states. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+5
@@ -277,3 +277,8 @@
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.toggle {
|
||||
margin-top: 0.5rem;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
+24
-2
@@ -12,6 +12,8 @@ import css from './PluginInventorySettingsTab.module.css'
|
||||
export interface PluginInventorySettingsTabInjected {
|
||||
/** Read a current Host inventory snapshot. */
|
||||
list: () => Promise<PluginInventorySnapshot>
|
||||
/** Toggle one plugin entry on or off; persists across a restart. */
|
||||
setEnabled: (entryId: PluginInventoryEntry['entryId'], enabled: boolean) => Promise<void>
|
||||
}
|
||||
|
||||
type PluginInventoryEntry = PluginInventorySnapshot['entries'][number]
|
||||
@@ -60,13 +62,14 @@ function matches(entry: PluginInventoryEntry, normalizedQuery: string): boolean
|
||||
.some(value => value.toLocaleLowerCase().includes(normalizedQuery))
|
||||
}
|
||||
|
||||
/** Render the read-only current Loader inventory. */
|
||||
export function PluginInventorySettingsTab({ list, t }: PluginInventorySettingsTabProps): ReactNode {
|
||||
/** Render the current Loader inventory with per-plugin enable/disable. */
|
||||
export function PluginInventorySettingsTab({ list, setEnabled, t }: PluginInventorySettingsTabProps): ReactNode {
|
||||
const catalogId = useId()
|
||||
const [request, setRequest] = useState(0)
|
||||
const [query, setQuery] = useState('')
|
||||
const [expanded, setExpanded] = useState<PluginInventoryEntry['entryId'] | null>(null)
|
||||
const [state, setState] = useState<ViewState>({ status: 'loading' })
|
||||
const [busy, setBusy] = useState<PluginInventoryEntry['entryId'] | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
let current = true
|
||||
@@ -77,6 +80,16 @@ export function PluginInventorySettingsTab({ list, t }: PluginInventorySettingsT
|
||||
return () => { current = false }
|
||||
}, [list, request])
|
||||
|
||||
/** Toggle one entry then re-read the inventory. */
|
||||
const toggle = (entryId: PluginInventoryEntry['entryId'], enabled: boolean): void => {
|
||||
if (busy !== null) return
|
||||
setBusy(entryId)
|
||||
void setEnabled(entryId, enabled).then(
|
||||
() => setRequest(value => value + 1),
|
||||
() => { /* the next list reflects the unchanged state */ },
|
||||
).finally(() => setBusy(null))
|
||||
}
|
||||
|
||||
const normalizedQuery = query.trim().toLocaleLowerCase()
|
||||
const filteredEntries = useMemo(
|
||||
() => state.status === 'ready'
|
||||
@@ -183,6 +196,15 @@ export function PluginInventorySettingsTab({ list, t }: PluginInventorySettingsT
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
<button
|
||||
className={css.toggle}
|
||||
type="button"
|
||||
disabled={busy === entry.entryId}
|
||||
aria-busy={busy === entry.entryId || undefined}
|
||||
onClick={() => { toggle(entry.entryId, !entry.enabled) }}
|
||||
>
|
||||
{busy === entry.entryId ? t('toggling') : entry.enabled ? t('disable') : t('enable')}
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
</li>
|
||||
|
||||
@@ -34,7 +34,13 @@ export function apply(ctx: ClientContext): void {
|
||||
}
|
||||
return result.value
|
||||
}
|
||||
const injected = (): PluginInventorySettingsTabInjected => ({ list })
|
||||
const setEnabled: PluginInventorySettingsTabInjected['setEnabled'] = async (entryId, enabled) => {
|
||||
const result = await ctx.remote.pluginInventory.setEnabled(entryId, enabled)
|
||||
if (!result.ok) {
|
||||
throw new Error(`pluginInventory.setEnabled failed: ${result.error.code}: ${result.error.message}`)
|
||||
}
|
||||
}
|
||||
const injected = (): PluginInventorySettingsTabInjected => ({ list, setEnabled })
|
||||
|
||||
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
||||
name: 'settings.plugins.tab',
|
||||
|
||||
@@ -20,6 +20,9 @@ export const zh = {
|
||||
active: '已挂载',
|
||||
failed: '挂载失败',
|
||||
unloading: '卸载中',
|
||||
enable: '启用',
|
||||
disable: '停用',
|
||||
toggling: '切换中…',
|
||||
} satisfies Record<string, string>
|
||||
|
||||
/** Plugin inventory locale key union. */
|
||||
@@ -45,4 +48,7 @@ export const en = {
|
||||
active: 'Mounted',
|
||||
failed: 'Mount failed',
|
||||
unloading: 'Unloading',
|
||||
enable: 'Enable',
|
||||
disable: 'Disable',
|
||||
toggling: 'Toggling…',
|
||||
} satisfies Record<PluginInventoryLocaleKey, string>
|
||||
|
||||
Reference in New Issue
Block a user