import { CircleSlash } from "lucide-react"; import { useTranslation } from "react-i18next"; import { Button } from "@/components/button"; import { usePermissions } from "@/hooks/use-permissions"; import { pluginName } from "@/lib/plugin-i18n"; import { OPEN_PLUGINS_EVENT } from "@/plugins/open-plugins"; import { usePluginStore } from "./plugin-store"; import { unregisteredViewStatus, type ViewKind } from "./view-ownership"; /** * Stands in for a tab, panel or card whose plugin is not running. * * A saved tab of a plugin that was switched off or removed must neither crash * the shell nor vanish without a word, so it renders this until the plugin is * back, at which point the real view takes over in place. */ export function PluginViewPlaceholder({ kind, viewId, compact = false, }: { kind: ViewKind; viewId: string; compact?: boolean; }) { const { t } = useTranslation(); // Subscribing re-renders this when plugin state changes. usePluginStore(); const { has } = usePermissions(); const { status, owner } = unregisteredViewStatus(kind, viewId); const name = owner ? pluginName(t, owner.summary) : viewId; if (status === "loading") { return (
); } const title = status === "failed" ? t("plugins.runtime.failed", { name }) : owner ? t("plugins.runtime.needsPlugin", { name }) : t("plugins.runtime.needsUnknownPlugin"); const hint = status === "failed" ? t("plugins.runtime.failedHint") : status === "disabled" ? t("plugins.runtime.disabledHint") : t("plugins.runtime.missingHint"); return (
{title} {hint} {!compact && status !== "failed" && has("admin.plugins.manage") && ( )}
); }