diff --git a/app/lib/common/constants.dart b/app/lib/common/constants.dart index 5333f948..f954726b 100644 --- a/app/lib/common/constants.dart +++ b/app/lib/common/constants.dart @@ -24,6 +24,8 @@ const cpicLookupUrl = const drugInteractionIndicator = '*'; const drugInteractionIndicatorName = 'asterisk'; +const testErrorMessage = 'THIS IS A TEST'; + // For shorter uniqueness check that also does not rely on variant; also format // HLA-A (which is currently unique) as HLA-B const definedNonUniqueGenes = ['HLA-A', 'HLA-B']; diff --git a/app/lib/common/widgets/error_handler.dart b/app/lib/common/widgets/error_handler.dart index 2b15cf42..aba27be9 100644 --- a/app/lib/common/widgets/error_handler.dart +++ b/app/lib/common/widgets/error_handler.dart @@ -1,5 +1,3 @@ -import 'package:flutter/foundation.dart'; - import '../module.dart'; class ErrorHandler extends StatefulWidget { @@ -19,8 +17,8 @@ class ErrorHandler extends StatefulWidget { class ErrorHandlerState extends State { @override void initState() { - FlutterError.onError = (details) { - _handleError(exception: details.exception, stackTrace: details.stack); + FlutterError.onError = (details) async { + await _handleError(exception: details.exception, stackTrace: details.stack); }; WidgetsBinding.instance.platformDispatcher.onError = (exception, stackTrace) { @@ -34,23 +32,21 @@ class ErrorHandlerState extends State { required Object exception, StackTrace? stackTrace, }) async { - debugPrint(exception.toString()); - debugPrintStack(stackTrace: stackTrace); - if (kDebugMode) { - if (exception is AssertionError) return; - } + final isFatal = _needToHandleError(exception); final errorString = exception.toString(); - if (_needToHandleError(exception)) { - final errorMailInfo = stackTrace != null - ? '$errorString\n\n${stackTrace.toString()}' - : errorString; - await widget.appRouter.push(ErrorRoute(error: errorMailInfo)); + if (isFatal) { + await widget.appRouter.push(ErrorRoute(error: errorString)); } } bool _needToHandleError(Object exception) { - final willIgnoreError = exception is FlutterError && + // Set to false to test that error screen appears (annoying when debugging + // with breakpoints anyways) + const ignoreTestError = true; + final isTestError = exception.toString().contains(testErrorMessage); + final isOverflowError = exception is FlutterError && exception.message.startsWith('A RenderFlex overflowed'); + final willIgnoreError = isOverflowError || (isTestError && ignoreTestError); return !willIgnoreError; } diff --git a/app/lib/more/pages/more.dart b/app/lib/more/pages/more.dart index 996be68c..5b30fde8 100644 --- a/app/lib/more/pages/more.dart +++ b/app/lib/more/pages/more.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; + import '../../common/module.dart'; import '../../common/utilities/hive_utils.dart'; @@ -71,6 +73,20 @@ class MorePage extends StatelessWidget { title: context.l10n.more_page_terms_and_conditions, onTap: () => context.router.push(TermsRoute()), ), + if (kDebugMode) SubheaderDivider( + text: 'Test Error Handling', + useLine: false, + ), + if (kDebugMode) _buildSettingsItem( + title: 'Throw Flutter Error', + style: TextStyle(color: PharMeTheme.errorColor), + onTap: () => throw FlutterError(testErrorMessage), + ), + if (kDebugMode) _buildSettingsItem( + title: 'Throw Other Error', + style: TextStyle(color: PharMeTheme.errorColor), + onTap: () async => throw Exception(testErrorMessage), + ), ] ), ); @@ -79,8 +95,9 @@ class MorePage extends StatelessWidget { Widget _buildSettingsItem({ required String title, required void Function() onTap, + TextStyle? style, }) => ListTile( - title: Text(title), + title: Text(title, style: style), trailing: Icon(Icons.chevron_right_rounded), iconColor: PharMeTheme.iconColor, onTap: onTap,