Files
flutterApp/lib/main.dart
2026-01-29 19:16:41 +08:00

118 lines
3.9 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:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:maibu_satabot_v2/features/auth/presentation/bloc/app_user_cubit.dart';
import 'package:maibu_satabot_v2/core/infrastructure/logging/app_bloc_observer.dart';
import 'package:maibu_satabot_v2/core/logging/i_logger_service.dart';
import 'package:maibu_satabot_v2/core/theme/AppTheme.dart';
import 'package:maibu_satabot_v2/features/auth/presentation/bloc/auth_cubit.dart';
import 'package:maibu_satabot_v2/features/devices/presentation/bloc/devices_cubit.dart';
import 'core/di/injection.dart';
import 'core/network/base/i_connection.dart';
import 'features/auth/presentation/bloc/login_cubit.dart';
import 'features/connectivity/presentation/bloc/connectivity_cubit.dart';
import 'features/connectivity/presentation/bloc/connectivity_state.dart';
void main() async {
// 1. 使用 runZonedGuarded 捕获所有未处理的异步错误
runZonedGuarded(
() async {
WidgetsFlutterBinding.ensureInitialized();
// 2. 初始化依赖注入 (这里面应包含 ILoggerService 的注册)
await init();
// 3. 从 sl 中获取 logger 实例并初始化 Sentry
final logger = sl<ILoggerService>();
await logger.init();
// 4. 设置全局 Bloc 观察者,自动上报 Bloc 错误
Bloc.observer = AppBlocObserver(logger);
runApp(const MyApp());
},
(error, stack) {
// 5. 捕获顶级错误并上报
sl<ILoggerService>().captureException(error, stackTrace: stack);
},
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
sl<AuthCubit>().appStarted();
return MultiBlocProvider(
providers: [
//BlocProvider<LoginBloc>(create: (_) => sl<LoginBloc>()),
BlocProvider<AppUserCubit>(create: (_) => sl<AppUserCubit>()),
BlocProvider<LoginCubit>(create: (_) => sl<LoginCubit>()),
BlocProvider<DevicesCubit>(
create: (_) =>
sl<DevicesCubit>()
..fetchAllDevices(sl<AppUserCubit>().state.user!.username),
),
BlocProvider(create: (_) => sl<ConnectivityCubit>()),
],
child: MaterialApp.router(
title: 'Maibu Satabot',
theme: AppTheme.lightTheme,
routerConfig: sl<GoRouter>(),
builder: (context, child) {
return BlocListener<ConnectivityCubit, ConnectivityState>(
// 只有当状态真正变为 disconnected 时才弹出
listenWhen: (prev, curr) => prev.status != curr.status,
listener: (context, state) {
if (state.status == ConnectionStatus.disconnected) {
_showGlobalDisconnectDialog();
}
},
child: child, // child 就是当前路由显示的页面内容
);
},
),
);
}
// 全局断连提示弹窗
void _showGlobalDisconnectDialog() {
// 直接从全局变量获取真正的 Navigator Context
final context = rootNavigatorKey.currentContext;
if (context != null) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
title: const Row(
children: [
Icon(Icons.warning, color: Colors.red),
SizedBox(width: 8),
Text("连接已断开"),
],
),
content: const Text("与服务器通信丢失,请检查网络连接。"),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // 关闭弹窗
// 如果需要,这里可以执行 context.go('/login');
},
child: const Text("知道了"),
),
],
),
);
} else {
print("DEBUG: 弹窗失败,rootNavigatorKey.currentContext 为空");
}
}
}