2026-06-21 22:04:49 +08:00
|
|
|
import 'package:dynamic_color/dynamic_color.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2026-06-23 09:35:26 +08:00
|
|
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
|
import 'package:google_fonts/google_fonts.dart';
|
2026-06-21 20:15:21 +08:00
|
|
|
import 'package:pdfrx/pdfrx.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
|
|
2026-06-21 20:15:21 +08:00
|
|
|
import 'editor/pdf/pen_capture_region.dart';
|
2026-06-23 09:35:26 +08:00
|
|
|
import 'l10n/app_localizations.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
import 'providers/settings_provider.dart';
|
|
|
|
|
import 'screens/home_screen.dart';
|
2026-06-24 20:45:16 +08:00
|
|
|
import 'screens/vault_setup_screen.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
import 'services/database_service.dart';
|
2026-06-24 20:45:16 +08:00
|
|
|
import 'services/vault_service.dart';
|
2026-06-24 23:05:10 +08:00
|
|
|
import 'storage/sqlite_to_sidecar_migrator.dart';
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
|
|
|
|
|
Future<void> main() async {
|
2026-06-21 20:15:21 +08:00
|
|
|
// Kind-aware binding (extends WidgetsFlutterBinding) must be the active
|
|
|
|
|
// binding before runApp so the M1 spike's PenCaptureRegion can gate
|
|
|
|
|
// hit-testing by pointer kind. Safe for the rest of the app: with no pen
|
|
|
|
|
// region mounted it behaves exactly like the default binding.
|
|
|
|
|
PenCaptureBinding.ensureInitialized();
|
|
|
|
|
// pdfrx native engine init (required before any PdfViewer is built).
|
|
|
|
|
pdfrxFlutterInitialize();
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
|
|
|
|
|
// Ensure DB is ready before the app starts so providers can use it eagerly
|
|
|
|
|
await DatabaseService.getInstance();
|
|
|
|
|
|
|
|
|
|
// Initialize SharedPreferences
|
|
|
|
|
await SharedPreferences.getInstance();
|
|
|
|
|
|
|
|
|
|
runApp(const ProviderScope(child: BadNoteApp()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class BadNoteApp extends ConsumerWidget {
|
|
|
|
|
const BadNoteApp({super.key});
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
|
|
|
final settings = ref.watch(settingsProvider);
|
|
|
|
|
|
2026-06-21 22:04:49 +08:00
|
|
|
// Material You: prefer the OS dynamic color (Windows/Android system accent);
|
|
|
|
|
// fall back to the user's seed color when the platform provides none.
|
|
|
|
|
return DynamicColorBuilder(
|
|
|
|
|
builder: (lightDynamic, darkDynamic) {
|
|
|
|
|
final lightScheme = lightDynamic?.harmonized() ??
|
|
|
|
|
ColorScheme.fromSeed(
|
|
|
|
|
seedColor: settings.colorSchemeSeed,
|
|
|
|
|
brightness: Brightness.light,
|
|
|
|
|
);
|
|
|
|
|
final darkScheme = darkDynamic?.harmonized() ??
|
|
|
|
|
ColorScheme.fromSeed(
|
|
|
|
|
seedColor: settings.colorSchemeSeed,
|
|
|
|
|
brightness: Brightness.dark,
|
|
|
|
|
);
|
|
|
|
|
return MaterialApp(
|
|
|
|
|
title: 'BadNote',
|
|
|
|
|
themeMode: settings.themeMode,
|
|
|
|
|
theme: _theme(lightScheme),
|
|
|
|
|
darkTheme: _theme(darkScheme),
|
2026-06-23 09:35:26 +08:00
|
|
|
// i18n: follows the OS language (en / zh) via the system locale.
|
|
|
|
|
localizationsDelegates: const [
|
|
|
|
|
AppLocalizations.delegate,
|
|
|
|
|
GlobalMaterialLocalizations.delegate,
|
|
|
|
|
GlobalWidgetsLocalizations.delegate,
|
|
|
|
|
GlobalCupertinoLocalizations.delegate,
|
|
|
|
|
],
|
|
|
|
|
supportedLocales: AppLocalizations.supportedLocales,
|
2026-06-24 20:45:16 +08:00
|
|
|
home: const VaultGate(),
|
2026-06-21 22:04:49 +08:00
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ThemeData _theme(ColorScheme scheme) => ThemeData(
|
|
|
|
|
colorScheme: scheme,
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
useMaterial3: true,
|
|
|
|
|
textTheme: GoogleFonts.interTextTheme(
|
2026-06-21 22:04:49 +08:00
|
|
|
ThemeData(brightness: scheme.brightness).textTheme,
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
),
|
2026-06-21 22:04:49 +08:00
|
|
|
);
|
Fix bugs across app + server, optimize UI/UX, add Gitea CI
Bug fixes (Flutter):
- Wrap multi-statement DB writes (insert/update/delete note, deleteDocument,
deletePageData, OCR FTS merge, migrations) in transactions to prevent data
loss on interruption and a read-modify-write FTS race.
- Fix PdfDocument leaks on exception (try/finally dispose) and preserve image
aspect ratio when stamping images onto PDF pages.
- Guard file-picker against empty selection (was .single -> crash).
- Fix eraser ConcurrentModificationError and unmodifiable-list crash on PDF
pages; capture page synchronously on save to stop wrong-page data loss.
- Fix Riverpod DB-not-ready races, broken pull-to-refresh, settings load race,
and search N+1; transform stored annotations on PDF page rotation.
- Normalize pen pressure for devices without a pressure range.
- PPT: single source of truth for slide strokes so ink displays and exports.
UI/UX:
- Material 3 typography, theme-aware colors (dark-mode fixes), hover cursors
and right-click/visible actions on desktop, keyboard shortcuts (undo/redo/
save/find), toolbar overflow handling, friendlier empty states, semantic OCR
status badges, relative timestamps, 1-based page indicators, large-deck PPT
navigation, and a scratchpad-scope label in split view.
Server (optional backend):
- Persist JWT secret (was per-process random), block path traversal in storage,
fix CORS '*'+credentials, add OCR job ownership checks, last-writer-wins sync
guard, constant-time login, and split out heavy OCR deps so the API/tests run
without them.
CI: Gitea workflows for format+analyze+test (Linux, system sqlite) and a
Windows release build; pristine `flutter analyze`, all Flutter and server tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:18:00 +08:00
|
|
|
}
|
2026-06-24 20:45:16 +08:00
|
|
|
|
|
|
|
|
/// Startup gate: shows [HomeScreen] only once a valid vault root folder has been
|
|
|
|
|
/// chosen. If none is set — or the saved folder no longer exists — it shows
|
|
|
|
|
/// [VaultSetupScreen] first (re-prompting on a missing folder rather than
|
|
|
|
|
/// silently scattering data elsewhere). Phase 0: records the vault path only;
|
|
|
|
|
/// editors still use SQLite.
|
|
|
|
|
class VaultGate extends StatefulWidget {
|
|
|
|
|
const VaultGate({super.key});
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
State<VaultGate> createState() => _VaultGateState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class _VaultGateState extends State<VaultGate> {
|
|
|
|
|
VaultService? _vault;
|
|
|
|
|
bool _valid = false;
|
|
|
|
|
bool _hadStoredPath = false;
|
|
|
|
|
bool _loading = true;
|
2026-06-24 23:05:10 +08:00
|
|
|
bool _migrating = false;
|
2026-06-24 20:45:16 +08:00
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void initState() {
|
|
|
|
|
super.initState();
|
|
|
|
|
_check();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> _check() async {
|
|
|
|
|
final vault = await VaultService.getInstance();
|
|
|
|
|
final valid = await vault.vaultRootValid();
|
|
|
|
|
if (!mounted) return;
|
|
|
|
|
setState(() {
|
|
|
|
|
_vault = vault;
|
|
|
|
|
_valid = valid;
|
|
|
|
|
// A stored-but-invalid path means the chosen folder went missing.
|
|
|
|
|
_hadStoredPath = (vault.vaultRoot?.isNotEmpty ?? false);
|
|
|
|
|
_loading = false;
|
|
|
|
|
});
|
2026-06-24 23:05:10 +08:00
|
|
|
if (valid) await _maybeMigrate(vault);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Run the one-time SQLite→sidecar migration ONCE per vault (Phase 5, §B).
|
|
|
|
|
/// Gated on [VaultService.vaultMigrationDone]; a fresh install (no legacy DB)
|
|
|
|
|
/// is a fast no-op. The live DB is first reopened at the vault cache location
|
|
|
|
|
/// so post-migration reads hit the new index, never the renamed legacy file.
|
|
|
|
|
Future<void> _maybeMigrate(VaultService vault) async {
|
|
|
|
|
// Move the live cache DB to the vault location now that the root is valid.
|
|
|
|
|
await DatabaseService.reopen();
|
|
|
|
|
if (vault.vaultMigrationDone) return;
|
|
|
|
|
if (mounted) setState(() => _migrating = true);
|
|
|
|
|
try {
|
|
|
|
|
await SqliteToSidecarMigrator(vault).run();
|
|
|
|
|
await vault.setVaultMigrationDone();
|
|
|
|
|
} catch (_) {
|
|
|
|
|
// A failed migration leaves the legacy DB intact (it is only renamed to
|
|
|
|
|
// `.premigration` after a successful pass) and the flag unset, so the
|
|
|
|
|
// next launch retries. Never block the user from reaching the app.
|
|
|
|
|
}
|
|
|
|
|
if (mounted) setState(() => _migrating = false);
|
2026-06-24 20:45:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
if (_loading) {
|
|
|
|
|
return const Scaffold(
|
|
|
|
|
body: Center(child: CircularProgressIndicator()),
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-06-24 23:05:10 +08:00
|
|
|
if (_migrating) {
|
|
|
|
|
return const Scaffold(
|
|
|
|
|
body: Center(
|
|
|
|
|
child: Column(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
children: [
|
|
|
|
|
CircularProgressIndicator(),
|
|
|
|
|
SizedBox(height: 16),
|
|
|
|
|
Text('Migrating your notebooks…'),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-06-24 20:45:16 +08:00
|
|
|
if (_valid) return const HomeScreen();
|
|
|
|
|
return VaultSetupScreen(
|
|
|
|
|
vaultService: _vault!,
|
|
|
|
|
missing: _hadStoredPath,
|
2026-06-24 23:05:10 +08:00
|
|
|
onVaultReady: () async {
|
|
|
|
|
if (_vault != null) await _maybeMigrate(_vault!);
|
|
|
|
|
if (mounted) setState(() => _valid = true);
|
|
|
|
|
},
|
2026-06-24 20:45:16 +08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|