feat(journals): implement auto-save toggle and visual status
- Added 'auto_save' preference to journals store - Added toggle and status indicators (Check/X/Loader) to JournalEntry_Header - Implemented auto-save logic with debounce in Journal Entry view
This commit is contained in:
@@ -81,6 +81,7 @@ const journals_local_data_struct: key_val = {
|
|||||||
llm__frequency_penalty: 0.0,
|
llm__frequency_penalty: 0.0,
|
||||||
llm__presence_penalty: 0.0,
|
llm__presence_penalty: 0.0,
|
||||||
|
|
||||||
|
auto_save: false,
|
||||||
edit: false,
|
edit: false,
|
||||||
edit_kv: {}
|
edit_kv: {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
Save, Eye, Pencil, Tags, Shapes,
|
Save, Eye, Pencil, Tags, Shapes,
|
||||||
Siren, MessageSquareWarning, Skull,
|
Siren, MessageSquareWarning, Skull,
|
||||||
Fingerprint, LockKeyhole, LockKeyholeOpen, Menu,
|
Fingerprint, LockKeyhole, LockKeyholeOpen, Menu,
|
||||||
Globe, BookHeart, BriefcaseBusiness
|
Globe, BookHeart, BriefcaseBusiness,
|
||||||
|
CircleCheck, CircleX, Loader2, RefreshCw
|
||||||
} from '@lucide/svelte';
|
} from '@lucide/svelte';
|
||||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||||
import { ae_loc } from '$lib/stores/ae_stores';
|
import { ae_loc } from '$lib/stores/ae_stores';
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
onChangeJournal: () => void;
|
onChangeJournal: () => void;
|
||||||
onAppend?: () => void;
|
onAppend?: () => void;
|
||||||
onPrepend?: () => void;
|
onPrepend?: () => void;
|
||||||
|
save_status?: 'saved' | 'unsaved' | 'saving';
|
||||||
log_lvl?: number;
|
log_lvl?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
onChangeJournal,
|
onChangeJournal,
|
||||||
onAppend,
|
onAppend,
|
||||||
onPrepend,
|
onPrepend,
|
||||||
|
save_status = 'saved',
|
||||||
log_lvl = 0
|
log_lvl = 0
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
@@ -96,6 +99,34 @@ p-2 md:p-3 rounded-lg shadow-md
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<!-- Auto Save Toggle & Status -->
|
||||||
|
{#if $journals_loc.entry.edit_kv[entry.journal_entry_id] === 'current'}
|
||||||
|
<div class="flex items-center gap-1 border-r border-surface-500/20 pr-2 mr-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-icon btn-icon-sm transition-all"
|
||||||
|
class:text-primary-500={$journals_loc.entry.auto_save}
|
||||||
|
class:opacity-50={!$journals_loc.entry.auto_save}
|
||||||
|
onclick={() => $journals_loc.entry.auto_save = !$journals_loc.entry.auto_save}
|
||||||
|
title="Toggle Auto Save"
|
||||||
|
>
|
||||||
|
<RefreshCw size="1.1em" class={$journals_loc.entry.auto_save ? '' : ''} />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if $journals_loc.entry.auto_save}
|
||||||
|
<div class="flex items-center" title="Auto Save Status: {save_status}">
|
||||||
|
{#if save_status === 'saving'}
|
||||||
|
<Loader2 size="1.1em" class="animate-spin text-primary-500" />
|
||||||
|
{:else if save_status === 'saved'}
|
||||||
|
<CircleCheck size="1.1em" class="text-success-500" />
|
||||||
|
{:else}
|
||||||
|
<CircleX size="1.1em" class="text-surface-400" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<h2 class="journal_entry__name text-base md:text-lg font-bold truncate max-w-[200px] md:max-w-md">
|
<h2 class="journal_entry__name text-base md:text-lg font-bold truncate max-w-[200px] md:max-w-md">
|
||||||
{#if $journals_loc.entry.edit_kv[entry.journal_entry_id] == 'current'}
|
{#if $journals_loc.entry.edit_kv[entry.journal_entry_id] == 'current'}
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -76,6 +76,30 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Auto Save Logic ---
|
||||||
|
let save_status: 'saved' | 'unsaved' | 'saving' = $state('saved');
|
||||||
|
let auto_save_timer: ReturnType<typeof setTimeout>;
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (tmp_entry_obj_changed) {
|
||||||
|
if (save_status !== 'saving') save_status = 'unsaved';
|
||||||
|
|
||||||
|
if ($journals_loc.entry.auto_save) {
|
||||||
|
clearTimeout(auto_save_timer);
|
||||||
|
auto_save_timer = setTimeout(() => {
|
||||||
|
if (tmp_entry_obj_changed) { // Double check
|
||||||
|
update_journal_entry();
|
||||||
|
}
|
||||||
|
}, 2000); // 2 seconds debounce
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearTimeout(auto_save_timer);
|
||||||
|
if (save_status !== 'saving') {
|
||||||
|
save_status = 'saved';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let decrypted_history: string = $state('');
|
let decrypted_history: string = $state('');
|
||||||
|
|
||||||
if (!$journals_loc?.entry?.decrypt_kv) {
|
if (!$journals_loc?.entry?.decrypt_kv) {
|
||||||
@@ -266,6 +290,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save_status = 'saving';
|
||||||
|
|
||||||
let data_kv: key_val = {
|
let data_kv: key_val = {
|
||||||
alert: tmp_entry_obj?.alert,
|
alert: tmp_entry_obj?.alert,
|
||||||
personal: tmp_entry_obj?.personal,
|
personal: tmp_entry_obj?.personal,
|
||||||
@@ -388,8 +414,10 @@
|
|||||||
});
|
});
|
||||||
if (log_lvl) console.log('Journal entry updated successfully:', response);
|
if (log_lvl) console.log('Journal entry updated successfully:', response);
|
||||||
updated_obj = true;
|
updated_obj = true;
|
||||||
|
save_status = 'saved';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating journal entry:', error);
|
console.error('Error updating journal entry:', error);
|
||||||
|
save_status = 'unsaved';
|
||||||
alert('Failed to update journal entry.');
|
alert('Failed to update journal entry.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,6 +555,7 @@
|
|||||||
onChangeJournal={change_journal_id}
|
onChangeJournal={change_journal_id}
|
||||||
onAppend={handle_append_start}
|
onAppend={handle_append_start}
|
||||||
onPrepend={handle_prepend_start}
|
onPrepend={handle_prepend_start}
|
||||||
|
{save_status}
|
||||||
{log_lvl}
|
{log_lvl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user