TF-4243 Implement delete a label in presentation layer

This commit is contained in:
dab246
2026-01-12 15:58:53 +07:00
committed by Dat H. Pham
parent 327d05d20b
commit 9760b6f077
11 changed files with 144 additions and 9 deletions
@@ -1,15 +1,16 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:labels/model/label.dart';
class DeletingALabel extends LoadingState {}
class DeleteALabelSuccess extends UIState {
final String labelDisplayName;
final Label deletedLabel;
DeleteALabelSuccess(this.labelDisplayName);
DeleteALabelSuccess(this.deletedLabel);
@override
List<Object> get props => [labelDisplayName];
List<Object> get props => [deletedLabel];
}
class DeleteALabelFailure extends FeatureFailure {
@@ -2,7 +2,6 @@ import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/extensions/label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
import 'package:tmail_ui_user/features/labels/domain/state/delete_a_label_state.dart';
@@ -18,8 +17,8 @@ class DeleteALabelInteractor {
) async* {
try {
yield Right(DeletingALabel());
await _labelRepository.createNewLabel(accountId, label);
yield Right(DeleteALabelSuccess(label.safeDisplayName));
await _labelRepository.deleteLabel(accountId, label);
yield Right(DeleteALabelSuccess(label));
} catch (e) {
yield Left(DeleteALabelFailure(e));
}
@@ -1,21 +1,28 @@
import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/extensions/label_extension.dart';
import 'package:labels/extensions/list_label_extension.dart';
import 'package:labels/model/label.dart';
import 'package:tmail_ui_user/features/base/mixin/message_dialog_action_manager.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/labels/domain/model/edit_label_request.dart';
import 'package:tmail_ui_user/features/labels/domain/state/delete_a_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_controller.dart';
import 'package:tmail_ui_user/features/labels/presentation/models/label_action_type.dart';
import 'package:tmail_ui_user/features/labels/presentation/widgets/create_new_label_modal.dart';
import 'package:tmail_ui_user/main/exceptions/logic_exception.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
extension HandleLabelActionTypeExtension on LabelController {
void handleLabelActionType({
required BuildContext context,
required LabelActionType actionType,
required AccountId? accountId,
Label? label,
@@ -29,6 +36,12 @@ extension HandleLabelActionTypeExtension on LabelController {
openEditLabelModal(accountId: accountId, label: label);
break;
case LabelActionType.delete:
if (label == null) return;
_openDeleteLabelModal(
context: context,
accountId: accountId,
label: label,
);
break;
}
}
@@ -109,4 +122,61 @@ extension HandleLabelActionTypeExtension on LabelController {
labels.add(newLabel);
labels.sortByAlphabetically();
}
Future<void> _openDeleteLabelModal({
required BuildContext context,
required AccountId? accountId,
required Label label,
}) async {
final appLocalizations = AppLocalizations.of(context);
MessageDialogActionManager().showConfirmDialogAction(
context,
appLocalizations.areYouSureYouWantToDeleteTheLabel(label.safeDisplayName),
appLocalizations.delete,
key: const Key('confirm_dialog_delete_label'),
title: appLocalizations.deleteLabel,
cancelTitle: appLocalizations.cancel,
onConfirmAction: () => _deleteLabel(accountId: accountId, label: label),
onCloseButtonAction: popBack,
alignCenter: true,
dialogMargin: MediaQuery.paddingOf(context).add(
const EdgeInsets.only(bottom: 12),
),
);
}
void _deleteLabel({
required AccountId? accountId,
required Label label,
}) {
log('LabelController::deleteLabel:label: $label');
if (accountId == null) {
emitFailure(
controller: this,
failure: DeleteALabelFailure(NotFoundAccountIdException()),
);
} else if (deleteALabelInteractor == null) {
emitFailure(
controller: this,
failure: DeleteALabelFailure(InteractorNotInitialized()),
);
} else {
consumeState(deleteALabelInteractor!.execute(accountId, label));
}
}
void handleDeleteLabelSuccess(DeleteALabelSuccess success) {
toastManager.showMessageSuccess(success);
syncListLabelsAfterDelete(success.deletedLabel);
}
void handleDeleteLabelFailure(DeleteALabelFailure failure) {
toastManager.showMessageFailure(failure);
}
void syncListLabelsAfterDelete(Label deletedLabel) {
labels.removeWhere((label) => label.id == deletedLabel.id);
labels.sortByAlphabetically();
}
}
@@ -13,9 +13,11 @@ import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
import 'package:tmail_ui_user/features/labels/domain/state/create_new_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/delete_a_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/get_all_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/create_new_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/edit_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/delete_a_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/presentation/extensions/handle_label_action_type_extension.dart';
import 'package:tmail_ui_user/features/labels/presentation/label_interactor_bindings.dart';
@@ -37,6 +39,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
CreateNewLabelInteractor? _createNewLabelInteractor;
GetLabelSettingStateInteractor? _getLabelSettingStateInteractor;
EditLabelInteractor? _editLabelInteractor;
DeleteALabelInteractor? _deleteALabelInteractor;
bool isLabelCapabilitySupported(Session session, AccountId accountId) {
return LabelsConstants.labelsCapability.isSupported(session, accountId);
@@ -62,10 +65,13 @@ class LabelController extends BaseController with LabelContextMenuMixin {
_getAllLabelInteractor = getBinding<GetAllLabelInteractor>();
_createNewLabelInteractor = getBinding<CreateNewLabelInteractor>();
_editLabelInteractor = getBinding<EditLabelInteractor>();
_deleteALabelInteractor = getBinding<DeleteALabelInteractor>();
}
EditLabelInteractor? get editLabelInteractor => _editLabelInteractor;
DeleteALabelInteractor? get deleteALabelInteractor => _deleteALabelInteractor;
void getAllLabels(AccountId accountId) {
if (_getAllLabelInteractor == null) return;
@@ -139,6 +145,8 @@ class LabelController extends BaseController with LabelContextMenuMixin {
_handleGetLabelSettingStateSuccess(success.isEnabled, success.accountId);
} else if (success is EditLabelSuccess) {
handleEditLabelSuccess(success);
} else if (success is DeleteALabelSuccess) {
handleDeleteLabelSuccess(success);
} else {
super.handleSuccessViewState(success);
}
@@ -155,6 +163,8 @@ class LabelController extends BaseController with LabelContextMenuMixin {
_clearLabelData();
} else if (failure is EditLabelFailure) {
handleEditLabelFailure(failure);
} else if (failure is DeleteALabelFailure) {
handleDeleteLabelFailure(failure);
} else {
super.handleFailureViewState(failure);
}
@@ -165,6 +175,7 @@ class LabelController extends BaseController with LabelContextMenuMixin {
_getAllLabelInteractor = null;
_createNewLabelInteractor = null;
_editLabelInteractor = null;
_deleteALabelInteractor = null;
_getLabelSettingStateInteractor = null;
super.onClose();
}
@@ -8,6 +8,7 @@ import 'package:tmail_ui_user/features/labels/data/repository/label_repository_i
import 'package:tmail_ui_user/features/labels/domain/repository/label_repository.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/create_new_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/edit_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/delete_a_label_interactor.dart';
import 'package:tmail_ui_user/features/labels/domain/usecases/get_all_label_interactor.dart';
import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/main/exceptions/remote_exception_thrower.dart';
@@ -35,6 +36,7 @@ class LabelInteractorBindings extends InteractorsBindings {
Get.lazyPut(() => GetAllLabelInteractor(Get.find<LabelRepository>()));
Get.lazyPut(() => CreateNewLabelInteractor(Get.find<LabelRepository>()));
Get.lazyPut(() => EditLabelInteractor(Get.find<LabelRepository>()));
Get.lazyPut(() => DeleteALabelInteractor(Get.find<LabelRepository>()));
Get.lazyPut(() => VerifyNameInteractor());
}
@@ -380,6 +380,7 @@ abstract class BaseMailboxView extends GetWidget<MailboxController>
onToggleLabelListState: labelController.toggleLabelListState,
onAddNewLabel: () =>
labelController.handleLabelActionType(
context: context,
actionType: LabelActionType.create,
accountId: accountId,
),
@@ -22,7 +22,11 @@ extension HandleLabelActionTypeExtension on MailboxDashBoardController {
imagePaths,
label,
position: position,
_onPerformLabelActionType,
(label, actionType) => _onPerformLabelActionType(
context: context,
label: label,
actionType: actionType,
),
);
} finally {
if (PlatformInfo.isWeb) {
@@ -31,8 +35,13 @@ extension HandleLabelActionTypeExtension on MailboxDashBoardController {
}
}
void _onPerformLabelActionType(Label label, LabelActionType actionType) {
void _onPerformLabelActionType({
required BuildContext context,
required Label label,
required LabelActionType actionType,
}) {
labelController.handleLabelActionType(
context: context,
actionType: actionType,
accountId: accountId.value,
label: label,
@@ -48,7 +57,11 @@ extension HandleLabelActionTypeExtension on MailboxDashBoardController {
context,
imagePaths,
label,
_onPerformLabelActionType,
(label, actionType) => _onPerformLabelActionType(
context: context,
label: label,
actionType: actionType,
),
);
}
}
+16
View File
@@ -5437,5 +5437,21 @@
"placeholders": {
"labelName": {}
}
},
"deleteLabelSuccessfullyMessage": "You successfully deleted the {labelName} label",
"@deleteLabelSuccessfullyMessage": {
"type": "text",
"placeholders_order": [
"labelName"
],
"placeholders": {
"labelName": {}
}
},
"deleteALabelFailure": "Delete a label failure",
"@deleteALabelFailure": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -5754,4 +5754,19 @@ class AppLocalizations {
args: [labelName],
);
}
String deleteLabelSuccessfullyMessage(String labelName) {
return Intl.message(
'You successfully deleted the $labelName label',
name: 'deleteLabelSuccessfullyMessage',
args: [labelName],
);
}
String get deleteALabelFailure {
return Intl.message(
'Delete a label failure',
name: 'deleteALabelFailure',
);
}
}
+7
View File
@@ -34,6 +34,7 @@ import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.d
import 'package:tmail_ui_user/features/home/domain/state/get_session_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/create_new_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/edit_label_state.dart';
import 'package:tmail_ui_user/features/labels/domain/state/delete_a_label_state.dart';
import 'package:tmail_ui_user/features/login/data/network/oidc_error.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/authentication_exception.dart';
import 'package:tmail_ui_user/features/login/domain/exceptions/oauth_authorization_error.dart';
@@ -224,6 +225,8 @@ class ToastManager {
appLocalizations.removeLabelFromThreadFailureMessage(
failure.labelDisplay,
);
} else if (failure is DeleteALabelFailure) {
message = message ?? appLocalizations.deleteALabelFailure;
}
log('ToastManager::showMessageFailure: Message: $message');
if (message?.trim().isNotEmpty == true) {
@@ -311,6 +314,10 @@ class ToastManager {
message = appLocalizations.removeLabelFromThreadSuccessfullyMessage(
success.labelDisplay,
);
} else if (success is DeleteALabelSuccess) {
message = appLocalizations.deleteLabelSuccessfullyMessage(
success.deletedLabel.safeDisplayName,
);
}
log('ToastManager::showMessageSuccess: Message: $message');
if (message?.trim().isNotEmpty == true) {