diff --git a/lib/features/composer/domain/usecases/send_email_interactor.dart b/lib/features/composer/domain/usecases/send_email_interactor.dart index 3123d24f8..18074116a 100644 --- a/lib/features/composer/domain/usecases/send_email_interactor.dart +++ b/lib/features/composer/domain/usecases/send_email_interactor.dart @@ -12,7 +12,7 @@ class SendEmailInteractor { Stream> execute(AccountId accountId, EmailRequest emailRequest) async* { try { - yield Right(UIState.loading); + yield Right(LoadingState()); final result = await emailRepository.sendEmail(accountId, emailRequest); if (result) { yield Right(SendEmailSuccess()); diff --git a/lib/features/email/domain/usecases/get_email_content_interactor.dart b/lib/features/email/domain/usecases/get_email_content_interactor.dart index 8ddb9a8e5..cc1e770ad 100644 --- a/lib/features/email/domain/usecases/get_email_content_interactor.dart +++ b/lib/features/email/domain/usecases/get_email_content_interactor.dart @@ -13,7 +13,7 @@ class GetEmailContentInteractor { Stream> execute(AccountId accountId, EmailId emailId) async* { try { - yield Right(UIState.loading); + yield Right(LoadingState()); final email = await emailRepository.getEmailContent(accountId, emailId); yield Right(GetEmailContentSuccess(email.toEmailContent())); } catch (e) { diff --git a/lib/features/email/presentation/email_view.dart b/lib/features/email/presentation/email_view.dart index 5bbec4d2b..f57c1ff3c 100644 --- a/lib/features/email/presentation/email_view.dart +++ b/lib/features/email/presentation/email_view.dart @@ -115,7 +115,7 @@ class EmailView extends GetWidget { Widget _buildLoadingView() { return Obx(() => emailController.viewState.value.fold( (failure) => SizedBox.shrink(), - (success) => success == UIState.loading + (success) => success is LoadingState ? Center(child: Padding( padding: EdgeInsets.only(top: 25, bottom: 16), child: SizedBox( diff --git a/lib/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart b/lib/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart index 2b428cc2c..34c2118ac 100644 --- a/lib/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart +++ b/lib/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart @@ -14,7 +14,7 @@ class GetAllMailboxInteractor { Stream> execute(AccountId accountId, {Properties? properties}) async* { try { - yield Right(UIState.loading); + yield Right(LoadingState()); final mailboxList = await mailboxRepository.getAllMailbox(accountId, properties: properties); final tupleList = mailboxList.splitMailboxList((mailbox) => mailbox.hasRole()); yield Right(GetAllMailboxSuccess(defaultMailboxList: tupleList.value1, folderMailboxList: tupleList.value2)); diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart index bc1df93fb..3bf82f1b7 100644 --- a/lib/features/mailbox/presentation/mailbox_view.dart +++ b/lib/features/mailbox/presentation/mailbox_view.dart @@ -110,7 +110,7 @@ class MailboxView extends GetWidget { Widget _buildLoadingView() { return Obx(() => controller.viewState.value.fold( (failure) => SizedBox.shrink(), - (success) => success == UIState.loading + (success) => success is LoadingState ? Center(child: Padding( padding: EdgeInsets.only(top: 16), child: SizedBox( diff --git a/lib/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart b/lib/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart index ceb5b84c3..150edf211 100644 --- a/lib/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart +++ b/lib/features/mailbox_dashboard/domain/usecases/get_user_profile_interactor.dart @@ -12,7 +12,7 @@ class GetUserProfileInteractor { Stream> execute() async* { try { - yield Right(UIState.loading); + yield Right(LoadingState()); final userProfile = await credentialRepository.getUserProfile(); yield Right(GetUserProfileSuccess(userProfile)); } catch (exception) { diff --git a/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart b/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart index 6fd906395..ee9aab0ce 100644 --- a/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart +++ b/lib/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart @@ -25,7 +25,7 @@ class GetEmailsInMailboxInteractor { } ) async* { try { - yield Right(UIState.loading); + yield Right(LoadingState()); final emailList = await threadRepository.getAllEmail( accountId, position: position, diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index 8d8fe5f20..ded856c58 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -2,7 +2,6 @@ import 'package:core/core.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/filter/filter.dart'; @@ -25,7 +24,6 @@ import 'package:tmail_ui_user/features/thread/domain/state/mark_as_multiple_emai import 'package:tmail_ui_user/features/thread/domain/usecases/get_emails_in_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/thread/domain/usecases/mark_as_multiple_email_read_interactor.dart'; import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state.dart'; -import 'package:tmail_ui_user/features/thread/presentation/widgets/email_context_menu_action_builder.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; @@ -60,6 +58,12 @@ class ThreadController extends BaseController { this._appToast, ); + @override + void onInit() { + super.onInit(); + dispatchState(Right(LoadingState())); + } + @override void onReady() { super.onReady(); @@ -86,11 +90,6 @@ class ThreadController extends BaseController { super.onClose(); } - @override - void onData(Either newState) { - super.onData(newState); - } - @override void onDone() { viewState.value.fold( @@ -121,7 +120,7 @@ class ThreadController extends BaseController { void _getAllEmailSuccess(Success success) { if (success is GetAllEmailSuccess) { - emailList.value += success.emailList; + emailList.addAll(success.emailList); lastGetTotal = emailList.length; loadMoreState.value = success.emailList.isEmpty ? LoadMoreState.COMPLETED : LoadMoreState.IDLE; } @@ -144,7 +143,7 @@ class ThreadController extends BaseController { loadMoreState.value = LoadMoreState.IDLE; } - void getAllEmailAction(AccountId accountId, + void _getAllEmailAction(AccountId accountId, { UnsignedInt? limit, int position = 0, @@ -152,7 +151,7 @@ class ThreadController extends BaseController { Filter? filter, Properties? properties, } - ) async { + ) { consumeState(_getEmailsInMailboxInteractor.execute( accountId, limit: limit, @@ -171,7 +170,7 @@ class ThreadController extends BaseController { final accountId = mailboxDashBoardController.accountId.value; if (accountId != null) { - getAllEmailAction( + _getAllEmailAction( accountId, limit: ThreadConstants.defaultLimit, position: positionCurrent, @@ -188,15 +187,13 @@ class ThreadController extends BaseController { final accountId = mailboxDashBoardController.accountId.value; if (accountId != null) { - Future.delayed(const Duration(milliseconds: 100), () { - getAllEmailAction( - accountId, - limit: ThreadConstants.defaultLimit, - position: positionCurrent, - sort: _getSortCurrent(), - properties: _properties, - filter: _getFilterConditionCurrent()); - }); + _getAllEmailAction( + accountId, + limit: ThreadConstants.defaultLimit, + position: positionCurrent, + sort: _getSortCurrent(), + properties: _properties, + filter: _getFilterConditionCurrent()); } } @@ -228,7 +225,7 @@ class ThreadController extends BaseController { bool _isUnSelectedAll() => emailList.every((email) => email.selectMode == SelectMode.INACTIVE); - bool _isEmailAllRead(List listEmail) => listEmail.every((email) => email.isReadEmail()); + bool isEmailAllRead(List listEmail) => listEmail.every((email) => email.isReadEmail()); void cancelSelectEmail() { emailList.value = emailList.map((email) => email.toSelectedEmail(selectMode: SelectMode.INACTIVE)).toList(); @@ -243,7 +240,7 @@ class ThreadController extends BaseController { final accountId = mailboxDashBoardController.accountId.value; if (accountId != null) { - getAllEmailAction( + _getAllEmailAction( accountId, limit: newLimit, position: 0, @@ -258,7 +255,7 @@ class ThreadController extends BaseController { popBack(); } - final readAction = _isEmailAllRead(listEmail) ? ReadActions.markAsUnread : ReadActions.markAsRead; + final readAction = isEmailAllRead(listEmail) ? ReadActions.markAsUnread : ReadActions.markAsRead; final listEmailId = listEmail .where((email) => readAction == ReadActions.markAsUnread ? email.isReadEmail() : email.isUnReadEmail()) @@ -315,69 +312,12 @@ class ThreadController extends BaseController { _appToast.showErrorToast(AppLocalizations.of(Get.context!).an_error_occurred); } - void openContextMenuSelectedEmail(BuildContext context, ImagePaths imagePaths, List listEmail) { + void openContextMenuSelectedEmail(BuildContext context, List actionTiles) { (ContextMenuBuilder(context) - ..addTiles(_contextMenuActionList(context, imagePaths, listEmail))) + ..addTiles(actionTiles)) .build(); } - List _contextMenuActionList(BuildContext context, ImagePaths imagePaths, List listEmail) { - return [ - _moveToTrashAction(context, imagePaths, listEmail), - _moveToMailboxAction(context, imagePaths, listEmail), - _markAsReadAction(context, imagePaths, listEmail), - _markAsFlagAction(context, imagePaths, listEmail), - _moveToSpamAction(context, imagePaths, listEmail), - SizedBox(height: 40), - ]; - } - - Widget _markAsReadAction(BuildContext context, ImagePaths imagePaths, List listEmail) { - return (EmailContextMenuActionBuilder( - Key('mark_as_read_context_menu_action'), - SvgPicture.asset(imagePaths.icEyeDisable, width: 24, height: 24, fit: BoxFit.fill), - _isEmailAllRead(listEmail) ? AppLocalizations.of(context).mark_as_unread : AppLocalizations.of(context).mark_as_read, - listEmail) - ..onActionClick((data) => markAsSelectedEmailRead(data, fromContextMenuAction: true))) - .build(); - } - - Widget _moveToTrashAction(BuildContext context, ImagePaths imagePaths, List listEmail) { - return (EmailContextMenuActionBuilder( - Key('move_to_trash_context_menu_action'), - SvgPicture.asset(imagePaths.icTrash, width: 24, height: 24, fit: BoxFit.fill), - AppLocalizations.of(context).move_to_trash, listEmail) - ..onActionClick((data) => {})) - .build(); - } - - Widget _moveToMailboxAction(BuildContext context, ImagePaths imagePaths, List listEmail) { - return (EmailContextMenuActionBuilder( - Key('move_to_mailbox_context_menu_action'), - SvgPicture.asset(imagePaths.icFolder, width: 24, height: 24, fit: BoxFit.fill), - AppLocalizations.of(context).move_to_mailbox, listEmail) - ..onActionClick((data) => {})) - .build(); - } - - Widget _markAsFlagAction(BuildContext context, ImagePaths imagePaths, List listEmail) { - return (EmailContextMenuActionBuilder( - Key('mark_as_flag_context_menu_action'), - SvgPicture.asset(imagePaths.icFlag, width: 24, height: 24, fit: BoxFit.fill), - AppLocalizations.of(context).mark_as_flag, listEmail) - ..onActionClick((data) => {})) - .build(); - } - - Widget _moveToSpamAction(BuildContext context, ImagePaths imagePaths, List listEmail) { - return (EmailContextMenuActionBuilder( - Key('move_to_spam_context_menu_action'), - SvgPicture.asset(imagePaths.icMailboxSpam, width: 24, height: 24, fit: BoxFit.fill), - AppLocalizations.of(context).move_to_spam, listEmail) - ..onActionClick((data) => {})) - .build(); - } - bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null && mailboxDashBoardController.userProfile.value != null && mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox); diff --git a/lib/features/thread/presentation/thread_view.dart b/lib/features/thread/presentation/thread_view.dart index 1a62c8a17..2a8001a1f 100644 --- a/lib/features/thread/presentation/thread_view.dart +++ b/lib/features/thread/presentation/thread_view.dart @@ -1,6 +1,7 @@ import 'package:core/core.dart'; import 'package:core/presentation/extensions/color_extension.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:model/email/presentation_email.dart'; import 'package:model/model.dart'; @@ -8,6 +9,7 @@ import 'package:tmail_ui_user/features/thread/presentation/model/load_more_state import 'package:tmail_ui_user/features/thread/presentation/thread_controller.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_select_mode_active_builder.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart'; +import 'package:tmail_ui_user/features/thread/presentation/widgets/email_context_menu_action_builder.dart'; import 'package:tmail_ui_user/features/thread/presentation/widgets/email_tile_builder.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -77,14 +79,73 @@ class ThreadView extends GetWidget { ..addCloseActionClick(() => controller.cancelSelectEmail()) ..addRemoveEmailActionClick((listEmail) => {}) ..addOnMarkAsEmailReadActionClick((listEmail) => controller.markAsSelectedEmailRead(listEmail)) - ..addOpenContextMenuActionClick((listEmail) => controller.openContextMenuSelectedEmail(context, imagePaths, listEmail))) + ..addOpenContextMenuActionClick((listEmail) => controller.openContextMenuSelectedEmail(context, _contextMenuEmailActionTile(context, listEmail)))) .build())); } + List _contextMenuEmailActionTile(BuildContext context, List listEmail) { + return [ + _moveToTrashAction(context, listEmail), + _moveToMailboxAction(context, listEmail), + _markAsReadAction(context, listEmail), + _markAsFlagAction(context, listEmail), + _moveToSpamAction(context, listEmail), + SizedBox(height: 30), + ]; + } + + Widget _markAsReadAction(BuildContext context, List listEmail) { + return (EmailContextMenuActionBuilder( + Key('mark_as_read_context_menu_action'), + SvgPicture.asset(imagePaths.icEyeDisable, width: 24, height: 24, fit: BoxFit.fill), + controller.isEmailAllRead(listEmail) + ? AppLocalizations.of(context).mark_as_unread + : AppLocalizations.of(context).mark_as_read, + listEmail) + ..onActionClick((data) => controller.markAsSelectedEmailRead(data, fromContextMenuAction: true))) + .build(); + } + + Widget _moveToTrashAction(BuildContext context, List listEmail) { + return (EmailContextMenuActionBuilder( + Key('move_to_trash_context_menu_action'), + SvgPicture.asset(imagePaths.icTrash, width: 24, height: 24, fit: BoxFit.fill), + AppLocalizations.of(context).move_to_trash, listEmail) + ..onActionClick((data) => {})) + .build(); + } + + Widget _moveToMailboxAction(BuildContext context, List listEmail) { + return (EmailContextMenuActionBuilder( + Key('move_to_mailbox_context_menu_action'), + SvgPicture.asset(imagePaths.icFolder, width: 24, height: 24, fit: BoxFit.fill), + AppLocalizations.of(context).move_to_mailbox, listEmail) + ..onActionClick((data) => {})) + .build(); + } + + Widget _markAsFlagAction(BuildContext context, List listEmail) { + return (EmailContextMenuActionBuilder( + Key('mark_as_flag_context_menu_action'), + SvgPicture.asset(imagePaths.icFlag, width: 24, height: 24, fit: BoxFit.fill), + AppLocalizations.of(context).mark_as_flag, listEmail) + ..onActionClick((data) => {})) + .build(); + } + + Widget _moveToSpamAction(BuildContext context, List listEmail) { + return (EmailContextMenuActionBuilder( + Key('move_to_spam_context_menu_action'), + SvgPicture.asset(imagePaths.icMailboxSpam, width: 24, height: 24, fit: BoxFit.fill), + AppLocalizations.of(context).move_to_spam, listEmail) + ..onActionClick((data) => {})) + .build(); + } + Widget _buildLoadingView() { return Obx(() => controller.viewState.value.fold( (failure) => SizedBox.shrink(), - (success) => success == UIState.loading && controller.loadMoreState.value != LoadMoreState.LOADING + (success) => success is LoadingState && controller.loadMoreState.value != LoadMoreState.LOADING ? Center(child: Padding( padding: EdgeInsets.only(top: 16, bottom: 16), child: SizedBox( @@ -117,15 +178,16 @@ class ThreadView extends GetWidget { ? RefreshIndicator( color: AppColor.primaryColor, onRefresh: () async => controller.refreshGetAllEmailAction(), - child: controller.emailList.isNotEmpty - ? _buildListEmailBody(context, controller.emailList) - : _buildEmptyEmail(context)) - : controller.emailList.isNotEmpty - ? _buildListEmailBody(context, controller.emailList) - : _buildEmptyEmail(context))); + child: _buildListEmailBody(context)) + : _buildListEmailBody(context))); } - Widget _buildListEmailBody(BuildContext context, List listPresentationEmail) { + Widget _buildListEmailBody(BuildContext context) { + return controller.emailList.isNotEmpty + ? _buildListEmailSuccess(context, controller.emailList) + : _buildEmptyEmail(context); + } + Widget _buildListEmailSuccess(BuildContext context, List listPresentationEmail) { if (listPresentationEmail.isEmpty) { return _buildEmptyEmail(context); } else { @@ -160,13 +222,16 @@ class ThreadView extends GetWidget { Widget _buildEmptyEmail(BuildContext context) { return Obx(() => controller.viewState.value.fold( - (failure) => SizedBox.shrink(), - (success) => success != UIState.loading - ? Text( + (failure) => Text( + AppLocalizations.of(context).no_emails, + maxLines: 1, + style: TextStyle(fontSize: 25, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold)), + (success) => success is LoadingState + ? SizedBox.shrink() + : Text( AppLocalizations.of(context).no_emails, maxLines: 1, - style: TextStyle(fontSize: 25, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold)) - : SizedBox.shrink()) + style: TextStyle(fontSize: 25, color: AppColor.mailboxTextColor, fontWeight: FontWeight.bold))) ); } } \ No newline at end of file