mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 15:49:49 +00:00
203 lines
5.8 KiB
Dart
203 lines
5.8 KiB
Dart
import 'package:args/args.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:gopeed/util/analytics.dart';
|
|
import 'package:hotkey_manager/hotkey_manager.dart';
|
|
import 'package:window_manager/window_manager.dart';
|
|
|
|
import 'api/api.dart' as api;
|
|
import 'app/modules/app/controllers/app_controller.dart';
|
|
import 'app/rpc/webview_rpc_service.dart';
|
|
import 'app/modules/app/views/app_view.dart';
|
|
import 'core/libgopeed_boot.dart';
|
|
import 'database/database.dart';
|
|
import 'i18n/message.dart';
|
|
import 'util/browser_extension_host/browser_extension_host.dart';
|
|
import 'util/locale_manager.dart';
|
|
import 'util/log_util.dart';
|
|
import 'util/package_info.dart';
|
|
import 'util/scheme_register/scheme_register.dart';
|
|
import 'util/updater.dart';
|
|
import 'util/util.dart';
|
|
import 'app/services/location_keep_alive_coordinator.dart';
|
|
|
|
class StartupArgs {
|
|
static const flagHidden = "hidden";
|
|
|
|
/// Command line --hidden flag (for auto-start)
|
|
bool hiddenFromArgs = false;
|
|
|
|
StartupArgs._();
|
|
|
|
/// Parse from command line arguments only
|
|
static StartupArgs parse(List<String> arguments) {
|
|
final args = StartupArgs._();
|
|
try {
|
|
final parser = ArgParser()..addFlag(flagHidden);
|
|
final results = parser.parse(arguments);
|
|
args.hiddenFromArgs = results.flag(flagHidden);
|
|
} catch (e) {
|
|
// ignore parse errors
|
|
}
|
|
return args;
|
|
}
|
|
}
|
|
|
|
void main(List<String> arguments) async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
final args = StartupArgs.parse(arguments);
|
|
|
|
await init(args);
|
|
onStart();
|
|
|
|
runApp(const AppView());
|
|
}
|
|
|
|
Future<void> init(StartupArgs args) async {
|
|
// Note: WidgetsFlutterBinding.ensureInitialized() is already called in main()
|
|
if (Util.isMobile()) {
|
|
FlutterForegroundTask.initCommunicationPort();
|
|
}
|
|
await Util.initStorageDir();
|
|
await Database.instance.init();
|
|
if (Util.isDesktop()) {
|
|
await windowManager.ensureInitialized();
|
|
final windowState = Database.instance.getWindowState();
|
|
|
|
// Check if menubar mode is enabled (only for macOS)
|
|
final runAsMenubarApp =
|
|
Util.isMacos() && Database.instance.getRunAsMenubarApp();
|
|
|
|
final windowOptions = WindowOptions(
|
|
size: Size(windowState?.width ?? 800, windowState?.height ?? 600),
|
|
center: true,
|
|
skipTaskbar: runAsMenubarApp,
|
|
);
|
|
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
|
await windowManager.setPreventClose(true);
|
|
});
|
|
|
|
// Register Cmd+W hotkey on macOS to close window
|
|
if (Util.isMacos()) {
|
|
await hotKeyManager.unregisterAll();
|
|
HotKey hotKey = HotKey(
|
|
key: PhysicalKeyboardKey.keyW,
|
|
modifiers: [HotKeyModifier.meta],
|
|
scope: HotKeyScope.inapp,
|
|
);
|
|
await hotKeyManager.register(
|
|
hotKey,
|
|
keyDownHandler: (hotKey) {
|
|
windowManager.hide();
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
initLogger();
|
|
|
|
try {
|
|
await initPackageInfo();
|
|
} catch (e) {
|
|
logger.e("init package info fail", e);
|
|
}
|
|
|
|
final controller =
|
|
Get.put(AppController(hiddenFromArgs: args.hiddenFromArgs));
|
|
try {
|
|
await controller.loadStartConfig();
|
|
final startCfg = controller.startConfig.value;
|
|
final webViewRpcConfig = await WebViewRpcService.instance.start();
|
|
if (webViewRpcConfig != null) {
|
|
startCfg.webViewRpcConfig = webViewRpcConfig;
|
|
}
|
|
controller.runningPort.value = await LibgopeedBoot.instance.start(startCfg);
|
|
api.init(startCfg.network, controller.runningAddress(), startCfg.apiToken);
|
|
} catch (e) {
|
|
logger.e("libgopeed init fail", e);
|
|
}
|
|
|
|
try {
|
|
await controller.loadDownloaderConfig();
|
|
} catch (e) {
|
|
logger.e("load config fail", e);
|
|
}
|
|
|
|
// iOS location keep-alive coordinator
|
|
if (Util.isIOS()) {
|
|
try {
|
|
await Get.putAsync(() async => LocationKeepAliveCoordinator());
|
|
await Get.find<LocationKeepAliveCoordinator>().reconcile();
|
|
Get.find<LocationKeepAliveCoordinator>().startPolling();
|
|
} catch (e) {
|
|
logger.e("location keep-alive coordinator init fail", e);
|
|
}
|
|
}
|
|
|
|
() async {
|
|
if (Util.isDesktop()) {
|
|
try {
|
|
registerUrlScheme("gopeed");
|
|
if (controller.downloaderConfig.value.extra.defaultBtClient) {
|
|
registerDefaultTorrentClient();
|
|
}
|
|
} catch (e) {
|
|
logger.e("register scheme fail", e);
|
|
}
|
|
|
|
try {
|
|
await installHost();
|
|
} catch (e) {
|
|
logger.e("browser extension host binary install fail", e);
|
|
}
|
|
for (final browser in Browser.values) {
|
|
try {
|
|
await installManifest(browser);
|
|
} catch (e) {
|
|
logger.e(
|
|
"browser [${browser.name}] extension host integration fail", e);
|
|
}
|
|
}
|
|
|
|
try {
|
|
await installUpdater();
|
|
} catch (e) {
|
|
logger.e("updater install fail", e);
|
|
}
|
|
}
|
|
}();
|
|
}
|
|
|
|
Future<void> onStart() async {
|
|
// if is debug mode, check language message is complete,change debug locale to your comfortable language if you want
|
|
if (kDebugMode) {
|
|
final debugLang = getLocaleKey(debugLocale);
|
|
final fullMessages = messages.keys[debugLang];
|
|
messages.keys.keys.where((e) => e != debugLang).forEach((lang) {
|
|
final langMessages = messages.keys[lang];
|
|
if (langMessages == null) {
|
|
logger.w("missing language: $lang");
|
|
return;
|
|
}
|
|
final missingKeys =
|
|
fullMessages!.keys.where((key) => langMessages[key] == null);
|
|
if (missingKeys.isNotEmpty) {
|
|
logger.w("missing language: $lang, keys: $missingKeys");
|
|
}
|
|
});
|
|
}
|
|
|
|
if (Config.isConfigured && Database.instance.getAnalyticsEnabled()) {
|
|
try {
|
|
await Analytics.instance.init();
|
|
await Analytics.instance.logAppOpen();
|
|
} catch (e) {
|
|
logger.w("GA4 init failed: $e");
|
|
}
|
|
}
|
|
}
|