feat(storage): app-pause flush + vault search index
Some checks failed
CI / Windows build (push) Has been cancelled
Some checks failed
CI / Windows build (push) Has been cancelled
Phase 6 (final storage phase). - SidecarRepositoryRegistry tracks every open repo; SidecarFlushObserver (a WidgetsBindingObserver in main) flushes them all on inactive/hidden/paused/detached, awaiting each flush — the last strokes can't be lost on app close, not just on the 800ms timer. - VaultSearchIndex rebuilds by scanning vault sidecars (the source of truth) — note titles, OCR text and document names — and search_provider queries it, so search spans notes + PDFs. Rebuilt on launch / after import. The vault file-based storage migration (Phases 0-6) is complete: annotations travel with the file, picked vault folder, atomic autosave, one Import-file entry, SQLite migrated to sidecars. analyze clean, tests green.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import '../editor/persistence/sidecar_repository.dart';
|
||||
import '../models/note.dart';
|
||||
import '../models/pen_tool.dart';
|
||||
import 'database_service.dart';
|
||||
@@ -6,7 +9,12 @@ import 'stroke_rasterizer.dart';
|
||||
|
||||
/// Runs OCR locally: typed text from strokes + handwriting via platform OCR.
|
||||
class OcrService {
|
||||
/// Extract searchable text from [note] and merge into the local FTS index.
|
||||
/// Extract searchable text from [note] and persist it for search. The text is
|
||||
/// written to the note's `*.badnote.json` sidecar `ocrText` field — the
|
||||
/// vault-scan source of truth the Phase 6 search index reads — and also
|
||||
/// appended to the (rebuildable) SQLite FTS cache so legacy callers keep
|
||||
/// working. [note.id] is the synthetic note path, which is exactly the
|
||||
/// `sourceFilePath` the editor opened its [SidecarRepository] with.
|
||||
Future<void> processNote(Note note) async {
|
||||
final parts = <String>[];
|
||||
|
||||
@@ -40,6 +48,22 @@ class OcrService {
|
||||
final combined = parts.join(' ').trim();
|
||||
if (combined.isEmpty) return;
|
||||
|
||||
// Persist into the note's sidecar so the vault-scan search index finds it.
|
||||
// Prefer the editor's already-open repo (same in-memory sidecar — no race);
|
||||
// if the note is closed, open/flush/dispose a transient handle.
|
||||
final open = SidecarRepositoryRegistry.forPath(note.id);
|
||||
if (open != null) {
|
||||
open.scheduleOcrTextSave(combined);
|
||||
await open.flush();
|
||||
} else if (await File('${note.id}$kSidecarSuffix').exists()) {
|
||||
final repo = await SidecarRepository.open(note.id, docType: 'notebook');
|
||||
repo.scheduleOcrTextSave(combined);
|
||||
await repo.flush();
|
||||
repo.dispose();
|
||||
}
|
||||
|
||||
// Also keep the legacy SQLite FTS cache warm (rebuildable; not the source
|
||||
// of truth). Harmless if the row is never read.
|
||||
final db = await DatabaseService.getInstance();
|
||||
await db.appendOcrToFts(note.id, combined);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user