mirror of
https://github.com/wgh136/pixes.git
synced 2025-09-27 21:07:24 +00:00
227 lines
8.6 KiB
Dart
227 lines
8.6 KiB
Dart
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<SimpleController>(
|
|
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<SystemUiOverlayStyle>(
|
|
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<String>? 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),
|
|
);
|
|
}
|