Files
monisuo/flutter_monisuo/lib/main.dart
sion123 7ed2435a4c refactor(theme): 迁移主题感知颜色至 ThemeExtension
- 创建 AppThemeColors ThemeExtension 类,统一管理主题感知颜色(涨跌色、卡片背景、渐变等)
- 从 AppColorScheme 移除主题感知辅助函数,仅保留静态颜色常量
- 在 AppTheme 中注册 ThemeExtension,支持深色/浅色主题工厂
- 重构所有 UI 组件使用 context.appColors 访问主题颜色,替代硬编码的 AppColorScheme 方法调用
- 移除组件中重复的 isDark 判断逻辑,简化颜色获取方式
- 保持向后兼容性,所有现有功能不变
2026-04-06 01:58:08 +08:00

183 lines
5.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'core/network/dio_client.dart';
import 'core/storage/local_storage.dart';
import 'core/theme/app_color_scheme.dart';
import 'core/theme/app_theme.dart';
import 'core/event/app_event_bus.dart';
import 'data/services/user_service.dart';
import 'data/services/market_service.dart';
import 'data/services/trade_service.dart';
import 'data/services/asset_service.dart';
import 'data/services/fund_service.dart';
import 'data/services/bonus_service.dart';
import 'providers/auth_provider.dart';
import 'providers/market_provider.dart';
import 'providers/asset_provider.dart';
import 'providers/theme_provider.dart';
import 'ui/pages/auth/login_page.dart';
import 'ui/pages/main/main_page.dart';
import 'ui/pages/onboarding/onboarding_page.dart';
void main() async {
// 确保 Flutter 绑定初始化
WidgetsFlutterBinding.ensureInitialized();
// 全局错误处理 - Flutter 框架错误
FlutterError.onError = (FlutterErrorDetails details) {
FlutterError.presentError(details);
debugPrint('Flutter Error: ${details.exception}');
debugPrint('Stack trace: ${details.stack}');
};
// 全局错误处理 - 异步未捕获错误
PlatformDispatcher.instance.onError = (error, stack) {
debugPrint('Uncaught error: $error');
debugPrint('Stack: $stack');
return true;
};
Provider.debugCheckInvalidValueType = null;
try {
await SharedPreferences.getInstance();
await LocalStorage.init();
debugPrint('App initialized successfully');
} catch (e, stack) {
debugPrint('Initialization error: $e');
debugPrint('Stack: $stack');
}
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: _buildProviders(),
child: Consumer<ThemeProvider>(
builder: (context, themeProvider, _) {
return ShadApp.custom(
themeMode: themeProvider.themeMode,
theme: ShadThemeData(
colorScheme: AppColorScheme.lightShad,
brightness: Brightness.light,
),
darkTheme: ShadThemeData(
colorScheme: AppColorScheme.darkShad,
brightness: Brightness.dark,
),
appBuilder: (context) => _buildMaterialApp(context, themeProvider.themeMode),
);
},
),
);
}
List<SingleChildWidget> _buildProviders() {
final dioClient = DioClient();
return [
// Theme Provider (必须放在最前面)
ChangeNotifierProvider<ThemeProvider>(
create: (_) => ThemeProvider()..init(),
),
// Services
Provider<DioClient>.value(value: dioClient),
Provider<AppEventBus>(create: (_) => AppEventBus()),
Provider<UserService>(create: (_) => UserService(dioClient)),
Provider<MarketService>(create: (_) => MarketService(dioClient)),
Provider<TradeService>(create: (_) => TradeService(dioClient)),
Provider<AssetService>(create: (_) => AssetService(dioClient)),
Provider<FundService>(create: (_) => FundService(dioClient)),
Provider<BonusService>(create: (_) => BonusService(dioClient)),
// State Management
ChangeNotifierProvider<AuthProvider>(
create: (ctx) {
final authProvider = AuthProvider(ctx.read<UserService>());
// token 过期时DioClient 回调 AuthProvider 强制登出
dioClient.onUnauthorized = authProvider.forceLogout;
return authProvider;
},
),
ChangeNotifierProvider<MarketProvider>(
create: (ctx) => MarketProvider(ctx.read<MarketService>()),
),
ChangeNotifierProvider<AssetProvider>(
create: (ctx) => AssetProvider(
ctx.read<AssetService>(),
ctx.read<FundService>(),
ctx.read<AppEventBus>(),
),
),
];
}
Widget _buildMaterialApp(BuildContext context, ThemeMode themeMode) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: themeMode,
localizationsDelegates: const [
GlobalShadLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
builder: (context, child) {
child = ShadAppBuilder(child: child!);
// 配置 BotToast 确保显示在所有内容之上
final botToastBuilder = BotToastInit();
child = botToastBuilder(context, child);
return child;
},
navigatorObservers: [BotToastNavigatorObserver()],
initialRoute: '/',
routes: {
'/': (context) => const RootPage(),
'/login': (context) => const LoginPage(),
'/main': (context) => const MainPage(),
},
);
}
}
/// 根页面 - 决定显示引导页还是主页面
class RootPage extends StatelessWidget {
const RootPage({super.key});
@override
Widget build(BuildContext context) {
// 检查是否需要显示引导页
if (!LocalStorage.isOnboardingCompleted) {
return OnboardingPage(
onComplete: () {
Navigator.of(context).pushReplacementNamed('/login');
},
);
}
return Consumer<AuthProvider>(
builder: (context, auth, _) {
if (auth.isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return auth.isLoggedIn ? const MainPage() : const LoginPage();
},
);
}
}