From 49fc3b2e1913ab5c2c9eb4203b00a670522c5a36 Mon Sep 17 00:00:00 2001 From: Arjun <6592213+arkml@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:31:29 +0530 Subject: [PATCH] added settings page --- .../src/components/settings-dialog.tsx | 125 +++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) 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 ( +
+ + Loading... +
+ ) + } + + return ( +
+
+

Lookback period

+

+ How far back to sync emails and meetings +

+ +
+
+

Note strictness

+

+ Controls what qualifies for creating a note +

+ +
+
+ ) +} + // --- Model Settings UI --- type LlmProviderFlavor = "openai" | "anthropic" | "google" | "openrouter" | "aigateway" | "ollama" | "openai-compatible" @@ -473,6 +587,7 @@ export function SettingsDialog({ children }: SettingsDialogProps) { const activeTabConfig = tabs.find((t) => t.id === activeTab)! const isJsonTab = activeTab === "mcp" || activeTab === "security" + const isCustomTab = activeTab === "models" || activeTab === "appearance" || activeTab === "preferences" const formatJson = (jsonString: string): string => { try { @@ -483,7 +598,7 @@ export function SettingsDialog({ children }: SettingsDialogProps) { } const loadConfig = useCallback(async (tab: ConfigTab) => { - if (tab === "appearance" || tab === "models") return + if (tab === "appearance" || tab === "models" || tab === "preferences") return const tabConfig = tabs.find((t) => t.id === tab)! if (!tabConfig.path) return setLoading(true) @@ -589,9 +704,11 @@ export function SettingsDialog({ children }: SettingsDialogProps) { {/* Content */} -
+
{activeTab === "models" ? ( + ) : activeTab === "preferences" ? ( + ) : activeTab === "appearance" ? ( ) : loading ? (