From 42811c9796f58e1d5c95ab1685500521834f33dd Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 06:45:12 +0000 Subject: [PATCH 1/7] docs: extend launcher module architecture --- context/modules/launcher.md | 859 +++++++++++++++++++++++++++++++++++- 1 file changed, 835 insertions(+), 24 deletions(-) diff --git a/context/modules/launcher.md b/context/modules/launcher.md index 1da9417..4d038cb 100644 --- a/context/modules/launcher.md +++ b/context/modules/launcher.md @@ -2,47 +2,858 @@ ## Crate -`crates/modules/launcher` → package `luna-module-launcher` +```text +crates/modules/launcher +``` + +Package: + +```text +luna-module-launcher +``` + +--- + +# Purpose -## Purpose +The Launcher is Luna's primary command/search surface. -Application discovery, search, ranking, selection and launch intent. The module renders inside the Notch and should be the first module used to validate module hosting. +It renders inside the Notch and should evolve beyond a simple application picker into a provider-based command interface capable of searching and executing multiple categories of actions. -## Responsibilities +The first implementation must remain small enough to validate the module-host architecture before expanding into a full Raycast-like experience. + +Conceptually: ```text -discover desktop applications -normalize application metadata -index/search applications -keyboard navigation -selection +Notch + ↓ hosts +Launcher Module + ↓ +Search Controller + ↓ +Provider Registry + ├── Applications + ├── Windows + ├── Calculator + ├── Files + ├── Commands + ├── Clipboard + └── Web Search +``` + +Only `ApplicationsProvider` is mandatory for the first MVP. + +--- + +# External references + +The Launcher should use existing Linux launchers as architectural and UX references rather than reimplementing every problem without prior art. + +## zlaunch — primary implementation reference + +Repository: + +```text +https://github.com/zortax/zlaunch +``` + +zlaunch is the most directly relevant implementation reference because it combines: + +```text +Rust +GPUI +Wayland +.desktop application discovery +icons +fuzzy search +window switching +calculator +web search +clipboard integration +persistent/daemon-oriented startup optimization +``` + +For Luna, study zlaunch primarily for: + +```text +GPUI composition +keyboard/focus handling +application discovery +.desktop parsing +icon resolution +search flow +result rendering +caching/startup behavior +Wayland-specific launcher behavior +``` + +Do not copy zlaunch's architecture blindly. Luna must preserve its own module/service boundaries and render inside the Notch rather than own an independent launcher surface. + +--- + +## Anyrun — provider architecture reference + +Repository: + +```text +https://github.com/anyrun-org/anyrun +``` + +Anyrun is useful as a conceptual reference for separating query sources into independent providers/plugins. + +The useful idea for Luna is: + +```text +query + ↓ +provider registry + ↓ +providers search independently + ↓ +normalized results + ↓ +ranking/merge + ↓ +UI +``` + +Luna should initially implement this using ordinary statically linked Rust types rather than Anyrun-style dynamic libraries. + +Preferred initial model: + +```rust +Vec> +``` + +Do not introduce a stable plugin ABI, `cdylib`, WASM plugins or runtime crate loading during the initial launcher implementation. + +--- + +## Walker — provider capability reference + +Repository: + +```text +https://github.com/abenz1267/walker +``` + +Walker is useful as a reference for the breadth of providers a Linux launcher can support, including: + +```text +applications +calculator +files +commands +web search +clipboard +symbols +windows +Bluetooth +audio/system actions +``` + +Walker uses a different UI stack, so it should be treated as a feature/architecture reference rather than a rendering implementation reference. + +--- + +## Vicinae — UX/product reference + +Repository: + +```text +https://github.com/vicinaehq/vicinae +``` + +Vicinae should be treated primarily as a UX/product reference for a Raycast-like command launcher. + +Relevant concepts: + +```text +search-first interaction +results + actions +secondary action menus +nested commands/views +keyboard-first navigation +rich result metadata +extensions/providers +``` + +Luna should borrow interaction patterns where useful without coupling itself to Vicinae's C++/Qt implementation or licensing model. + +--- + +# Architectural direction + +The Launcher should be implemented as a provider-oriented search system. + +```text +LauncherModule + │ + ├── QueryController + │ + ├── ProviderRegistry + │ ├── ApplicationsProvider + │ ├── WindowsProvider + │ ├── CalculatorProvider + │ ├── FilesProvider + │ ├── CommandsProvider + │ ├── ClipboardProvider + │ └── WebProvider + │ + ├── Ranking + │ + └── Launcher UI +``` + +This allows Luna to add launcher capabilities without turning `LauncherModule` into a large `match` statement containing unrelated search logic. + +--- + +# Provider contract + +The exact Rust API may evolve, but the conceptual contract should remain close to: + +```rust +pub trait LauncherProvider { + fn id(&self) -> ProviderId; + + fn metadata(&self) -> ProviderMetadata; + + fn search( + &self, + query: &LauncherQuery, + cx: &LauncherContext, + ) -> ProviderSearch; + + fn execute( + &self, + result: &LauncherResult, + action: ResultAction, + cx: &LauncherContext, + ) -> Result<(), LauncherError>; +} +``` + +`ProviderSearch` may be synchronous or asynchronous depending on the provider. + +The abstraction should support: + +```text +fast local providers +async providers +partial results +provider-specific actions +cancellation/stale-query rejection +``` + +Do not force every provider into async if it is unnecessary. + +--- + +# Core launcher types + +Recommended renderer-independent types: + +```rust +struct LauncherQuery { + text: String, + generation: u64, +} + +struct LauncherResult { + id: ResultId, + provider: ProviderId, + title: String, + subtitle: Option, + icon: Option, + score: f32, + actions: Vec, +} + +enum ResultAction { + Primary, + Secondary(ActionId), +} +``` + +These types should not contain GPUI-specific elements. + +The provider owns feature-specific payloads behind typed IDs/internal state rather than stuffing arbitrary infrastructure objects into `LauncherResult`. + +--- + +# Initial providers + +## ApplicationsProvider — MVP + +Responsible for: + +```text +freedesktop .desktop discovery +application metadata normalization +visibility rules +search/indexing +icon references launch intent -icon resolution requests ``` -## Dependencies +Normalize entries into an internal model such as: -Consumes application discovery/execution contracts and shared UI primitives. It must not invoke `hyprctl`, shell commands or desktop entry executables directly from widgets. +```rust +struct ApplicationEntry { + id: ApplicationId, + name: String, + generic_name: Option, + comment: Option, + keywords: Vec, + icon: Option, + executable: ApplicationCommand, +} +``` -## State +The UI must not execute the raw `Exec=` field directly. + +Execution flows through an application execution service: + +```text +Launcher UI + ↓ +LauncherAction::Execute(ApplicationId) + ↓ +ApplicationService + ↓ +validated desktop-entry execution +``` + +--- + +## WindowsProvider — later + +Consumes compositor-neutral window state from the core/compositor port. + +Responsibilities: + +```text +search open windows +show application/window title +focus selected window +optionally expose close/move actions later +``` + +It must not invoke Hyprland IPC directly. + +--- + +## CalculatorProvider — later + +Pure/local provider when possible. + +Responsibilities: + +```text +recognize mathematical expressions +evaluate safely +return copyable result +``` + +Do not shell out to arbitrary interpreters. + +--- + +## FilesProvider — later + +Responsibilities may include: + +```text +filename search +recent files +open containing directory +open selected file +``` + +Filesystem indexing strategy requires a separate decision before implementing broad full-disk indexing. + +--- + +## CommandsProvider — later + +This provider must distinguish safe shell actions from arbitrary command execution. + +Initial scope should favor typed Luna actions: + +```text +open settings +reload config +lock session +power actions +module navigation +``` + +A generic arbitrary-shell-command mode should not be part of the initial launcher. + +--- + +## ClipboardProvider — later + +Consumes a clipboard/history service rather than owning compositor/clipboard protocol clients. + +--- + +## WebProvider — later + +Produces browser/search actions from configured search engines. + +Network fetching should not be required merely to construct a search URL. + +--- + +# Search pipeline + +Recommended flow: + +```text +keyboard input + ↓ +LauncherQuery generation N + ↓ +ProviderRegistry + ↓ +providers + ↓ +normalized LauncherResult stream + ↓ +ranking + deduplication + ↓ +visible result list +``` + +Every new query increments a generation/revision. + +Results from older async searches must be discarded: + +```text +query generation 10 +query generation 11 +provider returns generation 10 +→ discard +``` + +This prevents stale results from replacing newer search state. + +--- + +# Ranking + +Ranking should remain independent from rendering. + +Initial factors may include: + +```text +fuzzy textual score +exact prefix/name match +provider priority +usage frequency +recency +pinned/favorite state +``` + +The first MVP does not need sophisticated learning-to-rank. + +Begin with deterministic fuzzy scoring and add usage/recency only after the base behavior is measured. + +Searchable application fields should include, where available: + +```text +Name +GenericName +Keywords +Comment +``` + +The primary application name should receive greater weight than secondary metadata. + +--- + +# Indexing and caching + +Application discovery should not parse every desktop entry during every keystroke. + +Expected flow: + +```text +startup / service initialization + ↓ +discover desktop entries + ↓ +parse + normalize + ↓ +build application index + ↓ +cache in memory + ↓ +query index repeatedly +``` + +Watch relevant application directories or refresh the index through controlled events where practical. + +Potential sources include the standard XDG application directories rather than hardcoded distro-specific paths. + +--- + +# Icons + +Icon resolution is part of infrastructure/shared asset handling, not arbitrary widget code. + +Flow: + +```text +.desktop Icon value + ↓ +IconRef + ↓ +icon resolver/cache + ↓ +renderable GPUI asset +``` + +Support: + +```text +freedesktop icon themes +absolute icon paths where valid +fallback icon +cache +``` + +The Launcher should not repeatedly walk icon directories during rendering. + +--- + +# UI stack + +The launcher crate is a presentation module and may use: + +```text +GPUI Kit +├── gpui-base behavior +└── gpui-component controls +``` + +Prefer GPUI Kit components directly when they satisfy Luna's requirements. + +Likely useful components/primitives include: + +```text +text input +scroll/list container +virtualized list where necessary +buttons/icon buttons +keyboard/focus helpers +tooltips +overlays/action menus +Presence / motion primitives +``` + +Luna-specific UI should be created only where the launcher requires behavior/appearance not provided cleanly by GPUI Kit. + +--- + +# Suggested crate layout + +```text +crates/modules/launcher/ +├── Cargo.toml +└── src/ + ├── lib.rs + ├── module.rs + ├── state.rs + ├── query.rs + ├── result.rs + ├── ranking.rs + ├── registry.rs + │ + ├── providers/ + │ ├── mod.rs + │ ├── applications.rs + │ ├── windows.rs + │ ├── calculator.rs + │ ├── files.rs + │ ├── commands.rs + │ ├── clipboard.rs + │ └── web.rs + │ + └── ui/ + ├── mod.rs + ├── search_input.rs + ├── results.rs + ├── result_row.rs + └── action_menu.rs +``` + +Do not create all provider files before they are implemented. The structure above is the target shape, not a requirement to scaffold unused code. + +--- + +# State + +Initial module state: + +```rust +struct LauncherState { + query: String, + query_generation: u64, + results: Vec, + selected_index: Option, + status: LauncherStatus, +} +``` + +Possible status: + +```rust +enum LauncherStatus { + Idle, + Searching, + Ready, + Error, +} +``` + +Provider/service state should not be duplicated unnecessarily inside the view state. + +--- + +# Keyboard interaction + +The Launcher is keyboard-first. + +Minimum behavior: + +```text +type → update query +ArrowUp → previous result +ArrowDown → next result +Enter → primary action +Escape → dismiss launcher +Tab / shortcut → action menu later +``` + +Focus ownership remains coordinated through the Notch/FocusManager. + +The Launcher must not independently manipulate Wayland keyboard interactivity. + +--- + +# Notch behavior + +The Launcher renders content inside the Notch. + +The Launcher controls its internal layout but does not own the outer shell geometry. + +```text +Launcher content + ↓ +layout measurement / preferred constraints + ↓ +Notch target size + ↓ +GPUI Kit motion / spring + ↓ +rendered Notch geometry +``` + +The Notch owns: + +```text +outer shape +concave corners +surface size +input region +focus boundary +open/close transition +click-outside dismissal +``` + +The Launcher owns: + +```text +search box +result list +selection +provider results +action UI +``` + +--- + +# Animation + +Use GPUI Kit motion primitives for launcher transitions where appropriate. + +Examples: + +```text +Presence → result/action view enter/exit +transition → opacity +spring → internal layout movement where useful +stagger → optional result appearance, only if it remains performant +``` + +Do not encode semantic launcher state as animation dimensions. + +Example: + +```text +state = SearchResults +``` + +not: + +```text +state.height = 480 +``` + +--- + +# Service boundaries + +The Launcher may consume: + +```text +ApplicationService +CompositorPort +ClipboardService +ConfigPort +Browser/OpenUrl service +future file index service +``` + +Forbidden inside launcher UI/provider rendering code: + +```text +Command::new("hyprctl") +raw Hyprland socket access +raw D-Bus connections +walking system directories during render +executing raw desktop-entry Exec strings from widgets +``` + +Providers should operate through typed services and application actions. + +--- + +# Performance requirements + +The launcher must feel immediate. + +Measure rather than invent hard performance numbers. + +At minimum benchmark: + +```text +first open latency +subsequent open latency +application index construction +query-to-results latency +large application-list behavior +rapid typing / stale async result handling +icon cache behavior +memory stability after repeated opening/closing +``` + +Consider lazy initialization and persistent in-memory indexing where useful. + +A separate daemon is not required initially; Luna itself is already a persistent shell process and can keep launcher indexes warm. + +This is an important difference from standalone launchers that need a daemon merely to achieve fast cold activation. + +--- + +# MVP + +The first Launcher milestone includes only: + +```text +ApplicationsProvider +.desktop discovery +normalized application index +fuzzy search +icons +keyboard navigation +primary application launch action +Escape / click-outside dismissal +Notch resize/animation +``` + +Explicitly defer: + +```text +WindowsProvider +CalculatorProvider +FilesProvider +CommandsProvider +ClipboardProvider +WebProvider +extensions/plugins +provider marketplace +runtime dynamic loading +``` + +The provider architecture should exist from the beginning, but only the application provider needs to be production-ready for the first milestone. + +--- + +# Future UX direction + +Long term, the Launcher may evolve toward a Raycast/Vicinae-style model: ```text query +↓ results -selected index -loading/error state +↓ +primary action +↓ +secondary actions +↓ +subviews / commands ``` -## Notch behavior +Possible examples: -The Launcher reports/render its content layout; the Notch owns the resulting resize and transition. +```text +Firefox +├── Open +├── Open new window +├── Pin +└── Show application info -## MVP +Window result +├── Focus +├── Move to workspace +└── Close -```text -open launcher -type query -navigate results -launch selected application -Escape / click outside dismiss +System command +├── Lock +├── Suspend +└── Power off ``` + +These actions must remain typed application intents, not arbitrary shell command strings. + +--- + +# Invariants + +1. `luna-module-launcher` is an independent module crate. +2. The Notch hosts the Launcher; the Launcher does not own a Wayland surface. +3. The Launcher uses GPUI Kit as its primary UI/component foundation. +4. Search providers are separate from visual rendering. +5. Application execution does not occur directly in widgets. +6. Hyprland-specific operations remain behind compositor contracts. +7. Async provider results from stale queries are discarded. +8. Application metadata is indexed/cached rather than reparsed per keystroke. +9. The first implementation uses statically linked providers, not dynamic plugins. +10. zlaunch is the primary GPUI implementation reference; Anyrun/Walker inform provider architecture; Vicinae informs UX. +11. External projects are references, not architectural authorities. +12. Performance decisions are based on measurements in Luna's persistent-shell environment. From b6919e1bd15c7f797fa3b5150df790d533ab5e02 Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:01:31 +0000 Subject: [PATCH 2/7] docs: expand calendar module architecture --- context/modules/calendar.md | 529 ++++++++++++++++++++++++++++++++++-- 1 file changed, 511 insertions(+), 18 deletions(-) diff --git a/context/modules/calendar.md b/context/modules/calendar.md index 9c5faab..405eab2 100644 --- a/context/modules/calendar.md +++ b/context/modules/calendar.md @@ -6,40 +6,533 @@ ## Purpose -Provide date/calendar information inside the Notch, with room for future agenda integration without coupling the shell to a specific calendar provider. +Provide a **fast calendar surface inside the Notch** for checking dates, seeing the next events and creating simple events without turning the Notch into a full productivity application. -## Responsibilities +The Calendar domain is expected to eventually have both a shell surface and a full application: ```text -current date -month/week navigation -calendar grid -date selection -future agenda/event presentation through ports +Calendar domain +├── luna-module-calendar +│ └── glance + quick actions +└── luna-calendar + └── deep calendar workflow ``` -## Dependencies +The module and future app must share the same calendar data/domain layer rather than maintain separate databases or synchronization logic. -Consumes time/date services and, if introduced later, a calendar/agenda port. Provider-specific APIs must remain outside the module UI. +--- -## State +## Shell vs full app boundary + +The Notch module is optimized for interactions that should take seconds: + +```text +check today +check this month +see upcoming events +jump between dates +quick-create an event +open an existing event summary +``` + +The following belong to a future `luna-calendar` application: + +```text +full day/week/month workspace +hour-by-hour week grid +large multi-calendar sidebar +drag and drop +resize events +advanced recurrence editing +attendee management +meeting scheduling +large event editor +account management +sync diagnostics +``` + +Rule: + +> The module answers “what is happening and what can I do quickly?”. The app owns sustained calendar work. + +--- + +# Reference applications and architecture + +## GNOME Calendar + Evolution Data Server + +GNOME's calendar ecosystem separates the presentation application from Evolution Data Server (EDS), which provides shared calendar/task data access through client libraries such as `libecal` and backend implementations. + +Useful lesson for Luna: + +```text +UI must not own remote calendar protocols +UI talks to calendar service/domain +backend owns storage/sync/provider details +``` + +EDS also exposes client-side views/change notifications, reinforcing the event-driven model Luna should use instead of making the calendar UI repeatedly query remote services. + +References: + +- https://gnome.pages.gitlab.gnome.org/evolution-data-server/libecal/ +- https://wiki.gnome.org/Apps%282f%29Evolution%282f%29EDS_Architecture.html + +## KDE Merkuro + Akonadi + +Merkuro uses Akonadi as shared PIM infrastructure. Akonadi sits between applications and local/remote resources and provides the core operations required to fetch, create, edit and delete events while keeping remote resources synchronized. + +Merkuro supports local calendars and providers such as Google Calendar, Outlook, Nextcloud and CalDAV without embedding each provider directly into its presentation layer. + +Useful lesson for Luna: + +```text +Calendar UI + ↓ +shared calendar model/cache + ↓ +synchronization resources/adapters + ↓ +remote services +``` + +Luna should adopt the separation, but with a smaller Rust-native local-first implementation rather than reproducing Akonadi as a general PIM server. + +References: + +- https://apps.kde.org/merkuro/ +- https://community.kde.org/KDE_PIM/Akonadi/Architecture +- https://github.com/KDE/merkuro + +--- + +# Target Luna architecture + +The long-term Calendar architecture should be local-first: + +```text +Google Calendar ─────┐ +Microsoft Outlook ───┼── provider adapters +CalDAV / iCloud ─────┘ + │ + ▼ + SyncEngine + │ + ▼ + CalendarRepository + │ + ▼ + SQLite + │ + ▼ + CalendarCore + ├── event queries + ├── mutations + ├── recurrence + └── notifications + │ + ┌────┴───────────┐ + ▼ ▼ +Notch module future app +``` + +The UI should always read from the local repository. Remote APIs update the local store through synchronization. + +This gives Luna: + +```text +instant local reads +offline operation +one source of truth +shared data between shell and app +provider-independent UI +``` + +--- + +# Proposed shared calendar crates + +The calendar module itself should not eventually contain all calendar infrastructure. + +A likely split is: + +```text +crates/ +├── calendar-core/ +│ ├── models +│ ├── recurrence +│ ├── repository contracts +│ └── sync contracts +│ +├── calendar-sqlite/ +│ └── local repository +│ +├── calendar-google/ +├── calendar-microsoft/ +├── calendar-caldav/ +│ +├── modules/calendar/ +│ └── Notch presentation +│ +└── apps/calendar/ # future + └── full calendar UI +``` + +These names are architectural direction, not a requirement to create every crate during the MVP. + +--- + +# Data model + +The domain should use an internal Luna identifier even for remote events. + +Conceptual entities: + +```text +Account +Calendar +Event +Attendee +Reminder +RecurrenceRule +SyncState +``` + +Conceptual `Event` fields: + +```text +id # Luna-owned ID +calendar_id +remote_id # optional provider ID + +title +description +location + +start_at +end_at +timezone +all_day + +recurrence_rule +recurrence_parent + +status +created_at +updated_at + +sync_status +remote_etag +``` + +Never make a Google/Microsoft/CalDAV remote ID the primary domain identity. + +A local-only event must be a first-class event, not a special provider hack. + +--- + +# SQLite persistence + +SQLite is the intended local source of truth. + +Initial conceptual tables: + +```text +accounts +calendars +events +event_attendees +event_reminders +recurrence_rules +sync_state +``` + +The repository layer owns SQL. GPUI widgets must never execute SQL directly. + +Possible flow: + +```text +CalendarModule + ↓ CalendarQuery / CalendarCommand +CalendarCore + ↓ +CalendarRepository + ↓ +SQLite +``` + +--- + +# Provider / synchronization model + +Provider-specific APIs stay behind a common interface. + +Conceptually: + +```rust +trait CalendarProvider { + async fn calendars(&self) -> Result>; + async fn initial_sync(&self, calendar: CalendarId) -> Result; + async fn sync(&self, cursor: SyncCursor) -> Result; + + async fn create_event(&self, event: &Event) -> Result; + async fn update_event(&self, event: &Event) -> Result; + async fn delete_event(&self, event: &Event) -> Result<()>; +} +``` + +Initial target adapters: + +```text +GoogleCalendarProvider +MicrosoftGraphProvider +CalDavProvider +``` + +`CalDavProvider` is strategically important because it can cover iCloud and other standards-based services such as Nextcloud, Fastmail, Radicale and similar servers. + +Synchronization is not UI behavior. A `SyncEngine` owns: + +```text +initial sync +incremental sync +provider cursor/token persistence +offline mutation queue +remote deletion handling +conflict policy +retry/backoff +sync diagnostics +``` + +The UI observes synchronization state through application events. + +--- + +# Difficult calendar semantics + +The architecture must explicitly prepare for: + +```text +recurring events +recurrence exceptions +timezones +DST transitions +all-day events +remote deletions +offline edits +conflicts +provider token invalidation +multiple accounts +multiple calendars +``` + +Do not encode recurrence as “duplicate rows forever”. Preserve recurrence rules and materialize occurrences only where useful for querying/rendering. + +--- + +# Calendar module responsibilities + +`luna-module-calendar` owns only the Notch presentation and local interaction state: ```text visible month selected date -optional agenda data +month navigation +today agenda +upcoming event cards +calendar visibility filters +quick-create UI +quick edit/delete intent +sync-state indicator +Open Calendar action +``` + +It does not own: + +```text +SQLite connection +OAuth tokens +Google API client +Microsoft Graph client +CalDAV client +recurrence engine +background synchronization +``` + +--- + +# State + +Presentation state: + +```text +visible_month +selected_date +selected_event +quick_editor_state +visible_calendar_ids loading/error state ``` -## Notch behavior +Application/domain state is supplied through calendar contracts: + +```text +today events +selected-date events +upcoming events +calendar metadata +sync status +``` + +--- + +# Notch UX + +Recommended expanded surface: + +```text +┌────────────────────────────────┐ +│ September 2026 ‹ › │ +│ M T W T F S S │ +│ 31 1 2 3 4 5 6 │ +│ • •• │ +│ │ +│ Today │ +│ 09:00 Daily │ +│ 13:30 Class │ +│ 18:00 Meeting │ +│ │ +│ + New event Open Calendar │ +└────────────────────────────────┘ +``` + +The module should not reproduce a full seven-column week workspace inside the Notch. + +The Notch owns final geometry, transition animation, input region and dismissal. + +--- + +# GPUI Kit usage + +Use GPUI Kit where appropriate for: + +```text +Button +IconButton +Popover +Dialog / quick editor surface +Input +Select +Checkbox +ScrollView +Tooltip +Presence / motion +``` + +Calendar-specific visual primitives remain Luna-owned: + +```text +MiniMonthGrid +DayCell +AgendaList +EventCard +CalendarDot +``` + +A future full calendar app will add custom structures such as: + +```text +WeekGrid +TimeRuler +EventBlock +MonthGrid +DragResizeController +``` + +--- + +# App integration + +The module should expose an explicit action: + +```text +Open Calendar +``` + +Future behavior: + +```text +CalendarModule + ↓ open_app(Calendar, optional_date/event) +luna-calendar +``` + +The app should accept context from the shell so opening an event or selected date does not lose the user's current intent. + +--- + +# MVP + +## MVP 1 — local Notch calendar + +```text +current month +month navigation +today highlight +selected date +agenda for selected date +SQLite-backed local events +quick-create simple event +quick delete/edit basic fields +``` + +## MVP 2 — synchronization + +Recommended order: + +```text +Google Calendar +Microsoft Outlook / Microsoft 365 +CalDAV / iCloud +``` + +## Later — full Luna Calendar app + +```text +Day view +Week view +Month view +Schedule view +multi-calendar sidebar +drag/drop +resize +advanced recurrence +account management +``` + +--- + +# Completion criteria + +The module is architecturally healthy when: + +- it renders entirely from local/application state; +- it remains usable without a network connection; +- remote provider code is absent from the module crate; +- SQLite access is absent from GPUI widgets; +- the Notch module stays useful without becoming a full calendar workspace; +- the same domain/repository can later serve `luna-calendar` without migration to a second storage model. -The Calendar renders its own content; the Notch owns size, animation, focus and dismissal. +--- -## MVP +# Non-goals for the module ```text -show current month -navigate months -select date -return to current date +full calendar desktop workspace +provider OAuth implementation +raw CalDAV protocol implementation +advanced meeting scheduling +full task manager +complete recurrence editor +per-provider UI logic ``` From 270705d73ebc077bc38e1fb37b984521f5863671 Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:01:57 +0000 Subject: [PATCH 3/7] docs: expand clock module architecture --- context/modules/clock.md | 322 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 303 insertions(+), 19 deletions(-) diff --git a/context/modules/clock.md b/context/modules/clock.md index 4269ea1..b454807 100644 --- a/context/modules/clock.md +++ b/context/modules/clock.md @@ -6,40 +6,324 @@ ## Purpose -Provide time/date presentation and clock-specific interaction inside the Notch while remaining independent from panel placement. +Provide fast access to **current time, date, world clocks, timers and alarms** inside the Notch without turning the shell into a permanently running clock application. -## Responsibilities +The Clock module is a shell quick-surface. A future standalone Clock app is optional and only justified if alarm/timer workflows become deep enough to need their own workspace. + +--- + +# Reference applications and architecture + +## GNOME Clocks + +GNOME Clocks separates four user-facing capabilities: + +```text +World +Alarm +Stopwatch +Timer +``` + +That separation is useful for Luna because these are different state machines rather than one generic "clock" feature. + +Useful lesson: + +```text +Clock shell surface +├── time/date presentation +├── world clocks +├── alarm state +├── timer state +└── stopwatch state +``` + +but each capability should own its own state and lifecycle. + +Reference: + +- https://apps.gnome.org/Clocks/ + +--- + +# Shell vs app boundary + +The Notch is appropriate for: + +```text +current time/date +secondary time zones +start/pause/reset timer +start/pause/reset stopwatch +see next alarms +quick alarm creation +``` + +A future standalone app becomes justified only for: + +```text +large alarm management +many world clocks +complex recurring alarms +rich timer presets +long-running activity history +``` + +Unlike Calendar, a Clock app is **not required by default**. Most clock workflows fit naturally inside the shell. + +--- + +# Proposed architecture + +```text +System clock / monotonic clock + │ + ▼ + ClockService + ┌─────┼─────────┐ + │ │ │ + ▼ ▼ ▼ + Timer Alarm Stopwatch + │ │ │ + └─────┴────┬────┘ + ▼ + luna-module-clock + │ + ▼ + Notch +``` + +The module must distinguish wall-clock time from elapsed-duration timing. + +Use: + +```text +wall clock +→ local date/time/timezone display + +monotonic clock +→ timer/stopwatch elapsed duration +``` + +Timer correctness must not depend on frame rate or repeated `sleep(1s)` increments. + +--- + +# Responsibilities + +The module owns: + +```text +current time/date presentation +12h/24h formatting +timezone presentation +world-clock list presentation +timer interaction state +stopwatch interaction state +alarm presentation/quick editing +``` + +The underlying clock/alarm service owns: + +```text +reliable timer deadlines +alarm scheduling +persistence +resume after UI close +suspend/resume reconciliation +system notification trigger +``` + +The module must not keep a long-running timer alive merely because a GPUI view remains mounted. + +--- + +# State model + +Presentation state: + +```text +active_tab +selected_world_clock +alarm_editor_state +``` + +Service/domain state: + +```text +current_datetime +configured_timezones +active_timer +stopwatch_state +alarms +next_alarm +``` + +Conceptual timer state: + +```text +Idle +Running { deadline } +Paused { remaining } +Finished +``` + +Conceptual stopwatch state: + +```text +Idle +Running { started_at, accumulated } +Paused { accumulated } +``` + +These should be derived from timestamps, not mutable counters updated every second. + +--- + +# Persistence + +Simple preferences belong in configuration: + +```text +12h/24h +show_seconds +world clock timezones +``` + +Persistent alarm/timer state should use a dedicated storage abstraction if/when alarms become real system features. + +Do not make `clock.toml` a live database of elapsed milliseconds. + +--- + +# Notifications and background behavior + +Timers and alarms must continue to function after the Notch closes. + +Flow: + +```text +ClockModule + ↓ command +ClockService + ↓ stores deadline +background scheduling + ↓ +deadline reached + ↓ +Notification / alarm event + ↓ +Shell notification + Clock state update +``` + +The UI should subscribe to state changes and periodically repaint display text while visible, but timer truth remains in the service. + +--- + +# Notch UX + +Recommended default expanded layout: + +```text +┌──────────────────────────────┐ +│ 06:42 │ +│ Sunday, September 13 │ +│ │ +│ São Paulo 06:42 │ +│ Tokyo 18:42 │ +│ │ +│ [ Timer ] [ Alarm ] [ ... ] │ +└──────────────────────────────┘ +``` + +Secondary views may use tabs or a segmented control: + +```text +World | Alarm | Stopwatch | Timer +``` + +The Notch owns final size and transitions between these layouts. + +--- + +# GPUI Kit usage + +Useful components: + +```text +Tabs / segmented control +Button +IconButton +Input +Select +Popover +ScrollView +Switch +Tooltip +Presence / transition / spring +``` + +Clock-specific UI remains Luna-owned: + +```text +DigitalClock +WorldClockRow +TimerDial / TimerReadout +StopwatchReadout +AlarmRow +``` + +Animation should never become the source of timing truth. + +--- + +# MVP + +## MVP 1 ```text current time current date -12h/24h formatting -timezone display -optional timer/alarm expansion later +12h/24h preference +optional seconds +correct timezone display ``` -## Dependencies +## MVP 2 -Consumes time/configuration contracts only. The clock module should remain lightweight and must not own a dedicated background process. +```text +world clocks +timer +stopwatch +``` -## State +## MVP 3 ```text -current time snapshot -format preference -timezone preference -optional expanded clock state +alarms +persistence +shell notifications +suspend/resume correctness ``` -## Notch behavior +--- + +# Completion criteria + +- Clock is a standalone module crate. +- timer/stopwatch math uses timestamps rather than frame counters. +- closing the Notch does not cancel background timer/alarm state. +- GPUI widgets do not own background threads solely for timekeeping. +- module remains functional with shell theme/config hot reload. -The module may expose compact and expanded clock views; the Notch owns host resizing and animation. +--- -## MVP +# Non-goals ```text -show current time -show date -respect 12h/24h preference -update without blocking UI +NTP implementation +system timezone configuration +calendar event management +weather +full scheduling suite ``` From 80b9a81258265a4bd11b91ab26a4e77e2d7f5874 Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:02:24 +0000 Subject: [PATCH 4/7] docs: expand player module architecture --- context/modules/player.md | 347 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 331 insertions(+), 16 deletions(-) diff --git a/context/modules/player.md b/context/modules/player.md index 094c186..2bc4d42 100644 --- a/context/modules/player.md +++ b/context/modules/player.md @@ -6,42 +6,357 @@ ## Purpose -Expose active media playback inside the Notch using MPRIS-backed state from the Linux service layer. +Provide fast control over the **currently active media session** inside the Notch. The Player module is a shell controller, not a full music-library application. -## Responsibilities +It should work with any Linux application exposing MPRIS rather than owning playback itself. + +--- + +# Reference applications and architecture + +## MPRIS + +MPRIS defines a common D-Bus interface for media players, including playback state, metadata, position, play/pause, next/previous, seek and player capabilities. + +This is the primary architectural contract Luna should target. + +Reference: + +- https://specifications.freedesktop.org/mpris-spec/latest/ + +## Amberol + +Amberol is intentionally focused on local music playback with a small, direct UI. The useful lesson for Luna is not to overload the shell controller with library-management concerns. + +Reference: + +- https://apps.gnome.org/Amberol/ + +## Elisa + +KDE Elisa separates playback control and library/browsing concerns. Luna should follow the same conceptual boundary: the Notch exposes transport and session state; a future full media app may own collection browsing. + +Reference: + +- https://apps.kde.org/elisa/ + +--- + +# Shell vs app boundary + +The Notch should own quick media actions: ```text -active player selection -track metadata presentation +current track +artist/title/artwork play/pause previous/next -playback state -optional progress/seek when supported +seek +volume shortcut if appropriate +switch active player +``` + +A standalone media application becomes appropriate for: + +```text +music library +album/artist browsing +playlists +queue management +local file import +streaming-provider browsing +lyrics workspace +large queue editing ``` -## Dependencies +Rule: + +> Player module controls an existing media session. A media app owns a media library/workspace. + +--- + +# Target architecture + +```text +MPRIS players + │ D-Bus + ▼ +MediaService +├── player discovery +├── active-player policy +├── metadata normalization +├── capability mapping +└── command dispatch + │ + ▼ +MediaState / MediaPort + │ + ▼ +luna-module-player + │ + ▼ +Notch +``` + +The GPUI module must never open its own D-Bus connection. + +--- + +# Active player policy -Consumes a media/MPRIS port from the service layer. The module must not talk directly to D-Bus from GPUI widgets. +Multiple MPRIS players may exist simultaneously. -## State +Luna needs deterministic selection rules, for example: ```text +1. currently Playing player +2. most recently interacted/changed player +3. user-selected pinned player +4. fallback to first available player +``` + +The exact policy belongs in `MediaService`, not inside the view. + +The UI may expose a player switcher when multiple sessions exist. + +--- + +# Normalized media model + +Provider-specific MPRIS data should be converted into a stable internal model. + +Conceptually: + +```text +MediaPlayer +├── id +├── identity +├── desktop_entry +├── playback_status +├── capabilities +└── metadata + +TrackMetadata +├── track_id +├── title +├── artists[] +├── album +├── artwork_uri +├── length +└── url +``` + +Capabilities should be explicit: + +```text +can_play +can_pause +can_go_next +can_go_previous +can_seek +can_control +``` + +Disabled controls should follow capabilities rather than guessing based on player identity. + +--- + +# Position and progress + +MPRIS position updates should not force an IPC request every frame. + +Recommended model: + +```text +last_position +last_position_timestamp +playback_status +rate + ↓ +derive visible progress locally + ↓ +periodic/event resync +``` + +This keeps the UI smooth while preserving authoritative service state. + +Seeking flow: + +```text +Slider interaction +→ MediaCommand::Seek(...) +→ MediaPort +→ MPRIS adapter +→ service event/state confirmation +``` + +--- + +# Artwork + +Artwork should be loaded asynchronously and cached outside the hot render path. + +Required behavior: + +```text +remote/file URI normalization +async image load +decode/cache +fallback artwork +cancel stale artwork loads when track changes +``` + +The module should not perform synchronous network/file reads during render. + +--- + +# State + +Presentation state: + +```text +expanded/collapsed content state +player switcher open +seek-drag state +artwork loading state +``` + +Service state: + +```text +available players active player track metadata playback status -progress/duration when available +position/duration +capabilities +``` + +--- + +# Notch UX + +Compact expanded view: + +```text +┌────────────────────────────────┐ +│ [art] Song Title │ +│ Artist │ +│ │ +│ ◀ ▶/❚❚ ▶ │ +│ 1:24 ━━━━━━━━━━━━━━━ 3:46 │ +└────────────────────────────────┘ +``` + +Optional richer mode: + +```text +artwork +metadata +transport +seek +output/player switcher +``` + +The Notch owns final host geometry and module transitions. + +--- + +# GPUI Kit usage + +Useful GPUI Kit components: + +```text +Button +IconButton +Slider +Popover +Dropdown / Select +Tooltip +Avatar/Image container +Presence +transition/spring +``` + +Luna-specific components: + +```text +ArtworkView +TrackMetadataView +TransportControls +PlaybackProgress +PlayerSwitcher ``` -## Notch behavior +--- -Compact and expanded layouts are owned by the module; the Notch owns geometry transitions and surface behavior. +# Future full media app -## MVP +A future `luna-music` or `luna-media` should not be required for the Player module to work. + +If created: ```text -show active track -show artist/title +media-core/library +├── Player module +└── full media app +``` + +The Player module remains a controller for system-wide active sessions even when the user plays media in Firefox, Spotify, VLC or another application. + +--- + +# MVP + +## MVP 1 + +```text +MPRIS player discovery +active-player selection +title/artist play/pause previous/next -handle no active player gracefully +no-player state +``` + +## MVP 2 + +```text +artwork +position/duration +seek +multiple-player switcher +``` + +## Later + +```text +output/device shortcuts +volume integration +queue glimpse when exposed +full media app integration +``` + +--- + +# Completion criteria + +- module owns no D-Bus connection; +- MediaService is authoritative for active-player state; +- control availability follows reported capabilities; +- progress remains smooth without polling MPRIS every frame; +- artwork loading does not block rendering; +- no-player and disappearing-player races are handled gracefully. + +--- + +# Non-goals + +```text +music library ownership +streaming service integration +playlist database +audio decoding +playback engine +speaker routing backend ``` From 56be6c34a471076d39d841113c6c417a1ec5036f Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:02:57 +0000 Subject: [PATCH 5/7] docs: expand resources module architecture --- context/modules/resources.md | 408 +++++++++++++++++++++++++++++++++-- 1 file changed, 388 insertions(+), 20 deletions(-) diff --git a/context/modules/resources.md b/context/modules/resources.md index 80cec05..c668b1a 100644 --- a/context/modules/resources.md +++ b/context/modules/resources.md @@ -6,44 +6,412 @@ ## Purpose -Provide a lightweight task-manager/resource view inside the Notch for observing system usage and, later, managing processes through explicit service contracts. +Provide a compact, real-time system resource surface inside the Notch for answering: -## Responsibilities +```text +Is the system under load? +Which resource is saturated? +Which processes are responsible? +``` + +The Notch module is intentionally lighter than a full task-manager application. + +--- + +# Reference applications and architecture + +## Mission Center + +Mission Center is a modern Linux system monitor focused on hardware/resource visualization and process/application usage. Its value as a Luna reference is the split between overview metrics and deeper task-manager views. + +Useful lesson: + +```text +summary first +→ CPU / memory / disk / network / GPU +→ drill into process/application details only when needed +``` + +Reference: + +- https://missioncenter.io/ +- https://github.com/missioncenter-dev/mission-center + +## Resources + +GNOME Resources provides a modern task-manager experience with resource graphs, applications/processes and system information. It reinforces that sampling, aggregation and process control should be separated from presentation. + +Reference: + +- https://apps.gnome.org/Resources/ + +## GNOME System Monitor / KDE System Monitor + +Traditional system monitors provide a useful boundary reference: + +```text +resource overview +process table +process actions +hardware/history views +``` + +For Luna, only the first two belong naturally in the Notch. A complete process-management workspace should become a standalone app if it grows beyond quick inspection. + +--- + +# Shell vs full app boundary + +The Notch should support: ```text CPU usage memory usage +swap GPU usage when available -disk/network activity -process list -sorting/filtering -future process actions through a dedicated port +disk activity +network activity +top CPU processes +top memory processes +quick process search +open full task manager +``` + +A future `luna-resources` / `luna-task-manager` app should own: + +```text +large sortable process table +process tree +per-process details +open files/connections +signals and priority management +historical graphs +hardware details +per-device drill-down +advanced GPU/process data ``` -## Dependencies +Rule: -Consumes system-resource/process ports from the Linux service layer. Widgets must not scrape `/proc`, execute `ps`, or send process signals directly. +> The module diagnoses quickly. The app manages deeply. -## State +--- + +# Target architecture ```text -resource snapshots -process list -sort/filter state -selected process -loading/error state +Linux metrics sources +├── /proc +├── /sys +├── cgroups/systemd where useful +├── GPU-specific adapters +└── network/disk counters + │ + ▼ + ResourceService + ├── sampling + ├── normalization + ├── deltas/rates + ├── process aggregation + └── bounded history + │ + ▼ + ResourceSnapshot / ProcessSnapshot + │ + ▼ + luna-module-resources + │ + ▼ + Notch ``` -## Notch behavior +The service layer owns data collection. The module owns only presentation and user interaction. + +--- -This module may require one of the largest Notch layouts. The module owns content/layout intent; the Notch owns final geometry transitions and surface/input semantics. +# Sampling model -## MVP +Many Linux counters are cumulative, so values such as CPU, disk and network activity must be derived from deltas between samples. + +Conceptual flow: + +```text +sample N-1 +sample N + ↓ +delta / elapsed time + ↓ +normalized rate +``` + +The module must not compute these deltas independently for each widget. + +Sampling cadence should be bounded and configurable internally. A reasonable design is: + +```text +visible module +→ higher refresh cadence + +module hidden +→ reduced cadence or summary-only collection +``` + +Do not tie collection frequency to GPUI frame rate. + +--- + +# Data model + +Conceptual snapshot: + +```text +ResourceSnapshot +├── timestamp +├── cpu +├── memory +├── swap +├── disks[] +├── network[] +├── gpus[] +└── processes[] +``` + +Conceptual process model: + +```text +ProcessSnapshot +├── pid +├── parent_pid +├── name +├── executable +├── command +├── cpu_percent +├── memory_bytes +├── read_rate +├── write_rate +├── user +└── state +``` + +The domain should use typed values/units rather than passing raw formatted strings from the collector. + +--- + +# Process grouping + +Linux desktop process trees often contain many helper processes. Luna should eventually support two views: + +```text +Applications +→ aggregate processes belonging to the same desktop application + +Processes +→ raw process-level view +``` + +The Notch MVP can begin with top processes and defer sophisticated application grouping. + +--- + +# GPU metrics + +GPU support must be capability-based because Linux exposes different data by vendor/driver. + +Conceptually: + +```text +GpuMetricsPort +├── AMD adapter +├── Intel adapter +└── NVIDIA adapter +``` + +A missing metric is represented as unavailable, not as zero. + +The Resources module must degrade gracefully on systems where GPU utilization/temperature cannot be read. + +--- + +# Process actions + +Process control is a separate privileged/sensitive command path. + +Forbidden in widgets: + +```text +kill(pid) +Command::new("kill") +renice +raw signal calls +``` + +Instead: + +```text +ResourcesModule +→ ProcessCommand::Terminate(pid) +→ ProcessControlPort +→ Linux adapter +``` + +Actions such as kill/stop/renice should be outside the first Notch MVP and should require explicit confirmation when added. + +--- + +# State + +Presentation state: + +```text +selected_metric +active_tab +sort_key +filter_text +selected_process +history_window +``` + +Service state: + +```text +latest resource snapshot +bounded metric history +process snapshots +collector capabilities +``` + +--- + +# Notch UX + +Recommended default view: + +```text +┌──────────────────────────────────┐ +│ Resources │ +│ CPU 23% ━━━━━━━ │ +│ Memory 61% ━━━━━━━━━━━ │ +│ GPU 14% ━━━ │ +│ │ +│ Top processes │ +│ firefox 12% 1.8GB │ +│ code 8% 1.2GB │ +│ cargo 4% 420MB │ +│ │ +│ Open Task Manager │ +└──────────────────────────────────┘ +``` + +Optional tabs: + +```text +Overview | Processes +``` + +Avoid putting a giant desktop process table inside the Notch. + +--- + +# GPUI Kit usage + +Useful components: + +```text +Tabs +Progress +ScrollView +Table/List +Input +Dropdown +Tooltip +Popover +Button +Badge +``` + +Luna-specific visualization components: + +```text +MetricGraph +ResourceBar +ProcessRow +Sparkline +UsageLegend +``` + +Graphs should use bounded histories and avoid allocating a new unbounded data structure every sample. + +--- + +# Future full app + +A future task-manager application should reuse the exact same `ResourceService` and process models: + +```text +ResourceService + │ + ┌────┴──────────┐ + ▼ ▼ +Notch module full task manager +``` + +The full app may add process tree, hardware panels and destructive process actions without moving those responsibilities into the shell module. + +--- + +# MVP + +## MVP 1 ```text CPU usage memory usage -process list -sort by CPU/memory -periodic event-driven or bounded sampling +swap +top processes by CPU +top processes by memory +bounded refresh +``` + +## MVP 2 + +```text +network activity +disk activity +GPU metrics where available +small metric history graphs +process filtering +``` + +## Later + +```text +application grouping +process actions +full task-manager app +process tree +hardware details +``` + +--- + +# Completion criteria + +- no `/proc` or `/sys` reads occur from GPUI render code; +- sampling is independent from frame rendering; +- cumulative counters are converted to rates centrally; +- hidden/visible module state can influence sampling cost without losing correctness; +- unavailable GPU/system capabilities degrade cleanly; +- process actions, when introduced, flow through an explicit port. + +--- + +# Non-goals + +```text +full htop replacement inside the Notch +kernel profiler +perf/eBPF frontend +process debugger +systemd service manager +hardware overclocking controls ``` From fc2c57d09e48ddf08be1a0dee9b61e4c4e119de0 Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:03:31 +0000 Subject: [PATCH 6/7] docs: expand settings module architecture --- context/modules/settings.md | 457 ++++++++++++++++++++++++++++++++++-- 1 file changed, 435 insertions(+), 22 deletions(-) diff --git a/context/modules/settings.md b/context/modules/settings.md index 15d35e2..df4e04c 100644 --- a/context/modules/settings.md +++ b/context/modules/settings.md @@ -6,41 +6,454 @@ ## Purpose -Expose shell configuration inside the Notch without making the settings UI the owner of configuration storage. +Provide **quick access to the most important Luna preferences inside the Notch** without making the Notch the complete desktop settings application. -## Responsibilities +The Settings module is a controller over validated configuration and service capabilities. It does not own TOML parsing, persistence, D-Bus clients, compositor IPC or system configuration backends. + +--- + +# Reference applications and architecture + +## KDE System Settings / KCM + +KDE System Settings is built around independent configuration modules (KCMs). Each settings area has a focused responsibility while the host application handles navigation, loading and presentation. + +Useful lesson for Luna: + +```text +Settings host +├── Appearance +├── Input +├── Network +├── Bluetooth +├── Power +└── ... +``` + +should be composed from capability-specific settings sections rather than one giant controller with direct system calls. + +Reference: + +- https://develop.kde.org/docs/features/configuration/kcm/ + +## GNOME Control Center + +GNOME Control Center similarly separates settings into panels backed by system services and configuration APIs. The UI is not the source of truth; it reflects and changes external settings through defined backends. + +Useful lesson: + +```text +settings presentation +→ typed settings/service API +→ authoritative backend +``` + +rather than: + +```text +settings widget +→ arbitrary filesystem/CLI mutation +``` + +--- + +# Shell vs full app boundary + +The Notch module should expose settings that are frequently toggled or adjusted quickly: + +```text +appearance shortcut +module enable/disable +animation toggle +compact theme options +clock format +basic panel/notch behavior +key preference shortcuts +quick network/bluetooth/power links +``` + +A future `luna-settings` app should own deeper configuration: + +```text +all modules +all keybindings +accounts +network configuration +Bluetooth pairing details +power profiles +outputs/displays +input devices +advanced compositor options +accessibility +privacy +updates +system information +``` + +Rule: + +> The Notch Settings module is a quick-control surface. The full Settings app is the configuration workspace. + +--- + +# Target architecture + +```text +Config files / system services + │ + ▼ + shell-config + service adapters + │ + ▼ +ValidatedConfig / CapabilityState + │ + ▼ + Settings application commands + │ + ┌────┴────────────┐ + ▼ ▼ +Settings module future Settings app +``` + +The module must never read or write TOML directly. + +--- + +# Settings section model + +The module should not hardcode a monolithic form. Use a typed section model that can grow safely. + +Conceptually: + +```text +SettingsSection +├── General +├── Appearance +├── Modules +├── Input +└── AdvancedShortcuts +``` + +Future full-app-only sections may include: + +```text +Network +Bluetooth +Power +Displays +Accounts +Privacy +Accessibility +``` + +A section should depend only on the capability/contracts it needs. + +--- + +# Configuration flow + +Read path: + +```text +ConfigLoader +→ ValidatedConfig +→ Config snapshot +→ SettingsModule +``` + +Write path: + +```text +user edits draft +→ typed SettingsCommand +→ validation +→ persistent config update +→ filesystem write +→ ConfigWatcher +→ full candidate reload +→ validation +→ atomic snapshot swap +→ ConfigChanged +→ UI rerender +``` + +This preserves a single configuration pipeline. + +The Settings module must not bypass hot reload by mutating live application state and separately writing disk later. + +--- + +# Draft / apply model + +Not all settings need the same commit behavior. + +Classify settings by application mode: + +```text +Immediate +→ safe visual preference; applies as user changes it + +ApplyRequired +→ multiple related values should validate together + +RecreateSurface +→ requires surface geometry/recreation + +RestartService +→ backend must restart/reconnect + +RestartShell +→ architecture/backend selection changed +``` + +Examples: + +```text +theme color → Immediate +clock format → Immediate +notch dimensions → RecreateSurface or validated live update +compositor backend → RestartShell +audio backend → RestartService initially +``` + +The UI should clearly communicate restart/recreate requirements rather than silently pretending every setting is live. + +--- + +# Capability-driven UI + +Settings should appear only when the system/backend supports them. + +Conceptually: + +```text +CompositorCapabilities +LinuxServiceCapabilities +ModuleCapabilities +``` + +Examples: ```text -read current validated config -edit supported user-facing options -validate drafts -apply/revert changes -navigate settings sections +Hyprland-only option +→ shown only when supported by active compositor adapter + +battery settings +→ hidden/disabled on systems without battery/power capability +``` + +Do not expose unavailable settings and then fail after interaction. + +--- + +# Module enablement + +The Settings module should manage the module registry configuration: + +```text +Launcher enabled +Calendar enabled +Player enabled +Resources enabled +Clock enabled +Theme enabled ``` -## Dependencies +Enabling/disabling a module changes configuration, while `shell-app` / application composition decides how the runtime registry reacts. + +The Settings module itself must not instantiate or destroy concrete module crates directly. + +--- -Consumes configuration models and commands from `shell-config`/application ports. The module must not parse TOML files directly or mutate files from widgets. +# State -## State +Presentation state: ```text -active section -configuration draft -validation state -unsaved-change state +active_section +search_query +configuration_draft +validation_errors +dirty_fields +restart_requirements ``` -## Notch behavior +External state: + +```text +validated config snapshot +module registry metadata +compositor capabilities +Linux service capabilities +``` + +--- + +# Notch UX + +Recommended quick settings layout: + +```text +┌────────────────────────────────┐ +│ Settings │ +│ │ +│ Appearance │ +│ Theme Luna Dark > │ +│ Animations [✓] │ +│ │ +│ Modules │ +│ Calendar [✓] │ +│ Player [✓] │ +│ Resources [✓] │ +│ │ +│ Clock │ +│ 24-hour format [✓] │ +│ │ +│ Open Settings │ +└────────────────────────────────┘ +``` + +The Notch should avoid deep navigation trees and very large forms. + +--- + +# Search + +A full Settings application should eventually support search by indexing setting metadata: + +```text +id +section +label +description +keywords +``` + +The Notch module may expose a lightweight search later, but this is not required for the first MVP. + +--- + +# GPUI Kit usage + +Useful components: + +```text +Tabs / navigation +Switch +Checkbox +Select +Slider +Input +SearchInput +Button +Dialog +Popover +Tooltip +Badge +ScrollView +``` + +Luna-specific components: + +```text +SettingsRow +SettingsSectionHeader +RestartRequirementBadge +ModuleToggleRow +CapabilityUnavailableState +``` + +Use GPUI Kit components directly where they fit; do not wrap every component merely to rename it. + +--- + +# Future full Settings app + +A future `luna-settings` app should share: + +```text +configuration models +validation +settings commands +capability models +settings metadata +``` + +with the Notch module. + +It should not fork into a second settings persistence mechanism. + +Architecture: + +```text +Settings domain/contracts + │ + ┌────┴──────────────┐ + ▼ ▼ +Notch quick module luna-settings app +``` + +--- + +# MVP + +## MVP 1 + +```text +general shell preferences +module enable/disable +clock preference +animation preference +link to Theme module +apply/revert where needed +validation feedback +``` + +## MVP 2 + +```text +keybind management +panel/notch behavior +capability-driven compositor settings +restart requirement handling +``` + +## Later / full app + +```text +network +Bluetooth +power +displays +input devices +accounts +privacy +accessibility +system info +``` + +--- + +# Completion criteria + +- GPUI widgets never parse/write TOML; +- all mutations pass through typed configuration/application commands; +- invalid drafts cannot replace the active valid config; +- unavailable capabilities are represented explicitly; +- module enablement is configuration-driven; +- Settings module does not directly instantiate other modules; +- quick settings remain usable without becoming a full control-center workspace. -Settings may use a larger multi-section layout; the Notch owns resizing, focus, dismissal and surface semantics. +--- -## MVP +# Non-goals for the Notch module ```text -general settings -theme entry point -module enable/disable controls -key user preferences -apply/revert +complete GNOME/KDE control-center replacement +raw NetworkManager UI +raw BlueZ UI +Hyprland config-file editor +system package/update manager +user/account administration +arbitrary text editing of TOML ``` From 78564efda4e76604566d999661cc69a4249bfbee Mon Sep 17 00:00:00 2001 From: Braga Date: Sun, 13 Sep 2026 07:04:09 +0000 Subject: [PATCH 7/7] docs: expand theme module architecture --- context/modules/theme.md | 463 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 442 insertions(+), 21 deletions(-) diff --git a/context/modules/theme.md b/context/modules/theme.md index b7e96c7..98e98f3 100644 --- a/context/modules/theme.md +++ b/context/modules/theme.md @@ -6,40 +6,461 @@ ## Purpose -Provide the user-facing theme editor and theme controls inside the Notch. This crate is distinct from `shell-theme`: `shell-theme` defines shared theme models/tokens; `luna-module-theme` is the interactive feature that edits/selects them. +Provide the user-facing **theme selector/editor inside the Notch** while keeping the actual design-system model centralized in `shell-theme`. -## Responsibilities +The Theme module edits and previews shared theme tokens. It does not own a second theme engine, a private color system, or per-module styling rules. + +--- + +# Reference applications and architecture + +## KDE Plasma Global Themes / Look-and-Feel + +KDE Plasma separates appearance into reusable theme/configuration layers such as color schemes, icons, cursors and global themes. A global theme can coordinate multiple visual resources without requiring every application/widget to define its own styling independently. + +Useful lesson for Luna: + +```text +shared visual model +├── colors +├── typography +├── spacing +├── radius +├── motion +├── shadows +└── icons +``` + +and a Theme UI edits/selects that shared model. + +Reference: + +- https://develop.kde.org/docs/plasma/theme/ +- https://develop.kde.org/docs/plasma/look-and-feel/ + +## GNOME appearance / Tweaks model + +GNOME tooling reinforces the distinction between: + +```text +settings UI +→ writes configuration/preferences +→ desktop/toolkit consumes those preferences +``` + +rather than styling each feature directly from the settings widget. + +Useful lesson: + +> Theme editing belongs in a controller surface; rendering consumes the centralized theme state elsewhere. + +--- + +# Shell vs full app boundary + +The Notch Theme module should be optimized for quick changes: + +```text +select installed theme +light/dark preference +accent/color preset +radius preset +motion preference +preview current theme +reset to defaults +``` + +A future full Appearance/Theme app becomes appropriate for: + +```text +full token editor +palette construction +advanced typography +icon/cursor packs +wallpaper integration +import/export theme packs +per-display wallpaper/theme behavior +community themes +full preview workspace +``` + +Rule: + +> The module chooses and tunes. A full appearance app authors and manages theme systems deeply. + +--- + +# Core boundary + +`luna-module-theme` is **not** `shell-theme`. + +```text +shell-theme +├── Theme model +├── semantic tokens +├── validation +├── defaults +└── conversion helpers + │ + ▼ +luna-module-theme +├── selection UI +├── editing UI +├── preview state +└── apply/reset commands +``` + +The module must never become the only place where token definitions exist. + +--- + +# Target architecture + +```text +theme.toml + │ + ▼ +shell-config + │ validated config + ▼ +shell-theme +├── semantic Theme model +├── defaults +└── validation + │ + ├───────────────┐ + ▼ ▼ +shell-ui-gpui Theme module + │ │ + │ translate │ edit/select + ▼ ▼ +GPUI Kit Theme SettingsCommand + │ │ + └───────┬───────┘ + ▼ + application config flow +``` + +This keeps GPUI Kit as presentation infrastructure while `shell-theme` remains renderer-independent. + +--- + +# Semantic tokens + +Luna should use semantic tokens instead of component-specific colors. + +Example: + +```text +background +surface +surface_raised +foreground +foreground_muted +border +accent +accent_foreground +danger +warning +success +``` + +Plus structural tokens: + +```text +spacing +radius +typography +shadows +motion +icons +``` + +Avoid tokens such as: ```text -theme selection -color/token editing -preview state -apply/reset actions -persist theme preferences through configuration ports +launcher_search_bar_gray +calendar_event_blue +player_button_hover ``` -## Dependencies +unless they represent a real reusable semantic role. + +--- -Consumes `shell-theme` models and configuration/application ports. It must not own the global design-system implementation. +# GPUI Kit integration -## State +GPUI Kit is the presentation foundation. + +The preferred dependency direction is: ```text -selected theme -editable token draft -preview state -validation errors +shell-theme + ↓ semantic values +shell-ui-gpui + ↓ conversion +GPUI Kit theme/components ``` -## Notch behavior +`luna-module-theme` may use GPUI Kit components directly for its interface, but edits `shell-theme`/configuration values rather than mutating GPUI Kit internals as the persistent source of truth. + +Conceptually: + +```rust +fn to_gpui_kit_theme(theme: &Theme) -> GpuiKitTheme { + // presentation mapping only +} +``` + +Exact API depends on the pinned GPUI Kit version. + +--- + +# Theme presets + +Themes should have stable metadata: + +```text +id +name +author +version +base_mode +``` + +A preset resolves to validated semantic tokens. + +Initial built-ins might include: + +```text +Luna Dark +Luna Light +System +``` + +The architecture should allow additional presets later without hardcoding each preset into module rendering logic. + +--- + +# Draft and preview model + +Theme editing benefits from temporary preview before persistence. + +Conceptual flow: + +```text +active Theme + ↓ clone +ThemeDraft + ↓ user edits +validated preview + ↓ +live UI preview + ├── Apply → persist through ConfigPort + └── Cancel → restore active Theme +``` + +The preview must still pass validation. Do not let malformed values enter global rendering state. + +If live preview is enabled, every module should update from the same preview snapshot rather than the Theme module locally faking its appearance. + +--- + +# Hot reload + +External edits to `theme.toml` remain supported: + +```text +filesystem event +→ debounce +→ load complete config +→ validate +→ atomic config/theme snapshot +→ ThemeChanged +→ GPUI Kit theme mapping updates +→ shell/modules rerender +``` + +Theme module writes should use the same pipeline instead of introducing a parallel write path. + +--- + +# System integration + +Luna may eventually expose compatibility options for external desktop appearance: + +```text +GTK theme +Qt theme +icon theme +cursor theme +wallpaper +``` + +These are separate system-integration concerns and should not be conflated with Luna's internal design tokens. + +Possible future layering: + +```text +Luna Theme +├── internal shell theme +└── optional system appearance adapters + ├── GTK + ├── Qt + ├── icons + └── cursors +``` + +The internal Luna shell must remain visually coherent even when external app theming cannot be perfectly synchronized. + +--- + +# State + +Presentation state: + +```text +selected_theme_id +ThemeDraft +preview_enabled +active_editor_section +validation_errors +``` + +Application state: + +```text +active validated Theme +available presets +config persistence state +``` + +--- + +# Notch UX + +Recommended quick editor: + +```text +┌────────────────────────────────┐ +│ Appearance │ +│ │ +│ Theme [ Luna Dark ▾]│ +│ Mode [ Dark / Light ] │ +│ Accent ● ● ● ● ● │ +│ Radius [ Compact — Round ]│ +│ Motion ✓ │ +│ │ +│ [Reset] [Apply] │ +│ Open Appearance│ +└────────────────────────────────┘ +``` + +The Notch should prioritize presets and high-value controls over exposing every token. + +--- + +# GPUI Kit components + +Useful directly: + +```text +Select +Tabs +Button +Switch +Slider +Popover +Dialog +Tooltip +ScrollView +Color-related input if available +Presence / transition +``` + +Luna-specific components may include: + +```text +ThemePreview +PaletteSwatch +TokenPreviewRow +ThemePresetCard +MotionPreview +``` + +Do not create wrappers unless Luna needs behavior or styling that cannot be expressed through normal GPUI Kit composition/theming. + +--- + +# Future full Appearance app + +A future `luna-appearance` or expanded `luna-settings` app can provide advanced theme authoring. + +It must reuse: + +```text +shell-theme models +same presets +same validation +same persistence +same preview mechanism +``` + +rather than inventing a separate theme format. + +--- + +# MVP + +## MVP 1 + +```text +Luna Dark / Light selection +accent selection +radius preference +motion enable/disable +live preview +apply/reset +``` + +## MVP 2 + +```text +additional semantic token editing +custom presets +import/export Luna theme file +``` + +## Later + +```text +external GTK/Qt/icon/cursor integration +wallpaper coordination +community/theme gallery +full appearance editor +``` + +--- + +# Completion criteria + +- `shell-theme` remains renderer-independent; +- Theme module is only a presentation/controller crate; +- GPUI Kit receives theme values through an adapter/mapping layer; +- all modules consume the same active theme snapshot; +- preview can be cancelled without corrupting persistent config; +- external `theme.toml` hot reload and Theme module edits converge on the same configuration pipeline; +- no module owns private duplicated design tokens without architectural justification. -The module owns its editor layout; the Notch owns host geometry, resize animation, focus and dismissal. +--- -## MVP +# Non-goals ```text -list/select themes -edit primary visual tokens -preview changes -apply/reset changes +forking GPUI Kit's complete styling system +per-module independent themes +hardcoding colors in every module +full GTK/Qt theming in MVP +wallpaper manager inside the Theme Notch module +CSS-like arbitrary runtime styling language ```