Support proxies search Support svg display Add some scenes auto close connections Update core Optimize more details
202 lines
5.9 KiB
Dart
202 lines
5.9 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
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<Application> createState() => ApplicationState();
|
|
}
|
|
|
|
class ApplicationState extends ConsumerState<Application> {
|
|
Timer? _autoUpdateGroupTaskTimer;
|
|
Timer? _autoUpdateProfilesTaskTimer;
|
|
|
|
final _pageTransitionsTheme = const PageTransitionsTheme(
|
|
builders: <TargetPlatform, PageTransitionsBuilder>{
|
|
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: (results) async {
|
|
if (!results.contains(ConnectivityResult.vpn)) {
|
|
await clashCore.closeConnections();
|
|
}
|
|
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<void> dispose() async {
|
|
linkManager.destroy();
|
|
_autoUpdateGroupTaskTimer?.cancel();
|
|
_autoUpdateProfilesTaskTimer?.cancel();
|
|
await clashCore.destroy();
|
|
await globalState.appController.savePreferences();
|
|
await globalState.appController.handleExit();
|
|
super.dispose();
|
|
}
|
|
}
|