import { useEffect, useMemo, useState } from "react"; import type React from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { Button } from "@/components/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/dialog"; import { SettingRow } from "@/components/section-card"; import { useConnectionDefaults } from "@/contexts/ConnectionDefaultsContext"; import { CURSOR_STYLES, TERMINAL_FONTS, TERMINAL_THEMES, } from "@/lib/terminal-themes"; import { fromTriState, toTriState, type TerminalDefaults, type TriState, } from "@/lib/connection-defaults"; import { getUserPreferences, parseCustomThemes, type SavedCustomTheme, } from "@/api/open-tabs-api"; const inputClass = "h-8 w-full border border-border bg-background px-2 text-xs outline-none focus:ring-1 focus:ring-ring"; const labelClass = "text-[10px] font-bold uppercase tracking-widest text-muted-foreground"; function Field({ label, children, }: { label: string; children: React.ReactNode; }) { return (
{label} {children}
); } function TriStateSelect({ value, onChange, }: { value?: boolean; onChange: (value: boolean | undefined) => void; }) { const { t } = useTranslation(); return ( ); } export function ConnectionDefaultsSettings() { const { t } = useTranslation(); const defaults = useConnectionDefaults(); const [open, setOpen] = useState(false); const [terminal, setTerminal] = useState({}); const [saving, setSaving] = useState(false); const [savedThemes, setSavedThemes] = useState([]); useEffect(() => { if (!defaults.ready) return; setTerminal(defaults.terminal); }, [defaults.ready, defaults.terminal]); useEffect(() => { if (!open) return; getUserPreferences() .then((prefs) => setSavedThemes(parseCustomThemes(prefs.customThemes))) .catch(() => {}); }, [open]); const configuredCount = useMemo(() => { const count = (source: Record) => Object.values(source).filter((value) => value !== undefined).length; return count(defaults.terminal); }, [defaults.terminal]); const updateTerminal = ( key: K, value: TerminalDefaults[K], ) => setTerminal((current) => ({ ...current, [key]: value })); const applySavedTheme = (id: string) => { if (!id) return; const theme = savedThemes.find((entry) => entry.id === id); if (!theme) return; setTerminal((current) => ({ ...current, theme: "custom", customThemeColors: { ...theme.colors }, })); }; async function save() { setSaving(true); try { await defaults.saveTerminalDefaults(terminal); toast.success(t("newUi.sidebar.connectionDefaults.saved")); setOpen(false); } catch { toast.error(t("newUi.sidebar.connectionDefaults.saveFailed")); } finally { setSaving(false); } } const inheritLabel = t("newUi.sidebar.connectionDefaults.inherit"); return ( <> 0 ? String(configuredCount) : undefined} > {t("newUi.sidebar.connectionDefaults.title")} {t("newUi.sidebar.connectionDefaults.dialogDescription")}{" "} {t("hosts.docsLink")}
{savedThemes.length > 0 && ( )} updateTerminal( "fontSize", e.target.value ? Number(e.target.value) : undefined, ) } /> updateTerminal( "lineHeight", e.target.value ? Number(e.target.value) : undefined, ) } /> updateTerminal( "scrollback", e.target.value ? Number(e.target.value) : undefined, ) } />
updateTerminal("cursorBlink", value)} />
); }