import { useState } from 'react'; import { ChevronRight, Logs, MessageSquare, Send, Settings } from 'lucide-react'; import { Button } from '../ui/button'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Separator } from '../ui/separator'; import { cn } from '../../lib/utils'; import { ContactAvatar } from '../ContactAvatar'; import { captureLastViewedConversationFromHash, getReopenLastConversationEnabled, setReopenLastConversationEnabled, } from '../../utils/lastViewedConversation'; import { ThemeSelector } from './ThemeSelector'; import { getLocalLabel, setLocalLabel, type LocalLabel } from '../../utils/localLabel'; import { DISTANCE_UNIT_LABELS, DISTANCE_UNITS, setSavedDistanceUnit, } from '../../utils/distanceUnits'; import { useDistanceUnit } from '../../contexts/DistanceUnitContext'; import { DEFAULT_FONT_SCALE, FONT_SCALE_SLIDER_STEP, MAX_FONT_SCALE, MIN_FONT_SCALE, getSavedFontScale, setSavedFontScale, } from '../../utils/fontScale'; import { getAutoFocusInputEnabled, setAutoFocusInputEnabled } from '../../utils/autoFocusInput'; import { BATTERY_DISPLAY_CHANGE_EVENT, getShowBatteryPercent, setShowBatteryPercent as saveBatteryPercent, getShowBatteryVoltage, setShowBatteryVoltage as saveBatteryVoltage, } from '../../utils/batteryDisplay'; export function SettingsLocalSection({ onLocalLabelChange, className, }: { onLocalLabelChange?: (label: LocalLabel) => void; className?: string; }) { const { distanceUnit, setDistanceUnit } = useDistanceUnit(); const [reopenLastConversation, setReopenLastConversation] = useState( getReopenLastConversationEnabled ); const [localLabelText, setLocalLabelText] = useState(() => getLocalLabel().text); const [localLabelColor, setLocalLabelColor] = useState(() => getLocalLabel().color); const [autoFocusInput, setAutoFocusInput] = useState(getAutoFocusInputEnabled); const [batteryPercent, setBatteryPercent] = useState(getShowBatteryPercent); const [batteryVoltage, setBatteryVoltage] = useState(getShowBatteryVoltage); const [fontScale, setFontScale] = useState(getSavedFontScale); const [fontScaleSlider, setFontScaleSlider] = useState(getSavedFontScale); const [fontScaleInput, setFontScaleInput] = useState(() => String(getSavedFontScale())); const commitFontScale = (nextScale: number) => { const normalized = setSavedFontScale(nextScale); setFontScale(normalized); setFontScaleSlider(normalized); setFontScaleInput(String(normalized)); }; const restoreFontScaleInput = () => { setFontScaleInput(String(fontScale)); }; const handleSliderChange = (nextScale: number) => { setFontScaleSlider(nextScale); setFontScaleInput(String(nextScale)); }; const handleSliderCommit = (nextScale: number) => { commitFontScale(nextScale); }; const handleToggleReopenLastConversation = (enabled: boolean) => { setReopenLastConversation(enabled); setReopenLastConversationEnabled(enabled); if (enabled) { captureLastViewedConversationFromHash(); } }; return (
These settings apply only to this device/browser.
Display a colored banner at the top of the page to identify this instance.
Controls how distances are shown throughout the app.
Battery data updates every 60 seconds and may take up to a minute to appear after connecting.
)}Scales the app's typography for this browser only. The slider moves in 5% steps; the number field accepts any value from 25% to 400%.
Preview alert, message, sidebar, and badge contrast for the selected theme.
Sidebar preview
Section Label
text-[0.625rem] uppercase tracking-wider text-muted-foreground font-medium
a1b2c3d4e5f6...7890abcdef01
text-xs font-mono — keys, identifiers
1h 23m 45s uptime
text-[0.6875rem] font-mono — metadata mono
$ req_status_sync 0xA1B2...
text-sm font-mono — console / code
Muted: bg-muted · Primary: bg-primary/10 · Unread/Mention: bg-badge-*
Standard variants (size sm)
Semantic outline variants
Metric selector pills
cursor-pointer hover:text-primary transition-colors — use role="button" + tabIndex
{title}
{children}Sample text at this size
{label} — {desc}