Subscribe the open Magic Notes workspace to committed database changes from desktop and Agent/MCP writes. Preserve selections and unsaved drafts during refresh and external deletion. File-level commit includes existing runtime edits in shared files; their remaining dependencies are still in the working tree. Release note: Magic Notes now updates automatically after Agent/MCP edits while preserving your selection and unsaved drafts.
61 lines
3.3 KiB
Markdown
61 lines
3.3 KiB
Markdown
# Magic Notes Technical Design
|
|
|
|
## Change Notifications
|
|
|
|
`AssistantDatabase` accepts `onMagicNotesChanged: () => void`. Every successful
|
|
note/entry create, update or delete emits once after the write commits, including
|
|
empty-note creation, initial content, title/pin updates and cascading deletion.
|
|
Saved note analysis, todo completion, saved todo analysis and assistant-data
|
|
clearing also emit. Revision conflicts, missing rows, rolled-back writes and
|
|
unchanged todo completion do not emit. Startup schema migrations run before the
|
|
workbench loads and do not publish notifications.
|
|
|
|
Desktop IPC and `KnowledgeMcpGateway` use this same database instance. The latter
|
|
also serves Agent tools; no tool-specific notification or daemon protocol change
|
|
is needed. Raw SQL writes from an unrelated process are outside this callback
|
|
contract.
|
|
|
|
Main queues notification delivery to the live window on `magic-notes:changed`.
|
|
The typed preload method `magicNotes.onChanged(listener)` exposes no Electron
|
|
objects and returns a function removing that listener. The existing
|
|
`onTodoStatusChanged` event remains the separate sidebar-count signal.
|
|
|
|
## Refresh Lifecycle
|
|
|
|
`MagicNotesWorkspace` subscribes on mount and coalesces notifications with a
|
|
100 ms debounce. Pending notifications wait for an active local save or analysis
|
|
to finish. Cleanup removes the listener, clears its timer and invalidates pending
|
|
refresh results. This does not introduce periodic database polling.
|
|
|
|
The existing list/detail loader reloads notes and todos, then the preferred note.
|
|
Request counters reject superseded results and preserve newer user selections.
|
|
Todo selection survives list reordering while the item exists; replacing the todo
|
|
snapshot also reloads the selected todo's source entry. Search, filters and layout
|
|
state are not reset.
|
|
|
|
Background application of a detail reads the current draft state after the
|
|
asynchronous fetch. A dirty title is retained, and the composer is not remounted.
|
|
An entry editor uses its original editing content and revision for both its React
|
|
key and save request; external revisions cannot remount it or bypass optimistic
|
|
concurrency checks. Deleted entries remain displayed only while their editor is
|
|
open. If an externally deleted note has a draft, its editor remains available
|
|
with a deletion explanation instead of moving the draft to another note.
|
|
|
|
Read failures use the existing retryable refresh error and retain successful
|
|
data and drafts. Retry uses the same draft-preserving loader. Interaction rules
|
|
are owned by [the UI design system](../../../UI-DESIGN.md#137-魔法笔记).
|
|
|
|
## Validation
|
|
|
|
- `assistant-database.test.ts` checks committed writes with a second SQLite
|
|
connection, successful mutation coverage, failures, no-op completion and reset.
|
|
- `knowledge-mcp-gateway.test.ts` exercises real database CRUD through Agent/MCP
|
|
access, including revision failure without an extra notification.
|
|
- `magic-notes-events.test.ts` executes the production preload, checking the
|
|
channel, payload-free callback and listener removal.
|
|
- `MagicNotesWorkspace.test.tsx` covers external updates and deletion, selection,
|
|
source reload, editor identity and draft saves, coalescing, deferred writes,
|
|
asynchronous selection races, error retry and unmount cleanup.
|
|
|
|
No schema migration, dependency, refresh control or network service is added.
|