2023-07-06 17:18:41 +03:30
|
|
|
import 'dart:async';
|
|
|
|
|
|
2023-08-24 14:49:23 +03:30
|
|
|
import 'package:flutter/foundation.dart';
|
2023-07-06 17:18:41 +03:30
|
|
|
import 'package:flutter/material.dart';
|
2023-12-22 14:16:24 +03:30
|
|
|
import 'package:flutter_loggy/flutter_loggy.dart';
|
2023-07-06 17:18:41 +03:30
|
|
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
2023-12-22 14:16:24 +03:30
|
|
|
import 'package:hiddify/core/analytics/analytics_controller.dart';
|
2023-12-01 12:56:24 +03:30
|
|
|
import 'package:hiddify/core/app_info/app_info_provider.dart';
|
2023-12-22 14:16:24 +03:30
|
|
|
import 'package:hiddify/core/directories/directories_provider.dart';
|
|
|
|
|
import 'package:hiddify/core/logger/logger.dart';
|
|
|
|
|
import 'package:hiddify/core/logger/logger_controller.dart';
|
2023-12-01 12:56:24 +03:30
|
|
|
import 'package:hiddify/core/model/environment.dart';
|
|
|
|
|
import 'package:hiddify/core/preferences/general_preferences.dart';
|
2023-12-09 19:38:06 +03:30
|
|
|
import 'package:hiddify/core/preferences/preferences_migration.dart';
|
2023-12-01 12:56:24 +03:30
|
|
|
import 'package:hiddify/core/preferences/preferences_provider.dart';
|
|
|
|
|
import 'package:hiddify/features/app/widget/app.dart';
|
2023-12-28 23:16:56 +03:30
|
|
|
import 'package:hiddify/features/auto_start/notifier/auto_start_notifier.dart';
|
2023-11-25 22:00:40 +03:30
|
|
|
import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart';
|
2023-11-28 18:24:31 +03:30
|
|
|
import 'package:hiddify/features/log/data/log_data_providers.dart';
|
2023-11-26 21:20:58 +03:30
|
|
|
import 'package:hiddify/features/profile/data/profile_data_providers.dart';
|
|
|
|
|
import 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';
|
2023-12-28 23:16:56 +03:30
|
|
|
import 'package:hiddify/features/system_tray/notifier/system_tray_notifier.dart';
|
|
|
|
|
import 'package:hiddify/features/window/notifier/window_notifier.dart';
|
2023-07-06 17:18:41 +03:30
|
|
|
import 'package:hiddify/services/deep_link_service.dart';
|
2023-12-01 12:56:24 +03:30
|
|
|
import 'package:hiddify/singbox/service/singbox_service_provider.dart';
|
2023-07-06 17:18:41 +03:30
|
|
|
import 'package:hiddify/utils/utils.dart';
|
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
|
import 'package:loggy/loggy.dart';
|
2023-09-17 00:23:31 +03:30
|
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
2023-07-06 17:18:41 +03:30
|
|
|
|
2023-09-12 15:22:58 +03:30
|
|
|
Future<void> lazyBootstrap(
|
|
|
|
|
WidgetsBinding widgetsBinding,
|
|
|
|
|
Environment env,
|
|
|
|
|
) async {
|
2023-07-15 18:00:44 +03:30
|
|
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
2023-09-18 22:34:17 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
Loggy.initLoggy(logPrinter: const PrettyDeveloperPrinter());
|
|
|
|
|
|
|
|
|
|
FlutterError.onError = Logger.logFlutterError;
|
|
|
|
|
WidgetsBinding.instance.platformDispatcher.onError =
|
|
|
|
|
Logger.logPlatformDispatcherError;
|
|
|
|
|
|
|
|
|
|
final stopWatch = Stopwatch()..start();
|
2023-07-15 18:00:44 +03:30
|
|
|
|
2023-07-06 17:18:41 +03:30
|
|
|
final container = ProviderContainer(
|
2023-09-12 15:22:58 +03:30
|
|
|
overrides: [
|
2023-12-01 12:56:24 +03:30
|
|
|
environmentProvider.overrideWithValue(env),
|
2023-09-12 15:22:58 +03:30
|
|
|
],
|
2023-07-06 17:18:41 +03:30
|
|
|
);
|
|
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
await _init(
|
|
|
|
|
"directories",
|
|
|
|
|
() => container.read(appDirectoriesProvider.future),
|
|
|
|
|
);
|
|
|
|
|
LoggerController.init(container.read(logPathResolverProvider).appFile().path);
|
2023-12-09 19:38:06 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
final appInfo = await _init(
|
|
|
|
|
"app info",
|
|
|
|
|
() => container.read(appInfoProvider.future),
|
|
|
|
|
);
|
|
|
|
|
await _init(
|
|
|
|
|
"preferences",
|
|
|
|
|
() => container.read(sharedPreferencesProvider.future),
|
|
|
|
|
);
|
2023-09-17 00:23:31 +03:30
|
|
|
|
2023-12-23 11:01:48 +03:30
|
|
|
final enableAnalytics =
|
|
|
|
|
await container.read(analyticsControllerProvider.future);
|
2023-12-22 14:16:24 +03:30
|
|
|
if (enableAnalytics) {
|
|
|
|
|
await _init(
|
|
|
|
|
"analytics",
|
|
|
|
|
() => container
|
|
|
|
|
.read(analyticsControllerProvider.notifier)
|
|
|
|
|
.enableAnalytics(),
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-09-17 00:23:31 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
await _init(
|
|
|
|
|
"preferences migration",
|
|
|
|
|
() async {
|
|
|
|
|
try {
|
|
|
|
|
await PreferencesMigration(
|
|
|
|
|
sharedPreferences:
|
|
|
|
|
container.read(sharedPreferencesProvider).requireValue,
|
|
|
|
|
).migrate();
|
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
Logger.bootstrap.error("preferences migration failed", e, stackTrace);
|
|
|
|
|
if (env == Environment.dev) rethrow;
|
|
|
|
|
Logger.bootstrap.info("clearing preferences");
|
|
|
|
|
await container.read(sharedPreferencesProvider).requireValue.clear();
|
|
|
|
|
}
|
2023-09-17 00:23:31 +03:30
|
|
|
},
|
|
|
|
|
);
|
2023-12-21 16:57:58 +03:30
|
|
|
|
2023-09-07 13:43:46 +03:30
|
|
|
final debug = container.read(debugModeNotifierProvider) || kDebugMode;
|
2023-08-24 16:18:05 +03:30
|
|
|
|
2023-12-28 23:16:56 +03:30
|
|
|
if (PlatformUtils.isDesktop) {
|
|
|
|
|
await _init(
|
|
|
|
|
"window controller",
|
|
|
|
|
() => container.read(windowNotifierProvider.future),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
final silentStart = container.read(silentStartNotifierProvider);
|
|
|
|
|
Logger.bootstrap
|
|
|
|
|
.debug("silent start [${silentStart ? "Enabled" : "Disabled"}]");
|
|
|
|
|
if (!silentStart) {
|
|
|
|
|
await container.read(windowNotifierProvider.notifier).open(focus: false);
|
|
|
|
|
} else {
|
|
|
|
|
Logger.bootstrap.debug("silent start, remain hidden accessible via tray");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _init(
|
|
|
|
|
"auto start service",
|
|
|
|
|
() => container.read(autoStartNotifierProvider.future),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
await _init(
|
|
|
|
|
"logs repository",
|
|
|
|
|
() => container.read(logRepositoryProvider.future),
|
|
|
|
|
);
|
|
|
|
|
await _init("logger controller", () => LoggerController.postInit(debug));
|
|
|
|
|
Logger.bootstrap.info(appInfo.format());
|
2023-07-06 17:18:41 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
await _init(
|
|
|
|
|
"geo assets repository",
|
|
|
|
|
() => container.read(geoAssetRepositoryProvider.future),
|
|
|
|
|
);
|
|
|
|
|
await _init(
|
|
|
|
|
"profile repository",
|
|
|
|
|
() => container.read(profileRepositoryProvider.future),
|
|
|
|
|
);
|
2023-08-23 00:06:51 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
await _init(
|
|
|
|
|
"sing-box",
|
|
|
|
|
() => container.read(singboxServiceProvider).init(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await _safeInit(
|
|
|
|
|
"active profile",
|
|
|
|
|
() => container.read(activeProfileProvider.future),
|
|
|
|
|
);
|
|
|
|
|
await _init(
|
|
|
|
|
"deep link service",
|
|
|
|
|
() => container.read(deepLinkServiceProvider.future),
|
|
|
|
|
);
|
2023-11-12 21:55:17 +03:30
|
|
|
|
|
|
|
|
if (PlatformUtils.isDesktop) {
|
2023-12-22 14:16:24 +03:30
|
|
|
await _safeInit(
|
|
|
|
|
"system tray",
|
2023-12-28 23:16:56 +03:30
|
|
|
() => container.read(systemTrayNotifierProvider.future),
|
2023-12-22 14:16:24 +03:30
|
|
|
timeout: 1000,
|
|
|
|
|
);
|
2023-11-12 21:55:17 +03:30
|
|
|
}
|
2023-07-06 17:18:41 +03:30
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
Logger.bootstrap.info("bootstrap took [${stopWatch.elapsedMilliseconds}ms]");
|
|
|
|
|
stopWatch.stop();
|
|
|
|
|
|
2023-07-06 17:18:41 +03:30
|
|
|
runApp(
|
|
|
|
|
ProviderScope(
|
|
|
|
|
parent: container,
|
2023-09-18 14:01:44 +03:30
|
|
|
child: SentryUserInteractionWidget(
|
2023-12-01 12:56:24 +03:30
|
|
|
child: const App(),
|
2023-09-18 14:01:44 +03:30
|
|
|
),
|
2023-07-06 17:18:41 +03:30
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
2023-12-28 23:16:56 +03:30
|
|
|
FlutterNativeSplash.remove();
|
2023-08-24 14:49:23 +03:30
|
|
|
}
|
|
|
|
|
|
2023-12-22 14:16:24 +03:30
|
|
|
Future<T> _init<T>(
|
|
|
|
|
String name,
|
|
|
|
|
Future<T> Function() initializer, {
|
|
|
|
|
int? timeout,
|
|
|
|
|
}) async {
|
|
|
|
|
final stopWatch = Stopwatch()..start();
|
|
|
|
|
Future<T> func() => timeout != null
|
|
|
|
|
? initializer().timeout(Duration(milliseconds: timeout))
|
|
|
|
|
: initializer();
|
|
|
|
|
try {
|
|
|
|
|
final result = await func();
|
|
|
|
|
Logger.bootstrap
|
|
|
|
|
.debug("[$name] initialized in ${stopWatch.elapsedMilliseconds}ms");
|
|
|
|
|
return result;
|
|
|
|
|
} catch (e, stackTrace) {
|
|
|
|
|
Logger.bootstrap.error("[$name] error initializing", e, stackTrace);
|
|
|
|
|
rethrow;
|
|
|
|
|
} finally {
|
|
|
|
|
stopWatch.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<T?> _safeInit<T>(
|
|
|
|
|
String name,
|
|
|
|
|
Future<T> Function() initializer, {
|
|
|
|
|
int? timeout,
|
|
|
|
|
}) async {
|
|
|
|
|
try {
|
|
|
|
|
return await _init(name, initializer, timeout: timeout);
|
|
|
|
|
} catch (_) {
|
|
|
|
|
return null;
|
2023-09-18 14:01:44 +03:30
|
|
|
}
|
2023-07-06 17:18:41 +03:30
|
|
|
}
|