Files
workavia-mail-front/lib/features/thread_detail/presentation/thread_detail_controller.dart
T
DatDang d210a892f2 TF-3698 Thread Detail Real time update
TF-3698 Thread Detail update reset RefreshThreadDetailAction position

TF-3698 Thread Detail refactor initializeThreadDetailEmails

TF-3698 Thread Detail refactor handleRefreshThreadDetailAction

TF-3698 Thread Detail create listThreadIds in ListEmailExtension
2025-07-21 05:34:53 +07:00

260 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:core/data/network/download/download_manager.dart';
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:dartz/dartz.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
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/individual_header_identifier.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:model/email/email_property.dart';
import 'package:model/email/presentation_email.dart';
import 'package:model/extensions/keyword_identifier_extension.dart';
import 'package:model/extensions/session_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/presentation/action/email_ui_action.dart';
import 'package:tmail_ui_user/features/email/presentation/model/email_loaded.dart';
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_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/mark_as_email_star_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachment_for_web_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/print_email_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_action_reactor/email_action_reactor.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/features/manage_account/domain/state/create_new_rule_filter_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/create_new_email_rule_filter_interactor.dart';
import 'package:tmail_ui_user/features/search/email/presentation/search_email_controller.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_by_id_state.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_emails_by_ids_state.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/state/get_thread_detail_status_state.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_by_id_interactor.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_emails_by_ids_interactor.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/action/thread_detail_ui_action.dart';
import 'package:tmail_ui_user/features/thread_detail/domain/usecases/get_thread_detail_status_interactor.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/close_thread_detail_action.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_email_ids_by_thread_id_success.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_emails_by_ids_success.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_get_thread_by_id_failure.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_refresh_thread_detail_action.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/initialize_thread_detail_emails.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/refresh_thread_detail_on_setting_changed.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/model/thread_detail_setting_status.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/handle_collapsed_email_download_states.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/mark_collapsed_email_star_success.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/mark_collapsed_email_unread_success.dart';
import 'package:tmail_ui_user/features/thread_detail/presentation/extension/quick_create_rule_from_collapsed_email_success.dart';
class ThreadDetailController extends BaseController {
final GetThreadDetailStatusInteractor _getThreadDetailStatusInteractor;
final GetThreadByIdInteractor _getEmailIdsByThreadIdInteractor;
final GetEmailsByIdsInteractor getEmailsByIdsInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
final PrintEmailInteractor _printEmailInteractor;
final GetEmailContentInteractor _getEmailContentInteractor;
final DownloadAttachmentForWebInteractor _downloadAttachmentForWebInteractor;
ThreadDetailController(
this._getThreadDetailStatusInteractor,
this._getEmailIdsByThreadIdInteractor,
this.getEmailsByIdsInteractor,
this._markAsEmailReadInteractor,
this._markAsStarEmailInteractor,
this._printEmailInteractor,
this._getEmailContentInteractor,
this._downloadAttachmentForWebInteractor,
);
final emailIdsPresentation = <EmailId, PresentationEmail?>{}.obs;
final currentExpandedEmailId = Rxn<EmailId>();
final currentEmailLoaded = Rxn<EmailLoaded>();
late final EmailActionReactor emailActionReactor;
final additionalProperties = Properties({
IndividualHeaderIdentifier.listPostHeader.value,
IndividualHeaderIdentifier.listUnsubscribeHeader.value,
});
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final searchEmailController = Get.find<SearchEmailController>();
final downloadManager = Get.find<DownloadManager>();
final downloadProgressState = StreamController<Either<Failure, Success>>();
ScrollController? scrollController;
CreateNewEmailRuleFilterInteractor? _createNewEmailRuleFilterInteractor;
AppLifecycleListener? appLifecycleListener;
ThreadDetailSettingStatus threadDetailSettingStatus = ThreadDetailSettingStatus.loading;
bool threadDetailWasEnabled = true;
AccountId? get accountId => mailboxDashBoardController.accountId.value;
Session? get session => mailboxDashBoardController.sessionCurrent;
MailboxId? get sentMailboxId => mailboxDashBoardController.getMailboxIdByRole(
PresentationMailbox.roleSent,
);
String? get ownEmailAddress => session?.getOwnEmailAddress();
bool get isSearchRunning {
final isWebSearchRunning = mailboxDashBoardController
.searchController
.isSearchEmailRunning;
final isMobileSearchRunning = searchEmailController
.searchIsRunning
.value == true;
return isWebSearchRunning || isMobileSearchRunning;
}
bool get isThreadDetailEnabled =>
threadDetailSettingStatus == ThreadDetailSettingStatus.enabled;
@override
void onInit() {
super.onInit();
consumeState(_getThreadDetailStatusInteractor.execute());
appLifecycleListener = AppLifecycleListener(
onResume: () {
if (threadDetailSettingStatus == ThreadDetailSettingStatus.loading) {
return;
}
consumeState(_getThreadDetailStatusInteractor.execute());
},
);
ever(mailboxDashBoardController.accountId, (accountId) {
if (accountId == null) return;
injectRuleFilterBindings(session, accountId);
_createNewEmailRuleFilterInteractor = getBinding<CreateNewEmailRuleFilterInteractor>();
emailActionReactor = EmailActionReactor(
_markAsEmailReadInteractor,
_markAsStarEmailInteractor,
_createNewEmailRuleFilterInteractor,
_printEmailInteractor,
_getEmailContentInteractor,
_downloadAttachmentForWebInteractor,
);
});
downloadProgressState.stream.listen(handleDownloadProgressState);
ever(mailboxDashBoardController.selectedEmail, (presentationEmail) async {
if (presentationEmail?.threadId == null) {
closeThreadDetailAction(currentContext);
return;
}
if (!isThreadDetailEnabled && presentationEmail?.id != null) {
consumeState(Stream.value(Right(GetThreadByIdSuccess([
presentationEmail!.id!,
]))));
return;
}
if (session != null &&
accountId != null &&
sentMailboxId != null &&
ownEmailAddress != null) {
scrollController = ScrollController();
consumeState(_getEmailIdsByThreadIdInteractor.execute(
presentationEmail!.threadId!,
session!,
accountId!,
sentMailboxId!,
ownEmailAddress!,
selectedEmailId: presentationEmail.id,
));
}
});
ever(mailboxDashBoardController.threadDetailUIAction, (action) {
if (action is UpdatedEmailKeywordsAction) {
emailIdsPresentation
[action.emailId]
?.keywords
?[action.updatedKeyword] = action.value;
if (action.updatedKeyword == KeyWordIdentifierExtension.unsubscribeMail) {
emailIdsPresentation
[action.emailId]
?..emailHeader?.removeWhere((element) {
return element.name == EmailProperty.headerUnsubscribeKey;
})
..listUnsubscribeHeader?.clear();
}
} else if (action is UpdatedThreadDetailSettingAction) {
consumeState(_getThreadDetailStatusInteractor.execute());
mailboxDashBoardController.dispatchThreadDetailUIAction(
ThreadDetailUIAction(),
);
}
});
ever(mailboxDashBoardController.emailUIAction, (action) {
if (action is RefreshThreadDetailAction) {
mailboxDashBoardController.dispatchEmailUIAction(EmailUIAction());
handleRefreshThreadDetailAction(
action,
_getEmailIdsByThreadIdInteractor,
);
}
});
}
void reset() {
emailIdsPresentation.clear();
scrollController?.dispose();
scrollController = null;
currentExpandedEmailId.value = null;
currentEmailLoaded.value = null;
}
@override
void handleSuccessViewState(success) {
if (success is GetThreadByIdSuccess) {
handleGetEmailIdsByThreadIdSuccess(success);
initializeThreadDetailEmails(success);
} else if (success is GetEmailsByIdsSuccess) {
handleGetEmailsByIdsSuccess(success);
} else if (success is MarkAsEmailReadSuccess) {
markCollapsedEmailReadSuccess(success);
} else if (success is MarkAsStarEmailSuccess) {
markCollapsedEmailStarSuccess(success);
} else if (success is CreateNewRuleFilterSuccess) {
quickCreateRuleFromCollapsedEmailSuccess(success);
} else if (success is DownloadAttachmentForWebSuccess) {
handleDownloadSuccess(success);
} else if (success is GetThreadDetailStatusSuccess) {
threadDetailSettingStatus = success.threadDetailEnabled
? ThreadDetailSettingStatus.enabled
: ThreadDetailSettingStatus.disabled;
refreshThreadDetailOnSettingChanged();
} else if (success is GettingThreadDetailStatus) {
threadDetailSettingStatus = ThreadDetailSettingStatus.loading;
} else {
super.handleSuccessViewState(success);
}
}
@override
void handleFailureViewState(failure) {
if (failure is GetThreadByIdFailure) {
handleGetThreadByIdFailure(failure);
}
if (failure is GetEmailsByIdsFailure) {
if (failure.updateCurrentThreadDetail) return;
showRetryToast(failure);
return;
}
if (failure is DownloadAttachmentForWebFailure) {
handleDownloadFailure(failure);
return;
}
if (failure is GetThreadDetailStatusFailure) {
threadDetailSettingStatus = ThreadDetailSettingStatus.enabled;
refreshThreadDetailOnSettingChanged();
}
super.handleFailureViewState(failure);
}
}