diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 7997c6615..29d4f3f83 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -5061,5 +5061,14 @@ } } }, - "saved": "Saved" + "saved": "Saved", + "reset": "Reset", + "errorGenerateActivityMessage": "Failed to generate activity", + "errorRegenerateActivityMessage": "Failed to regenerate activity", + "errorFetchingActivitiesMessage": "Failed to fetch activities", + "errorFetchingDefinition": "Failed to fetch definition", + "errorProcessAnalytics": "Failed to process analytics", + "errorDownloading": "Download failed", + "errorFetchingLevelSummary": "Failed to fetch level summary", + "errorLoadingSpaceChildren": "Failed to load chats within this space" } diff --git a/lib/pangea/activity_generator/activity_generator.dart b/lib/pangea/activity_generator/activity_generator.dart index e2803ef8a..00820afb1 100644 --- a/lib/pangea/activity_generator/activity_generator.dart +++ b/lib/pangea/activity_generator/activity_generator.dart @@ -33,7 +33,7 @@ class ActivityGenerator extends StatefulWidget { class ActivityGeneratorState extends State { bool loading = false; - String? error; + Object? error; List? activities; final formKey = GlobalKey(); @@ -219,7 +219,7 @@ class ActivityGeneratorState extends State { activities = resp.activityPlans; await _setModeImageURL(); } catch (e, s) { - error = e.toString(); + error = e; ErrorHandler.logError( e: e, s: s, diff --git a/lib/pangea/activity_generator/activity_generator_view.dart b/lib/pangea/activity_generator/activity_generator_view.dart index a7c5ffa1c..1153d9b32 100644 --- a/lib/pangea/activity_generator/activity_generator_view.dart +++ b/lib/pangea/activity_generator/activity_generator_view.dart @@ -11,6 +11,7 @@ import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart import 'package:fluffychat/pangea/activity_planner/suggestion_form_field.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart'; @@ -38,10 +39,12 @@ class ActivityGeneratorView extends StatelessWidget { } else if (controller.error != null) { body = Center( child: Column( + spacing: 16.0, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(l10n.oopsSomethingWentWrong), - const SizedBox(height: 16), + ErrorIndicator( + message: l10n.errorGenerateActivityMessage, + ), ElevatedButton( onPressed: controller.generate, child: Text(l10n.tryAgain), diff --git a/lib/pangea/activity_planner/activity_planner_builder.dart b/lib/pangea/activity_planner/activity_planner_builder.dart index 293d75a35..acebff482 100644 --- a/lib/pangea/activity_planner/activity_planner_builder.dart +++ b/lib/pangea/activity_planner/activity_planner_builder.dart @@ -56,7 +56,7 @@ class ActivityPlannerBuilderState extends State { @override void initState() { super.initState(); - _resetActivity(); + resetActivity(); } @override @@ -91,7 +91,7 @@ class ActivityPlannerBuilderState extends State { ); } - Future _resetActivity() async { + Future resetActivity() async { avatar = null; filename = null; imageURL = null; @@ -230,7 +230,7 @@ class ActivityPlannerBuilderState extends State { } Future clearEdits() async { - await _resetActivity(); + await resetActivity(); if (mounted) { setState(() { isEditing = false; diff --git a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart index f7e6aec33..0b3ffc8a6 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart +++ b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart @@ -14,6 +14,7 @@ import 'package:fluffychat/pangea/activity_suggestions/activity_room_selection.d import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card_row.dart'; import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -117,9 +118,26 @@ class ActivitySuggestionDialogState extends State { } } + void _resetActivity() { + widget.controller.resetActivity(); + setState(() { + _pageMode = _PageMode.activity; + _loading = false; + _error = null; + }); + } + @override Widget build(BuildContext context) { final theme = Theme.of(context); + final buttonStyle = ElevatedButton.styleFrom( + backgroundColor: theme.colorScheme.primaryContainer, + foregroundColor: theme.colorScheme.onPrimaryContainer, + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + ), + ); + final body = Stack( alignment: Alignment.topCenter, children: [ @@ -132,12 +150,30 @@ class ActivitySuggestionDialogState extends State { if (_pageMode == _PageMode.activity) { if (_error != null) { return Center( - child: Row( - spacing: 8.0, + child: Column( + spacing: 16.0, mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.error, color: theme.colorScheme.error), - Text(L10n.of(context).oopsSomethingWentWrong), + ErrorIndicator( + message: + L10n.of(context).errorRegenerateActivityMessage, + ), + Row( + spacing: 8.0, + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: _onRegenerate, + style: buttonStyle, + child: Text(L10n.of(context).tryAgain), + ), + ElevatedButton( + onPressed: _resetActivity, + style: buttonStyle, + child: Text(L10n.of(context).reset), + ), + ], + ), ], ), ); @@ -547,15 +583,7 @@ class ActivitySuggestionDialogState extends State { children: [ Expanded( child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), + style: buttonStyle, onPressed: widget.controller.saveEdits, child: Row( children: [ @@ -572,15 +600,7 @@ class ActivitySuggestionDialogState extends State { ), Expanded( child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), + style: buttonStyle, onPressed: widget.controller.clearEdits, child: Row( children: [ @@ -605,15 +625,7 @@ class ActivitySuggestionDialogState extends State { children: [ Expanded( child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), + style: buttonStyle, child: Row( children: [ const Icon(Icons.edit), @@ -632,16 +644,7 @@ class ActivitySuggestionDialogState extends State { if (widget.replaceActivity != null) Expanded( child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme.colorScheme - .onPrimaryContainer, - padding: - const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), + style: buttonStyle, onPressed: _onRegenerate, child: Row( children: [ @@ -664,15 +667,7 @@ class ActivitySuggestionDialogState extends State { children: [ Expanded( child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), + style: buttonStyle, onPressed: _launchActivity, child: Row( children: [ diff --git a/lib/pangea/activity_suggestions/activity_suggestions_area.dart b/lib/pangea/activity_suggestions/activity_suggestions_area.dart index 7d43c9180..051125513 100644 --- a/lib/pangea/activity_suggestions/activity_suggestions_area.dart +++ b/lib/pangea/activity_suggestions/activity_suggestions_area.dart @@ -19,6 +19,7 @@ import 'package:fluffychat/pangea/activity_planner/media_enum.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_plan_search_repo.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -206,25 +207,27 @@ class ActivitySuggestionsAreaState extends State { child: (_timeout || !_loading && cards.isEmpty) ? Padding( padding: const EdgeInsets.all(8.0), - child: RichText( - text: TextSpan( - style: DefaultTextStyle.of(context).style, - children: [ - const WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.info_outline, + child: Column( + spacing: 16.0, + mainAxisSize: MainAxisSize.min, + children: [ + ErrorIndicator( + message: _timeout + ? L10n.of(context).activitySuggestionTimeoutMessage + : L10n.of(context).errorFetchingActivitiesMessage, + ), + ElevatedButton( + onPressed: _setActivityItems, + style: ElevatedButton.styleFrom( + backgroundColor: theme.colorScheme.primaryContainer, + foregroundColor: theme.colorScheme.onPrimaryContainer, + padding: const EdgeInsets.symmetric( + horizontal: 12.0, ), ), - const TextSpan(text: " "), - TextSpan( - text: _timeout - ? L10n.of(context) - .activitySuggestionTimeoutMessage - : L10n.of(context).oopsSomethingWentWrong, - ), - ], - ), + child: Text(L10n.of(context).tryAgain), + ), + ], ), ) : Container( diff --git a/lib/pangea/analytics_details_popup/analytics_details_popup.dart b/lib/pangea/analytics_details_popup/analytics_details_popup.dart index bbf3b880a..79f5054e5 100644 --- a/lib/pangea/analytics_details_popup/analytics_details_popup.dart +++ b/lib/pangea/analytics_details_popup/analytics_details_popup.dart @@ -1,16 +1,11 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:material_symbols_icons/symbols.dart'; - -import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/analytics_details_popup/morph_analytics_list_view.dart'; import 'package:fluffychat/pangea/analytics_details_popup/morph_details_view.dart'; import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_details_view.dart'; import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_list_view.dart'; import 'package:fluffychat/pangea/analytics_downloads/analytics_download_button.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/constructs/construct_level_enum.dart'; @@ -25,13 +20,11 @@ class AnalyticsPopupWrapper extends StatefulWidget { this.constructZoom, required this.view, this.backButtonOverride, - this.showAppBar = true, }); final ConstructTypeEnum view; final ConstructIdentifier? constructZoom; final Widget? backButtonOverride; - final bool showAppBar; @override AnalyticsPopupWrapperState createState() => AnalyticsPopupWrapperState(); @@ -124,84 +117,31 @@ class AnalyticsPopupWrapperState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: widget.showAppBar - ? AppBar( - title: kIsWeb - ? Text( - localView == ConstructTypeEnum.morph - ? ConstructTypeEnum.morph.indicator.tooltip(context) - : ConstructTypeEnum.vocab.indicator.tooltip(context), - ) - : null, - leading: widget.backButtonOverride ?? - IconButton( - icon: localConstructZoom == null - ? const Icon(Icons.close) - : const Icon(Icons.arrow_back), - onPressed: localConstructZoom == null - ? () => Navigator.of(context).pop() - : () => setConstructZoom(null), - ), - actions: [ - TextButton.icon( - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - backgroundColor: localView == ConstructTypeEnum.vocab - ? Theme.of(context).colorScheme.primary.withAlpha(50) - : Theme.of(context).colorScheme.surface, - ), - label: Text(L10n.of(context).vocab), - icon: const Icon(Symbols.dictionary), - onPressed: () => setState(() { - localView = ConstructTypeEnum.vocab; - localConstructZoom = null; - }), - ), - const SizedBox(width: 4.0), - TextButton.icon( - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10.0), - ), - backgroundColor: localView == ConstructTypeEnum.morph - ? Theme.of(context).colorScheme.primary.withAlpha(50) - : Theme.of(context).colorScheme.surface, - ), - label: Text(L10n.of(context).grammar), - icon: const Icon(Symbols.toys_and_games), - onPressed: () => setState(() { - localView = ConstructTypeEnum.morph; - localConstructZoom = null; - }), - ), - const SizedBox(width: 4.0), - if (kIsWeb) const DownloadAnalyticsButton(), - if (kIsWeb) const SizedBox(width: 4.0), - ], - ) - : null, - body: Stack( + body: Column( children: [ - localView == ConstructTypeEnum.morph - ? localConstructZoom == null - ? MorphAnalyticsListView(controller: this) - : MorphDetailsView(constructId: localConstructZoom!) - : localConstructZoom == null - ? VocabAnalyticsListView(controller: this) - : VocabDetailsView(constructId: localConstructZoom!), - if (localConstructZoom != null) - Positioned( - top: 0, - left: 0, - child: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () { - setConstructZoom(null); - }, - ), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + localConstructZoom != null + ? IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + setConstructZoom(null); + }, + ) + : const SizedBox(), + const DownloadAnalyticsButton(), + ], + ), + Expanded( + child: localView == ConstructTypeEnum.morph + ? localConstructZoom == null + ? MorphAnalyticsListView(controller: this) + : MorphDetailsView(constructId: localConstructZoom!) + : localConstructZoom == null + ? VocabAnalyticsListView(controller: this) + : VocabDetailsView(constructId: localConstructZoom!), + ), ], ), ); diff --git a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart index 692fde21f..a116ca647 100644 --- a/lib/pangea/analytics_details_popup/morph_meaning_widget.dart +++ b/lib/pangea/analytics_details_popup/morph_meaning_widget.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; import 'package:fluffychat/pangea/morphs/morph_features_enum.dart'; import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_repo.dart'; @@ -32,7 +33,7 @@ class MorphMeaningWidgetState extends State { static const int maxCharacters = 140; String? _cachedResponse; bool _isLoading = true; - String? _error; + Object? _error; @override void didUpdateWidget(covariant MorphMeaningWidget oldWidget) { @@ -62,7 +63,8 @@ class MorphMeaningWidgetState extends State { final response = await _morphMeaning(); _setMeaningText(response); } catch (e) { - _error = e.toString(); + debugger(when: kDebugMode); + _error = e; } finally { if (mounted) setState(() => _isLoading = false); } @@ -114,11 +116,10 @@ class MorphMeaningWidgetState extends State { } if (_error != null) { - debugger(when: kDebugMode); - return Text( - L10n.of(context).oopsSomethingWentWrong, - textAlign: TextAlign.center, - style: widget.style, + return Center( + child: ErrorIndicator( + message: L10n.of(context).errorFetchingDefinition, + ), ); } diff --git a/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart b/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart index 927571f8d..8659df623 100644 --- a/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart +++ b/lib/pangea/analytics_downloads/analytics_dowload_dialog.dart @@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart'; import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart'; import 'package:fluffychat/pangea/chat_settings/utils/download_file.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart'; @@ -49,6 +50,9 @@ class AnalyticsDownloadDialogState extends State { } Future _downloadAnalytics() async { + List vocabSummary; + List morphSummary; + try { setState(() { _downloading = true; @@ -56,9 +60,27 @@ class AnalyticsDownloadDialogState extends State { _error = null; }); - final vocabSummary = await _getVocabAnalytics(); - final morphSummary = await _getMorphAnalytics(); + vocabSummary = await _getVocabAnalytics(); + morphSummary = await _getMorphAnalytics(); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + "downloadType": _downloadType, + }, + ); + if (mounted) { + setState(() { + _downloading = false; + _error = L10n.of(context).errorProcessAnalytics; + }); + } + return; + } + + try { final content = _getExcelFileContent({ ConstructTypeEnum.vocab: vocabSummary, ConstructTypeEnum.morph: morphSummary, @@ -72,6 +94,7 @@ class AnalyticsDownloadDialogState extends State { fileName, _downloadType, ); + _downloaded = true; } catch (e, s) { ErrorHandler.logError( e: e, @@ -80,12 +103,9 @@ class AnalyticsDownloadDialogState extends State { "downloadType": _downloadType, }, ); - _error = e.toString(); + _error = L10n.of(context).errorDownloading; } finally { - setState(() { - _downloading = false; - _downloaded = true; - }); + if (mounted) setState(() => _downloading = false); } } @@ -376,7 +396,9 @@ class AnalyticsDownloadDialogState extends State { child: _error != null ? Padding( padding: const EdgeInsets.all(8.0), - child: Text(L10n.of(context).oopsSomethingWentWrong), + child: ErrorIndicator( + message: _error!, + ), ) : const SizedBox(), ), diff --git a/lib/pangea/analytics_misc/level_up/level_up_popup.dart b/lib/pangea/analytics_misc/level_up/level_up_popup.dart index 795700652..3a28a3368 100644 --- a/lib/pangea/analytics_misc/level_up/level_up_popup.dart +++ b/lib/pangea/analytics_misc/level_up/level_up_popup.dart @@ -18,6 +18,7 @@ import 'package:fluffychat/pangea/analytics_misc/level_up/level_up_manager.dart' import 'package:fluffychat/pangea/analytics_misc/level_up/rain_confetti.dart'; import 'package:fluffychat/pangea/analytics_summary/progress_bar/level_bar.dart'; import 'package:fluffychat/pangea/analytics_summary/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; import 'package:fluffychat/pangea/constructs/construct_repo.dart'; import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; @@ -386,12 +387,8 @@ class _LevelUpPopupContentState extends State else if (_error != null) Padding( padding: const EdgeInsets.all(16.0), - child: Text( - L10n.of(context).oopsSomethingWentWrong, - style: TextStyle( - color: Theme.of(context).colorScheme.error, - fontSize: 16, - ), + child: ErrorIndicator( + message: L10n.of(context).errorFetchingLevelSummary, ), ) else if (_constructSummary != null) diff --git a/lib/pangea/analytics_page/analytics_page_view.dart b/lib/pangea/analytics_page/analytics_page_view.dart index 256c634e0..7ee037d2b 100644 --- a/lib/pangea/analytics_page/analytics_page_view.dart +++ b/lib/pangea/analytics_page/analytics_page_view.dart @@ -58,14 +58,12 @@ class AnalyticsPageView extends StatelessWidget { return AnalyticsPopupWrapper( constructZoom: controller.widget.constructZoom, view: ConstructTypeEnum.morph, - showAppBar: false, ); } else if (controller.selectedIndicator == ProgressIndicatorEnum.wordsUsed) { return AnalyticsPopupWrapper( constructZoom: controller.widget.constructZoom, view: ConstructTypeEnum.vocab, - showAppBar: false, ); } diff --git a/lib/pangea/chat_settings/widgets/delete_space_dialog.dart b/lib/pangea/chat_settings/widgets/delete_space_dialog.dart index 4adce8e62..f8a7edd3d 100644 --- a/lib/pangea/chat_settings/widgets/delete_space_dialog.dart +++ b/lib/pangea/chat_settings/widgets/delete_space_dialog.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pangea/chat_settings/utils/delete_room.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; class DeleteSpaceDialog extends StatefulWidget { @@ -32,7 +33,9 @@ class DeleteSpaceDialogState extends State { @override void initState() { super.initState(); - _getSpaceChildrenToDelete(); + WidgetsBinding.instance.addPostFrameCallback( + (_) => _getSpaceChildrenToDelete(), + ); } Future _getSpaceChildrenToDelete() async { @@ -44,7 +47,7 @@ class DeleteSpaceDialogState extends State { try { _rooms = await widget.space.getSpaceChildrenToDelete(); } catch (e, s) { - _roomLoadError = L10n.of(context).oopsSomethingWentWrong; + _roomLoadError = L10n.of(context).errorLoadingSpaceChildren; ErrorHandler.logError( e: e, s: s, @@ -162,16 +165,9 @@ class DeleteSpaceDialogState extends State { if (_roomLoadError != null) { return Center( - child: Column( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.error_outline, - color: Theme.of(context).colorScheme.error, - ), - Text(L10n.of(context).oopsSomethingWentWrong), - ], + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: ErrorIndicator(message: _roomLoadError!), ), ); } @@ -252,7 +248,7 @@ class DeleteSpaceDialogState extends State { child: _deleteError != null ? Padding( padding: const EdgeInsets.all(8.0), - child: Text(L10n.of(context).oopsSomethingWentWrong), + child: Text(_deleteError!), ) : const SizedBox(), ), diff --git a/lib/pangea/common/widgets/error_indicator.dart b/lib/pangea/common/widgets/error_indicator.dart new file mode 100644 index 000000000..8f33143a6 --- /dev/null +++ b/lib/pangea/common/widgets/error_indicator.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class ErrorIndicator extends StatelessWidget { + final String message; + final double? iconSize; + final TextStyle? style; + + const ErrorIndicator({ + super.key, + required this.message, + this.iconSize, + this.style, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.error, + color: Theme.of(context).colorScheme.error, + size: iconSize ?? 24.0, + ), + const SizedBox(width: 8), + Text( + message, + style: style, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ); + } +}