/
dbnrbv
/
Habit
Обзор
Документация
Войти
/
dbnrbv
/
Habit
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop
lib/main.dart
170 строк
5 KB
Daba
test coverage > 50%: add test
04 июн 2026, 17:57
04 июн 2026, 17:57
fd28867
Код
Авторство
О чём код?
// coverage:ignore-file import 'dart:ui' as ui show PlatformDispatcher; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'core/constants/app_constants.dart'; import 'core/utils/app_logger.dart'; import 'firebase_options.dart'; import 'features/auth/presentation/auth_provider.dart'; import 'features/auth/presentation/auth_screen.dart'; import 'features/habits/presentation/home_screen.dart'; import 'features/habits/providers/habit_providers.dart'; import 'core/services/scaffold_messenger_service.dart'; import 'core/theme/app_theme.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); FlutterError.onError = (FlutterErrorDetails details) { AppLogger.e('FLUTTER', 'Error', error: details.exception); }; ui.PlatformDispatcher.instance.onError = (error, stack) { AppLogger.e('DART', 'Uncaught error', error: error); return true; }; await _initHive(); await _initFirebase(); runApp(const ProviderScope(child: MyApp())); } Future<void> _initHive() async { try { await Hive.initFlutter(); AppLogger.d('MAIN', 'Hive initialized'); await _openBoxSafe<Map>(AppConstants.habitsBoxName); await _openBoxSafe<Map>(AppConstants.quoteBoxName); await _openBoxSafe<Map>(AppConstants.executionsBoxName); await _openBoxSafe(AppConstants.userBoxName); await _openBoxSafe<Map>(AppConstants.syncMetadataBoxName); } catch (e) { AppLogger.e('MAIN', 'CRITICAL Hive error', error: e); runApp(const MaterialApp( home: Scaffold( body: Center( child: Text( 'Ошибка инициализации хранилища. Перезапустите приложение.', textAlign: TextAlign.center, ), ), ), )); } } /// Открывает Hive box. При повреждении — удаляет и пересоздаёт (данные теряются, /// но приложение не падает; при следующей синхронизации данные восстановятся). Future<void> _openBoxSafe<T>(String name) async { try { await Hive.openBox<T>(name); AppLogger.d('MAIN', 'Box "$name" opened'); } catch (e) { AppLogger.w('MAIN', 'Box "$name" corrupted, recreating: $e'); try { await Hive.deleteBoxFromDisk(name); await Hive.openBox<T>(name); AppLogger.d('MAIN', 'Box "$name" recreated successfully'); } catch (e2) { // Если и пересоздание упало — пробрасываем наверх, поймает внешний catch AppLogger.e('MAIN', 'Box "$name" recreation failed', error: e2); rethrow; } } } Future<void> _initFirebase() async { try { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform); AppLogger.d('MAIN', 'Firebase initialized'); } catch (e) { AppLogger.e('MAIN', 'CRITICAL Firebase error', error: e); runApp(const MaterialApp( home: Scaffold( body: Center( child: Text( 'Ошибка инициализации Firebase. Проверьте подключение к интернету.', textAlign: TextAlign.center, ), ), ), )); } } class MyApp extends ConsumerWidget { const MyApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final lightColorScheme = ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.light, ); final darkColorScheme = ColorScheme.fromSeed( seedColor: Colors.blue, brightness: Brightness.dark, ); final themeMode = ref.watch(themeModeProvider); return MaterialApp( debugShowCheckedModeBanner: false, scaffoldMessengerKey: rootScaffoldMessengerKey, navigatorKey: rootNavigatorKey, themeMode: themeMode, theme: ThemeData( useMaterial3: true, colorScheme: lightColorScheme, inputDecorationTheme: InputDecorationTheme( border: const OutlineInputBorder(), filled: true, fillColor: lightColorScheme.surfaceContainerHighest, ), ), darkTheme: ThemeData( useMaterial3: true, colorScheme: darkColorScheme, inputDecorationTheme: InputDecorationTheme( border: const OutlineInputBorder(), filled: true, fillColor: darkColorScheme.surfaceContainerHighest, ), ), home: const AuthStateSwitcher(), ); } } class AuthStateSwitcher extends ConsumerWidget { const AuthStateSwitcher({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final authState = ref.watch(authStateChangesProvider); ref.listen(authStateChangesProvider, (previous, next) { final previousUid = previous?.valueOrNull?.uid; final nextUid = next.valueOrNull?.uid; if (nextUid != null && nextUid != previousUid) { ref.read(syncStatusProvider.notifier).startAutoSync(nextUid); } }); return authState.when( data: (firebaseUser) => firebaseUser == null ? const AuthScreen() : const HomeScreen(), loading: () => const Scaffold( body: Center(child: CircularProgressIndicator()), ), error: (_, __) => const Scaffold( body: Center(child: Text('Ошибка авторизации')), ), ); } }