feat(storage): app-pause flush + vault search index
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:
2026-06-24 23:19:21 +08:00
parent 4886f1b2df
commit 24d13642fd
9 changed files with 749 additions and 68 deletions

View File

@@ -6,6 +6,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:pdfrx/pdfrx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'editor/persistence/sidecar_flush_observer.dart';
import 'editor/pdf/pen_capture_region.dart';
import 'l10n/app_localizations.dart';
import 'providers/settings_provider.dart';
@@ -33,11 +34,33 @@ Future<void> main() async {
runApp(const ProviderScope(child: BadNoteApp()));
}
class BadNoteApp extends ConsumerWidget {
class BadNoteApp extends ConsumerStatefulWidget {
const BadNoteApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
ConsumerState<BadNoteApp> createState() => _BadNoteAppState();
}
class _BadNoteAppState extends ConsumerState<BadNoteApp> {
// Phase 6 / §F.3: flush any open sidecar repos when the app is suspended or
// closed so the last strokes are never lost to an OS kill. Lives for the whole
// app lifetime (attached here, detached on app teardown).
final SidecarFlushObserver _flushObserver = SidecarFlushObserver();
@override
void initState() {
super.initState();
_flushObserver.attach();
}
@override
void dispose() {
_flushObserver.detach();
super.dispose();
}
@override
Widget build(BuildContext context) {
final settings = ref.watch(settingsProvider);
// Material You: prefer the OS dynamic color (Windows/Android system accent);