Lots of updates to the notes. Style/layout fix for main Journals page.

This commit is contained in:
Scott Idem
2026-01-14 16:48:00 -05:00
parent c907a95c57
commit 11e022d21e
2 changed files with 38 additions and 15 deletions

View File

@@ -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.

View File

@@ -8,11 +8,11 @@
import { goto } from '$app/navigation';
// *** Icons
import {
BookPlus, SquareLibrary, Wrench,
FileUp, Loader2, Sparkles
import {
BookPlus, SquareLibrary, Wrench,
FileUp, Loader2, Sparkles
} from '@lucide/svelte';
// *** Libraries & Stores
import { liveQuery } from 'dexie';
import { Modal } from 'flowbite-svelte';
@@ -85,15 +85,13 @@
</script>
<div class="page_container flex flex-col gap-8 items-center w-full min-h-screen p-4 md:p-8">
<!-- Header Section -->
<header class="text-center space-y-2 max-w-3xl">
<div class="flex items-center justify-center gap-3 mb-2">
<div class="p-3 bg-surface-500/10 rounded-2xl">
<SquareLibrary size="3em" class="text-primary-500" />
</div>
</div>
<h1 class="text-4xl md:text-5xl font-black tracking-tight text-surface-900 dark:text-surface-100">
<!-- <div class="p-3 bg-surface-500/10 rounded-2xl"> -->
<SquareLibrary size="1em" class="text-primary-500 inline-block" />
<!-- </div> -->
Journals
</h1>
<p class="text-surface-600 dark:text-surface-400 font-medium">
@@ -108,9 +106,9 @@
<section class="w-full max-w-2xl">
<div class="relative group">
<div class="absolute -inset-1 bg-gradient-to-r from-primary-500 to-secondary-500 rounded-2xl blur opacity-25 group-hover:opacity-50 transition duration-1000 group-hover:duration-200"></div>
<AeCompJournalEntryQuickAdd
<AeCompJournalEntryQuickAdd
journals_li={$lq__journal_obj_li}
class="relative shadow-2xl rounded-xl overflow-hidden border border-surface-500/10 bg-surface-50 dark:bg-surface-900"
class="relative shadow-2xl rounded-xl overflow-hidden border border-surface-500/10 bg-surface-50 dark:bg-surface-900"
/>
</div>
<div class="mt-2 flex items-center justify-center gap-2 text-xs opacity-50 font-bold uppercase tracking-widest">