import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/custom_toast.dart'; import 'package:pilipala/http/common.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/models/common/color_type.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/router/app_pages.dart'; import 'package:pilipala/pages/main/view.dart'; import 'package:pilipala/services/service_locator.dart'; import 'package:pilipala/utils/app_scheme.dart'; import 'package:pilipala/utils/data.dart'; import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:media_kit/media_kit.dart'; import 'package:pilipala/utils/recommend_filter.dart'; import 'package:catcher_2/catcher_2.dart'; import './services/loggeer.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); await SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); await GStorage.init(); clearLogs(); Request(); await Request.setCookie(); // 异常捕获 logo记录 final Catcher2Options releaseConfig = Catcher2Options( SilentReportMode(), [FileHandler(await getLogsPath())], ); Catcher2( releaseConfig: releaseConfig, runAppFunction: () { runApp(const MyApp()); }, ); // 小白条、导航栏沉浸 if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 29) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, statusBarColor: Colors.transparent, systemNavigationBarContrastEnforced: false, )); } PiliSchame.init(); await GlobalDataCache.initialize(); CommonHttp.buvidActivate(); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { Box setting = GStorage.setting; // 主题色 Color defaultColor = colorThemeTypes[setting.get(SettingBoxKey.customColor, defaultValue: 0)] ['color']; Color brandColor = defaultColor; // 主题模式 ThemeType currentThemeValue = ThemeType.values[setting .get(SettingBoxKey.themeMode, defaultValue: ThemeType.system.code)]; // 是否动态取色 bool isDynamicColor = setting.get(SettingBoxKey.dynamicColor, defaultValue: true); // 字体缩放大小 double textScale = setting.get(SettingBoxKey.defaultTextScale, defaultValue: 1.0); // 强制设置高帧率 if (Platform.isAndroid) { try { late List modes; FlutterDisplayMode.supported.then((value) { modes = value; var storageDisplay = setting.get(SettingBoxKey.displayMode); DisplayMode f = DisplayMode.auto; if (storageDisplay != null) { f = modes.firstWhere((e) => e.toString() == storageDisplay); } DisplayMode preferred = modes.toList().firstWhere((el) => el == f); FlutterDisplayMode.setPreferredMode(preferred); }); } catch (_) {} } if (Platform.isAndroid) { return AndroidApp( brandColor: brandColor, isDynamicColor: isDynamicColor, currentThemeValue: currentThemeValue, textScale: textScale, ); } else { return OtherApp( brandColor: brandColor, currentThemeValue: currentThemeValue, textScale: textScale, ); } } } class AndroidApp extends StatelessWidget { const AndroidApp({ super.key, required this.brandColor, required this.isDynamicColor, required this.currentThemeValue, required this.textScale, }); final Color brandColor; final bool isDynamicColor; final ThemeType currentThemeValue; final double textScale; @override Widget build(BuildContext context) { return DynamicColorBuilder( builder: ((ColorScheme? lightDynamic, ColorScheme? darkDynamic) { ColorScheme? lightColorScheme; ColorScheme? darkColorScheme; if (lightDynamic != null && darkDynamic != null && isDynamicColor) { // dynamic取色成功 lightColorScheme = lightDynamic.harmonized(); darkColorScheme = darkDynamic.harmonized(); } else { // dynamic取色失败,采用品牌色 lightColorScheme = ColorScheme.fromSeed( seedColor: brandColor, brightness: Brightness.light, ); darkColorScheme = ColorScheme.fromSeed( seedColor: brandColor, brightness: Brightness.dark, ); } return BuildMainApp( lightColorScheme: lightColorScheme, darkColorScheme: darkColorScheme, currentThemeValue: currentThemeValue, textScale: textScale, ); }), ); } } class OtherApp extends StatelessWidget { const OtherApp({ super.key, required this.brandColor, required this.currentThemeValue, required this.textScale, }); final Color brandColor; final ThemeType currentThemeValue; final double textScale; @override Widget build(BuildContext context) { return BuildMainApp( lightColorScheme: ColorScheme.fromSeed( seedColor: brandColor, brightness: Brightness.light, ), darkColorScheme: ColorScheme.fromSeed( seedColor: brandColor, brightness: Brightness.dark, ), currentThemeValue: currentThemeValue, textScale: textScale, ); } } class BuildMainApp extends StatelessWidget { const BuildMainApp({ super.key, required this.lightColorScheme, required this.darkColorScheme, required this.currentThemeValue, required this.textScale, }); final ColorScheme lightColorScheme; final ColorScheme darkColorScheme; final ThemeType currentThemeValue; final double textScale; @override Widget build(BuildContext context) { Box setting = GStorage.setting; /// 纯黑模式主题配置 ColorScheme? pureDarkColorScheme; final bool enablePureBlack = setting.get(SettingBoxKey.enablePureBlack, defaultValue: false); if (enablePureBlack) { pureDarkColorScheme = darkColorScheme.copyWith( background: Colors.black, surface: Colors.black, onPrimary: Colors.black, onSecondary: Colors.black, ); } final SnackBarThemeData snackBarTheme = SnackBarThemeData( actionTextColor: lightColorScheme.primary, backgroundColor: lightColorScheme.secondaryContainer, closeIconColor: lightColorScheme.secondary, contentTextStyle: TextStyle(color: lightColorScheme.secondary), elevation: 20, ); AppBarTheme appBarTheme(ColorScheme colorScheme) { return AppBarTheme( backgroundColor: colorScheme.surface, foregroundColor: colorScheme.onSurface, elevation: 0, titleSpacing: 0, scrolledUnderElevation: 0, // titleTextStyle: TextStyle( // fontSize: Theme.of(context).textTheme.titleLarge!.fontSize), ); } ThemeData buildThemeData(ColorScheme colorScheme) { return ThemeData( colorScheme: colorScheme, snackBarTheme: snackBarTheme, appBarTheme: appBarTheme(colorScheme), pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.android: ZoomPageTransitionsBuilder( allowEnterRouteSnapshotting: false, ), }, ), ); } return GetMaterialApp( title: 'PiliPala', theme: buildThemeData( currentThemeValue == ThemeType.dark ? pureDarkColorScheme ?? darkColorScheme : lightColorScheme, ), darkTheme: buildThemeData( currentThemeValue == ThemeType.light ? lightColorScheme : pureDarkColorScheme ?? darkColorScheme, ), localizationsDelegates: const [ GlobalCupertinoLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], locale: const Locale("zh", "CN"), supportedLocales: const [Locale("zh", "CN"), Locale("en", "US")], fallbackLocale: const Locale("zh", "CN"), getPages: Routes.getPages, home: const MainApp(), builder: (BuildContext context, Widget? child) { return FlutterSmartDialog( toastBuilder: (String msg) => CustomToast(msg: msg), child: MediaQuery( data: MediaQuery.of(context) .copyWith(textScaler: TextScaler.linear(textScale)), child: child!, ), ); }, navigatorObservers: [ VideoDetailPage.routeObserver, SearchPage.routeObserver, ], onReady: () async { RecommendFilter(); Data.init(); setupServiceLocator(); }, ); } }