Files
llm_chat/lib/main.dart
2025-12-30 01:06:42 +08:00

171 lines
4.9 KiB
Dart

import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
import 'package:system_theme/system_theme.dart';
import 'providers/chat_provider.dart';
import 'screens/chat_screen.dart';
import 'screens/settings_screen.dart';
import 'theme/app_theme.dart';
const String appTitle = 'AI Chat';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb &&
[
TargetPlatform.windows,
TargetPlatform.android,
].contains(defaultTargetPlatform)) {
SystemTheme.accentColor.load();
}
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AppTheme()),
ChangeNotifierProvider(create: (_) => ChatProvider()),
],
child: Consumer<AppTheme>(
builder: (context, appTheme, child) {
return FluentApp(
title: appTitle,
themeMode: appTheme.mode,
debugShowCheckedModeBanner: false,
color: appTheme.color,
darkTheme: FluentThemeData(
brightness: Brightness.dark,
accentColor: appTheme.color,
visualDensity: VisualDensity.standard,
focusTheme: FocusThemeData(
glowFactor: is10footScreen(context) ? 2.0 : 0.0,
),
fontFamily: 'MiSans',
),
theme: FluentThemeData(
accentColor: appTheme.color,
visualDensity: VisualDensity.standard,
focusTheme: FocusThemeData(
glowFactor: is10footScreen(context) ? 2.0 : 0.0,
),
fontFamily: 'MiSans',
),
builder: (context, child) {
return Directionality(
textDirection: appTheme.textDirection,
child: child!,
);
},
home: const MyHomePage(),
);
},
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
final viewKey = GlobalKey(debugLabel: 'Navigation View Key');
@override
Widget build(BuildContext context) {
final appTheme = context.watch<AppTheme>();
final theme = FluentTheme.of(context);
return NavigationView(
key: viewKey,
appBar: NavigationAppBar(
automaticallyImplyLeading: false,
title: const Text(appTitle),
actions: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsetsDirectional.only(end: 8),
child: ToggleSwitch(
checked: theme.brightness == Brightness.dark,
onChanged: (v) {
if (v) {
appTheme.mode = ThemeMode.dark;
} else {
appTheme.mode = ThemeMode.light;
}
},
content: const Text('Dark Mode'),
),
),
],
),
),
pane: NavigationPane(
selected: _selectedIndex,
onChanged: (index) => setState(() => _selectedIndex = index),
header: SizedBox(
height: kOneLineTileHeight,
child: ShaderMask(
shaderCallback: (rect) {
final color = appTheme.color.defaultBrushFor(theme.brightness);
return LinearGradient(colors: [color, color]).createShader(rect);
},
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(FluentIcons.robot, size: 24, color: Colors.white),
SizedBox(width: 8),
Text(
'AI Chat',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
),
),
displayMode: appTheme.displayMode,
indicator: () {
switch (appTheme.indicator) {
case NavigationIndicators.end:
return const EndNavigationIndicator();
case NavigationIndicators.sticky:
return const StickyNavigationIndicator();
}
}(),
items: [
PaneItem(
icon: const Icon(FluentIcons.chat),
title: const Text('Chat'),
body: const ChatScreen(),
),
],
footerItems: [
PaneItemSeparator(),
PaneItem(
icon: const Icon(FluentIcons.settings),
title: const Text('Settings'),
body: const SettingsScreen(),
),
],
),
);
}
}