Template
chore: 初始化脚手架 — sunny_mochi 企业级 Flutter 模板
Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库 7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系 5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter 通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:sunny_mochi/app.dart';
|
||||
import 'package:sunny_mochi/core/config/env.dart';
|
||||
import 'package:sunny_mochi/core/crash/crash_reporter.dart';
|
||||
import 'package:sunny_mochi/core/observability/sentry_setup.dart';
|
||||
import 'package:sunny_mochi/core/observability/talker_setup.dart';
|
||||
import 'package:sunny_mochi/core/storage/app_database.dart';
|
||||
import 'package:sunny_mochi/core/sync/sync_service.dart';
|
||||
import 'package:sunny_mochi/features/error_report/data/error_logger.dart';
|
||||
import 'package:sunny_mochi/i18n/strings.g.dart';
|
||||
import 'package:talker_riverpod_logger/talker_riverpod_logger.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
unawaited(LocaleSettings.useDeviceLocale());
|
||||
|
||||
// 1. 崩溃日志预初始化(必须在 Sentry 之前)
|
||||
await CrashReporter.preInit();
|
||||
final pendingCrash = CrashReporter.consumePending();
|
||||
|
||||
// 2. Sentry 初始化(空 DSN 时直接 runApp)
|
||||
await SentrySetup.init(
|
||||
appRunner: () async {
|
||||
// 3. 挂载崩溃钩子
|
||||
CrashReporter.installHooks();
|
||||
appTalker.info('App boot · env=${Env.name} · mock=${Env.useMock}');
|
||||
|
||||
// 4. 打开加密 SQLite 数据库
|
||||
final database = await AppDatabase.open();
|
||||
|
||||
runApp(
|
||||
TranslationProvider(
|
||||
child: ProviderScope(
|
||||
retry: (_, _) => null,
|
||||
overrides: [
|
||||
appDatabaseProvider.overrideWithValue(database),
|
||||
pendingCrashProvider.overrideWithValue(pendingCrash),
|
||||
],
|
||||
observers: [
|
||||
if (Env.enableDevPanel)
|
||||
TalkerRiverpodObserver(talker: appTalker),
|
||||
],
|
||||
child: const _SyncBootstrap(child: AppRoot()),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 在 ProviderScope 内启动 SyncService 和 ErrorLogger 清理。
|
||||
class _SyncBootstrap extends ConsumerStatefulWidget {
|
||||
const _SyncBootstrap({required this.child});
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
ConsumerState<_SyncBootstrap> createState() => _SyncBootstrapState();
|
||||
}
|
||||
|
||||
class _SyncBootstrapState extends ConsumerState<_SyncBootstrap> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
unawaited(ref.read(syncServiceProvider).start());
|
||||
unawaited(ref.read(errorLoggerProvider).pruneOld());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
unawaited(ref.read(syncServiceProvider).dispose());
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => widget.child;
|
||||
}
|
||||
|
||||
class AppRoot extends StatelessWidget {
|
||||
const AppRoot({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 设计基准 375pt(与 iOS JPScaleValue 一致;如设计方调整需同步)
|
||||
return const ScreenUtilInit(
|
||||
designSize: Size(375, 812),
|
||||
minTextAdapt: true,
|
||||
child: App(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user