import 'dart:io'; import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; // import 'package:flutter_easyloading/flutter_easyloading.dart'; // 已替换为自定义组件 import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter/services.dart'; // import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart'; import 'package:get/get.dart'; // import 'package:flutter_stripe/flutter_stripe.dart'; import 'package:kaer_with_panels/app/themes/kr_theme_service.dart'; import 'package:kaer_with_panels/app/localization/getx_translations.dart'; import 'package:kaer_with_panels/app/localization/kr_language_utils.dart'; import 'package:kaer_with_panels/app/routes/app_pages.dart'; import 'package:kaer_with_panels/app/widgets/kr_local_image.dart'; import 'package:kaer_with_panels/app/utils/kr_window_manager.dart'; import 'app/services/singbox_imp/kr_sing_box_imp.dart'; import 'app/common/app_run_data.dart'; import 'app/utils/kr_secure_storage.dart'; import 'app/common/app_config.dart'; import 'app/services/kr_site_config_service.dart'; import 'app/services/global_overlay_service.dart'; import 'app/utils/kr_log_util.dart'; import 'app/utils/kr_secure_storage.dart'; import 'app/utils/kr_init_log_collector.dart'; import 'app/utils/kr_file_logger.dart'; import 'package:kaer_with_panels/app/routes/transitions/slide_transparent_transition.dart'; import 'package:kaer_with_panels/app/routes/transitions/transition_config.dart'; // 全局导航键 final GlobalKey navigatorKey = GlobalKey(); void main() async { // 🔧 全局异常捕获:捕获所有未处理的异常 runZonedGuarded(() async { WidgetsFlutterBinding.ensureInitialized(); // 🔧 初始化日志收集器(必须最先初始化) final logCollector = KRInitLogCollector(); // 🔧 P6修复: 必须await完成初始化,否则日志会丢失 await logCollector.initialize(); logCollector.log('🚀 应用启动', tag: 'MAIN'); // 🔧 诊断信息: 记录平台和设备信息 logCollector.log('平台: ${Platform.operatingSystem}', tag: 'DEVICE'); logCollector.log('系统版本: ${Platform.operatingSystemVersion}', tag: 'DEVICE'); logCollector.log('Dart版本: ${Platform.version}', tag: 'DEVICE'); // 🔧 Flutter框架异常捕获 FlutterError.onError = (FlutterErrorDetails details) { logCollector.logError( 'Flutter框架异常: ${details.exception}', tag: 'FLUTTER_ERROR', error: details.exception, stackTrace: details.stack, ); FlutterError.presentError(details); }; // 🔧 异步异常捕获(PlatformDispatcher) PlatformDispatcher.instance.onError = (error, stack) { logCollector.logError( '平台异步异常: $error', tag: 'PLATFORM_ERROR', error: error, stackTrace: stack, ); return true; }; await _initializeApp(logCollector); }, (error, stack) { // 🔧 Zone捕获的未处理异常 final logCollector = KRInitLogCollector(); logCollector.logError( 'Zone未处理异常: $error', tag: 'ZONE_ERROR', error: error, stackTrace: stack, ); }); } Future _initializeApp(KRInitLogCollector logCollector) async { try { logCollector.logPhaseStart('初始化核心服务'); // 🔧 初始化文件日志系统(用于诊断 UI 卡死问题) logCollector.log('初始化文件日志系统', tag: 'FILE_LOGGER'); await KRFileLogger.initialize(); await KRFileLogger.log('📝 文件日志系统已启动'); logCollector.logSuccess('文件日志系统初始化完成', tag: 'FILE_LOGGER'); // 为所有 HttpClient 请求统一注入代理策略 logCollector.log('配置 HTTP 代理策略', tag: 'HTTP'); HttpOverrides.global = KRProxyHttpOverrides(); // 初始化 Hive logCollector.log('初始化 Hive 数据库', tag: 'HIVE'); await KRSecureStorage().kr_initHive(); logCollector.logSuccess('Hive 初始化完成', tag: 'HIVE'); // 初始化主题 logCollector.log('初始化主题服务', tag: 'THEME'); await KRThemeService().init(); logCollector.logSuccess('主题初始化完成', tag: 'THEME'); // 初始化翻译 logCollector.log('加载多语言翻译', tag: 'I18N'); final translations = GetxTranslations(); await translations.loadAllTranslations(); logCollector.logSuccess('翻译加载完成', tag: 'I18N'); // 获取最后保存的语言 final initialLocale = await KRLanguageUtils.getLastSavedLocale(); logCollector.log('使用语言: ${initialLocale.toString()}', tag: 'I18N'); logCollector.logPhaseEnd('初始化核心服务', success: true); // 启动域名预检测(异步,不阻塞应用启动) logCollector.log('启动域名预检测', tag: 'DOMAIN'); KRDomain.kr_preCheckDomains(); logCollector.log('✅ 核心服务初始化完成,启动应用', tag: 'MAIN'); // 🔧 P9修复: 不要立即finalize,让日志文件保持打开以收集后续信息 // finalize会在应用关闭或_AppLifecycleWrapper的dispose时调用 // 初始化全局 Overlay 服务 Get.put(GlobalOverlayService()); // 🔧 关键修复:必须先 runApp(),让 Flutter 引擎启动 // 窗口管理器初始化移到 runApp 之后,通过 WidgetsBinding.addPostFrameCallback 延迟执行 // 这样可以确保窗口显示时 Flutter UI 已经渲染完成 runApp(_myApp(translations, initialLocale)); // 🔧 在 Flutter 引擎启动后再初始化窗口管理器 if (Platform.isMacOS || Platform.isWindows) { // 使用 addPostFrameCallback 确保在首帧渲染后再显示窗口 WidgetsBinding.instance.addPostFrameCallback((_) async { logCollector.logPhaseStart('初始化窗口管理器'); await KRWindowManager().kr_initWindowManager(); logCollector.logPhaseEnd('初始化窗口管理器', success: true); }); } } catch (error, stackTrace) { logCollector.logError( '应用初始化失败', tag: 'INIT_FATAL', error: error, stackTrace: stackTrace, ); await logCollector.finalize(); rethrow; } } Widget _myApp(GetxTranslations translations, Locale initialLocale) { return _AppLifecycleWrapper( child: GetMaterialApp( navigatorKey: navigatorKey, // 使用全局导航键 title: "Hi快VPN", initialRoute: Routes.KR_SPLASH, getPages: AppPages.routes, builder: (context, child) { // 🔧 P2修复: 将ScreenUtil初始化移到StatefulWidget中,避免重复初始化 return _ScreenUtilInitializer( child: child ?? Container(), ); }, theme: KRThemeService().kr_lightTheme(), darkTheme: KRThemeService().kr_darkTheme(), themeMode: KRThemeService().kr_Theme, translations: translations, locale: initialLocale, fallbackLocale: const Locale('zh', 'CN'), debugShowCheckedModeBanner: false, transitionDuration: TransitionConfig.defaultDuration, // 设置动画持续时间 customTransition: TransitionConfig.createDefaultTransition(), routingCallback: (routing) { if (routing == null) return; if(Routes.KR_PURCHASE_MEMBERSHIP.contains(routing.current)) return; // 需要显示订阅按钮的路由列表 const showButtonRoutes = [ Routes.MR_LOGIN, Routes.HI_MENU, Routes.KR_HOME, Routes.HI_USER_INFO, Routes.KR_ORDER_STATUS, ]; print('routing.current${routing.current}'); GlobalOverlayService.instance.updateSubscriptionButtonColor(null); if (showButtonRoutes.contains(routing.current)) { GlobalOverlayService.instance.safeShowSubscriptionButton(); } else { GlobalOverlayService.instance.hideSubscriptionButton(); } }, ) ); } /// 🔧 P2修复: ScreenUtil初始化包装器,避免重复初始化 /// 🔧 P0修复: 使用静态变量确保全局只初始化一次,防止Widget重建导致的状态丢失 class _ScreenUtilInitializer extends StatefulWidget { final Widget child; const _ScreenUtilInitializer({required this.child}); @override State<_ScreenUtilInitializer> createState() => _ScreenUtilInitializerState(); } class _ScreenUtilInitializerState extends State<_ScreenUtilInitializer> { // 🔧 P0修复: 使用静态变量,确保即使Widget重建也不会重复初始化 static bool _isGlobalInitialized = false; // 🔧 P0修复: 记录初始化时的屏幕尺寸,用于检测屏幕变化 static Size? _lastScreenSize; @override Widget build(BuildContext context) { final mediaQuery = MediaQuery.of(context); final currentSize = mediaQuery.size; // 🔧 P0修复: 只在以下情况初始化: // 1. 从未初始化过 // 2. 屏幕尺寸发生显著变化(如旋转屏幕) final needsInit = !_isGlobalInitialized || (_lastScreenSize != null && ((_lastScreenSize!.width - currentSize.width).abs() > 50 || (_lastScreenSize!.height - currentSize.height).abs() > 50)); if (needsInit) { // 🔧 P9修复: 记录屏幕信息(延迟记录,确保能写入文件) if (kDebugMode || AppConfig.enableInitLogCollection) { // 延迟记录,确保在UI线程空闲时执行 WidgetsBinding.instance.addPostFrameCallback((_) { final logCollector = KRInitLogCollector(); logCollector.log('━━━ 屏幕信息诊断 ━━━', tag: 'SCREEN'); logCollector.log('屏幕尺寸: ${mediaQuery.size.width} x ${mediaQuery.size.height}', tag: 'SCREEN'); logCollector.log('设备像素比: ${mediaQuery.devicePixelRatio}', tag: 'SCREEN'); logCollector.log('文本缩放: ${mediaQuery.textScaler.scale(1.0)}', tag: 'SCREEN'); logCollector.log('安全区域: top=${mediaQuery.padding.top}, bottom=${mediaQuery.padding.bottom}', tag: 'SCREEN'); }); } if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) { // 🔧 修复:设计尺寸改为实际窗口尺寸 800x668,确保字体和UI元素正确缩放 ScreenUtil.init(context, designSize: const Size(800, 668), minTextAdapt: true); if (kDebugMode || AppConfig.enableInitLogCollection) { KRInitLogCollector().log('ScreenUtil初始化: 桌面模式 800x668', tag: 'SCREEN'); } } else { ScreenUtil.init(context, designSize: const Size(375, 667), minTextAdapt: true); if (kDebugMode || AppConfig.enableInitLogCollection) { KRInitLogCollector().log('ScreenUtil初始化: 移动模式 375x667', tag: 'SCREEN'); } } _isGlobalInitialized = true; _lastScreenSize = currentSize; } // 如果是 Mac 平台,添加顶部安全区域 Widget wrappedChild = widget.child; if (Platform.isMacOS) { wrappedChild = MediaQuery( data: MediaQuery.of(context).copyWith( padding: MediaQuery.of(context).padding.copyWith( top: 10.w, // Mac 平台顶部安全区域 ), ), child: wrappedChild, ); } return Stack( fit: StackFit.expand, children: [ // 背景层:使用您的自定义组件 const KrLocalImage( imageName: 'global-bg', imageType: ImageType.jpg, fit: BoxFit.cover, // 确保背景覆盖整个屏幕 ), // 内容层 wrappedChild, Overlay( initialEntries: [ OverlayEntry(builder: (_) => const SizedBox.shrink()), // 初始化空 Overlay ], ), ], ); } } /// 🔧 P3修复: 应用生命周期监听包装器 class _AppLifecycleWrapper extends StatefulWidget { final Widget child; const _AppLifecycleWrapper({required this.child}); @override State<_AppLifecycleWrapper> createState() => _AppLifecycleWrapperState(); } class _AppLifecycleWrapperState extends State<_AppLifecycleWrapper> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { // 🔧 P9修复: 应用关闭时finalize日志文件 KRInitLogCollector().finalize(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (kDebugMode) { print('🔄 应用生命周期变化: $state'); } // 🔧 P3修复: 当应用从后台恢复时,重置关键服务 if (state == AppLifecycleState.resumed) { if (kDebugMode) { print('♻️ 应用恢复,开始重置关键服务...'); } _resetCriticalServices(); } } /// 🔧 P3修复: 重置关键服务,防止状态污染 Future _resetCriticalServices() async { try { // 🔧 P1修复: 重置主题服务 await KRThemeService().reset(); if (kDebugMode) { print('✅ 主题服务已重置'); } // 🔧 P1修复: 重置应用运行时数据 await KRAppRunData.getInstance().kr_resetRuntimeState(); if (kDebugMode) { print('✅ 应用运行时数据已重置'); } // 🔧 P1修复: 清理域名检测状态 KRDomain.kr_resetDomainState(); if (kDebugMode) { print('✅ 域名状态已重置'); } // 刷新UI if (mounted) { setState(() {}); } } catch (e) { if (kDebugMode) { print('⚠️ 服务重置失败: $e'); } } } @override Widget build(BuildContext context) { return widget.child; } } /// 全局 HttpOverrides,确保所有 dart:io 网络请求遵循 sing-box 代理策略 class KRProxyHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { final client = super.createHttpClient(context); client.findProxy = (uri) => KRSingBoxImp.instance.kr_buildProxyRule(); return client; } }