fix(journals): harden privacy toggle and add effect diagnostics

- Ensured content is decrypted before allowing conversion to plain text.
- Added detailed diagnostic logging to reactive effects to debug loop issues.
- Integrated background sync skip logic to preserve decrypted state.
This commit is contained in:
Scott Idem
2026-01-14 16:10:30 -05:00
parent 693a2e42c4
commit 574403244b
3 changed files with 34 additions and 9 deletions

View File

@@ -81,7 +81,7 @@ export async function decrypt_journal_entry(
}
}
console.log(`decrypt_journal_entry: SUCCESS. Content length: ${decrypted_text.length}. Preview: ${decrypted_text.substring(0, 20)}...`);
console.log(`decrypt_journal_entry: SUCCESS. Source: ${key_source}, Content length: ${decrypted_text.length}. Preview: ${decrypted_text.substring(0, 30).replace(/\n/g, ' ')}...`);
return {
success: true,
content: decrypted_text,

View File

@@ -200,16 +200,27 @@ p-2 md:p-3 rounded-lg shadow-md
<button
type="button"
class:hidden={journal?.cfg_json?.hide_btn_private || (entry.private && !$ae_loc.edit_mode)}
onclick={() => {
onclick={async () => {
if (!entry.private && entry.content) {
if (confirm('Encrypt and resave this entry?')) {
tmp_entry_obj.private = true;
onSave();
}
} else if (entry.private && entry.content_encrypted) {
if (confirm('Decrypt and resave unencrypted?')) {
tmp_entry_obj.private = false;
onSave();
// CRITICAL: Ensure we have the decrypted content before we turn OFF privacy
if (!tmp_entry_obj.content) {
console.log('Header: Content not decrypted. Attempting decryption before toggle.');
await onDecrypt();
}
// Check again after attempted decryption
if (tmp_entry_obj.content) {
if (confirm('Decrypt and resave as plain text?')) {
tmp_entry_obj.private = false;
onSave();
}
} else {
alert('Cannot convert to plain text: Entry is not decrypted. Please enter passcode first.');
}
}
}}

View File

@@ -78,16 +78,20 @@
const journal = $lq__journal_obj;
if (entry && (entry.updated_on || entry.created_on)) {
// Determine if we are in a decrypted state for this journal
const is_decrypted = $journals_sess?.journal_kv[journal?.id]?.journal_passcode_decrypted === true;
const session_kv = $journals_sess?.journal_kv[journal?.id];
const is_decrypted = session_kv?.journal_passcode_decrypted === true;
console.log(`ae_view: Effect[Sync] trigger. Entry updated_on: ${entry.updated_on}. Decrypted in session: ${is_decrypted}`);
// Only sync if saved and not currently processing/editing
if (save_status === 'saved' && !has_unsaved_changes && !is_processing) {
// If the journal is already decrypted, we MUST NOT overwrite the decrypted content with null from DB
if (is_decrypted && tmp_entry_obj.content && !entry.content) {
console.log('ae_view: Background sync skipped to preserve decrypted content.');
console.log('ae_view: Effect[Sync] SKIPPED to preserve decrypted content.');
return;
}
console.log('ae_view: Effect[Sync] PROCEEDING. Updating local state from DB.');
const base = {
...entry,
content: entry.content ?? null,
@@ -95,6 +99,8 @@
};
orig_entry_obj = { ...base };
tmp_entry_obj = { ...base };
} else {
console.log(`ae_view: Effect[Sync] BLOCKED. status: ${save_status}, has_changes: ${has_unsaved_changes}, processing: ${is_processing}`);
}
}
});
@@ -103,11 +109,15 @@
$effect(() => {
const _trigger = tmp_entry_obj.content;
if (has_unsaved_changes && !is_processing) {
console.log('ae_view: Effect[AutoSave] trigger. Changes detected.');
if (save_status !== 'saving') save_status = 'unsaved';
if ($journals_loc.entry.auto_save) {
clearTimeout(auto_save_timer);
auto_save_timer = setTimeout(() => {
if (untrack(() => has_unsaved_changes)) update_journal_entry();
if (untrack(() => has_unsaved_changes)) {
console.log('ae_view: Effect[AutoSave] Timer fired. Updating...');
update_journal_entry();
}
}, 2000);
}
} else if (save_status !== 'saving' && !has_unsaved_changes) {
@@ -123,8 +133,12 @@
const session = $journals_sess?.journal_kv[journal.id];
const is_verified = session?.journal_passcode_verified;
const decrypted_status = session?.journal_passcode_decrypted;
const has_encrypted_content = !!$lq__journal_entry_obj?.content_encrypted;
console.log(`ae_view: Effect[Decryption] check. Encrypted: ${has_encrypted_content}, Verified: ${is_verified}, Status: ${decrypted_status}`);
if ($lq__journal_entry_obj?.content_encrypted && is_verified && decrypted_status !== true && decrypted_status !== 'processing') {
if (has_encrypted_content && is_verified && decrypted_status !== true && decrypted_status !== 'processing') {
console.log('ae_view: Effect[Decryption] PROCEEDING to run workflow.');
run_decryption_workflow();
}
});