diff --git a/GEMINI.md b/GEMINI.md index 736e1ab1..6fd9bfb1 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -11,10 +11,11 @@ This project is the frontend UI/UX for the Aether (AE) system, built with Svelte ## 🏗️ Architecture & Standards -### Svelte v5 (Runes) -- **State Management:** Use `$state` and `$derived`. Props are passed via `$props()` and can be `$bindable`. -- **Event Handling:** Use lowercase `onevent` attributes (e.g., `onclick`). Handle `preventDefault` inside functions. -- **Dexie Integration:** `liveQuery` results are observables and require the `$` prefix (e.g., `$lq__obj`) in templates. Subscribe in `onMount` to avoid SSR issues. +### Reactivity & Stores +- **Svelte 5 Runes:** Use `$state`, `$derived`, and `$effect` for component-level reactivity. +- **Dexie LiveQuery:** Results from `liveQuery` are observables. You **MUST** use the `$` prefix (e.g., `$lq__obj`) in templates and logic to subscribe to the live data. Failure to do so will result in accessing the observable object instead of its data. +- **Persistence:** Use `svelte-persisted-store` for data that must survive page refreshes (e.g., `ae_loc`, `journals_loc`). +- **Initialization:** Always initialize reactive state (`$state`) outside of `$props()` destructuring. Use `untrack` inside `$effect` when synchronizing props to local state to prevent infinite loops. ### ID Convention (Triple-ID Pattern) - **Standard:** Use `id`, `[obj_type]_id`, and `[obj_type]_id_random` consistently. diff --git a/TODO.md b/TODO.md index 150541e9..f8725b9a 100644 --- a/TODO.md +++ b/TODO.md @@ -31,6 +31,7 @@ This is a list of tasks to be completed before the next event/show/conference. - [ ] **Phase 2: UI/UX Excellence** - [x] Implement "Quick Add" for high-velocity entry. - [x] Add rapid append/prepend functionality to existing entries. + - [x] Standardize Module, Journal, and Entry configuration modals (Aether Orange pattern). - [ ] Ensure full cross-platform responsiveness (Mobile -> Workstation). - [ ] **Phase 3: Content Portability** - [x] Implement Structured Markdown import (with metadata). diff --git a/documentation/AE_UI_Journals_module_update_2026.md b/documentation/AE_UI_Journals_module_update_2026.md index 065c3f89..5a28e69f 100644 --- a/documentation/AE_UI_Journals_module_update_2026.md +++ b/documentation/AE_UI_Journals_module_update_2026.md @@ -71,8 +71,9 @@ This document outlines the modernization of the Journals module UI in the Svelte ### Phase 4: Polish & Security (ACTIVE) - [x] Implement Auto-Save toggle and visual status indicators. - [x] Extract decryption workflow to non-reactive helper. -- [ ] Solidify E2EE passcode system for Journals and Entries. +- [x] **Standardize Configuration Modals:** Refactored Module, Journal, and Entry configuration into a unified tabbed UI. - [x] **RESOLVED:** Decryption workflow stability (Fixed via dependency isolation). +- [ ] Solidify E2EE passcode system for Journals and Entries. - [ ] Audit encryption flow for Quick Added and Imported entries. - [ ] Integrate Outbound Email sharing. @@ -80,14 +81,25 @@ This document outlines the modernization of the Journals module UI in the Svelte ## 🧠 Lessons Learned: Solving the Svelte 5 Reactivity Hang -During the implementation of the Privacy/Decryption toggle, we encountered a critical browser hang caused by an infinite reactivity loop. Here is how we resolved it and the patterns we should follow in the future: +During the implementation of the Privacy/Decryption toggle and the new Configuration Modals, we encountered critical browser hangs caused by infinite reactivity loops. Here is how we resolved them: ### 1. Rigorous Dependency Isolation (`untrack`) Svelte 5 runes (`$effect`, `$derived`) automatically track **every** reactive variable read inside them. * **The Problem:** An effect would read `save_status` or `tmp_entry_obj.content` to decide if it should sync, but the act of syncing would update those same variables, re-triggering the effect. -* **The Fix:** Wrap any "check-only" state or store reads in `untrack(() => ... )`. This allows the effect to use the value without becoming a dependency of it. +* **The Fix:** Wrap any "check-only" state or store reads in `untrack(() => ... )`. This allows the effect to use the value without becoming a dependency of it. This is **CRITICAL** when initializing local state from props inside an effect. -### 2. Manual Deep Copying vs. Proxies +### 2. Standardized Modal UI ("Aether Orange") +We have established a unified design language for configuration interfaces: +* **Header/Footer:** Use `bg-orange-100 dark:bg-orange-900` with consistent borders. +* **Tabs:** Center-aligned tabbed navigation using Skeleton UI `btn` and `variant-filled-primary` / `variant-soft-surface`. +* **Icons:** Every tab and primary action should have a Lucide icon for better scannability. +* **Explicit Persistence:** All configuration modals must follow an "Edit working copy -> Save Changes" pattern to prevent accidental store/API churn. + +### 3. Dexie LiveQuery Subscriptions +* **The Problem:** Accessing `liveQuery` observables directly in templates results in `[object Object]` or `undefined` property errors. +* **The Mandate:** ALWAYS use the `$` prefix (e.g. `$lq__obj`) when passing or using data from a Dexie `liveQuery`. + +### 4. Manual Deep Copying vs. Proxies Svelte 5 state is backed by Proxies. * **The Problem:** Using `JSON.parse(JSON.stringify(proxy))` can sometimes trigger unexpected behavior or loops when used inside a reactive context. * **The Fix:** Implement a manual `deep_copy` helper or selective property assignment when syncing "Original" vs "Temporary" state. This ensures `orig_entry_obj` is a plain JS object, making the `has_unsaved_changes` check stable. diff --git a/src/routes/journals/JournalEntry_SettingsMenu.svelte b/src/routes/journals/JournalEntry_SettingsMenu.svelte deleted file mode 100644 index 765cae9c..00000000 --- a/src/routes/journals/JournalEntry_SettingsMenu.svelte +++ /dev/null @@ -1,227 +0,0 @@ - - -