From 32408b96c024e303a268c93b49351c2c6741bdac Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Thu, 20 Apr 2023 16:26:11 -0400 Subject: [PATCH] Add stack trace logging and context.mounted check in buildSnackBar --- .../media_uploads_control.dart | 10 +++--- lib/controls/notifications_control.dart | 12 ++++--- .../timeline/interactions_bar_control.dart | 3 ++ lib/models/exec_error.dart | 15 +++++++- lib/screens/editor.dart | 34 ++++++++++++------- lib/screens/group_create_screen.dart | 8 ++--- lib/screens/group_editor_screen.dart | 8 ++--- lib/utils/snackbar_builder.dart | 3 ++ pubspec.lock | 2 +- pubspec.yaml | 1 + 10 files changed, 61 insertions(+), 35 deletions(-) diff --git a/lib/controls/entry_media_attachments/media_uploads_control.dart b/lib/controls/entry_media_attachments/media_uploads_control.dart index b2af863..ed3bcc7 100644 --- a/lib/controls/entry_media_attachments/media_uploads_control.dart +++ b/lib/controls/entry_media_attachments/media_uploads_control.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; +import 'package:relatica/models/exec_error.dart'; import 'package:result_monad/result_monad.dart'; import '../../models/gallery_data.dart'; @@ -55,10 +56,9 @@ class _MediaUploadsControlState extends State { .entryMediaItems.attachments .addAll(newEntries)), onError: (error) { - if (mounted) { - buildSnackbar(context, - 'Error selecting attachments: $error'); - } + buildSnackbar(context, + 'Error selecting attachments: $error'); + logError(error, _logger); }); }, icon: const Icon(Icons.camera_alt), @@ -111,7 +111,7 @@ class _MediaUploadsControlState extends State { alignLabelWithHint: true, border: OutlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).backgroundColor, + color: Theme.of(context).colorScheme.background, ), borderRadius: BorderRadius.circular(5.0), ), diff --git a/lib/controls/notifications_control.dart b/lib/controls/notifications_control.dart index f0a1d49..459698d 100644 --- a/lib/controls/notifications_control.dart +++ b/lib/controls/notifications_control.dart @@ -3,8 +3,10 @@ import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; +import 'package:result_monad/result_monad.dart'; import '../globals.dart'; +import '../models/exec_error.dart'; import '../models/user_notification.dart'; import '../routes.dart'; import '../services/connections_manager.dart'; @@ -139,11 +141,11 @@ class NotificationControl extends StatelessWidget { onPressed: manager == null ? null : () async { - final result = await manager.markSeen(notification); - if (result.isFailure) { - buildSnackbar(context, - 'Error marking notification: ${result.error}'); - } + await manager.markSeen(notification).withError((error) { + buildSnackbar( + context, 'Error marking notification: $error'); + logError(error, _logger); + }); }, icon: Icon(Icons.close_rounded)), ); diff --git a/lib/controls/timeline/interactions_bar_control.dart b/lib/controls/timeline/interactions_bar_control.dart index cca4239..831879d 100644 --- a/lib/controls/timeline/interactions_bar_control.dart +++ b/lib/controls/timeline/interactions_bar_control.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; +import 'package:relatica/models/exec_error.dart'; import 'package:result_monad/result_monad.dart'; import '../../globals.dart'; @@ -102,6 +103,7 @@ class _InteractionsBarControlState extends State { }); }, onError: (error) { buildSnackbar(context, 'Error resharing post by ${widget.entry.author}'); + logError(error, _logger); }); setState(() { isProcessing = false; @@ -128,6 +130,7 @@ class _InteractionsBarControlState extends State { }, onError: (error) { buildSnackbar( context, 'Error un-resharing post by ${widget.entry.author}'); + logError(error, _logger); }); setState(() { isProcessing = false; diff --git a/lib/models/exec_error.dart b/lib/models/exec_error.dart index 5653fc5..d13b723 100644 --- a/lib/models/exec_error.dart +++ b/lib/models/exec_error.dart @@ -1,4 +1,6 @@ +import 'package:logging/logging.dart'; import 'package:result_monad/result_monad.dart'; +import 'package:stack_trace/stack_trace.dart'; Result buildErrorResult({ required ErrorType type, @@ -14,22 +16,28 @@ Result buildErrorResult({ class ExecError { final ErrorType type; final String message; + final Trace trace; - ExecError({required this.type, this.message = ''}); + ExecError({required this.type, this.message = '', Trace? trace}) + : trace = trace ?? Trace.current(1); ExecError copy({ ErrorType? type, String? message, + Trace? trace, }) => ExecError( type: type ?? this.type, message: message ?? this.message, + trace: trace ?? this.trace, ); @override String toString() { return 'ExecError{type: $type, message: $message}'; } + + String printStackTrace() => trace.terse.toString(); } enum ErrorType { @@ -50,3 +58,8 @@ extension ExecErrorExtension on Result { FutureResult execErrorCastAsync() async => execErrorCast(); } + +void logError(ExecError error, Logger logger, + {Level logLevel = Level.INFO, String message = ''}) { + logger.log(logLevel, '$message $error\n${error.trace}'); +} diff --git a/lib/screens/editor.dart b/lib/screens/editor.dart index dc82777..a28c2af 100644 --- a/lib/screens/editor.dart +++ b/lib/screens/editor.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart'; import 'package:provider/provider.dart'; +import 'package:result_monad/result_monad.dart'; import 'package:uuid/uuid.dart'; import '../controls/autocomplete/hashtag_autocomplete_options.dart'; @@ -15,6 +16,7 @@ import '../controls/padding.dart'; import '../controls/standard_appbar.dart'; import '../controls/timeline/status_header_control.dart'; import '../globals.dart'; +import '../models/exec_error.dart'; import '../models/group_data.dart'; import '../models/image_entry.dart'; import '../models/link_preview_data.dart'; @@ -110,13 +112,8 @@ class _EditorScreenState extends State { loaded = true; }); }, onError: (error) { - if (context.mounted) { - buildSnackbar( - context, - 'Error getting post for editing: $error', - ); - } - _logger.severe('Error getting post for editing: $error'); + buildSnackbar(context, 'Error getting post for editing: $error'); + logError(error, _logger); }); } @@ -152,20 +149,25 @@ class _EditorScreenState extends State { isSubmitting = true; }); - final result = await manager.createNewStatus( + final result = await manager + .createNewStatus( bodyText, spoilerText: spoilerController.text, inReplyToId: widget.parentId, newMediaItems: newMediaItems, existingMediaItems: existingMediaItems, visibility: visibility, - ); + ) + .withError((error) { + buildSnackbar(context, 'Error posting: $error'); + logError(error, _logger); + }); + setState(() { isSubmitting = false; }); if (result.isFailure) { - buildSnackbar(context, 'Error posting: ${result.error}'); return; } @@ -184,7 +186,8 @@ class _EditorScreenState extends State { isSubmitting = true; }); - final result = await manager.editStatus( + final result = await manager + .editStatus( widget.id, bodyText, spoilerText: spoilerController.text, @@ -192,13 +195,17 @@ class _EditorScreenState extends State { newMediaItems: newMediaItems, existingMediaItems: existingMediaItems, newMediaItemVisibility: visibility, - ); + ) + .withError((error) { + buildSnackbar(context, 'Error updating $statusType: $error'); + logError(error, _logger); + }); + setState(() { isSubmitting = false; }); if (result.isFailure) { - buildSnackbar(context, 'Error Updating $statusType: ${result.error}'); return; } @@ -468,6 +475,7 @@ class _EditorScreenState extends State { if (mounted) { buildSnackbar( context, 'Error building link preview: $error'); + logError(error, _logger); } }); }, diff --git a/lib/screens/group_create_screen.dart b/lib/screens/group_create_screen.dart index c5c522c..6797111 100644 --- a/lib/screens/group_create_screen.dart +++ b/lib/screens/group_create_screen.dart @@ -27,10 +27,10 @@ class _GroupCreateScreenState extends State { final result = await manager.createGroup(groupTextController.text); if (context.mounted) { result.match( - onSuccess: (_) => context.canPop() ? context.pop() : null, - onError: (error) => - buildSnackbar(context, 'Error trying to create new group: $error'), - ); + onSuccess: (_) => context.canPop() ? context.pop() : null, + onError: (error) { + buildSnackbar(context, 'Error trying to create new group: $error'); + }); } } diff --git a/lib/screens/group_editor_screen.dart b/lib/screens/group_editor_screen.dart index f51b376..23e4a4c 100644 --- a/lib/screens/group_editor_screen.dart +++ b/lib/screens/group_editor_screen.dart @@ -46,9 +46,7 @@ class _GroupEditorScreenState extends State { allowNameEditing = false; }); }, onError: (error) { - if (mounted) { - buildSnackbar(context, 'Error renaming group: $error'); - } + buildSnackbar(context, 'Error renaming group: $error'); }); } else { groupTextController.text = groupData.name; @@ -81,9 +79,7 @@ class _GroupEditorScreenState extends State { onSuccess: (_) => 'Removed $messageBase', onError: (error) => 'Error removing $messageBase: $error', ); - if (context.mounted) { - buildSnackbar(context, message); - } + buildSnackbar(context, message); } } diff --git a/lib/utils/snackbar_builder.dart b/lib/utils/snackbar_builder.dart index f34ec83..9751204 100644 --- a/lib/utils/snackbar_builder.dart +++ b/lib/utils/snackbar_builder.dart @@ -2,6 +2,9 @@ import 'package:flutter/material.dart'; Future buildSnackbar(BuildContext context, String message, {int durationSec = 3}) async { + if (!context.mounted) { + return; + } final snackBar = SnackBar( content: SelectableText(message), duration: Duration(seconds: durationSec), diff --git a/pubspec.lock b/pubspec.lock index 52712b8..bc159db 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1140,7 +1140,7 @@ packages: source: hosted version: "1.11.0" stack_trace: - dependency: transitive + dependency: "direct main" description: name: stack_trace sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 diff --git a/pubspec.yaml b/pubspec.yaml index fca9d5c..e9bbde4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,7 @@ dependencies: string_validator: ^0.3.0 device_preview: ^1.1.0 color_blindness: ^0.1.2 + stack_trace: ^1.11.0 dev_dependencies: flutter_test: