import 'dart:async'; import 'package:fl_clash/clash/clash.dart'; import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/l10n/l10n.dart'; import 'package:fl_clash/manager/hotkey_manager.dart'; import 'package:fl_clash/manager/manager.dart'; import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/providers/providers.dart'; import 'package:fl_clash/state.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'controller.dart'; import 'pages/pages.dart'; class Application extends ConsumerStatefulWidget { const Application({ super.key, }); @override ConsumerState createState() => ApplicationState(); } class ApplicationState extends ConsumerState { Timer? _autoUpdateGroupTaskTimer; Timer? _autoUpdateProfilesTaskTimer; final _pageTransitionsTheme = const PageTransitionsTheme( builders: { TargetPlatform.android: CommonPageTransitionsBuilder(), TargetPlatform.windows: CommonPageTransitionsBuilder(), TargetPlatform.linux: CommonPageTransitionsBuilder(), TargetPlatform.macOS: CommonPageTransitionsBuilder(), }, ); ColorScheme _getAppColorScheme({ required Brightness brightness, int? primaryColor, }) { return ref.read(genColorSchemeProvider(brightness)); } @override void initState() { super.initState(); _autoUpdateGroupTask(); _autoUpdateProfilesTask(); globalState.appController = AppController(context, ref); WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { final currentContext = globalState.navigatorKey.currentContext; if (currentContext != null) { globalState.appController = AppController(currentContext, ref); } await globalState.appController.init(); globalState.appController.initLink(); app?.initShortcuts(); }); } _autoUpdateGroupTask() { _autoUpdateGroupTaskTimer = Timer(const Duration(milliseconds: 20000), () { WidgetsBinding.instance.addPostFrameCallback((_) { globalState.appController.updateGroupsDebounce(); _autoUpdateGroupTask(); }); }); } _autoUpdateProfilesTask() { _autoUpdateProfilesTaskTimer = Timer(const Duration(minutes: 20), () async { await globalState.appController.autoUpdateProfiles(); _autoUpdateProfilesTask(); }); } _buildPlatformState(Widget child) { if (system.isDesktop) { return WindowManager( child: TrayManager( child: HotKeyManager( child: ProxyManager( child: child, ), ), ), ); } return AndroidManager( child: TileManager( child: child, ), ); } _buildState(Widget child) { return AppStateManager( child: ClashManager( child: ConnectivityManager( onConnectivityChanged: () { globalState.appController.updateLocalIp(); globalState.appController.addCheckIpNumDebounce(); }, child: child, ), ), ); } _buildPlatformApp(Widget child) { if (system.isDesktop) { return WindowHeaderContainer( child: child, ); } return VpnManager( child: child, ); } _buildApp(Widget child) { return MessageManager( child: ThemeManager( child: child, ), ); } @override Widget build(context) { return _buildPlatformState( _buildState( Consumer( builder: (_, ref, child) { final locale = ref.watch(appSettingProvider.select((state) => state.locale)); final themeProps = ref.watch(themeSettingProvider); return MaterialApp( debugShowCheckedModeBanner: false, navigatorKey: globalState.navigatorKey, localizationsDelegates: const [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate ], builder: (_, child) { return AppEnvManager( child: _buildPlatformApp( _buildApp(child!), ), ); }, scrollBehavior: BaseScrollBehavior(), title: appName, locale: utils.getLocaleForString(locale), supportedLocales: AppLocalizations.delegate.supportedLocales, themeMode: themeProps.themeMode, theme: ThemeData( useMaterial3: true, pageTransitionsTheme: _pageTransitionsTheme, colorScheme: _getAppColorScheme( brightness: Brightness.light, primaryColor: themeProps.primaryColor, ), ), darkTheme: ThemeData( useMaterial3: true, pageTransitionsTheme: _pageTransitionsTheme, colorScheme: _getAppColorScheme( brightness: Brightness.dark, primaryColor: themeProps.primaryColor, ).toPureBlack(themeProps.pureBlack), ), home: child, ); }, child: const HomePage(), ), ), ); } @override Future dispose() async { linkManager.destroy(); _autoUpdateGroupTaskTimer?.cancel(); _autoUpdateProfilesTaskTimer?.cancel(); await clashCore.destroy(); await globalState.appController.savePreferences(); await globalState.appController.handleExit(); super.dispose(); } }