diff --git a/apps/x/apps/renderer/src/components/settings-dialog.tsx b/apps/x/apps/renderer/src/components/settings-dialog.tsx index 840b9cf4..844ada8d 100644 --- a/apps/x/apps/renderer/src/components/settings-dialog.tsx +++ b/apps/x/apps/renderer/src/components/settings-dialog.tsx @@ -2,7 +2,7 @@ import * as React from "react" import { useState, useEffect, useCallback } from "react" -import { Server, Key, Shield, Palette, Monitor, Sun, Moon, Loader2, CheckCircle2 } from "lucide-react" +import { Server, Key, Shield, Palette, Monitor, Sun, Moon, Loader2, CheckCircle2, SlidersHorizontal } from "lucide-react" import { Dialog, @@ -22,7 +22,7 @@ import { cn } from "@/lib/utils" import { useTheme } from "@/contexts/theme-context" import { toast } from "sonner" -type ConfigTab = "models" | "mcp" | "security" | "appearance" +type ConfigTab = "models" | "mcp" | "security" | "preferences" | "appearance" interface TabConfig { id: ConfigTab @@ -54,6 +54,12 @@ const tabs: TabConfig[] = [ path: "config/security.json", description: "Configure allowed shell commands", }, + { + id: "preferences", + label: "Knowledge Graph", + icon: SlidersHorizontal, + description: "Configure sync and note creation behavior", + }, { id: "appearance", label: "Appearance", @@ -132,6 +138,114 @@ function AppearanceSettings() { ) } +// --- Preferences Settings UI --- + +function PreferencesSettings({ dialogOpen }: { dialogOpen: boolean }) { + const [lookbackDays, setLookbackDays] = useState<7 | 30 | 90>(30) + const [noteStrictness, setNoteStrictness] = useState<"auto" | "high" | "medium" | "low">("auto") + const [loading, setLoading] = useState(true) + + useEffect(() => { + if (!dialogOpen) return + async function load() { + setLoading(true) + try { + const lookback = await window.ipc.invoke('config:getLookback', null) + setLookbackDays(lookback.days) + } catch (error) { + console.error('Failed to load lookback config:', error) + } + try { + const strictness = await window.ipc.invoke('config:getNoteStrictness', null) + if (strictness.configured) { + setNoteStrictness(strictness.strictness) + } else { + setNoteStrictness("auto") + } + } catch (error) { + console.error('Failed to load note strictness config:', error) + } + setLoading(false) + } + load() + }, [dialogOpen]) + + const handleLookbackChange = useCallback(async (value: string) => { + const days = Number(value) as 7 | 30 | 90 + setLookbackDays(days) + try { + await window.ipc.invoke('config:setLookback', { days }) + toast.success('Lookback period updated') + } catch (error) { + console.error('Failed to save lookback config:', error) + toast.error('Failed to save lookback period') + } + }, []) + + const handleNoteStrictnessChange = useCallback(async (value: string) => { + const strictness = value as "auto" | "high" | "medium" | "low" + setNoteStrictness(strictness) + try { + if (strictness === "auto") { + await window.ipc.invoke('config:resetNoteStrictness', null) + } else { + await window.ipc.invoke('config:setNoteStrictness', { strictness }) + } + toast.success('Note strictness updated') + } catch (error) { + console.error('Failed to save note strictness config:', error) + toast.error('Failed to save note strictness') + } + }, []) + + if (loading) { + return ( +
+ How far back to sync emails and meetings +
+ ++ Controls what qualifies for creating a note +
+ +