123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- import 'dart:io';
- import 'package:device_info_plus/device_info_plus.dart';
- import 'package:easy_localization/easy_localization.dart';
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:flutter_displaymode/flutter_displaymode.dart';
- import 'package:hooks_riverpod/hooks_riverpod.dart';
- import 'package:immich_mobile/constants/locales.dart';
- import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
- import 'package:immich_mobile/modules/backup/models/backup_album.model.dart';
- import 'package:immich_mobile/modules/backup/models/duplicated_asset.model.dart';
- import 'package:immich_mobile/routing/router.dart';
- import 'package:immich_mobile/routing/tab_navigation_observer.dart';
- import 'package:immich_mobile/shared/models/album.dart';
- import 'package:immich_mobile/shared/models/android_device_asset.dart';
- import 'package:immich_mobile/shared/models/asset.dart';
- import 'package:immich_mobile/shared/models/etag.dart';
- import 'package:immich_mobile/shared/models/exif_info.dart';
- import 'package:immich_mobile/shared/models/ios_device_asset.dart';
- import 'package:immich_mobile/shared/models/logger_message.model.dart';
- import 'package:immich_mobile/shared/models/store.dart';
- import 'package:immich_mobile/shared/models/user.dart';
- import 'package:immich_mobile/shared/providers/app_state.provider.dart';
- import 'package:immich_mobile/shared/providers/db.provider.dart';
- import 'package:immich_mobile/shared/providers/release_info.provider.dart';
- import 'package:immich_mobile/shared/services/immich_logger.service.dart';
- import 'package:immich_mobile/shared/services/local_notification.service.dart';
- import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
- import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
- import 'package:immich_mobile/utils/immich_app_theme.dart';
- import 'package:immich_mobile/utils/migration.dart';
- import 'package:isar/isar.dart';
- import 'package:logging/logging.dart';
- import 'package:path_provider/path_provider.dart';
- void main() async {
- WidgetsFlutterBinding.ensureInitialized();
- final db = await loadDb();
- await initApp();
- await migrateDatabaseIfNeeded(db);
- runApp(getMainWidget(db));
- }
- Future<void> initApp() async {
- await EasyLocalization.ensureInitialized();
- if (kReleaseMode && Platform.isAndroid) {
- try {
- await FlutterDisplayMode.setHighRefreshRate();
- debugPrint("Enabled high refresh mode");
- } catch (e) {
- debugPrint("Error setting high refresh rate: $e");
- }
- }
- // Initialize Immich Logger Service
- ImmichLogger();
- var log = Logger("ImmichErrorLogger");
- FlutterError.onError = (details) {
- FlutterError.presentError(details);
- log.severe(
- 'Catch all error: ${details.toString()} - ${details.exception} - ${details.library} - ${details.context} - ${details.stack}',
- details,
- details.stack,
- );
- };
- PlatformDispatcher.instance.onError = (error, stack) {
- log.severe('Catch all error: ${error.toString()} - $error', error, stack);
- return true;
- };
- }
- Future<Isar> loadDb() async {
- final dir = await getApplicationDocumentsDirectory();
- Isar db = await Isar.open(
- [
- StoreValueSchema,
- ExifInfoSchema,
- AssetSchema,
- AlbumSchema,
- UserSchema,
- BackupAlbumSchema,
- DuplicatedAssetSchema,
- LoggerMessageSchema,
- ETagSchema,
- if (Platform.isAndroid) AndroidDeviceAssetSchema,
- if (Platform.isIOS) IOSDeviceAssetSchema,
- ],
- directory: dir.path,
- maxSizeMiB: 256,
- );
- Store.init(db);
- return db;
- }
- Widget getMainWidget(Isar db) {
- return EasyLocalization(
- supportedLocales: locales,
- path: translationsPath,
- useFallbackTranslations: true,
- fallbackLocale: locales.first,
- child: ProviderScope(
- overrides: [dbProvider.overrideWithValue(db)],
- child: const ImmichApp(),
- ),
- );
- }
- class ImmichApp extends ConsumerStatefulWidget {
- const ImmichApp({super.key});
- @override
- ImmichAppState createState() => ImmichAppState();
- }
- class ImmichAppState extends ConsumerState<ImmichApp>
- with WidgetsBindingObserver {
- @override
- void didChangeAppLifecycleState(AppLifecycleState state) {
- switch (state) {
- case AppLifecycleState.resumed:
- debugPrint("[APP STATE] resumed");
- ref.read(appStateProvider.notifier).handleAppResume();
- break;
- case AppLifecycleState.inactive:
- debugPrint("[APP STATE] inactive");
- ref.read(appStateProvider.notifier).handleAppInactivity();
- break;
- case AppLifecycleState.paused:
- debugPrint("[APP STATE] paused");
- ref.read(appStateProvider.notifier).handleAppPause();
- break;
- case AppLifecycleState.detached:
- debugPrint("[APP STATE] detached");
- ref.read(appStateProvider.notifier).handleAppDetached();
- break;
- case AppLifecycleState.hidden:
- debugPrint("[APP STATE] hidden");
- ref.read(appStateProvider.notifier).handleAppHidden();
- break;
- }
- }
- Future<void> initApp() async {
- WidgetsBinding.instance.addObserver(this);
- // Draw the app from edge to edge
- SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
- // Sets the navigation bar color
- SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(
- systemNavigationBarColor: Colors.transparent,
- );
- if (Platform.isAndroid) {
- // Android 8 does not support transparent app bars
- final info = await DeviceInfoPlugin().androidInfo;
- if (info.version.sdkInt <= 26) {
- overlayStyle =
- MediaQuery.of(context).platformBrightness == Brightness.light
- ? SystemUiOverlayStyle.light
- : SystemUiOverlayStyle.dark;
- }
- }
- SystemChrome.setSystemUIOverlayStyle(overlayStyle);
- await ref.read(localNotificationService).setup();
- }
- @override
- initState() {
- super.initState();
- initApp().then((_) => debugPrint("App Init Completed"));
- WidgetsBinding.instance.addPostFrameCallback((_) {
- // needs to be delayed so that EasyLocalization is working
- ref.read(backgroundServiceProvider).resumeServiceIfEnabled();
- });
- }
- @override
- void dispose() {
- WidgetsBinding.instance.removeObserver(this);
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- var router = ref.watch(appRouterProvider);
- ref.watch(releaseInfoProvider.notifier).checkGithubReleaseInfo();
- return MaterialApp(
- localizationsDelegates: context.localizationDelegates,
- supportedLocales: context.supportedLocales,
- locale: context.locale,
- debugShowCheckedModeBanner: false,
- home: Stack(
- children: [
- MaterialApp.router(
- title: 'Immich',
- debugShowCheckedModeBanner: false,
- themeMode: ref.watch(immichThemeProvider),
- darkTheme: immichDarkTheme,
- theme: immichLightTheme,
- routeInformationParser: router.defaultRouteParser(),
- routerDelegate: router.delegate(
- navigatorObservers: () => [TabNavigationObserver(ref: ref)],
- ),
- ),
- const ImmichLoadingOverlay(),
- const VersionAnnouncementOverlay(),
- ],
- ),
- );
- }
- }
|