From 0fa93d7ee5a63f338737969a28d45ef1c43f4b14 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 8 May 2026 16:21:22 -0400 Subject: [PATCH] Fix auto-save stopping after the first save in journal entry editor The auto-save $effect wrapped has_unsaved_changes in untrack(), which meant it was never tracked when save_status was 'saved' (JS short-circuit in the else-if branch). After every successful save the effect lost its reactive dependency on user edits and never re-fired until something else changed save_status first. Fix: track tmp_entry_obj.content and tmp_entry_obj.name directly (void reads) so the effect re-runs on every keystroke and the debounce timer resets correctly (fires 2 s after the last change, not the first). has_unsaved_changes is also tracked directly so the status indicator resets cleanly when changes are cleared. All side-effects remain in untrack() to prevent reactive loops. Co-Authored-By: Claude Sonnet 4.6 --- .../ae_comp__journal_entry_obj_id_view.svelte | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte b/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte index a341b07f..1818b015 100644 --- a/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte +++ b/src/routes/journals/ae_comp__journal_entry_obj_id_view.svelte @@ -154,33 +154,38 @@ $effect(() => { // 2. Auto-Save Debounce $effect(() => { - // Isolate logic from secondary dependencies - const should_save = untrack( - () => has_unsaved_changes && !is_processing && save_status !== 'saving' - ); + // Track content and name directly so this effect re-runs on every keystroke, + // resetting the debounce timer each time (fires 2 s after the LAST change). + // Tracking has_unsaved_changes ensures the effect also wakes up when changes + // are cleared (e.g. after a save) so the status indicator resets correctly. + // All side-effects (save_status writes, $journals_loc reads) stay in untrack + // to avoid creating reactive loops. + void tmp_entry_obj.content; + void tmp_entry_obj.name; + const changed = has_unsaved_changes; - if (should_save) { - if (save_status !== 'saving') save_status = 'unsaved'; + clearTimeout(auto_save_timer); - const auto_save_enabled = untrack(() => $journals_loc.entry.auto_save); - if (auto_save_enabled) { - clearTimeout(auto_save_timer); - auto_save_timer = setTimeout(() => { - if ( - untrack( - () => - has_unsaved_changes && - !is_processing && - save_status !== 'saving' - ) - ) { - update_journal_entry(); - } - }, 2000); - } - } else if (save_status === 'unsaved' && !has_unsaved_changes) { - save_status = 'saved'; + if (!changed) { + untrack(() => { + if (save_status === 'unsaved') save_status = 'saved'; + }); + return; } + + untrack(() => { + if (save_status !== 'saving') save_status = 'unsaved'; + }); + + if (!untrack(() => $journals_loc.entry.auto_save)) return; + + auto_save_timer = setTimeout(() => { + untrack(() => { + if (has_unsaved_changes && !is_processing && save_status !== 'saving') { + update_journal_entry(); + } + }); + }, 2000); }); // 3. Auto-Decryption Workflow