From 7a7ba6086a2cb52cf5691f3510da4d888352dcad Mon Sep 17 00:00:00 2001 From: lucaronin Date: Fri, 6 Mar 2026 23:01:05 +0100 Subject: [PATCH] fix: refresh Changes panel after trash/archive operations Trash, archive, restore, and unarchive wrote frontmatter to disk but never called loadModifiedFiles, so the change didn't appear in the Changes panel until the next manual refresh. Co-Authored-By: Claude Opus 4.6 --- src/App.tsx | 1 + src/hooks/useEntryActions.test.ts | 7 +++++++ src/hooks/useEntryActions.ts | 15 ++++++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 135ffdc0..4335583a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -330,6 +330,7 @@ function App() { handleUpdateFrontmatter: notes.handleUpdateFrontmatter, handleDeleteProperty: notes.handleDeleteProperty, setToastMessage, createTypeEntry: notes.createTypeEntrySilent, + onFrontmatterPersisted: vault.loadModifiedFiles, }) const handleDeleteNote = useCallback(async (path: string) => { diff --git a/src/hooks/useEntryActions.test.ts b/src/hooks/useEntryActions.test.ts index bf82b312..c8141b32 100644 --- a/src/hooks/useEntryActions.test.ts +++ b/src/hooks/useEntryActions.test.ts @@ -50,10 +50,13 @@ describe('useEntryActions', () => { handleDeleteProperty, setToastMessage, createTypeEntry, + onFrontmatterPersisted, }) ) } + const onFrontmatterPersisted = vi.fn() + beforeEach(() => { vi.clearAllMocks() }) @@ -73,6 +76,7 @@ describe('useEntryActions', () => { trashedAt: expect.any(Number), }) expect(setToastMessage).toHaveBeenCalledWith('Note moved to trash') + expect(onFrontmatterPersisted).toHaveBeenCalledTimes(1) }) }) @@ -91,6 +95,7 @@ describe('useEntryActions', () => { trashedAt: null, }) expect(setToastMessage).toHaveBeenCalledWith('Note restored from trash') + expect(onFrontmatterPersisted).toHaveBeenCalledTimes(1) }) }) @@ -105,6 +110,7 @@ describe('useEntryActions', () => { expect(handleUpdateFrontmatter).toHaveBeenCalledWith('/vault/note/test.md', 'archived', true) expect(updateEntry).toHaveBeenCalledWith('/vault/note/test.md', { archived: true }) expect(setToastMessage).toHaveBeenCalledWith('Note archived') + expect(onFrontmatterPersisted).toHaveBeenCalledTimes(1) }) }) @@ -119,6 +125,7 @@ describe('useEntryActions', () => { expect(handleUpdateFrontmatter).toHaveBeenCalledWith('/vault/note/test.md', 'archived', false) expect(updateEntry).toHaveBeenCalledWith('/vault/note/test.md', { archived: false }) expect(setToastMessage).toHaveBeenCalledWith('Note unarchived') + expect(onFrontmatterPersisted).toHaveBeenCalledTimes(1) }) }) diff --git a/src/hooks/useEntryActions.ts b/src/hooks/useEntryActions.ts index 0d8efa20..a2be2b91 100644 --- a/src/hooks/useEntryActions.ts +++ b/src/hooks/useEntryActions.ts @@ -8,6 +8,7 @@ interface EntryActionsConfig { handleDeleteProperty: (path: string, key: string) => Promise setToastMessage: (msg: string | null) => void createTypeEntry: (typeName: string) => Promise + onFrontmatterPersisted?: () => void } function findTypeEntry(entries: VaultEntry[], typeName: string): VaultEntry | undefined { @@ -15,7 +16,7 @@ function findTypeEntry(entries: VaultEntry[], typeName: string): VaultEntry | un } export function useEntryActions({ - entries, updateEntry, handleUpdateFrontmatter, handleDeleteProperty, setToastMessage, createTypeEntry, + entries, updateEntry, handleUpdateFrontmatter, handleDeleteProperty, setToastMessage, createTypeEntry, onFrontmatterPersisted, }: EntryActionsConfig) { const handleTrashNote = useCallback(async (path: string) => { const now = new Date().toISOString().slice(0, 10) @@ -23,26 +24,30 @@ export function useEntryActions({ await handleUpdateFrontmatter(path, 'Trashed at', now) updateEntry(path, { trashed: true, trashedAt: Date.now() / 1000 }) setToastMessage('Note moved to trash') - }, [handleUpdateFrontmatter, updateEntry, setToastMessage]) + onFrontmatterPersisted?.() + }, [handleUpdateFrontmatter, updateEntry, setToastMessage, onFrontmatterPersisted]) const handleRestoreNote = useCallback(async (path: string) => { await handleUpdateFrontmatter(path, 'Trashed', false) await handleDeleteProperty(path, 'Trashed at') updateEntry(path, { trashed: false, trashedAt: null }) setToastMessage('Note restored from trash') - }, [handleUpdateFrontmatter, handleDeleteProperty, updateEntry, setToastMessage]) + onFrontmatterPersisted?.() + }, [handleUpdateFrontmatter, handleDeleteProperty, updateEntry, setToastMessage, onFrontmatterPersisted]) const handleArchiveNote = useCallback(async (path: string) => { await handleUpdateFrontmatter(path, 'archived', true) updateEntry(path, { archived: true }) setToastMessage('Note archived') - }, [handleUpdateFrontmatter, updateEntry, setToastMessage]) + onFrontmatterPersisted?.() + }, [handleUpdateFrontmatter, updateEntry, setToastMessage, onFrontmatterPersisted]) const handleUnarchiveNote = useCallback(async (path: string) => { await handleUpdateFrontmatter(path, 'archived', false) updateEntry(path, { archived: false }) setToastMessage('Note unarchived') - }, [handleUpdateFrontmatter, updateEntry, setToastMessage]) + onFrontmatterPersisted?.() + }, [handleUpdateFrontmatter, updateEntry, setToastMessage, onFrontmatterPersisted]) const handleCustomizeType = useCallback(async (typeName: string, icon: string, color: string) => { let typeEntry = findTypeEntry(entries, typeName)