TF-4301 Add "Create a new label" button in Label As menus and wire up tagging in email view

This commit is contained in:
dab246
2026-02-04 13:53:01 +07:00
committed by Dat H. Pham
parent 061793846e
commit 190ccc7bc3
29 changed files with 600 additions and 247 deletions
@@ -1,6 +1,7 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:core/utils/app_logger.dart';
import 'package:flutter/material.dart';
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';
@@ -18,6 +19,7 @@ import 'package:tmail_ui_user/features/email/presentation/extensions/presentatio
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/presentation/widgets/add_label_to_email_modal.dart';
import 'package:tmail_ui_user/features/labels/presentation/widgets/label_list_context_menu.dart';
import 'package:tmail_ui_user/features/thread/domain/exceptions/thread_exceptions.dart';
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
import 'package:tmail_ui_user/main/utils/toast_manager.dart';
@@ -180,7 +182,10 @@ mixin AddLabelToEmailMixin on EmitStateMixin {
);
}
Future<void> openAddLabelToEmailDialogModal(PresentationEmail email) async {
Future<void> openAddLabelToEmailDialogModal({
required PresentationEmail email,
required OnCreateANewLabelAction onCreateANewLabelAction,
}) async {
final emailId = email.id;
if (emailId == null) {
logWarning(
@@ -192,8 +197,9 @@ mixin AddLabelToEmailMixin on EmitStateMixin {
final labels = currentLabelList;
final emailLabels = email.getLabelList(labels);
await DialogRouter().openDialogModal(
final newLabel = await DialogRouter().openDialogModal(
child: AddLabelToEmailModal(
key: const Key('add_label_to_email_modal'),
labels: labels,
emailLabels: emailLabels,
emailIds: [emailId],
@@ -202,9 +208,14 @@ mixin AddLabelToEmailMixin on EmitStateMixin {
toggleLabelToEmail(emailIds.first, label, isSelected);
}
},
onCreateANewLabelAction: onCreateANewLabelAction,
),
dialogLabel: 'add-label-to-email-modal',
);
if (newLabel is Label) {
toggleLabelToEmail(emailId, newLabel, true);
}
}
void subscribeLabelViewStateSuccess(Success success) {
@@ -0,0 +1,56 @@
import 'package:core/presentation/resources/image_paths.dart';
import 'package:flutter/material.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:labels/model/label.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/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/features/mailbox_creator/domain/usecases/verify_name_interactor.dart';
import 'package:tmail_ui_user/main/routes/dialog_router.dart';
mixin LabelModalMixin {
List<Label> get labels;
ImagePaths get imagePaths;
CreateNewLabelInteractor? get createNewLabelInteractor;
EditLabelInteractor? get editLabelInteractor;
Future<dynamic> openCreateNewLabelModal({
required AccountId accountId,
required VerifyNameInteractor verifyNameInteractor,
}) async {
return DialogRouter().openDialogModal(
child: CreateNewLabelModal(
key: const Key('create_label_modal'),
labels: labels,
accountId: accountId,
imagePaths: imagePaths,
verifyNameInteractor: verifyNameInteractor,
createNewLabelInteractor: createNewLabelInteractor!,
editLabelInteractor: editLabelInteractor!,
),
dialogLabel: 'create-new-label-modal',
);
}
Future<dynamic> openEditLabelModal({
required Label selectedLabel,
required AccountId accountId,
required VerifyNameInteractor verifyNameInteractor,
}) async {
return DialogRouter().openDialogModal(
child: CreateNewLabelModal(
key: const Key('edit_label_modal'),
labels: labels,
accountId: accountId,
imagePaths: imagePaths,
selectedLabel: selectedLabel,
actionType: LabelActionType.edit,
verifyNameInteractor: verifyNameInteractor,
createNewLabelInteractor: createNewLabelInteractor!,
editLabelInteractor: editLabelInteractor!,
),
dialogLabel: 'edit-label-modal',
);
}
}
@@ -15,8 +15,9 @@ mixin LabelSubMenuMixin {
required PresentationEmail presentationEmail,
required List<Label>? labels,
required OnSelectLabelAction onSelectLabelAction,
required OnCreateANewLabelAction onCreateANewLabelAction,
}) {
if (actionType == EmailActionType.labelAs && labels?.isNotEmpty == true) {
if (actionType == EmailActionType.labelAs) {
final listLabels = labels ?? [];
final emailLabels = presentationEmail.getLabelList(listLabels);
return LabelListContextMenu(
@@ -24,6 +25,7 @@ mixin LabelSubMenuMixin {
emailLabels: emailLabels,
imagePaths: imagePaths,
onSelectLabelAction: onSelectLabelAction,
onCreateANewLabelAction: onCreateANewLabelAction,
);
}
return null;