todo-app/lib/main.dart
Krzysztof kuhy Rudnicki ce2ea5b410 Simplify capture UI behind an advanced-mode toggle, add usage analytics
Hide priority/status/template/mode chrome and routine sync-status text
behind a Firebase-synced "Enable advanced" setting (default off); remove
the Capture title and Save button in favor of autosave + a plain reset
icon; sort notes by priority then recency; add interaction-only usage
analytics buffered locally and flushed to Firebase alongside note sync.

Code review (self + follow-up verification pass) found and fixed 3 real
bugs during this work: a widget-key placement bug that discarded an
in-progress draft when advancedMode was toggled mid-typing, a data-loss
bug in the analytics buffer's flush-and-clear logic under concurrent
cap-eviction, and two spots where an expired/wrong-account Firebase
session (FirebaseAuthError) escaped a narrower catch clause and would
have failed an otherwise-successful sync pass.

Also fixes an unrelated pre-existing test-isolation bug in
wrapper_server_test.dart, which was reading the real
~/.config/todo/firebase_auth.json instead of a test-scoped path.

320 tests, 100% line coverage on all touched files (one pre-existing,
out-of-scope 5-line gap in settings_screen.dart unrelated to this
change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 21:30:40 +02:00

71 lines
2.2 KiB
Dart

// coverage:ignore-file
// App bootstrap: opens the platform's note store and calls runApp. Exercised
// end-to-end by running the app, not unit tests.
import 'package:flutter/material.dart';
import 'package:todo/analytics/analytics_service.dart';
import 'package:todo/data/app_settings.dart';
import 'package:todo/data/note_repository.dart';
import 'package:todo/data/repository_factory.dart';
import 'package:todo/frame_stats.dart';
import 'package:todo/ui/capture_screen.dart';
import 'package:todo/ui/theme.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
installFrameStats();
// Where the log lives, and whether a legacy sqlite DB needs importing, is
// platform-specific and resolved by a conditional import: `dart:io` cannot be
// imported at all in a web compile, and the desktop app is now a web build.
final repository = await openRepository();
final appSettings = ValueNotifier(await AppSettings.load());
final analytics = AnalyticsService(nodeId: repository.nodeId);
runApp(
TodoApp(
repository: repository,
appSettings: appSettings,
analytics: analytics,
),
);
}
/// Root widget. Holds the single [NoteRepository] instance and hands it
/// to the screens that need it.
class TodoApp extends StatelessWidget {
/// Creates a [TodoApp] wrapping the given [repository], [appSettings] and
/// [analytics].
const TodoApp({
required this.repository,
required this.appSettings,
required this.analytics,
super.key,
});
/// The single, app-wide note store, injected into every screen.
final NoteRepository repository;
/// The single, app-wide preferences notifier (currently just
/// `advancedMode`), injected into every screen that reads or changes it.
final ValueNotifier<AppSettings> appSettings;
/// The single, app-wide analytics logger, injected into every screen that
/// reports interaction events.
final AnalyticsService analytics;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'todo',
theme: buildLightTheme(),
darkTheme: buildDarkTheme(),
home: CaptureScreen(
repository: repository,
appSettings: appSettings,
analytics: analytics,
),
);
}
}