TF-4268 Refactor app runner: split web/mobile runners, add platform error handlers

This commit is contained in:
dab246
2026-04-07 16:09:49 +07:00
committed by Dat H. Pham
parent 78e76b5aac
commit 2a666056c2
8 changed files with 78 additions and 54 deletions
+3 -3
View File
@@ -10,7 +10,8 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations_delegate.dart';
import 'package:tmail_ui_user/main/localizations/localization_service.dart';
import 'package:tmail_ui_user/main/main_entry.dart';
import 'package:tmail_ui_user/main/app_runner.dart';
import 'package:tmail_ui_user/main/runner/app_runner_mobile.dart'
if (dart.library.html) 'package:tmail_ui_user/main/runner/app_runner_web.dart';
import 'package:tmail_ui_user/main/pages/app_pages.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -27,7 +28,6 @@ class TMailApp extends StatefulWidget {
}
class _TMailAppState extends State<TMailApp> {
DeepLinksManager? _deepLinksManager;
@override
@@ -85,4 +85,4 @@ class _TMailAppState extends State<TMailApp> {
}
super.dispose();
}
}
}
-49
View File
@@ -1,49 +0,0 @@
import 'dart:async';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/sentry/sentry_manager.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/main.dart';
import 'package:tmail_ui_user/main/main_entry.dart';
Future<void> runAppWithMonitoring(Future<void> Function() runTmail) async {
await runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
// Handling Flutter UI and Build Errors
FlutterError.onError = (details) async {
logError(
'FlutterError: ${details.exception}',
exception: details.exception,
stackTrace: details.stack,
);
FlutterError.presentError(details);
};
// Handling Uncaught and Platform-Specific Errors
PlatformDispatcher.instance.onError = (error, stack) {
logError(
'PlatformDispatcher: Error: $error',
exception: error,
stackTrace: stack,
);
return true;
};
await SentryManager.instance.initialize(
appRunner: () async {
await runTmailPreload();
runApp(SentryWidget(child: const TMailApp()));
},
fallBackRunner: runTmail,
);
}, (error, stack) async {
logError(
'Uncaught zone error: $error',
exception: error,
stackTrace: stack,
);
});
}
-2
View File
@@ -1,6 +1,5 @@
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/utils/build_utils.dart';
import 'package:core/utils/config/env_loader.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
@@ -23,7 +22,6 @@ Future<void> runTmailPreload() async {
await Future.wait([
MainBindings().dependencies(),
HiveCacheConfig.instance.setUp(),
EnvLoader.loadEnvFile(),
if (PlatformInfo.isWeb) AssetPreloader.preloadHtmlEditorAssets(),
], eagerError: false);
+30
View File
@@ -0,0 +1,30 @@
import 'dart:ui';
import 'package:core/utils/app_logger.dart';
import 'package:core/utils/build_utils.dart';
import 'package:flutter/material.dart';
/// Configures global error handlers for both Flutter framework and Platform dispatcher.
void setupErrorHooks() {
// Handle Flutter Framework Errors (Rendering, Build, Layout, etc.)
FlutterError.onError = (details) {
logError(
'FlutterError: ${details.exception}',
exception: details.exception,
stackTrace: details.stack,
);
// Show the "Red Screen of Death" in debug mode.
FlutterError.presentError(details);
};
// Handle Asynchronous Errors (Futures, Streams, Platform Channels)
PlatformDispatcher.instance.onError = (error, stack) {
logError(
'PlatformDispatcherError: $error',
exception: error,
stackTrace: stack,
);
// Return true in release to prevent crashes; false in debug to surface errors.
return BuildUtils.isReleaseMode;
};
}
+12
View File
@@ -0,0 +1,12 @@
import 'dart:async';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/main/runner/app_error_handlers.dart';
Future<void> runAppGuarded(Future<void> Function() runner) async {
SentryWidgetsFlutterBinding.ensureInitialized();
setupErrorHooks();
await runner();
}
+10
View File
@@ -0,0 +1,10 @@
import 'package:core/utils/config/env_loader.dart';
import 'package:tmail_ui_user/main/runner/app_runner_base.dart';
Future<void> runAppWithMonitoring(Future<void> Function() runTmail) async {
await runAppGuarded(() async {
await EnvLoader.loadEnvFile();
await runTmail();
});
}
+21
View File
@@ -0,0 +1,21 @@
import 'package:core/utils/config/env_loader.dart';
import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:tmail_ui_user/main.dart';
import 'package:tmail_ui_user/main/main_entry.dart';
import 'package:core/utils/sentry/sentry_manager.dart';
import 'package:tmail_ui_user/main/runner/app_runner_base.dart';
Future<void> runAppWithMonitoring(Future<void> Function() runTmail) async {
await runAppGuarded(() async {
await EnvLoader.loadEnvFile();
await SentryManager.instance.initialize(
appRunner: () async {
await runTmailPreload();
runApp(SentryWidget(child: const TMailApp()));
},
fallBackRunner: runTmail,
);
});
}