import "dart:async"; import "dart:ui"; import "package:dynamic_color/dynamic_color.dart"; import "package:fluent_ui/fluent_ui.dart"; import "package:flutter/foundation.dart"; import "package:flutter/material.dart" as md; import "package:flutter/services.dart"; import "package:flutter_acrylic/flutter_acrylic.dart" as flutter_acrylic; import "package:pixes/appdata.dart"; import "package:pixes/components/keyboard.dart"; import "package:pixes/components/md.dart"; import "package:pixes/components/message.dart"; import "package:pixes/foundation/app.dart"; import "package:pixes/foundation/history.dart"; import "package:pixes/foundation/log.dart"; import "package:pixes/network/app_dio.dart"; import "package:pixes/pages/main_page.dart"; import "package:pixes/utils/app_links.dart"; import "package:pixes/utils/loop.dart"; import "package:pixes/utils/translation.dart"; import "package:pixes/utils/update.dart"; import "package:pixes/utils/window.dart"; import "package:window_manager/window_manager.dart"; void main() { runZonedGuarded(() async { Future.delayed(const Duration(seconds: 3), checkUpdate); WidgetsFlutterBinding.ensureInitialized(); FlutterError.onError = (details) { Log.error("Unhandled", "${details.exception}\n${details.stack}"); }; setSystemProxy(); await App.init(); await appdata.readData(); await Translation.init(); HistoryManager().init(); handleLinks(); if (App.isDesktop) { await flutter_acrylic.Window.initialize(); if (App.isWindows) { await flutter_acrylic.Window.hideWindowControls(); } await WindowManager.instance.ensureInitialized(); windowManager.waitUntilReadyToShow().then((_) async { await windowManager.setTitleBarStyle( TitleBarStyle.hidden, windowButtonVisibility: false, ); if (App.isLinux) { // https://github.com/leanflutter/window_manager/issues/460 return; } await windowManager.setMinimumSize(const Size(500, 600)); var placement = await WindowPlacement.loadFromFile(); await placement.applyToWindow(); await windowManager.show(); Loop.register(WindowPlacement.loop); }); } Loop.start(); Log.info("APP", "Application started"); runApp(const MyApp()); }, (error, stack) { Log.error("Unhandled Exception", "$error\n$stack"); }); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); return StateBuilder( init: SimpleController(), tag: "MyApp", builder: (controller) { Brightness brightness = PlatformDispatcher.instance.platformBrightness; if (appdata.settings["theme"] == "Dark") { brightness = Brightness.dark; } else if (appdata.settings["theme"] == "Light") { brightness = Brightness.light; } return AnnotatedRegion( value: SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, statusBarColor: Colors.transparent, statusBarIconBrightness: brightness.opposite, systemNavigationBarIconBrightness: brightness.opposite, ), child: DynamicColorBuilder( builder: (light, dark) { final colorScheme = (brightness == Brightness.light ? light : dark) ?? md.ColorScheme.fromSeed( seedColor: Colors.blue, brightness: brightness); return FluentApp( navigatorKey: App.rootNavigatorKey, debugShowCheckedModeBanner: false, title: 'pixes', theme: FluentThemeData( brightness: brightness, fontFamily: App.isWindows ? "Microsoft YaHei UI" : null, accentColor: AccentColor.swatch({ 'darkest': darken(colorScheme.primary, 30), 'darker': darken(colorScheme.primary, 20), 'dark': darken(colorScheme.primary, 10), 'normal': colorScheme.primary, 'light': lighten(colorScheme.primary, 10), 'lighter': lighten(colorScheme.primary, 20), 'lightest': lighten(colorScheme.primary, 30) }), focusTheme: const FocusThemeData( primaryBorder: BorderSide.none, secondaryBorder: BorderSide.none, )), home: const MainPage(), builder: (context, child) { ErrorWidget.builder = (details) { if (details.exception .toString() .contains("RenderFlex overflowed")) { return const SizedBox.shrink(); } Log.error( "UI", "${details.exception}\n${details.stack}"); return Text(details.exception.toString()); }; if (child == null) { throw "widget is null"; } String? font; List? fallback; if (App.isLinux || App.isWindows) { font = 'Noto Sans CJK'; fallback = [ 'Segoe UI', 'Noto Sans SC', 'Noto Sans TC', 'Noto Sans', 'Microsoft YaHei', 'PingFang SC', 'Arial', 'sans-serif' ]; } Widget widget = MdTheme( data: MdThemeData.from( colorScheme: colorScheme, useMaterial3: true), child: DefaultTextStyle.merge( style: TextStyle( fontFamily: font, fontFamilyFallback: fallback, ), child: OverlayWidget(child), ), ); if (App.isWindows) { if (App.windowsVersion == 11) { flutter_acrylic.Window.setEffect( effect: flutter_acrylic.WindowEffect.mica, dark: FluentTheme.of(context).brightness == Brightness.dark); widget = NavigationPaneTheme( data: const NavigationPaneThemeData( backgroundColor: Colors.transparent, ), child: widget, ); } /* else if (App.windowsVersion == 10) { flutter_acrylic.Window.setEffect( effect: flutter_acrylic.WindowEffect.acrylic, dark: FluentTheme.of(context).brightness == Brightness.dark); widget = NavigationPaneTheme( data: NavigationPaneThemeData( backgroundColor: FluentTheme.of(context) .micaBackgroundColor .withOpacity(0.72), ), child: widget, ); }*/ } return KeyEventListener(child: widget); }); }, ), ); }); } } int _floatToInt8(double x) { return (x * 255.0).round() & 0xff; } Color darken(Color c, [int percent = 10]) { assert(1 <= percent && percent <= 100); var f = 1 - percent / 100; return Color.fromARGB( _floatToInt8(c.a), _floatToInt8(c.r * f), _floatToInt8(c.g * f), _floatToInt8(c.b * f), ); } Color lighten(Color c, [int percent = 10]) { assert(1 <= percent && percent <= 100); var p = percent / 100; return Color.fromARGB( _floatToInt8(c.a), _floatToInt8(c.r + (1 - c.r) * p), _floatToInt8(c.g + (1 - c.g) * p), _floatToInt8(c.b + (1 - c.b) * p), ); }