fix: replace broken auto-save with explicit Cmd+S save

Removes the debounced auto-save (useAutoSave hook) which was causing the
editor to reload previous content. Replaces it with explicit save on
Cmd+S (⌘S), consistent with the git-based UX of the app.

- Removed useAutoSave hook and its debounce mechanism
- Added useSaveNote hook for direct persist-to-disk
- Added useEditorSave hook that manages pending content buffer + save
- Cmd+S now persists the current editor content immediately
- Rename-before-save: saves pending content before rename to prevent
  the "Failed to rename note" error
- Updated E2E test to verify Cmd+S behavior
- 471 tests passing, code health gates passed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lucaronin
2026-02-23 19:53:36 +01:00
parent 0053d3b985
commit 785720b3dd
10 changed files with 322 additions and 243 deletions

29
src/hooks/useSaveNote.ts Normal file
View File

@@ -0,0 +1,29 @@
import { useCallback } from 'react'
import { invoke } from '@tauri-apps/api/core'
import { isTauri, mockInvoke, updateMockContent } from '../mock-tauri'
async function persistContent(path: string, content: string): Promise<void> {
if (isTauri()) {
await invoke('save_note_content', { path, content })
} else {
await mockInvoke('save_note_content', { path, content })
}
}
/**
* Hook that provides an explicit save function for note content.
* Called on Cmd+S — no debounce, no auto-save.
*
* @param updateContent - callback to also update in-memory state after save
*/
export function useSaveNote(updateContent: (path: string, content: string) => void) {
const saveNote = useCallback(async (path: string, content: string) => {
await persistContent(path, content)
if (!isTauri()) {
updateMockContent(path, content)
}
updateContent(path, content)
}, [updateContent])
return { saveNote }
}