fix(plugins): isole les contributions plugin en erreur et durcit menus.ts
Le chargement de l'archive hello-plugin (build/hello-plugin-0.1.0.zip) vidait la fenêtre principale : une contribution plugin fautive remontait jusqu'au rendu global au lieu de rester locale à la cellule. Ajoute un boundary local dans PluginLayoutCellView/PluginLayoutSelectorSection et durcit menus.ts/loader.ts/registry.ts contre les entrées de menu ou contributions malformées. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -10,6 +10,8 @@
|
||||
* calls from inside a plugin component).
|
||||
*/
|
||||
|
||||
import { Component, type ErrorInfo, type ReactNode } from "react";
|
||||
|
||||
import type { CustomPluginLayoutCell, PluginAdmin } from "@/domain";
|
||||
import { useGateways } from "@/app/di";
|
||||
import { usePluginRuntime } from "./PluginRuntimeProvider";
|
||||
@ -25,6 +27,38 @@ interface PluginLayoutCellViewProps {
|
||||
onChooseAnotherLayout: () => void;
|
||||
}
|
||||
|
||||
interface PluginLayoutErrorBoundaryProps {
|
||||
resetKey: string;
|
||||
fallback: ReactNode;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
class PluginLayoutErrorBoundary extends Component<
|
||||
PluginLayoutErrorBoundaryProps,
|
||||
{ hasError: boolean }
|
||||
> {
|
||||
state = { hasError: false };
|
||||
|
||||
static getDerivedStateFromError(): { hasError: boolean } {
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
||||
console.error("[plugin-layout] render failed", error, errorInfo);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: PluginLayoutErrorBoundaryProps): void {
|
||||
if (prevProps.resetKey !== this.props.resetKey && this.state.hasError) {
|
||||
this.setState({ hasError: false });
|
||||
}
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
if (this.state.hasError) return this.props.fallback;
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
export function PluginLayoutCellView({
|
||||
projectId,
|
||||
cell,
|
||||
@ -36,11 +70,11 @@ export function PluginLayoutCellView({
|
||||
const { registry } = usePluginRuntime();
|
||||
const gateways = useGateways();
|
||||
const availability = resolvePluginLayoutAvailability(registry, cell, installedPlugins);
|
||||
const providerDisplayName =
|
||||
registry.get(cell.pluginId)?.displayName ??
|
||||
installedPlugins?.find((p) => p.id === cell.pluginId)?.displayName;
|
||||
|
||||
if (availability !== "available") {
|
||||
const providerDisplayName =
|
||||
registry.get(cell.pluginId)?.displayName ??
|
||||
installedPlugins?.find((p) => p.id === cell.pluginId)?.displayName;
|
||||
return (
|
||||
<PluginLayoutFallback
|
||||
cell={cell}
|
||||
@ -53,21 +87,35 @@ export function PluginLayoutCellView({
|
||||
}
|
||||
|
||||
const Component = registry.layoutComponent(cell.pluginId, cell.layoutType)!;
|
||||
return (
|
||||
<Component
|
||||
projectId={projectId}
|
||||
nodeId={cell.id}
|
||||
layoutType={cell.layoutType}
|
||||
state={cell.state}
|
||||
setState={onStateChange}
|
||||
availability="available"
|
||||
gateways={{
|
||||
project: gateways.project,
|
||||
git: gateways.git,
|
||||
terminal: gateways.terminal,
|
||||
agents: gateways.agent,
|
||||
system: gateways.system,
|
||||
}}
|
||||
const fallback = (
|
||||
<PluginLayoutFallback
|
||||
cell={cell}
|
||||
availability="incompatible"
|
||||
providerDisplayName={providerDisplayName}
|
||||
onOpenPlugins={onOpenPlugins}
|
||||
onChooseAnotherLayout={onChooseAnotherLayout}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<PluginLayoutErrorBoundary
|
||||
resetKey={`${cell.pluginId}:${cell.layoutType}:${cell.id}`}
|
||||
fallback={fallback}
|
||||
>
|
||||
<Component
|
||||
projectId={projectId}
|
||||
nodeId={cell.id}
|
||||
layoutType={cell.layoutType}
|
||||
state={cell.state}
|
||||
setState={onStateChange}
|
||||
availability="available"
|
||||
gateways={{
|
||||
project: gateways.project,
|
||||
git: gateways.git,
|
||||
terminal: gateways.terminal,
|
||||
agents: gateways.agent,
|
||||
system: gateways.system,
|
||||
}}
|
||||
/>
|
||||
</PluginLayoutErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user