// SPDX-FileCopyrightText: 2026 FocusFlow contributors // SPDX-License-Identifier: AGPL-3.0-only /// Launches the FocusFlow Flutter desktop application. library; import 'package:flutter/material.dart'; import 'package:scheduler_core/scheduler_core.dart' as scheduler_core show logger; import 'app/focus_flow_app.dart'; import 'app/persistent_scheduler_composition.dart'; import 'app/runtime/focus_flow_file_logger.dart'; import 'app/runtime/focus_flow_runtime_config.dart'; export 'app/demo_scheduler_composition.dart'; export 'app/focus_flow_app.dart'; export 'app/persistent_scheduler_composition.dart'; /// Starts the FocusFlow app with the persistent SQLite scheduler composition. Future main() async { WidgetsFlutterBinding.ensureInitialized(); var logger = FocusFlowFileLogger.disabled(); try { final config = await FocusFlowRuntimeConfig.load(); logger = await FocusFlowFileLogger.open(config); scheduler_core.logger.info(() => 'FocusFlow startup started.'); scheduler_core.logger.debug( () => 'Runtime config loaded. fileLogging=${logger.isEnabled}', ); final composition = await PersistentSchedulerComposition.open( logger: logger, uiTimeZone: config.timeZone, ); scheduler_core.logger.info(() => 'FocusFlow startup completed.'); runApp(FocusFlowApp(composition: composition)); } on Object catch (error, stackTrace) { scheduler_core.logger.error( () => 'FocusFlow startup failed.', error: error, stackTrace: stackTrace, ); runApp(_StartupFailureApp(message: error.toString())); } } /// Minimal failure app shown when persistent startup cannot finish. class _StartupFailureApp extends StatelessWidget { /// Creates a startup failure app with [message]. const _StartupFailureApp({required this.message}); /// Diagnostic startup failure message. final String message; /// Builds the widget subtree for this component. /// The method translates the current widget configuration and state into Flutter UI without mutating scheduler domain data. @override Widget build(BuildContext context) { return MaterialApp( title: 'FocusFlow', debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: Padding( padding: const EdgeInsets.all(24), child: Text('Unable to open local schedule data.\n$message'), ), ), ), ); } }