import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Check, Gauge, Layers, RotateCcw, Sparkles, Wrench, } from "lucide-react"; import { Button } from "@/components/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/dialog"; import { useUiPreferencesContext } from "@/contexts/UiPreferencesContext"; import { applyPresetSideEffects } from "@/lib/apply-ui-preset"; import { usePluginStore } from "@/plugin-host/plugin-store"; import { UI_AREA_KEYS, type UiAreaKey, type UiPreset, } from "@/types/ui-preferences"; const SELECTABLE_PRESETS: Exclude[] = [ "simple", "balanced", "advanced", ]; const PRESET_ICONS = { simple: Sparkles, balanced: Gauge, advanced: Wrench, } as const; export function InterfacePresetSettings({ onRunSetupAgain, }: { onRunSetupAgain?: () => void; }) { const { t } = useTranslation(); const ctx = useUiPreferencesContext(); const [pendingPreset, setPendingPreset] = useState | null>(null); const [applying, setApplying] = useState(false); // The chosen preset stays highlighted even once knobs diverge from it -- // the customizations are listed separately below. const activeLabel = ctx?.preferences.preset ?? "balanced"; const pluginStore = usePluginStore(); const customizedAreas = useMemo(() => { if (!ctx) return [] as Array<{ key: string; label: string }>; const overrides = ctx.preferences.overrides as Record< string, Record | undefined >; const core = UI_AREA_KEYS.filter( (area) => Object.keys(overrides[area] ?? {}).length > 0, ).map((area) => ({ key: area as string, label: t(`newUi.sidebar.userProfile.uiArea_${area}`), })); // A plugin's own area is labelled with the plugin's name. const plugins = Object.keys(overrides) .filter( (area) => area.startsWith("plugin:") && Object.keys(overrides[area] ?? {}).length > 0, ) .map((area) => { const pluginId = area.slice("plugin:".length); return { key: area, label: pluginStore.records.get(pluginId)?.summary.name ?? pluginId, }; }); return [...core, ...plugins]; }, [ctx, pluginStore, t]); if (!ctx) return null; async function confirmPreset() { if (!pendingPreset) return; setApplying(true); try { ctx.setPreset(pendingPreset); // Picking a preset is a deliberate reset, so any knob the user had // pinned goes back to following the preset. ctx.clearAllOverrides(); await applyPresetSideEffects(pendingPreset); } finally { setApplying(false); setPendingPreset(null); } } return (

{t("newUi.sidebar.userProfile.interfacePresetDesc")}

{/* Stacked rather than a grid: this panel lives in the sidebar, which can be as narrow as 160px, so side-by-side cards would wrap. */}
{SELECTABLE_PRESETS.map((preset) => { const Icon = PRESET_ICONS[preset]; const active = activeLabel === preset; return ( ); })}
{customizedAreas.length > 0 && (
{t("newUi.sidebar.userProfile.presetOverridesTitle")} {customizedAreas.map((area) => (
{area.label}
))}
)} {onRunSetupAgain && (
{t("newUi.sidebar.userProfile.runSetupAgainDesc")}
)} !open && setPendingPreset(null)} > {t("newUi.sidebar.userProfile.presetConfirmTitle", { preset: pendingPreset ? t(`newUi.sidebar.userProfile.preset_${pendingPreset}`) : "", })} {t("newUi.sidebar.userProfile.presetConfirmDesc")}
); }