fix(frontend,plugins): évite le crash sur install/uninstall/reinstall par rechargement systématique de la liste (#120)
- usePlugins.ts: remplace les mises à jour optimistes du state par des appels listPlugins() après chaque opération backend - PluginsPanel.tsx: ajoute la normalisation isInstallable() pour éviter les crashes si installable est undefined - Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -217,11 +217,13 @@ export function PluginsPanel() {
|
||||
<ConfirmDialog
|
||||
title={`Installer "${installFlow.review.displayName}" ?`}
|
||||
body={reviewSummary(installFlow.review)}
|
||||
confirmLabel={installFlow.review.installable ? "Installer" : "Corriger avant d'installer"}
|
||||
confirmLabel={
|
||||
isInstallable(installFlow.review) ? "Installer" : "Corriger avant d'installer"
|
||||
}
|
||||
busy={vm.busy}
|
||||
danger={!installFlow.review.installable}
|
||||
danger={!isInstallable(installFlow.review)}
|
||||
onConfirm={() => {
|
||||
if (installFlow.review.installable) void confirmInstall();
|
||||
if (isInstallable(installFlow.review)) void confirmInstall();
|
||||
else setInstallFlow(null);
|
||||
}}
|
||||
onCancel={() => setInstallFlow(null)}
|
||||
@ -259,7 +261,13 @@ function reviewSummary(review: PluginReview): string {
|
||||
review.description ?? null,
|
||||
`Confiance : full-trust — ce plugin peut exécuter du code arbitraire dans IdeA.`,
|
||||
`Contributions : ${c.topLevelMenus} menu(s), ${c.menuItems} item(s), ${c.layouts} layout(s), ${c.mcpServers} serveur(s) MCP.`,
|
||||
...review.issues.map((i) => `${i.severity === "error" ? "Erreur" : "Avertissement"} : ${i.message}`),
|
||||
...(review.issues ?? []).map(
|
||||
(i) => `${i.severity === "error" ? "Erreur" : "Avertissement"} : ${i.message}`,
|
||||
),
|
||||
].filter((p): p is string => Boolean(p));
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
function isInstallable(review: PluginReview): boolean {
|
||||
return review.installable ?? true;
|
||||
}
|
||||
|
||||
@ -86,8 +86,8 @@ export function usePlugins(): PluginsViewModel {
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await plugin.installFromArchive(path);
|
||||
setPlugins((prev) => [...prev.filter((p) => p.id !== result.plugin.id), result.plugin]);
|
||||
await plugin.installFromArchive(path);
|
||||
setPlugins(await plugin.listPlugins());
|
||||
return true;
|
||||
} catch (e) {
|
||||
setError(describe(e));
|
||||
@ -104,8 +104,8 @@ export function usePlugins(): PluginsViewModel {
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
const result = await plugin.installFromDirectory(path);
|
||||
setPlugins((prev) => [...prev.filter((p) => p.id !== result.plugin.id), result.plugin]);
|
||||
await plugin.installFromDirectory(path);
|
||||
setPlugins(await plugin.listPlugins());
|
||||
return true;
|
||||
} catch (e) {
|
||||
setError(describe(e));
|
||||
@ -122,8 +122,8 @@ export function usePlugins(): PluginsViewModel {
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
const updated = await plugin.setEnabled(pluginId, enabled);
|
||||
setPlugins((prev) => prev.map((p) => (p.id === pluginId ? updated : p)));
|
||||
await plugin.setEnabled(pluginId, enabled);
|
||||
setPlugins(await plugin.listPlugins());
|
||||
} catch (e) {
|
||||
setError(describe(e));
|
||||
} finally {
|
||||
@ -139,7 +139,7 @@ export function usePlugins(): PluginsViewModel {
|
||||
setError(null);
|
||||
try {
|
||||
await plugin.uninstall(pluginId);
|
||||
setPlugins((prev) => prev.filter((p) => p.id !== pluginId));
|
||||
setPlugins(await plugin.listPlugins());
|
||||
} catch (e) {
|
||||
setError(describe(e));
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user