Lots of updates to the notes. Style/layout fix for main Journals page.
This commit is contained in:
@@ -68,16 +68,41 @@ This document outlines the modernization of the Journals module UI in the Svelte
|
||||
- [x] Implement Bulk Export/Import system.
|
||||
- [x] Establish centralized Export Template engine.
|
||||
|
||||
### Phase 4: Polish & Security (ACTIVE BLOCKER)
|
||||
### 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.
|
||||
- [ ] **BLOCKER:** Decryption workflow is currently unstable due to Svelte 5 reactivity loops.
|
||||
- [x] **RESOLVED:** Decryption workflow stability (Fixed via dependency isolation).
|
||||
- [ ] Audit encryption flow for Quick Added and Imported entries.
|
||||
- [ ] Integrate Outbound Email sharing.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Technical Blocker: The "Decryption-Sync" Loop
|
||||
## 🧠 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:
|
||||
|
||||
### 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.
|
||||
|
||||
### 2. 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.
|
||||
|
||||
### 3. Concurrency Locking (`is_processing`)
|
||||
* **The Problem:** Decryption (Async) and Auto-Save (Debounced Async) can fire nearly simultaneously.
|
||||
* **The Fix:** Use a simple `is_processing` boolean flag. If any async workflow is active, block others from starting and prevent the `has_unsaved_changes` derived rune from reporting `true`.
|
||||
|
||||
### 4. Comparison Normalization
|
||||
* **The Problem:** Trivial differences (e.g., `null` vs `""` or trailing whitespace) would trigger "unsaved changes" and fire the save loop.
|
||||
* **The Fix:** Use a `normalize()` function in the `has_unsaved_changes` derived rune to trim strings and treat `null/undefined` as empty strings during comparison.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Technical Blocker: The "Decryption-Sync" Loop (Resolved)
|
||||
|
||||
### The Issue
|
||||
The component is suffering from a **Reactive Feedback Loop** between decryption, auto-save, and background IDB refreshes.
|
||||
|
||||
Reference in New Issue
Block a user