TF-348 Fix unread email counter not updating

This commit is contained in:
dab246
2022-03-25 16:03:02 +07:00
committed by Dat H. Pham
parent 90cad03f56
commit aceac30149
16 changed files with 225 additions and 109 deletions
@@ -109,7 +109,7 @@ class ButtonBuilder {
child: Container( child: Container(
key: _key, key: _key,
alignment: Alignment.center, alignment: Alignment.center,
color: _decoration == null ? _colorButton ?? Colors.white : null, color: _decoration == null ? _colorButton : null,
decoration: _decoration, decoration: _decoration,
width: _maxWidth, width: _maxWidth,
padding: _padding ?? EdgeInsets.zero, padding: _padding ?? EdgeInsets.zero,
+1
View File
@@ -6,6 +6,7 @@ abstract class BaseController extends GetxController {
final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle)); final viewState = Rx<Either<Failure, Success>>(Right(UIState.idle));
void consumeState(Stream<Either<Failure, Success>> newStateStream) async { void consumeState(Stream<Either<Failure, Success>> newStateStream) async {
log('BaseController::consumeState():');
newStateStream.listen( newStateStream.listen(
(state) => onData(state), (state) => onData(state),
onError: (error) => onError(error), onError: (error) => onError(error),
@@ -14,7 +14,6 @@ abstract class BaseMailboxController extends BaseController {
BaseMailboxController(this._treeBuilder); BaseMailboxController(this._treeBuilder);
final allMailboxNodeList = <MailboxNode>[].obs;
final folderMailboxTree = MailboxTree(MailboxNode.root()).obs; final folderMailboxTree = MailboxTree(MailboxNode.root()).obs;
final defaultMailboxTree = MailboxTree(MailboxNode.root()).obs; final defaultMailboxTree = MailboxTree(MailboxNode.root()).obs;
@@ -24,6 +23,15 @@ abstract class BaseMailboxController extends BaseController {
folderMailboxTree.value = tupleTree.value2; folderMailboxTree.value = tupleTree.value2;
} }
Future refreshTree(List<PresentationMailbox> allMailbox) async {
final tupleTree = await _treeBuilder.generateMailboxTreeInUIAfterRefreshChanges(
allMailbox, defaultMailboxTree.value, folderMailboxTree.value);
defaultMailboxTree.firstRebuild = true;
folderMailboxTree.firstRebuild = true;
defaultMailboxTree.value = tupleTree.value1;
folderMailboxTree.value = tupleTree.value2;
}
void toggleMailboxFolder(MailboxNode selectedMailboxNode) { void toggleMailboxFolder(MailboxNode selectedMailboxNode) {
final newExpandMode = selectedMailboxNode.expandMode == ExpandMode.COLLAPSE final newExpandMode = selectedMailboxNode.expandMode == ExpandMode.COLLAPSE
? ExpandMode.EXPAND ? ExpandMode.EXPAND
@@ -35,7 +35,6 @@ class EmailBindings extends BaseBindings {
Get.find<MarkAsEmailReadInteractor>(), Get.find<MarkAsEmailReadInteractor>(),
Get.find<DownloadAttachmentsInteractor>(), Get.find<DownloadAttachmentsInteractor>(),
Get.find<DeviceManager>(), Get.find<DeviceManager>(),
Get.find<AppToast>(),
Get.find<ExportAttachmentInteractor>(), Get.find<ExportAttachmentInteractor>(),
Get.find<MoveToMailboxInteractor>(), Get.find<MoveToMailboxInteractor>(),
Get.find<MarkAsStarEmailInteractor>(), Get.find<MarkAsStarEmailInteractor>(),
@@ -45,12 +45,12 @@ class EmailController extends BaseController {
final mailboxDashBoardController = Get.find<MailboxDashBoardController>(); final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
final responsiveUtils = Get.find<ResponsiveUtils>(); final responsiveUtils = Get.find<ResponsiveUtils>();
final imagePaths = Get.find<ImagePaths>(); final imagePaths = Get.find<ImagePaths>();
final _appToast = Get.find<AppToast>();
final GetEmailContentInteractor _getEmailContentInteractor; final GetEmailContentInteractor _getEmailContentInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor; final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final DownloadAttachmentsInteractor _downloadAttachmentsInteractor; final DownloadAttachmentsInteractor _downloadAttachmentsInteractor;
final DeviceManager _deviceManager; final DeviceManager _deviceManager;
final AppToast _appToast;
final ExportAttachmentInteractor _exportAttachmentInteractor; final ExportAttachmentInteractor _exportAttachmentInteractor;
final MoveToMailboxInteractor _moveToMailboxInteractor; final MoveToMailboxInteractor _moveToMailboxInteractor;
final MarkAsStarEmailInteractor _markAsStarEmailInteractor; final MarkAsStarEmailInteractor _markAsStarEmailInteractor;
@@ -72,7 +72,6 @@ class EmailController extends BaseController {
this._markAsEmailReadInteractor, this._markAsEmailReadInteractor,
this._downloadAttachmentsInteractor, this._downloadAttachmentsInteractor,
this._deviceManager, this._deviceManager,
this._appToast,
this._exportAttachmentInteractor, this._exportAttachmentInteractor,
this._moveToMailboxInteractor, this._moveToMailboxInteractor,
this._markAsStarEmailInteractor, this._markAsStarEmailInteractor,
@@ -83,12 +82,12 @@ class EmailController extends BaseController {
void onReady() { void onReady() {
super.onReady(); super.onReady();
mailboxDashBoardController.selectedEmail.listen((presentationEmail) { mailboxDashBoardController.selectedEmail.listen((presentationEmail) {
log('EmailController::onReady(): ${presentationEmail.toString()}');
if (_currentEmailId != presentationEmail?.id) { if (_currentEmailId != presentationEmail?.id) {
_clearEmailContent();
_currentEmailId = presentationEmail?.id; _currentEmailId = presentationEmail?.id;
final accountId = mailboxDashBoardController.accountId.value; _resetToOriginalValue();
if (accountId != null && presentationEmail != null) { if (presentationEmail != null) {
_getEmailContentAction(accountId, presentationEmail.id); _getEmailContentAction(presentationEmail.id);
if (presentationEmail.isUnReadEmail()) { if (presentationEmail.isUnReadEmail()) {
markAsEmailRead(presentationEmail, ReadActions.markAsRead); markAsEmailRead(presentationEmail, ReadActions.markAsRead);
} }
@@ -103,9 +102,12 @@ class EmailController extends BaseController {
super.onClose(); super.onClose();
} }
void _getEmailContentAction(AccountId accountId, EmailId emailId) async { void _getEmailContentAction(EmailId emailId) async {
final accountId = mailboxDashBoardController.accountId.value;
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(); final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl();
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl)); if (accountId != null && baseDownloadUrl != null) {
consumeState(_getEmailContentInteractor.execute(accountId, emailId, baseDownloadUrl));
}
} }
@override @override
@@ -153,7 +155,7 @@ class EmailController extends BaseController {
attachments.value = success.attachments; attachments.value = success.attachments;
} }
void _clearEmailContent() { void _resetToOriginalValue() {
attachmentsExpandMode.value = ExpandMode.COLLAPSE; attachmentsExpandMode.value = ExpandMode.COLLAPSE;
emailAddressExpandMode.value = ExpandMode.COLLAPSE; emailAddressExpandMode.value = ExpandMode.COLLAPSE;
isDisplayFullEmailAddress.value = false; isDisplayFullEmailAddress.value = false;
@@ -185,9 +187,6 @@ class EmailController extends BaseController {
} }
void _markAsEmailReadSuccess(Success success) { void _markAsEmailReadSuccess(Success success) {
if (success is MarkAsEmailReadSuccess) {
mailboxDashBoardController.setSelectedEmail(success.updatedEmail.toPresentationEmail(selectMode: SelectMode.ACTIVE));
}
mailboxDashBoardController.dispatchState(Right(success)); mailboxDashBoardController.dispatchState(Right(success));
if (success is MarkAsEmailReadSuccess if (success is MarkAsEmailReadSuccess
@@ -496,9 +495,7 @@ class EmailController extends BaseController {
} }
void backToThreadView(BuildContext context) { void backToThreadView(BuildContext context) {
attachmentsExpandMode.value = ExpandMode.COLLAPSE; mailboxDashBoardController.clearSelectedEmail();
emailAddressExpandMode.value = ExpandMode.COLLAPSE;
isDisplayFullEmailAddress.value = false;
if (responsiveUtils.isDesktop(context) || responsiveUtils.isTabletLarge(context)) { if (responsiveUtils.isDesktop(context) || responsiveUtils.isTabletLarge(context)) {
mailboxDashBoardController.dispatchRoute(AppRoutes.THREAD); mailboxDashBoardController.dispatchRoute(AppRoutes.THREAD);
} else { } else {
+29 -23
View File
@@ -31,29 +31,35 @@ class EmailView extends GetView with UserSettingPopupMenuMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return WillPopScope(
backgroundColor: responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white, onWillPop: () async {
body: Container( emailController.backToThreadView(context);
padding: EdgeInsets.zero, return true;
margin: EdgeInsets.zero, },
decoration: responsiveUtils.isTabletLarge(context) child: Scaffold(
? BoxDecoration(border: Border(left: BorderSide(color: AppColor.colorLineLeftEmailView, width: 1.0))) backgroundColor: responsiveUtils.isDesktop(context) ? AppColor.colorBgDesktop : Colors.white,
: null, body: Container(
child: SafeArea( padding: EdgeInsets.zero,
right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), margin: EdgeInsets.zero,
left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context), decoration: responsiveUtils.isTabletLarge(context)
child: Column( ? BoxDecoration(border: Border(left: BorderSide(color: AppColor.colorLineLeftEmailView, width: 1.0)))
mainAxisAlignment: MainAxisAlignment.center, : null,
children: [ child: SafeArea(
if (responsiveUtils.isDesktop(context)) right: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
Container( left: responsiveUtils.isMobileDevice(context) && responsiveUtils.isLandscape(context),
color: Colors.white, child: Column(
padding: EdgeInsets.only(right: 10, top: 16, bottom: 10), mainAxisAlignment: MainAxisAlignment.center,
child: _buildHeader(context)), children: [
Expanded(child: _buildBody(context)), if (responsiveUtils.isDesktop(context))
] Container(
) color: Colors.white,
), padding: EdgeInsets.only(right: 10, top: 16, bottom: 10),
child: _buildHeader(context)),
Expanded(child: _buildBody(context)),
]
)
),
)
) )
); );
} }
@@ -0,0 +1,25 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:model/mailbox/presentation_mailbox.dart';
class RefreshChangesAllMailboxSuccess extends UIState {
final List<PresentationMailbox> mailboxList;
final State? currentMailboxState;
RefreshChangesAllMailboxSuccess({
required this.mailboxList,
required this.currentMailboxState
});
@override
List<Object?> get props => [mailboxList, currentMailboxState];
}
class RefreshChangesAllMailboxFailure extends FeatureFailure {
final exception;
RefreshChangesAllMailboxFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -5,7 +5,7 @@ import 'package:jmap_dart_client/jmap/core/state.dart' as jmapState;
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_mailboxes_state.dart';
class RefreshAllMailboxInteractor { class RefreshAllMailboxInteractor {
final MailboxRepository _mailboxRepository; final MailboxRepository _mailboxRepository;
@@ -20,7 +20,7 @@ class RefreshAllMailboxInteractor {
.refresh(accountId, currentState) .refresh(accountId, currentState)
.map(_toGetMailboxState); .map(_toGetMailboxState);
} catch (e) { } catch (e) {
yield Left<Failure, Success>(GetAllMailboxFailure(e)); yield Left<Failure, Success>(RefreshChangesAllMailboxFailure(e));
} }
} }
@@ -29,7 +29,7 @@ class RefreshAllMailboxInteractor {
?.map((mailbox) => mailbox.toPresentationMailbox()).toList() ?.map((mailbox) => mailbox.toPresentationMailbox()).toList()
?? List<PresentationMailbox>.empty(); ?? List<PresentationMailbox>.empty();
return Right<Failure, Success>(GetAllMailboxSuccess( return Right<Failure, Success>(RefreshChangesAllMailboxSuccess(
mailboxList: mailboxList, mailboxList: mailboxList,
currentMailboxState: mailboxResponse.state) currentMailboxState: mailboxResponse.state)
); );
@@ -17,11 +17,13 @@ import 'package:tmail_ui_user/features/composer/domain/state/save_email_as_draft
import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/send_email_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_state.dart'; import 'package:tmail_ui_user/features/composer/domain/state/update_email_drafts_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_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/rename_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/refresh_changes_all_mailboxes_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/rename_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/rename_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/search_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart';
@@ -107,18 +109,22 @@ class MailboxController extends BaseMailboxController {
mailboxDashBoardController.viewState.listen((state) { mailboxDashBoardController.viewState.listen((state) {
state.map((success) { state.map((success) {
if (success is MarkAsEmailReadSuccess || log('MailboxController::onReady(): ${success.runtimeType}');
success is MarkAsMultipleEmailReadAllSuccess ||
success is MarkAsMultipleEmailReadHasSomeEmailFailure) { if (success is MarkAsMultipleEmailReadAllSuccess
|| success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
mailboxDashBoardController.clearState();
refreshMailboxChanges(); refreshMailboxChanges();
} else if (success is MoveMultipleEmailToMailboxAllSuccess } else if (success is MoveMultipleEmailToMailboxAllSuccess
|| success is MoveMultipleEmailToMailboxHasSomeEmailFailure) { || success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
mailboxDashBoardController.clearState(); mailboxDashBoardController.clearState();
refreshMailboxChanges(); refreshMailboxChanges();
} else if (success is SaveEmailAsDraftsSuccess } else if (success is MarkAsEmailReadSuccess
|| success is RemoveEmailDraftsSuccess || success is MoveToMailboxSuccess
|| success is SendEmailSuccess || success is SaveEmailAsDraftsSuccess
|| success is UpdateEmailDraftsSuccess) { || success is RemoveEmailDraftsSuccess
|| success is SendEmailSuccess
|| success is UpdateEmailDraftsSuccess) {
refreshMailboxChanges(); refreshMailboxChanges();
} }
}); });
@@ -147,6 +153,13 @@ class MailboxController extends BaseMailboxController {
currentMailboxState = success.currentMailboxState; currentMailboxState = success.currentMailboxState;
await buildTree(allMailboxes); await buildTree(allMailboxes);
_setUpMapMailboxIdDefault(allMailboxes, defaultMailboxTree.value, folderMailboxTree.value);
} else if (success is RefreshChangesAllMailboxSuccess) {
log('MailboxController::onData(): ${allMailboxes.length}');
allMailboxes = success.mailboxList;
currentMailboxState = success.currentMailboxState;
await refreshTree(allMailboxes);
_setUpMapMailboxIdDefault(allMailboxes, defaultMailboxTree.value, folderMailboxTree.value); _setUpMapMailboxIdDefault(allMailboxes, defaultMailboxTree.value, folderMailboxTree.value);
} }
}); });
@@ -171,10 +184,8 @@ class MailboxController extends BaseMailboxController {
_searchMailboxSuccess(success); _searchMailboxSuccess(success);
} else if (success is DeleteMultipleMailboxSuccess) { } else if (success is DeleteMultipleMailboxSuccess) {
_deleteMailboxSuccess(success); _deleteMailboxSuccess(success);
} else if (success is GetAllMailboxSuccess) { } else if ((success is GetAllMailboxSuccess || success is RefreshChangesAllMailboxSuccess) && isSearchActive()) {
if (isSearchActive()) { _searchMailboxAction(allMailboxes, searchQuery.value);
_searchMailboxAction(allMailboxes, searchQuery.value);
}
} else if (success is RenameMailboxSuccess) { } else if (success is RenameMailboxSuccess) {
refreshMailboxChanges(); refreshMailboxChanges();
} }
@@ -75,4 +75,54 @@ class TreeBuilder {
defaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox)); defaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox));
return Tuple2(defaultTree, folderTree); return Tuple2(defaultTree, folderTree);
} }
Future<Tuple2<MailboxTree, MailboxTree>> generateMailboxTreeInUIAfterRefreshChanges(
List<PresentationMailbox> allMailboxes,
MailboxTree defaultTreeBeforeChanges,
MailboxTree folderTreeBeforeChanges,
) async {
final Map<MailboxId, MailboxNode> mailboxDictionary = HashMap();
final newDefaultTree = MailboxTree(MailboxNode.root());
final newFolderTree = MailboxTree(MailboxNode.root());
allMailboxes.forEach((mailbox) {
final mailboxNodeBeforeChanges = defaultTreeBeforeChanges.findNode((node) => node.item.id == mailbox.id) ??
folderTreeBeforeChanges.findNode((node) => node.item.id == mailbox.id);
if (mailboxNodeBeforeChanges != null) {
mailboxDictionary[mailbox.id] = MailboxNode(
mailbox,
expandMode: mailboxNodeBeforeChanges.expandMode,
selectMode: mailboxNodeBeforeChanges.selectMode);
} else {
mailboxDictionary[mailbox.id] = MailboxNode(mailbox);
}
});
allMailboxes.forEach((mailbox) {
final parentId = mailbox.parentId;
final parentNode = mailboxDictionary[parentId];
final node = mailboxDictionary[mailbox.id];
if (node != null) {
if (parentNode != null) {
parentNode.addChildNode(node);
parentNode.childrenItems?.sortByCompare<MailboxName?>(
(node) => node.item.name,
(name, other) => name?.compareAlphabetically(other) ?? -1
);
} else {
var tree = mailbox.hasRole() ? newDefaultTree : newFolderTree;
tree.root.addChildNode(node);
tree.root.childrenItems?.sortByCompare<MailboxName?>(
(node) => node.item.name,
(name, other) => name?.compareAlphabetically(other) ?? -1
);
}
}
});
newDefaultTree.root.childrenItems?.sort((thisMailbox, thatMailbox) => thisMailbox.compareTo(thatMailbox));
return Tuple2(newDefaultTree, newFolderTree);
}
} }
@@ -0,0 +1,22 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:model/model.dart';
class RefreshChangesAllEmailSuccess extends UIState {
final List<PresentationEmail> emailList;
final State? currentEmailState;
RefreshChangesAllEmailSuccess({required this.emailList, this.currentEmailState});
@override
List<Object?> get props => [emailList, currentEmailState];
}
class RefreshChangesAllEmailFailure extends FeatureFailure {
final exception;
RefreshChangesAllEmailFailure(this.exception);
@override
List<Object> get props => [exception];
}
@@ -6,9 +6,9 @@ import 'package:jmap_dart_client/jmap/core/sort/comparator.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap; import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:tmail_ui_user/features/thread/domain/state/refresh_changes_all_email_state.dart';
class RefreshChangesEmailsInMailboxInteractor { class RefreshChangesEmailsInMailboxInteractor {
final ThreadRepository threadRepository; final ThreadRepository threadRepository;
@@ -40,7 +40,7 @@ class RefreshChangesEmailsInMailboxInteractor {
filterOption: filterOption) filterOption: filterOption)
.map(_toGetEmailState); .map(_toGetEmailState);
} catch (e) { } catch (e) {
yield Left(GetAllEmailFailure(e)); yield Left(RefreshChangesAllEmailFailure(e));
} }
} }
@@ -48,7 +48,7 @@ class RefreshChangesEmailsInMailboxInteractor {
final presentationEmailList = emailResponse.emailList final presentationEmailList = emailResponse.emailList
?.map((email) => email.toPresentationEmail()).toList() ?? List.empty(); ?.map((email) => email.toPresentationEmail()).toList() ?? List.empty();
return Right<Failure, Success>(GetAllEmailSuccess( return Right<Failure, Success>(RefreshChangesAllEmailSuccess(
emailList: presentationEmailList, emailList: presentationEmailList,
currentEmailState: emailResponse.state)); currentEmailState: emailResponse.state));
} }
@@ -36,6 +36,7 @@ import 'package:tmail_ui_user/features/thread/domain/state/load_more_emails_stat
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_email_read_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/mark_as_star_multiple_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/move_multiple_email_to_mailbox_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/refresh_changes_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/search_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/state/search_more_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/search_more_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart';
@@ -125,21 +126,18 @@ class ThreadController extends BaseController {
mailboxDashBoardController.viewState.listen((state) { mailboxDashBoardController.viewState.listen((state) {
state.map((success) { state.map((success) {
if (success is MarkAsEmailReadSuccess log('ThreadController::onReady(): ${success.runtimeType}');
|| success is MarkAsMultipleEmailReadAllSuccess
|| success is MarkAsMultipleEmailReadHasSomeEmailFailure if (success is SearchEmailNewQuery){
|| success is MoveToMailboxSuccess
|| success is MarkAsStarEmailSuccess) {
cancelSelectEmail();
_refreshEmailChanges();
} else if (success is SearchEmailNewQuery){
_searchEmail();
mailboxDashBoardController.clearState(); mailboxDashBoardController.clearState();
} else if (success is SaveEmailAsDraftsSuccess _searchEmail();
} else if (success is MarkAsEmailReadSuccess
|| success is MoveToMailboxSuccess
|| success is MarkAsStarEmailSuccess
|| success is SaveEmailAsDraftsSuccess
|| success is RemoveEmailDraftsSuccess || success is RemoveEmailDraftsSuccess
|| success is SendEmailSuccess || success is SendEmailSuccess
|| success is UpdateEmailDraftsSuccess) { || success is UpdateEmailDraftsSuccess) {
cancelSelectEmail();
_refreshEmailChanges(); _refreshEmailChanges();
} }
}); });
@@ -175,6 +173,8 @@ class ThreadController extends BaseController {
(success) { (success) {
if (success is GetAllEmailSuccess) { if (success is GetAllEmailSuccess) {
_getAllEmailSuccess(success); _getAllEmailSuccess(success);
} else if (success is RefreshChangesAllEmailSuccess) {
_refreshChangesAllEmailSuccess(success);
} else if (success is LoadMoreEmailsSuccess) { } else if (success is LoadMoreEmailsSuccess) {
_loadMoreEmailsSuccess(success); _loadMoreEmailsSuccess(success);
} else if (success is SearchEmailSuccess) { } else if (success is SearchEmailSuccess) {
@@ -194,7 +194,7 @@ class ThreadController extends BaseController {
(failure) { (failure) {
if (failure is MarkAsMultipleEmailReadAllFailure if (failure is MarkAsMultipleEmailReadAllFailure
|| failure is MarkAsMultipleEmailReadFailure) { || failure is MarkAsMultipleEmailReadFailure) {
_markAsSelectedEmailReadFailure(failure); _markAsReadSelectedMultipleEmailFailure(failure);
} else if (failure is MarkAsStarMultipleEmailAllFailure } else if (failure is MarkAsStarMultipleEmailAllFailure
|| failure is MarkAsStarMultipleEmailFailure) { || failure is MarkAsStarMultipleEmailFailure) {
_markAsStarMultipleEmailFailure(failure); _markAsStarMultipleEmailFailure(failure);
@@ -203,7 +203,7 @@ class ThreadController extends BaseController {
(success) { (success) {
if (success is MarkAsMultipleEmailReadAllSuccess if (success is MarkAsMultipleEmailReadAllSuccess
|| success is MarkAsMultipleEmailReadHasSomeEmailFailure) { || success is MarkAsMultipleEmailReadHasSomeEmailFailure) {
_markAsSelectedEmailReadSuccess(success); _markAsReadSelectedMultipleEmailSuccess(success);
} else if (success is MoveMultipleEmailToMailboxAllSuccess } else if (success is MoveMultipleEmailToMailboxAllSuccess
|| success is MoveMultipleEmailToMailboxHasSomeEmailFailure) { || success is MoveMultipleEmailToMailboxHasSomeEmailFailure) {
_moveSelectedMultipleEmailToMailboxSuccess(success); _moveSelectedMultipleEmailToMailboxSuccess(success);
@@ -242,6 +242,12 @@ class ThreadController extends BaseController {
emailList.value = success.emailList; emailList.value = success.emailList;
} }
void _refreshChangesAllEmailSuccess(RefreshChangesAllEmailSuccess success) {
log('ThreadController::_refreshChangesAllEmailSuccess(): ${success.emailList.length}');
_currentEmailState = success.currentEmailState;
emailList.value = success.emailList;
}
void _getAllEmailAction(AccountId accountId, {MailboxId? mailboxId}) { void _getAllEmailAction(AccountId accountId, {MailboxId? mailboxId}) {
log('ThreadController::_getAllEmailAction(): mailboxId = $mailboxId'); log('ThreadController::_getAllEmailAction(): mailboxId = $mailboxId');
consumeState(_getEmailsInMailboxInteractor.execute( consumeState(_getEmailsInMailboxInteractor.execute(
@@ -431,13 +437,10 @@ class ThreadController extends BaseController {
currentSelectMode.value = SelectMode.INACTIVE; currentSelectMode.value = SelectMode.INACTIVE;
} }
void markAsSelectedEmailRead(List<PresentationEmail> listPresentationEmail, {bool fromContextMenuAction = false}) { void markAsReadSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail) {
if (fromContextMenuAction) { cancelSelectEmail();
popBack();
}
final readAction = listPresentationEmail.isAllEmailRead ? ReadActions.markAsUnread : ReadActions.markAsRead; final readAction = listPresentationEmail.isAllEmailRead ? ReadActions.markAsUnread : ReadActions.markAsRead;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value; final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (_accountId != null && mailboxCurrent != null) { if (_accountId != null && mailboxCurrent != null) {
final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList(); final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList();
@@ -445,9 +448,7 @@ class ThreadController extends BaseController {
} }
} }
void _markAsSelectedEmailReadSuccess(Success success) { void _markAsReadSelectedMultipleEmailSuccess(Success success) {
cancelSelectEmail();
mailboxDashBoardController.dispatchState(Right(success)); mailboxDashBoardController.dispatchState(Right(success));
ReadActions? readActions; ReadActions? readActions;
@@ -467,11 +468,14 @@ class ThreadController extends BaseController {
message: message, message: message,
icon: readActions == ReadActions.markAsUnread ? _imagePaths.icUnreadToast : _imagePaths.icReadToast); icon: readActions == ReadActions.markAsUnread ? _imagePaths.icUnreadToast : _imagePaths.icReadToast);
} }
_refreshEmailChanges();
} }
void _markAsSelectedEmailReadFailure(Failure failure) { void _markAsReadSelectedMultipleEmailFailure(Failure failure) {
cancelSelectEmail(); if (currentContext != null) {
_appToast.showErrorToast(AppLocalizations.of(currentContext!).an_error_occurred); _appToast.showErrorToast(AppLocalizations.of(currentContext!).an_error_occurred);
}
} }
void openFilterMessagesCupertinoActionSheet(BuildContext context, List<Widget> actionTiles, {Widget? cancelButton}) { void openFilterMessagesCupertinoActionSheet(BuildContext context, List<Widget> actionTiles, {Widget? cancelButton}) {
@@ -514,6 +518,8 @@ class ThreadController extends BaseController {
if (currentMailbox != null && _accountId != null) { if (currentMailbox != null && _accountId != null) {
popBack(); popBack();
cancelSelectEmail();
final listEmailIds = listEmail.map((email) => email.id).toList(); final listEmailIds = listEmail.map((email) => email.id).toList();
final destinationMailbox = await push( final destinationMailbox = await push(
AppRoutes.DESTINATION_PICKER, AppRoutes.DESTINATION_PICKER,
@@ -538,7 +544,6 @@ class ThreadController extends BaseController {
} }
void _moveSelectedMultipleEmailToMailboxSuccess(Success success) { void _moveSelectedMultipleEmailToMailboxSuccess(Success success) {
cancelSelectEmail();
mailboxDashBoardController.dispatchState(Right(success)); mailboxDashBoardController.dispatchState(Right(success));
String? destinationPath; String? destinationPath;
@@ -603,16 +608,10 @@ class ThreadController extends BaseController {
_refreshEmailChanges(); _refreshEmailChanges();
} }
void markAsStarSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail, void markAsStarSelectedMultipleEmail(List<PresentationEmail> listPresentationEmail) {
{bool fromContextMenuAction = false, MarkStarAction? markStarAction}) { cancelSelectEmail();
if (fromContextMenuAction) {
popBack();
}
final starAction = markStarAction != null
? markStarAction
: listPresentationEmail.isAllEmailStarred ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
final starAction = listPresentationEmail.isAllEmailStarred ? MarkStarAction.unMarkStar : MarkStarAction.markStar;
final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value; final mailboxCurrent = mailboxDashBoardController.selectedMailbox.value;
if (_accountId != null && mailboxCurrent != null) { if (_accountId != null && mailboxCurrent != null) {
final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList(); final listEmail = listPresentationEmail.map((presentationEmail) => presentationEmail.toEmail()).toList();
@@ -621,9 +620,6 @@ class ThreadController extends BaseController {
} }
void _markAsStarMultipleEmailSuccess(Success success) { void _markAsStarMultipleEmailSuccess(Success success) {
cancelSelectEmail();
_refreshEmailChanges();
MarkStarAction? markStarAction; MarkStarAction? markStarAction;
int countMarkStarSuccess = 0; int countMarkStarSuccess = 0;
@@ -640,10 +636,11 @@ class ThreadController extends BaseController {
? AppLocalizations.of(currentContext!).marked_unstar_multiple_item(countMarkStarSuccess) ? AppLocalizations.of(currentContext!).marked_unstar_multiple_item(countMarkStarSuccess)
: AppLocalizations.of(currentContext!).marked_star_multiple_item(countMarkStarSuccess)); : AppLocalizations.of(currentContext!).marked_star_multiple_item(countMarkStarSuccess));
} }
_refreshEmailChanges();
} }
void _markAsStarMultipleEmailFailure(Failure failure) { void _markAsStarMultipleEmailFailure(Failure failure) {
cancelSelectEmail();
if (currentContext != null) { if (currentContext != null) {
_appToast.showErrorToast(AppLocalizations.of(currentContext!).an_error_occurred); _appToast.showErrorToast(AppLocalizations.of(currentContext!).an_error_occurred);
} }
@@ -716,7 +713,7 @@ class ThreadController extends BaseController {
switch(actionType) { switch(actionType) {
case EmailActionType.markAsRead: case EmailActionType.markAsRead:
case EmailActionType.markAsUnread: case EmailActionType.markAsUnread:
markAsSelectedEmailRead(selectionEmail); markAsReadSelectedMultipleEmail(selectionEmail);
break; break;
case EmailActionType.markAsStar: case EmailActionType.markAsStar:
case EmailActionType.markAsUnStar: case EmailActionType.markAsUnStar:
@@ -144,7 +144,7 @@ class ThreadView extends GetWidget<ThreadController> with UserSettingPopupMenuMi
: controller.emailList.allEmailUnread; : controller.emailList.allEmailUnread;
if (listEmail.isNotEmpty) { if (listEmail.isNotEmpty) {
controller.markAsSelectedEmailRead(listEmail); controller.markAsReadSelectedMultipleEmail(listEmail);
} }
}) })
..text(AppLocalizations.of(context).mark_all_as_read, isVertical: false)) ..text(AppLocalizations.of(context).mark_all_as_read, isVertical: false))
@@ -111,9 +111,9 @@ class EmailTileBuilder {
Padding( Padding(
padding: EdgeInsets.only(left: 8), padding: EdgeInsets.only(left: 8),
child: (ButtonBuilder(_imagePaths.icAttachment) child: (ButtonBuilder(_imagePaths.icAttachment)
..paddingIcon(EdgeInsets.zero) ..paddingIcon(EdgeInsets.zero)
..size(16)) ..size(16))
.build()), .build()),
Padding( Padding(
padding: EdgeInsets.only(right: 4, left: 8), padding: EdgeInsets.only(right: 4, left: 8),
child: Text( child: Text(
@@ -122,9 +122,9 @@ class EmailTileBuilder {
overflow:TextOverflow.ellipsis, overflow:TextOverflow.ellipsis,
style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))), style: TextStyle(fontSize: 13, color: AppColor.colorContentEmail))),
(ButtonBuilder(_imagePaths.icChevron) (ButtonBuilder(_imagePaths.icChevron)
..paddingIcon(EdgeInsets.zero) ..paddingIcon(EdgeInsets.zero)
..size(16)) ..size(16))
.build(), .build(),
], ],
) )
), ),
@@ -169,9 +169,9 @@ class EmailTileBuilder {
), ),
if (_presentationEmail.isFlaggedEmail() ) if (_presentationEmail.isFlaggedEmail() )
(ButtonBuilder(_imagePaths.icStar) (ButtonBuilder(_imagePaths.icStar)
..paddingIcon(EdgeInsets.zero) ..paddingIcon(EdgeInsets.zero)
..size(15)) ..size(15))
.build(), .build(),
], ],
)), )),
Padding( Padding(
@@ -12,7 +12,7 @@ import 'package:mockito/mockito.dart';
import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart'; import 'package:tmail_ui_user/features/thread/domain/model/email_response.dart';
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart'; import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart';
import 'package:tmail_ui_user/features/thread/domain/state/get_all_email_state.dart'; import 'package:tmail_ui_user/features/thread/domain/state/refresh_changes_all_email_state.dart';
import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor.dart';
import '../../../../fixtures/account_fixtures.dart'; import '../../../../fixtures/account_fixtures.dart';
@@ -66,7 +66,7 @@ void main() {
expect(states.length, equals(2)); expect(states.length, equals(2));
expect(states, containsAllInOrder({ expect(states, containsAllInOrder({
Right(RefreshingState()), Right(RefreshingState()),
Right(GetAllEmailSuccess( Right(RefreshChangesAllEmailSuccess(
emailList: { emailList: {
EmailFixtures.email1.toPresentationEmail(), EmailFixtures.email1.toPresentationEmail(),
EmailFixtures.email2.toPresentationEmail(), EmailFixtures.email2.toPresentationEmail(),