/** * Settings Page - Standalone settings window content * This component is rendered in a separate Electron window */ import { AppWindow, Cloud, FileType, HardDrive, Keyboard, Palette, Puzzle, Sparkles, TerminalSquare, X } from "lucide-react"; import React, { lazy, Suspense, useCallback, useEffect, useMemo, useState } from "react"; import { useAISettingsState } from "../application/state/useAISettingsState"; import { useAvailableFonts } from "../application/state/fontStore"; import { usePortForwardingState } from "../application/state/usePortForwardingState"; import { useVaultState } from "../application/state/useVaultState"; import { useWindowControls } from "../application/state/useWindowControls"; import { useUpdateCheck } from "../application/state/useUpdateCheck"; import { I18nProvider, useI18n } from "../application/i18n/I18nProvider"; import { sanitizePortForwardingRulesForSync } from "../application/syncPayload"; import type { AppLockGateRenderContext } from "./AppLockGate"; import { toast } from "./ui/toast"; import { SettingsTabContent } from "./settings/settings-ui"; import { SettingsFocusProvider, useSettingsFocus } from "./settings/SettingsFocusContext"; import { SettingsSearchControl } from "./settings/SettingsSearchControl"; import { cancelSettingsFocus, focusSettingsAnchor } from "./settings/settingsFocus"; import { Tabs, TabsList, TabsTrigger } from "./ui/tabs"; import { LazyLoadBoundary } from "./ui/lazy-load-boundary"; import { ExternalMcpApprovalsHost } from "./ai/ExternalMcpApprovalsHost"; import { useExternalMcpGrantPersister } from "./ai/useExternalMcpGrantPersister"; import { setupMcpApprovalBridge } from "../infrastructure/ai/shared/approvalGate"; import { usePluginContributions } from "../application/state/usePluginContributions"; import { PluginContributionHost } from "./plugins/PluginContributionHost"; import { matchesKeyBinding } from "../domain/models"; import { isPrimaryModifierWBinding } from "../application/state/windowCommandClose"; const LazySettingsApplicationTab = lazy(() => import("./SettingsApplicationTab")); const LazySettingsAppearanceTab = lazy(() => import("./settings/tabs/SettingsAppearanceTab")); const LazySettingsFileAssociationsTab = lazy(() => import("./settings/tabs/SettingsFileAssociationsTab")); const LazySettingsShortcutsTab = lazy(() => import("./settings/tabs/SettingsShortcutsTab")); const LazySettingsAITab = lazy(() => import("./settings/tabs/SettingsAITab")); const LazySettingsSyncTab = lazy(() => import("./settings/tabs/SettingsSyncTab")); const LazySettingsTerminalTab = lazy(() => import("./settings/tabs/SettingsTerminalTab")); const LazySettingsSystemTab = lazy(() => import("./settings/tabs/SettingsSystemTab")); const LazySettingsPluginsTab = lazy(() => import("./settings/tabs/SettingsPluginsTab")); const isMac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform); type AITabErrorBoundaryProps = { children: React.ReactNode }; type AITabErrorBoundaryState = { error: Error | null }; class AITabErrorBoundary extends React.Component< AITabErrorBoundaryProps, AITabErrorBoundaryState > { declare props: Readonly; state: { error: Error | null } = { error: null }; static getDerivedStateFromError(error: Error) { return { error }; } render() { if (this.state.error) { return (

AI Settings Error

{this.state.error.message}
{this.state.error.stack}
); } return this.props.children; } } type SettingsState = AppLockGateRenderContext["settings"]; type AppLockState = AppLockGateRenderContext["appLock"]; const settingsTabTriggerClassName = "w-full justify-start gap-2 px-3 py-2 text-sm data-[state=active]:bg-background hover:bg-background/60 rounded-md transition-colors overflow-hidden"; const settingsTabIconClassName = "shrink-0"; const settingsTabLabelClassName = "min-w-0 truncate"; const SettingsTabLoading = ({ value }: { value: string }) => (