import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:hiddify/core/app/app.dart'; import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/data/data_providers.dart'; import 'package:hiddify/features/common/active_profile/active_profile_notifier.dart'; import 'package:hiddify/features/common/common.dart'; import 'package:hiddify/features/common/window/window_controller.dart'; import 'package:hiddify/features/system_tray/system_tray.dart'; import 'package:hiddify/services/deep_link_service.dart'; import 'package:hiddify/services/service_providers.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:loggy/loggy.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stack_trace/stack_trace.dart' as stack_trace; import 'package:window_manager/window_manager.dart'; final _loggy = Loggy('bootstrap'); final _stopWatch = Stopwatch(); Future lazyBootstrap(WidgetsBinding widgetsBinding) async { _stopWatch.start(); // temporary solution: https://github.com/rrousselGit/riverpod/issues/1874 FlutterError.demangleStackTrace = (StackTrace stack) { if (stack is stack_trace.Trace) return stack.vmTrace; if (stack is stack_trace.Chain) return stack.toTrace().vmTrace; return stack; }; FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); if (PlatformUtils.isDesktop) await windowManager.ensureInitialized(); final sharedPreferences = await SharedPreferences.getInstance(); final container = ProviderContainer( overrides: [sharedPreferencesProvider.overrideWithValue(sharedPreferences)], ); // Loggy.initLoggy(logPrinter: const PrettyPrinter()); final filesEditor = container.read(filesEditorServiceProvider); await filesEditor.init(); Loggy.initLoggy( logPrinter: MultiLogPrinter( const PrettyPrinter(), FileLogPrinter(filesEditor.appLogsPath), ), ); _loggy.debug( "os: ${Platform.operatingSystem}(${Platform.operatingSystemVersion})", ); _loggy.debug("basic setup took [${_stopWatch.elapsedMilliseconds}]ms"); final silentStart = container.read(prefsControllerProvider).general.silentStart; if (silentStart) { FlutterNativeSplash.remove(); } if (PlatformUtils.isDesktop) { await container.read(windowControllerProvider.future); } await initAppServices(container.read); await initControllers(container.read); runApp( ProviderScope( parent: container, child: const AppView(), ), ); if (!silentStart) FlutterNativeSplash.remove(); _stopWatch.stop(); _loggy.debug("bootstrapping took [${_stopWatch.elapsedMilliseconds}]ms"); } Future initAppServices( Result Function(ProviderListenable) read, ) async { _loggy.debug("initializing app services"); await Future.wait( [ read(connectivityServiceProvider).init(), read(notificationServiceProvider).init(), ], ); _loggy.debug('initialized app services'); } Future initControllers( Result Function(ProviderListenable) read, ) async { _loggy.debug("initializing controllers"); await Future.wait( [ read(activeProfileProvider.future), read(deepLinkServiceProvider.future), read(runtimeDetailsNotifierProvider.future), if (PlatformUtils.isDesktop) read(systemTrayControllerProvider.future), ], ); _loggy.debug("initialized base controllers"); }