import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../application/focus_seed_controller.dart'; import '../../application/focus_timer_controller.dart'; import '../../data/focus_seed_store.dart'; import '../../l10n/l10n.dart'; import '../../models/appearance_preference.dart'; import '../../models/language_preference.dart'; import '../../widgets/loading_view.dart'; import '../journey/journey_screen.dart'; import '../me/me_screen.dart'; import '../today/today_screen.dart'; class FocusSeedHome extends StatefulWidget { const FocusSeedHome({ required this.appearance, required this.onAppearanceChanged, required this.language, required this.showLanguageTools, required this.onLanguageChanged, this.focusSeedStore, super.key, }); final AppearancePreference appearance; final ValueChanged onAppearanceChanged; final LanguagePreference language; final bool showLanguageTools; final ValueChanged onLanguageChanged; final FocusSeedStore? focusSeedStore; @override State createState() => _FocusSeedHomeState(); } class _FocusSeedHomeState extends State { FocusSeedController? _controller; FocusTimerController? _timerController; int _tabIndex = 0; @override void didChangeDependencies() { super.didChangeDependencies(); if (_controller != null) { return; } _controller = FocusSeedController( store: widget.focusSeedStore, defaultHabitTitles: localizedStarterHabits(context.l10n), ); _timerController = FocusTimerController( onCompleted: (minutes) async { final saved = await _controller!.completeFocusSession(minutes); if (saved) { await HapticFeedback.mediumImpact(); } }, ); _controller!.load(); } @override Widget build(BuildContext context) { final controller = _controller; final timerController = _timerController; if (controller == null || timerController == null) { return const Scaffold(body: SafeArea(child: LoadingView())); } return AnimatedBuilder( animation: controller, builder: (context, _) { controller.updateDefaultHabitTitles( localizedStarterHabits(context.l10n), ); final state = controller.state; if (controller.isLoading) { return const Scaffold(body: SafeArea(child: LoadingView())); } if (state == null) { final l10n = context.l10n; return Scaffold( body: SafeArea( child: Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.error_outline_rounded, size: 42), const SizedBox(height: 12), Text( _messageForError(l10n, controller.error) ?? l10n.couldNotOpenApp, textAlign: TextAlign.center, ), const SizedBox(height: 16), FilledButton.icon( onPressed: controller.load, icon: const Icon(Icons.refresh_rounded), label: Text(l10n.tryAgain), ), ], ), ), ), ), ); } final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: isDark ? Brightness.light : Brightness.dark, systemNavigationBarColor: theme.navigationBarTheme.backgroundColor ?? theme.colorScheme.surface, systemNavigationBarIconBrightness: isDark ? Brightness.light : Brightness.dark, ), child: Scaffold( body: SafeArea( child: IndexedStack( index: _tabIndex, children: [ TodayScreen( controller: controller, timerController: timerController, ), JourneyScreen(controller: controller), MeScreen( controller: controller, appearance: widget.appearance, onAppearanceChanged: widget.onAppearanceChanged, language: widget.language, showLanguageTools: widget.showLanguageTools, onLanguageChanged: widget.onLanguageChanged, ), ], ), ), bottomNavigationBar: NavigationBar( selectedIndex: _tabIndex, onDestinationSelected: (index) { HapticFeedback.selectionClick(); setState(() => _tabIndex = index); }, destinations: [ NavigationDestination( icon: const Icon(Icons.eco_outlined), selectedIcon: const Icon(Icons.eco_rounded), label: context.l10n.navToday, ), NavigationDestination( icon: const Icon(Icons.landscape_outlined), selectedIcon: const Icon(Icons.landscape_rounded), label: context.l10n.navJourney, ), NavigationDestination( icon: const Icon(Icons.person_outline_rounded), selectedIcon: const Icon(Icons.person_rounded), label: context.l10n.navMe, ), ], ), ), ); }, ); } @override void dispose() { _timerController?.dispose(); _controller?.dispose(); super.dispose(); } } String? _messageForError(AppLocalizations l10n, FocusSeedError? error) { return switch (error) { FocusSeedError.openFailed => l10n.openFailed, FocusSeedError.saveFailed => l10n.saveFailed, null => null, }; }