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:
SkyJourney
2026-05-14 12:51:05 +08:00
commit 61017f1c39
204 changed files with 15386 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:sunny_mochi/core/error/exception_mapper.dart';
import 'package:sunny_mochi/core/widgets/app_toast.dart';
import 'package:sunny_mochi/features/error_report/data/error_logger.dart';
extension BuildContextX on BuildContext {
/// 弹一个 Toast 风格的 SnackBar(对应 iOS Mkt.makeToast(...))。
void showToast(
String message, {
ToastType type = ToastType.info,
Duration duration = const Duration(seconds: 4),
}) => AppToast.show(this, message, type: type, duration: duration);
/// 异常 → ExceptionMapper.fromUnknown(e, st) → toast(Failure.message)。
///
/// 兜底替代散落的 `on Object catch (e, st) { mapper.fromUnknown; if(mounted) showToast }`
/// 模板(5+ 处 mine 表单提交流程)。
void showError(WidgetRef ref, Object error, StackTrace stackTrace) {
final failure =
ref.read(exceptionMapperProvider).fromUnknown(error, stackTrace);
// 写入本地错误日志(fire-and-forget,不阻塞 UI
unawaited(ref.read(errorLoggerProvider).log(failure));
if (mounted) showToast(failure.userMessage, type: ToastType.error);
}
/// 当前 Theme 快捷读取。
ThemeData get theme => Theme.of(this);
ColorScheme get colors => theme.colorScheme;
TextTheme get textTheme => theme.textTheme;
/// 屏幕信息快捷读取。
Size get screenSize => MediaQuery.sizeOf(this);
EdgeInsets get screenPadding => MediaQuery.paddingOf(this);
double get screenWidth => screenSize.width;
double get screenHeight => screenSize.height;
}