import 'dart:io'; import 'package:PiliPlus/build_config.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; import 'package:flex_seed_scheme/flex_seed_scheme.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:PiliPlus/common/widgets/custom_toast.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/models/common/color_type.dart'; import 'package:PiliPlus/pages/video/detail/index.dart'; import 'package:PiliPlus/router/app_pages.dart'; import 'package:PiliPlus/pages/main/view.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/data.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:media_kit/media_kit.dart'; // Provides [Player], [Media], [Playlist] etc. import 'package:PiliPlus/utils/recommend_filter.dart'; import 'package:catcher_2/catcher_2.dart'; import './services/loggeer.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); await GStorage.init(); if (GStorage.setting.get(SettingBoxKey.autoClearCache, defaultValue: false)) { await CacheManage.clearLibraryCache(); } if (GStorage.setting .get(SettingBoxKey.horizontalScreen, defaultValue: false)) { await SystemChrome.setPreferredOrientations( //支持竖屏与横屏 [ DeviceOrientation.portraitUp, // DeviceOrientation.portraitDown, DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ], ); } else { await SystemChrome.setPreferredOrientations( //支持竖屏 [ DeviceOrientation.portraitUp, ], ); } if (GStorage.badCertificateCallback) { HttpOverrides.global = _CustomHttpOverrides(); } await setupServiceLocator(); Request(); await Request.setCookie(); RecommendFilter(); SmartDialog.config.loading = SmartConfigLoading(backType: SmartBackType.normal); // 异常捕获 logo记录 final String buildConfig = '''\n Build Time: ${BuildConfig.buildTime} Commit Hash: ${BuildConfig.commitHash}'''; final Catcher2Options debugConfig = Catcher2Options( SilentReportMode(), [ FileHandler(await getLogsPath()), ConsoleHandler( enableDeviceParameters: false, enableApplicationParameters: false, enableCustomParameters: true, ) ], customParameters: { 'BuildConfig': buildConfig, }, ); final Catcher2Options releaseConfig = Catcher2Options( SilentReportMode(), [ FileHandler(await getLogsPath()), ConsoleHandler( enableCustomParameters: true, ) ], customParameters: { 'BuildConfig': buildConfig, }, ); Catcher2( debugConfig: debugConfig, releaseConfig: releaseConfig, runAppFunction: () { runApp(const MyApp()); }, ); // 小白条、导航栏沉浸 SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, systemNavigationBarDividerColor: Colors.transparent, statusBarColor: Colors.transparent, systemNavigationBarContrastEnforced: false, )); Data.init(); PiliScheme.init(); } class MyApp extends StatelessWidget { const MyApp({super.key}); Box get setting => GStorage.setting; @override Widget build(BuildContext context) { // 主题色 Color defaultColor = colorThemeTypes[setting.get(SettingBoxKey.customColor, defaultValue: 0)] ['color']; Color brandColor = defaultColor; // 是否动态取色 bool isDynamicColor = setting.get(SettingBoxKey.dynamicColor, defaultValue: true); // 字体缩放大小 double textScale = setting.get(SettingBoxKey.defaultTextScale, defaultValue: 1.0); // DynamicSchemeVariant dynamicSchemeVariant = // DynamicSchemeVariant.values[GStorage.schemeVariant]; FlexSchemeVariant variant = FlexSchemeVariant.values[GStorage.schemeVariant]; // 强制设置高帧率 if (Platform.isAndroid) { 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, orElse: () => f); } DisplayMode preferred = modes.toList().firstWhere((el) => el == f); FlutterDisplayMode.setPreferredMode(preferred); }); } 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 = SeedColorScheme.fromSeeds( primaryKey: brandColor, brightness: Brightness.light, variant: variant, // dynamicSchemeVariant: dynamicSchemeVariant, // tones: FlexTones.soft(Brightness.light), ); darkColorScheme = SeedColorScheme.fromSeeds( primaryKey: brandColor, brightness: Brightness.dark, variant: variant, // dynamicSchemeVariant: dynamicSchemeVariant, // tones: FlexTones.soft(Brightness.dark), ); } // 图片缓存 // PaintingBinding.instance.imageCache.maximumSizeBytes = 1000 << 20; return GetMaterialApp( // showSemanticsDebugger: true, title: 'PiliPlus', theme: _getThemeData( colorScheme: lightColorScheme, isDynamic: lightDynamic != null && isDynamicColor, variant: variant, ), darkTheme: _getThemeData( colorScheme: darkColorScheme, isDynamic: darkDynamic != null && isDynamicColor, isDark: true, variant: variant, ), themeMode: GStorage.themeMode, 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, MainApp.routeObserver, ], ); }), ); } ThemeData _getThemeData({ required ColorScheme colorScheme, required bool isDynamic, bool isDark = false, required FlexSchemeVariant variant, }) { return ThemeData( colorScheme: colorScheme, useMaterial3: true, appBarTheme: AppBarTheme( elevation: 0, titleSpacing: 0, centerTitle: false, scrolledUnderElevation: 0, backgroundColor: isDynamic ? null : colorScheme.surface, titleTextStyle: TextStyle(fontSize: 16, color: colorScheme.onSurface), ), navigationBarTheme: NavigationBarThemeData( surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, ), snackBarTheme: SnackBarThemeData( actionTextColor: colorScheme.primary, backgroundColor: colorScheme.secondaryContainer, closeIconColor: colorScheme.secondary, contentTextStyle: TextStyle(color: colorScheme.secondary), elevation: 20, ), pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.android: ZoomPageTransitionsBuilder( allowEnterRouteSnapshotting: false, ), }, ), popupMenuTheme: PopupMenuThemeData( surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, ), cardTheme: CardTheme( elevation: 1, surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : isDark ? colorScheme.onSurfaceVariant : null, shadowColor: Colors.transparent, ), // dialogTheme: DialogTheme( // surfaceTintColor: isDark ? colorScheme.onSurfaceVariant : null, // ), progressIndicatorTheme: ProgressIndicatorThemeData( refreshBackgroundColor: colorScheme.onSecondary, ), dialogTheme: DialogTheme( titleTextStyle: TextStyle( fontSize: 18, color: colorScheme.onSurface, ), ), ); } } class _CustomHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { return super.createHttpClient(context) ..badCertificateCallback = (X509Certificate cert, String host, int port) => true; } }