From aee458ce838bc208c6c61106b73e583ec75660bc Mon Sep 17 00:00:00 2001 From: dtoro Date: Mon, 20 Jul 2026 11:00:57 +0200 Subject: [PATCH] feat(web): add windowed Settings app, separate from initial Config screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The taskbar's gear icon reopened the full-page "Connect to Oikos" screen even once already connected. Split that: Config.svelte stays as the first-run/unconfigured screen; a new Settings app (windowed, like Tasks or Operations) now handles in-session changes, with a section list (Connection, Appearance) built to grow — future settings are one more entry, not a new screen. - pages/Settings.svelte: Connection (server URL/token/Authentik, reusing config.ts + oidc.ts) and Appearance (Terracotta/Carbon picker) sections. - apps.ts: registered as a normal desktop app. - Taskbar's gear button now opens the Settings window; removed the onOpenConnection prop threaded through App -> Desktop -> Taskbar, since Settings' "Forget saved connection" (clear config + reload) replaces it. Co-Authored-By: Claude Sonnet 5 --- web/src/App.svelte | 2 +- web/src/lib/apps.ts | 12 ++ .../components/desktop-shell/Desktop.svelte | 4 +- .../components/desktop-shell/Taskbar.svelte | 8 +- web/src/pages/Settings.svelte | 193 ++++++++++++++++++ 5 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 web/src/pages/Settings.svelte diff --git a/web/src/App.svelte b/web/src/App.svelte index 2b74e65..304bd6e 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -62,5 +62,5 @@ /> {:else} - (configured = false)} /> + {/if} diff --git a/web/src/lib/apps.ts b/web/src/lib/apps.ts index e2fb233..8df7806 100644 --- a/web/src/lib/apps.ts +++ b/web/src/lib/apps.ts @@ -15,12 +15,14 @@ import Ops from '../pages/Ops.svelte' import Signals from '../pages/Signals.svelte' import Knowledge from '../pages/Knowledge.svelte' import Learning from '../pages/Learning.svelte' +import Settings from '../pages/Settings.svelte' import ListTodoIcon from '@lucide/svelte/icons/list-todo' import DatabaseIcon from '@lucide/svelte/icons/database' import ShieldCheckIcon from '@lucide/svelte/icons/shield-check' import SirenIcon from '@lucide/svelte/icons/siren' import SearchIcon from '@lucide/svelte/icons/search' import TrendingUpIcon from '@lucide/svelte/icons/trending-up' +import SettingsIcon from '@lucide/svelte/icons/settings' export interface AppDef { id: string @@ -99,6 +101,16 @@ export const APPS: AppDef[] = [ height: 600, minWidth: 440, minHeight: 340 + }, + { + id: 'settings', + title: 'Settings', + icon: SettingsIcon, + component: Settings, + width: 640, + height: 480, + minWidth: 480, + minHeight: 360 } ] diff --git a/web/src/lib/components/desktop-shell/Desktop.svelte b/web/src/lib/components/desktop-shell/Desktop.svelte index ea65339..05092f2 100644 --- a/web/src/lib/components/desktop-shell/Desktop.svelte +++ b/web/src/lib/components/desktop-shell/Desktop.svelte @@ -21,8 +21,6 @@ import Undo2Icon from '@lucide/svelte/icons/undo-2' import Redo2Icon from '@lucide/svelte/icons/redo-2' - let { onOpenConnection }: { onOpenConnection: () => void } = $props() - // Clicking the bare desktop (not an icon, not a window) blurs the focused // window — the familiar "click empty desktop to deselect" affordance. function onSurfaceClick(e: MouseEvent) { @@ -104,7 +102,7 @@ - + {#if menuPos} diff --git a/web/src/lib/components/desktop-shell/Taskbar.svelte b/web/src/lib/components/desktop-shell/Taskbar.svelte index 49604d1..f51125d 100644 --- a/web/src/lib/components/desktop-shell/Taskbar.svelte +++ b/web/src/lib/components/desktop-shell/Taskbar.svelte @@ -6,7 +6,7 @@ // to the old MinimizedWindowsBar, which only ever showed minimized windows // and gave no way to see/switch between windows that were merely // unfocused), plus a system tray for theme/connection/version. - import { wm, wmState, toggleShowDesktop } from '$lib/stores/windows' + import { wm, wmState, toggleShowDesktop, openAppWindow } from '$lib/stores/windows' import { appById, appIdFromWindowId } from '$lib/apps' import { summary } from '$lib/stores/context' import { truncateMiddle } from '$lib/utils' @@ -19,8 +19,6 @@ import LayoutGridIcon from '@lucide/svelte/icons/layout-grid' import XIcon from '@lucide/svelte/icons/x' - let { onOpenConnection }: { onOpenConnection: () => void } = $props() - const SESSION_PREFIX = 'session:' const buttons = $derived( @@ -121,8 +119,8 @@ diff --git a/web/src/pages/Settings.svelte b/web/src/pages/Settings.svelte new file mode 100644 index 0000000..e2dd5e2 --- /dev/null +++ b/web/src/pages/Settings.svelte @@ -0,0 +1,193 @@ + + +
+
+ + +
+ {#if section === 'connection'} +
+
+

Connection

+

Where the control room talks to your Oikos server.

+
+ + {#if oidcUser} +

+ Signed in via Authentik as {oidcUser} +

+ {/if} + +
+ +
+ + +
+
+ + + +
+ + or use + +
+ +
{ e.preventDefault(); save() }}> +
+ + +
+ +
+ + {#if error} +

{error}

+ {/if} + + {#if existing.token || oidcConfigured} +
+ +
+ {/if} +
+ {:else if section === 'appearance'} +
+
+

Appearance

+

Pick the theme for the whole desktop.

+
+ +
+ {#each Object.entries(THEME_LABELS) as [id, label] (id)} + + {/each} +
+
+ {/if} +
+
+ +
Oikos {VERSION}
+