From 879b18bc45722a164313ad161edb812c1dc53790 Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 20 Jan 2026 16:21:37 +0700 Subject: [PATCH] TF-4236 Fix guard delete UI when no handler is provided. --- integration_test/robots/email_robot.dart | 7 +++++- integration_test/robots/thread_robot.dart | 1 + .../remove_a_label_from_email_scenario.dart | 1 - .../remove_a_label_from_email_test.dart | 2 +- .../email/data/network/email_api.dart | 4 +-- ...> remove_a_label_from_a_thread_state.dart} | 0 ...move_a_label_from_a_thread_interactor.dart | 2 +- .../widgets/email_subject_widget.dart | 25 +++++++++++-------- .../remove_label_from_thread_extension.dart | 2 +- .../thread_detail_controller.dart | 2 +- lib/l10n/intl_messages.arb | 2 +- lib/main/localizations/app_localizations.dart | 2 +- lib/main/utils/toast_manager.dart | 2 +- 13 files changed, 29 insertions(+), 23 deletions(-) rename lib/features/email/domain/state/labels/{remove_a_label_from_an_thread_state.dart => remove_a_label_from_a_thread_state.dart} (100%) diff --git a/integration_test/robots/email_robot.dart b/integration_test/robots/email_robot.dart index 7ca79f2f6..be6871481 100644 --- a/integration_test/robots/email_robot.dart +++ b/integration_test/robots/email_robot.dart @@ -88,6 +88,11 @@ class EmailRobot extends CoreRobot { } Future tapRemoveLabelButton(String labelDisplayName) async { - await $(EmailSubjectWidget).$(LabelWidget).$(TagWidget).$(InkWell).tap(); + await $(EmailSubjectWidget) + .$(LabelWidget) + .$(TagWidget) + .which((widget) => widget.text == labelDisplayName) + .$(InkWell) + .tap(); } } \ No newline at end of file diff --git a/integration_test/robots/thread_robot.dart b/integration_test/robots/thread_robot.dart index f43403f62..75d26dfb1 100644 --- a/integration_test/robots/thread_robot.dart +++ b/integration_test/robots/thread_robot.dart @@ -42,6 +42,7 @@ class ThreadRobot extends CoreRobot { ); await $.waitUntilVisible(email); await email.tap(); + await $.pump(const Duration(seconds: 2)); } Future openMailbox() async { diff --git a/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart b/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart index 4365f9c52..9d00e0e67 100644 --- a/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart +++ b/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart @@ -48,7 +48,6 @@ class RemoveALabelFromEmailScenario extends BaseTestScenario await _expectEmailListDisplayedCorrectByTag(labelDisplayName); await threadRobot.openEmailWithLabel(labelDisplayName); - await $.pumpAndSettle(duration: const Duration(seconds: 1)); await _expectLabelDisplayedOnEmailSubject(labelDisplayName); await emailRobot.tapRemoveLabelButton(labelDisplayName); diff --git a/integration_test/tests/labels/remove_a_label_from_email_test.dart b/integration_test/tests/labels/remove_a_label_from_email_test.dart index af2353f83..8e002dd65 100644 --- a/integration_test/tests/labels/remove_a_label_from_email_test.dart +++ b/integration_test/tests/labels/remove_a_label_from_email_test.dart @@ -4,7 +4,7 @@ import '../../scenarios/labels/remove_a_label_from_email_scenario.dart'; void main() { TestBase().runPatrolTest( description: - 'Should remove tag on email subject when click click on the cross on a tag in the opened mail', + 'Should remove tag on email subject when clicking on the cross on a tag in the opened mail', scenarioBuilder: ($) => RemoveALabelFromEmailScenario($), ); } diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index a28c55852..2abb44e32 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -991,9 +991,7 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin { final isUpdated = emailIdsUpdated.every(ids.contains); if (emailIdsUpdated.isEmpty || !isUpdated) { - for (var id in emailIds) { - throw parseErrorForSetResponse(response, id.id); - } + throw parseErrorForSetResponse(response, emailIds.first.id); } } diff --git a/lib/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart b/lib/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart similarity index 100% rename from lib/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart rename to lib/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart diff --git a/lib/features/email/domain/usecases/labels/remove_a_label_from_a_thread_interactor.dart b/lib/features/email/domain/usecases/labels/remove_a_label_from_a_thread_interactor.dart index f84c227e6..925104e28 100644 --- a/lib/features/email/domain/usecases/labels/remove_a_label_from_a_thread_interactor.dart +++ b/lib/features/email/domain/usecases/labels/remove_a_label_from_a_thread_interactor.dart @@ -6,7 +6,7 @@ import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; -import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart'; class RemoveALabelFromAThreadInteractor { final EmailRepository _emailRepository; diff --git a/lib/features/email/presentation/widgets/email_subject_widget.dart b/lib/features/email/presentation/widgets/email_subject_widget.dart index 8b0fb5f9a..c626f8e0d 100644 --- a/lib/features/email/presentation/widgets/email_subject_widget.dart +++ b/lib/features/email/presentation/widgets/email_subject_widget.dart @@ -103,11 +103,15 @@ class _EmailSubjectWidgetState extends State { } List _buildLabelWidgets() { + final canRemove = widget.onDeleteLabelAction != null; return _currentLabels - ?.map((label) => LabelWidget.create( + ?.map((label) => LabelWidget( label: label, - removeLabelAction: _buildRemoveLabelWidget(label), - padding: const EdgeInsetsDirectional.only(start: 4, end: 2), + actionWidget: + canRemove ? _buildRemoveLabelWidget(label) : null, + padding: canRemove + ? const EdgeInsetsDirectional.only(start: 4, end: 2) + : null, )) .toList() ?? const []; @@ -125,13 +129,12 @@ class _EmailSubjectWidgetState extends State { } void _onDeleteLabelAction(Label labelRemoved) { - if (mounted) { - setState(() { - _currentLabels = _currentLabels - ?.where((label) => label.id != labelRemoved.id) - .toList(); - }); - widget.onDeleteLabelAction?.call(labelRemoved); - } + if (!mounted || widget.onDeleteLabelAction == null) return; + setState(() { + _currentLabels = _currentLabels + ?.where((label) => label.id != labelRemoved.id) + .toList(); + }); + widget.onDeleteLabelAction!.call(labelRemoved); } } diff --git a/lib/features/thread_detail/presentation/extension/labels/remove_label_from_thread_extension.dart b/lib/features/thread_detail/presentation/extension/labels/remove_label_from_thread_extension.dart index f19af047a..5cbc97a87 100644 --- a/lib/features/thread_detail/presentation/extension/labels/remove_label_from_thread_extension.dart +++ b/lib/features/thread_detail/presentation/extension/labels/remove_label_from_thread_extension.dart @@ -2,7 +2,7 @@ import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:labels/labels.dart'; -import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart'; import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart'; import 'package:tmail_ui_user/features/labels/domain/exceptions/label_exceptions.dart'; import 'package:tmail_ui_user/features/thread_detail/presentation/extension/labels/add_label_to_thread_extension.dart'; diff --git a/lib/features/thread_detail/presentation/thread_detail_controller.dart b/lib/features/thread_detail/presentation/thread_detail_controller.dart index 1f7d7c982..b655a6b23 100644 --- a/lib/features/thread_detail/presentation/thread_detail_controller.dart +++ b/lib/features/thread_detail/presentation/thread_detail_controller.dart @@ -17,7 +17,7 @@ import 'package:model/extensions/keyword_identifier_extension.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/email/domain/state/add_a_label_to_an_thread_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/print_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/add_a_label_to_a_thread_interactor.dart'; diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 47f442d77..a0f40fbe7 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -5412,7 +5412,7 @@ "labelName": {} } }, - "removeLabelFromThreadFailureMessage": "Cannot remove all emails from thread to the \"{labelName}\" label", + "removeLabelFromThreadFailureMessage": "Cannot remove all emails in thread from the \"{labelName}\" label", "@removeLabelFromThreadFailureMessage": { "type": "text", "placeholders_order": [ diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index 1587699a6..29284a14b 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -5735,7 +5735,7 @@ class AppLocalizations { String removeLabelFromThreadFailureMessage(String labelName) { return Intl.message( - 'Cannot remove all emails from thread to the "$labelName" label', + 'Cannot remove all emails in thread from the "$labelName" label', name: 'removeLabelFromThreadFailureMessage', args: [labelName], ); diff --git a/lib/main/utils/toast_manager.dart b/lib/main/utils/toast_manager.dart index 96db4eab4..e2fd1e469 100644 --- a/lib/main/utils/toast_manager.dart +++ b/lib/main/utils/toast_manager.dart @@ -25,7 +25,7 @@ import 'package:tmail_ui_user/features/email/domain/model/move_action.dart'; import 'package:tmail_ui_user/features/email/domain/state/add_a_label_to_an_email_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/add_a_label_to_an_thread_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/calendar_event_reply_state.dart'; -import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_an_thread_state.dart'; +import 'package:tmail_ui_user/features/email/domain/state/labels/remove_a_label_from_a_thread_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_star_state.dart'; import 'package:tmail_ui_user/features/download/domain/state/parse_email_by_blob_id_state.dart'; import 'package:tmail_ui_user/features/download/domain/state/preview_email_from_eml_file_state.dart';