fix: persist property-only frontmatter edits
This commit is contained in:
@@ -270,6 +270,7 @@ export interface FrontmatterOpOptions {
|
||||
export interface FrontmatterApplyCallbacks {
|
||||
updateTab: (path: VaultPath, content: MarkdownContent) => void
|
||||
updateEntry: (path: VaultPath, patch: Partial<VaultEntry>) => void
|
||||
cacheContent?: (path: VaultPath, content: MarkdownContent) => void
|
||||
toast: (message: ToastMessage) => void
|
||||
getEntry?: (path: VaultPath) => VaultEntry | undefined
|
||||
onMissingNotePath?: (path: VaultPath, error: unknown) => void | Promise<void>
|
||||
@@ -395,6 +396,7 @@ export async function runFrontmatterAndApply(request: FrontmatterRunRequest): Pr
|
||||
const { op, path, key, value, callbacks, options } = request
|
||||
try {
|
||||
const newContent = await executeFrontmatterOp(op, path, key, value)
|
||||
callbacks.cacheContent?.(path, newContent)
|
||||
if (callbacks.shouldApply && !callbacks.shouldApply(path)) return undefined
|
||||
callbacks.updateTab(path, newContent)
|
||||
applyEntryPatch(path, callbacks, frontmatterToEntryPatch(op, key, value))
|
||||
|
||||
@@ -7,6 +7,7 @@ import { RAPID_CREATE_NOTE_SETTLE_MS } from './useNoteCreation'
|
||||
import { useNoteActions } from './useNoteActions'
|
||||
import type { NoteActionsConfig } from './useNoteActions'
|
||||
import { GITIGNORED_VISIBILITY_APPLIED_EVENT } from '../lib/gitignoredVisibilityEvents'
|
||||
import { clearNoteContentCache, getCachedNoteContentEntry } from './noteContentCache'
|
||||
|
||||
vi.mock('@tauri-apps/api/core', () => ({ invoke: vi.fn() }))
|
||||
vi.mock('../mock-tauri', () => ({
|
||||
@@ -85,6 +86,7 @@ describe('useNoteActions hook', () => {
|
||||
vi.clearAllMocks()
|
||||
vi.mocked(invoke).mockReset()
|
||||
vi.mocked(isTauri).mockReturnValue(false)
|
||||
clearNoteContentCache()
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
@@ -283,6 +285,44 @@ describe('useNoteActions hook', () => {
|
||||
expect(setToastMessage).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps property-only frontmatter writes in the note cache after a note switch wins the apply guard', async () => {
|
||||
vi.mocked(isTauri).mockReturnValue(true)
|
||||
const noteA = makeEntry({ path: '/vault/note-a.md', filename: 'note-a.md', title: 'Note A' })
|
||||
const noteB = makeEntry({ path: '/vault/note-b.md', filename: 'note-b.md', title: 'Note B' })
|
||||
const updatedContent = '---\nStatus: Done\n---\nBody'
|
||||
let resolveFrontmatterWrite: ((content: string) => void) | null = null
|
||||
vi.mocked(invoke).mockImplementation(() => new Promise((resolve) => {
|
||||
resolveFrontmatterWrite = (content) => { resolve(content) }
|
||||
}))
|
||||
|
||||
const { result } = renderHook(() => useNoteActions(makeConfig([noteA, noteB])))
|
||||
act(() => {
|
||||
result.current.handleSwitchTab(noteA.path)
|
||||
})
|
||||
|
||||
let updatePromise: Promise<void> = Promise.resolve()
|
||||
await act(async () => {
|
||||
updatePromise = result.current.handleUpdateFrontmatter(
|
||||
noteA.path,
|
||||
'Status',
|
||||
'Done',
|
||||
{ requireActivePath: noteA.path },
|
||||
)
|
||||
await Promise.resolve()
|
||||
})
|
||||
act(() => {
|
||||
result.current.handleSwitchTab(noteB.path)
|
||||
})
|
||||
await act(async () => {
|
||||
resolveFrontmatterWrite?.(updatedContent)
|
||||
await updatePromise
|
||||
})
|
||||
|
||||
expect(updateEntry).not.toHaveBeenCalled()
|
||||
expect(setToastMessage).not.toHaveBeenCalled()
|
||||
expect(getCachedNoteContentEntry(noteA.path)?.value).toBe(updatedContent)
|
||||
})
|
||||
|
||||
it('handleCreateNoteImmediate creates note with timestamp-based title', async () => {
|
||||
const createdEntry = await createImmediateEntry()
|
||||
expect(createdEntry.title).toBe('Untitled Note 1700000000')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, type MutableRefObject } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import type { FrontmatterValue } from '../components/Inspector'
|
||||
import { useTabManagement } from './useTabManagement'
|
||||
import { cacheNoteContent, useTabManagement } from './useTabManagement'
|
||||
import {
|
||||
GITIGNORED_VISIBILITY_APPLIED_EVENT,
|
||||
type GitignoredVisibilityAppliedEvent,
|
||||
@@ -474,6 +474,7 @@ function useFrontmatterRunner({
|
||||
key,
|
||||
value,
|
||||
callbacks: {
|
||||
cacheContent: cacheNoteContent,
|
||||
updateTab: updateTabContent,
|
||||
updateEntry,
|
||||
toast: setToastMessage,
|
||||
|
||||
Reference in New Issue
Block a user