feat(storage): notes are vault sidecar notebooks
All checks were successful
CI / Windows build (push) Successful in 12m55s
All checks were successful
CI / Windows build (push) Successful in 12m55s
Phase 4. Standalone notes move off SQLite into the vault, like the PDF annotations. - "Create notebook" makes a vault folder with a notebook.badnote.json (BadnoteSidecar docType 'notebook' + a title field), opened via SidecarRepository. - PenNoteScreen loads/saves its strokes (page 0) + title to that sidecar instead of the SQLite Note model. - note_provider lists notes from a vault scan (VaultService.scanNotes = folders with notebook.badnote.json and no source file); the doc scan still excludes them. Delete removes the folder. PDF/slide editors unchanged; pre-existing SQLite notes migrate in Phase 5. analyze clean, tests green.
This commit is contained in:
@@ -200,4 +200,58 @@ void main() {
|
||||
expect(sl.scratchpad.strokes.single.id, 's');
|
||||
after.dispose();
|
||||
});
|
||||
|
||||
group('Phase 4 standalone notebook (notebook.badnote.json)', () {
|
||||
late String notePath;
|
||||
|
||||
setUp(() {
|
||||
// The synthetic note "source" is <folder>/notebook → sidecar is
|
||||
// <folder>/notebook.badnote.json (no real source file on disk).
|
||||
notePath = '${tmpDir.path}/notebook';
|
||||
});
|
||||
|
||||
test('a note\'s strokes (page 0) + title round-trip through the sidecar',
|
||||
() async {
|
||||
final repo =
|
||||
await SidecarRepository.open(notePath, debounce: _fast, docType: 'notebook');
|
||||
expect(repo.sidecarFile.path, '$notePath.badnote.json');
|
||||
|
||||
repo.scheduleTitleSave('My Note');
|
||||
repo.scheduleStrokeSave(0, [
|
||||
_stroke('p', tool: EditorTool.pen),
|
||||
_stroke('h', tool: EditorTool.highlighter),
|
||||
]);
|
||||
await repo.flush();
|
||||
repo.dispose();
|
||||
|
||||
// Re-open the same standalone notebook sidecar.
|
||||
final reopened =
|
||||
await SidecarRepository.open(notePath, debounce: _fast, docType: 'notebook');
|
||||
expect(reopened.loadedTitle, 'My Note');
|
||||
expect(reopened.sidecar.docType, 'notebook');
|
||||
final page0 = reopened.loadedStrokes[0]!;
|
||||
expect(page0.map((s) => s.id), ['p', 'h']);
|
||||
expect(page0.first.tool, EditorTool.pen);
|
||||
expect(page0.last.tool, EditorTool.highlighter);
|
||||
expect(page0.first.color, 0xFF112233);
|
||||
reopened.dispose();
|
||||
});
|
||||
|
||||
test('editing the title persists; unchanged title is a no-op', () async {
|
||||
final repo =
|
||||
await SidecarRepository.open(notePath, debounce: _fast, docType: 'notebook');
|
||||
repo.scheduleTitleSave('First');
|
||||
await repo.flush();
|
||||
// Same title again: no write needed, but flush stays safe.
|
||||
repo.scheduleTitleSave('First');
|
||||
repo.scheduleTitleSave('Second');
|
||||
await repo.flush();
|
||||
repo.dispose();
|
||||
|
||||
final reopened =
|
||||
await SidecarRepository.open(notePath, debounce: _fast, docType: 'notebook');
|
||||
expect(reopened.loadedTitle, 'Second');
|
||||
reopened.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user