From e739e23c62eec08c30e7b2d4b3ac64642a67e677 Mon Sep 17 00:00:00 2001 From: dab246 Date: Wed, 23 Feb 2022 12:39:37 +0700 Subject: [PATCH] TF-233 Implement create new mailbox and sub-folder --- .../destination_picker_controller.dart | 6 +- .../presentation/destination_picker_view.dart | 156 ++++++++++++------ .../model/destination_picker_arguments.dart | 4 +- .../app_bar_destination_picker_builder.dart | 10 +- .../email/presentation/email_controller.dart | 4 +- .../data/datasource/mailbox_datasource.dart | 3 + .../mailbox_cache_datasource_impl.dart | 6 + .../mailbox_datasource_impl.dart | 10 ++ .../extensions/mailbox_cache_extension.dart | 22 +-- .../data/extensions/mailbox_extension.dart | 2 +- .../mailbox/data/network/mailbox_api.dart | 33 ++++ .../repository/mailbox_repository_impl.dart | 8 +- .../model/create_new_mailbox_request.dart | 16 ++ .../domain/repository/mailbox_repository.dart | 4 + .../state/create_new_mailbox_state.dart | 21 +++ .../create_new_mailbox_interactor.dart | 25 +++ .../presentation/mailbox_bindings.dart | 8 + .../presentation/mailbox_controller.dart | 66 +++++++- .../mailbox/presentation/mailbox_view.dart | 4 +- ...ilbox_action.dart => mailbox_actions.dart} | 8 +- .../name_validator_string_extension.dart | 2 +- .../mailbox_creator_controller.dart | 22 ++- .../presentation/mailbox_creator_view.dart | 2 +- .../model/new_mailbox_arguments.dart | 11 +- .../presentation/thread_controller.dart | 4 +- lib/main/localizations/app_localizations.dart | 15 ++ model/lib/extensions/mailbox_extension.dart | 40 +++-- .../presentation_mailbox_extension.dart | 22 +-- test/fixtures/email_fixtures.dart | 10 +- test/fixtures/mailbox_fixtures.dart | 88 +++++----- 30 files changed, 460 insertions(+), 172 deletions(-) create mode 100644 lib/features/mailbox/domain/model/create_new_mailbox_request.dart create mode 100644 lib/features/mailbox/domain/state/create_new_mailbox_state.dart create mode 100644 lib/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart rename lib/features/mailbox/presentation/model/{mailbox_action.dart => mailbox_actions.dart} (71%) diff --git a/lib/features/destination_picker/presentation/destination_picker_controller.dart b/lib/features/destination_picker/presentation/destination_picker_controller.dart index 091b5e31e..f74345540 100644 --- a/lib/features/destination_picker/presentation/destination_picker_controller.dart +++ b/lib/features/destination_picker/presentation/destination_picker_controller.dart @@ -7,7 +7,7 @@ import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; @@ -23,7 +23,7 @@ class DestinationPickerController extends BaseController { MailboxTree folderMailboxTree = MailboxTree(MailboxNode.root()); final defaultMailboxList = [].obs; final folderMailboxNodeList = [].obs; - final mailboxAction = Rxn(); + final mailboxAction = Rxn(); AccountId? accountId; DestinationPickerController( @@ -87,7 +87,7 @@ class DestinationPickerController extends BaseController { folderMailboxNodeList.value = newMailboxNodeList; } - void moveEmailToMailboxAction(PresentationMailbox destinationMailbox) { + void selectMailboxAction(PresentationMailbox? destinationMailbox) { popBack(result: destinationMailbox); } diff --git a/lib/features/destination_picker/presentation/destination_picker_view.dart b/lib/features/destination_picker/presentation/destination_picker_view.dart index d21ee078b..aedba5a13 100644 --- a/lib/features/destination_picker/presentation/destination_picker_view.dart +++ b/lib/features/destination_picker/presentation/destination_picker_view.dart @@ -1,16 +1,18 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/destination_picker_controller.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart'; import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_displayed.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_folder_tile_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/widgets/mailbox_tile_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class DestinationPickerView extends GetWidget { @@ -19,13 +21,13 @@ class DestinationPickerView extends GetWidget { @override Widget build(BuildContext context) { - DestinationPickerArguments? _destinationPickerArguments; + MailboxActions? actions; final arguments = Get.arguments; if (arguments != null && arguments is DestinationPickerArguments) { - _destinationPickerArguments = arguments; + actions = arguments.mailboxAction; } - if (_destinationPickerArguments?.mailboxAction == MailboxAction.create) { + if (actions == MailboxActions.create) { return Card( margin: EdgeInsets.zero, borderOnForeground: false, @@ -34,14 +36,16 @@ class DestinationPickerView extends GetWidget { onTap: () => controller.closeDestinationPicker(), child: ResponsiveWidget( responsiveUtils: _responsiveUtils, - mobile: Container( - child: _buildBody(context), - width: _responsiveUtils.getSizeWidthScreen(context)), + mobile: _responsiveUtils.isPortrait(context) + ? Container( + child: _buildBodyMailboxLocation(context, actions), + width: _responsiveUtils.getSizeWidthScreen(context)) + : _buildBodyMailboxDestination(context, actions), tablet: Container( child: Row( children: [ Expanded(flex: 1, child: Container(color: Colors.transparent)), - Expanded(flex: 1, child: _buildBody(context)), + Expanded(flex: 1, child: _buildBodyMailboxLocation(context, actions)), ] ) ), @@ -49,7 +53,7 @@ class DestinationPickerView extends GetWidget { child: Row( children: [ Expanded(flex: 7, child: Container(color: Colors.transparent)), - Expanded(flex: 13, child: _buildBody(context)), + Expanded(flex: 13, child: _buildBodyMailboxLocation(context, actions)), ] ) ), @@ -57,7 +61,7 @@ class DestinationPickerView extends GetWidget { child: Row( children: [ Expanded(flex: 1, child: Container(color: Colors.transparent)), - Expanded(flex: 3, child: _buildBody(context)), + Expanded(flex: 3, child: _buildBodyMailboxLocation(context, actions)), ] ) ) @@ -65,42 +69,46 @@ class DestinationPickerView extends GetWidget { ) ); } else { - return GestureDetector( - onTap: () => controller.closeDestinationPicker(), - child: Card( - margin: EdgeInsets.zero, - borderOnForeground: false, - color: Colors.transparent, - child: Container( - margin: _getMarginDestinationPicker(context), - child: ClipRRect( - borderRadius: _radiusDestinationPicker(context, 14), - child: GestureDetector( - onTap: () => {}, - child: SafeArea( - top: _responsiveUtils.isMobile(context) ? true : false, - bottom: false, - right: false, - left: false, - child: Column( - children: [ - _buildAppBar(context), - Expanded(child: - Container( - color: AppColor.colorBgMailbox, - child: _buildBodyDestinationPicker(context))) - ], - ) - ) - ) - ) - ) - ) - ); + return _buildBodyMailboxDestination(context, actions); } } - Widget _buildBody(BuildContext context) { + Widget _buildBodyMailboxDestination(BuildContext context, MailboxActions? actions) { + return GestureDetector( + onTap: () => controller.closeDestinationPicker(), + child: Card( + margin: EdgeInsets.zero, + borderOnForeground: false, + color: Colors.transparent, + child: Container( + margin: _getMarginDestinationPicker(context), + child: ClipRRect( + borderRadius: _radiusDestinationPicker(context, 14), + child: GestureDetector( + onTap: () => {}, + child: SafeArea( + top: _responsiveUtils.isMobile(context) ? true : false, + bottom: false, + right: false, + left: false, + child: Column( + children: [ + _buildAppBar(context), + Expanded(child: + Container( + color: AppColor.colorBgMailbox, + child: _buildBodyDestinationPicker(context, actions))) + ], + ) + ) + ) + ) + ) + ) + ); + } + + Widget _buildBodyMailboxLocation(BuildContext context, MailboxActions? actions) { return SafeArea( top: _responsiveUtils.isMobile(context) ? true : false, bottom: false, @@ -122,10 +130,12 @@ class DestinationPickerView extends GetWidget { child: Column( children: [ _buildAppBar(context), - Expanded(child: - Container( + Expanded( + child: Container( color: AppColor.colorBgMailbox, - child: _buildBodyDestinationPicker(context))) + child: _buildBodyDestinationPicker(context, actions) + ) + ) ] ), ) @@ -145,7 +155,7 @@ class DestinationPickerView extends GetWidget { .build()); } - Widget _buildBodyDestinationPicker(BuildContext context) { + Widget _buildBodyDestinationPicker(BuildContext context, MailboxActions? actions) { return RefreshIndicator( color: AppColor.primaryColor, onRefresh: () async => controller.getAllMailboxAction(), @@ -160,7 +170,8 @@ class DestinationPickerView extends GetWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildLoadingView(), - _buildListMailbox(context) + if (actions == MailboxActions.create) _buildUnifiedMailbox(context), + _buildListMailbox(context, actions) ] ) ) @@ -182,7 +193,7 @@ class DestinationPickerView extends GetWidget { : SizedBox.shrink())); } - Widget _buildListMailbox(BuildContext context) { + Widget _buildListMailbox(BuildContext context, MailboxActions? actions) { return ListView( primary: false, shrinkWrap: true, @@ -191,7 +202,7 @@ class DestinationPickerView extends GetWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), color: Colors.white), - margin: EdgeInsets.only(left: 16, right: 16, top: 16), + margin: EdgeInsets.only(left: 16, right: 16, top: _getTopPaddingListMailbox(context, actions)), child: _buildDefaultMailbox(context)), SizedBox(height: 20), Container( @@ -204,6 +215,14 @@ class DestinationPickerView extends GetWidget { ); } + double _getTopPaddingListMailbox(BuildContext context, MailboxActions? actions) { + if (actions == MailboxActions.create) { + return (_responsiveUtils.isMobile(context) || _responsiveUtils.isMobileDevice(context)) ? 20.0 : 5.0; + } else { + return (_responsiveUtils.isMobile(context) || _responsiveUtils.isMobileDevice(context)) ? 16.0 : 10.0; + } + } + Widget _buildDefaultMailbox(BuildContext context) { return Obx(() => controller.viewState.value.fold( (failure) => SizedBox.shrink(), @@ -222,7 +241,7 @@ class DestinationPickerView extends GetWidget { mailboxDisplayed: MailboxDisplayed.destinationPicker, isLastElement: index == defaultMailboxList.length - 1) ..onOpenMailboxAction((mailbox) => - controller.moveEmailToMailboxAction(mailbox.toPresentationMailboxWithMailboxPath(mailbox.name?.name ?? '')))) + controller.selectMailboxAction(mailbox.toPresentationMailboxWithMailboxPath(mailbox.name?.name ?? '')))) .build()); } else { return SizedBox.shrink(); @@ -257,7 +276,7 @@ class DestinationPickerView extends GetWidget { _imagePaths, mailboxNode, mailboxDisplayed: MailboxDisplayed.destinationPicker) - ..addOnSelectMailboxFolderClick((mailboxNode) => controller.moveEmailToMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath( + ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath( mailboxNode.getPathMailboxNode( controller.folderMailboxTree, controller.defaultMailboxList, @@ -273,7 +292,7 @@ class DestinationPickerView extends GetWidget { _imagePaths, mailboxNode, mailboxDisplayed: MailboxDisplayed.destinationPicker) - ..addOnSelectMailboxFolderClick((mailboxNode) => controller.moveEmailToMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath( + ..addOnSelectMailboxFolderClick((mailboxNode) => controller.selectMailboxAction(mailboxNode.item.toPresentationMailboxWithMailboxPath( mailboxNode.getPathMailboxNode( controller.folderMailboxTree, controller.defaultMailboxList, @@ -325,4 +344,35 @@ class DestinationPickerView extends GetWidget { return BorderRadius.only(topLeft: Radius.circular(radius), topRight: Radius.circular(radius)); } } + + Widget _buildUnifiedMailbox(BuildContext context) { + return Container( + alignment: Alignment.center, + margin: EdgeInsets.only(left: 16, right: 16, top: 16), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), color: Colors.white), + child: MediaQuery( + data: MediaQueryData(padding: EdgeInsets.zero), + child: ListTile( + contentPadding: EdgeInsets.zero, + onTap: () => controller.selectMailboxAction(null), + leading: Padding( + padding: EdgeInsets.only(left: 16), + child: SvgPicture.asset(_imagePaths.icFolderMailbox, width: 28, height: 28, fit: BoxFit.fill)), + title: Transform( + transform: Matrix4.translationValues(-5.0, 0.0, 0.0), + child: Row( + children: [ + Expanded(child: Text( + AppLocalizations.of(context).default_mailbox, + maxLines: 1, + overflow:TextOverflow.ellipsis, + style: TextStyle(fontSize: 15, color: AppColor.colorNameEmail), + )) + ] + ) + ), + ), + ) + ); + } } \ No newline at end of file diff --git a/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart b/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart index 07192e75f..cfeb5aaf8 100644 --- a/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart +++ b/lib/features/destination_picker/presentation/model/destination_picker_arguments.dart @@ -1,11 +1,11 @@ import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; class DestinationPickerArguments with EquatableMixin { final AccountId accountId; - final MailboxAction mailboxAction; + final MailboxActions mailboxAction; DestinationPickerArguments(this.accountId, this.mailboxAction); diff --git a/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart b/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart index 3d3befa1e..1adca931c 100644 --- a/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart +++ b/lib/features/destination_picker/presentation/widgets/app_bar_destination_picker_builder.dart @@ -2,7 +2,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; typedef OnCloseActionClick = void Function(); @@ -12,7 +12,7 @@ class AppBarDestinationPickerBuilder { final BuildContext _context; final ImagePaths _imagePaths; final ResponsiveUtils _responsiveUtils; - final MailboxAction? _mailboxAction; + final MailboxActions? _mailboxAction; AppBarDestinationPickerBuilder( this._context, @@ -53,7 +53,7 @@ class AppBarDestinationPickerBuilder { color: Colors.transparent, child: _responsiveUtils.isMobile(_context) ? IconButton( - color: _mailboxAction == MailboxAction.create ? AppColor.colorTextButton : AppColor.baseTextColor, + color: _mailboxAction == MailboxActions.create ? AppColor.colorTextButton : AppColor.baseTextColor, icon: _getBackIcon(), onPressed: () => _onCloseActionClick?.call()) : SizedBox(width: 40, height: 40) @@ -74,7 +74,7 @@ class AppBarDestinationPickerBuilder { } TextAlign _getAlignTitle() { - if (_mailboxAction == MailboxAction.create) { + if (_mailboxAction == MailboxActions.create) { return TextAlign.center; } else { return _responsiveUtils.isMobile(_context) ? TextAlign.start : TextAlign.center; @@ -82,7 +82,7 @@ class AppBarDestinationPickerBuilder { } Widget _getBackIcon() { - if (_mailboxAction == MailboxAction.create) { + if (_mailboxAction == MailboxActions.create) { return SvgPicture.asset(_imagePaths.icBack, fit: BoxFit.fill); } else { return SvgPicture.asset(_imagePaths.icComposerClose, fit: BoxFit.fill); diff --git a/lib/features/email/presentation/email_controller.dart b/lib/features/email/presentation/email_controller.dart index 68682812e..5326d8ead 100644 --- a/lib/features/email/presentation/email_controller.dart +++ b/lib/features/email/presentation/email_controller.dart @@ -23,7 +23,7 @@ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_ import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/move_to_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; @@ -276,7 +276,7 @@ class EmailController extends BaseController { if (currentMailbox != null && accountId != null) { final destinationMailbox = await push( AppRoutes.DESTINATION_PICKER, - arguments: DestinationPickerArguments(accountId, MailboxAction.moveEmail) + arguments: DestinationPickerArguments(accountId, MailboxActions.moveEmail) ); if (destinationMailbox != null && destinationMailbox is PresentationMailbox) { diff --git a/lib/features/mailbox/data/datasource/mailbox_datasource.dart b/lib/features/mailbox/data/datasource/mailbox_datasource.dart index cf0015d17..6322d2e5d 100644 --- a/lib/features/mailbox/data/datasource/mailbox_datasource.dart +++ b/lib/features/mailbox/data/datasource/mailbox_datasource.dart @@ -3,6 +3,7 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; abstract class MailboxDataSource { @@ -13,4 +14,6 @@ abstract class MailboxDataSource { Future getChanges(AccountId accountId, State sinceState); Future update({List? updated, List? created, List? destroyed}); + + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest); } \ No newline at end of file diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart index 00cf385bb..3bbf8e724 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_cache_datasource_impl.dart @@ -6,6 +6,7 @@ import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasourc import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/extensions/mailbox_extension.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; class MailboxCacheDataSourceImpl extends MailboxDataSource { @@ -43,4 +44,9 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource { throw error; }); } + + @override + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) { + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart index 77027f7b4..ef76df489 100644 --- a/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart +++ b/lib/features/mailbox/data/datasource_impl/mailbox_datasource_impl.dart @@ -4,6 +4,7 @@ import 'package:jmap_dart_client/jmap/core/state.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; @@ -40,4 +41,13 @@ class MailboxDataSourceImpl extends MailboxDataSource { Future> getAllMailboxCache() { throw UnimplementedError(); } + + @override + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) { + return Future.sync(() async { + return await mailboxAPI.createNewMailbox(accountId, newMailboxRequest); + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart b/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart index 38c97d2d2..a0bf40109 100644 --- a/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart +++ b/lib/features/mailbox/data/extensions/mailbox_cache_extension.dart @@ -8,17 +8,17 @@ import 'package:tmail_ui_user/features/mailbox/data/extensions/mailbox_rights_ca extension MailboxCacheExtension on MailboxCache { Mailbox toMailbox() { return Mailbox( - MailboxId(Id(id)), - name != null ? MailboxName(name!) : null, - parentId != null ? MailboxId(Id(parentId!)) : null, - role != null ? Role(role!) : null, - sortOrder != null ? SortOrder(sortValue: sortOrder!) : null, - totalEmails != null ? TotalEmails(UnsignedInt(totalEmails!)) : null, - unreadEmails != null ? UnreadEmails(UnsignedInt(unreadEmails!)) : null, - totalThreads != null ? TotalThreads(UnsignedInt(totalThreads!)) : null, - unreadThreads != null ? UnreadThreads(UnsignedInt(unreadThreads!)) : null, - myRights != null ? myRights!.toMailboxRights() : null, - isSubscribed != null ? IsSubscribed(isSubscribed!) : null + id: MailboxId(Id(id)), + name: name != null ? MailboxName(name!) : null, + parentId: parentId != null ? MailboxId(Id(parentId!)) : null, + role: role != null ? Role(role!) : null, + sortOrder: sortOrder != null ? SortOrder(sortValue: sortOrder!) : null, + totalEmails: totalEmails != null ? TotalEmails(UnsignedInt(totalEmails!)) : null, + unreadEmails: unreadEmails != null ? UnreadEmails(UnsignedInt(unreadEmails!)) : null, + totalThreads: totalThreads != null ? TotalThreads(UnsignedInt(totalThreads!)) : null, + unreadThreads: unreadThreads != null ? UnreadThreads(UnsignedInt(unreadThreads!)) : null, + myRights: myRights != null ? myRights!.toMailboxRights() : null, + isSubscribed: isSubscribed != null ? IsSubscribed(isSubscribed!) : null ); } } \ No newline at end of file diff --git a/lib/features/mailbox/data/extensions/mailbox_extension.dart b/lib/features/mailbox/data/extensions/mailbox_extension.dart index 291f7767f..fe657d35d 100644 --- a/lib/features/mailbox/data/extensions/mailbox_extension.dart +++ b/lib/features/mailbox/data/extensions/mailbox_extension.dart @@ -6,7 +6,7 @@ extension MailboxExtension on Mailbox { MailboxCache toMailboxCache() { return MailboxCache( - id.id.value, + id!.id.value, name: name?.name, parentId: parentId?.id.value, role: role?.value, diff --git a/lib/features/mailbox/data/network/mailbox_api.dart b/lib/features/mailbox/data/network/mailbox_api.dart index 5967f30f0..56439886a 100644 --- a/lib/features/mailbox/data/network/mailbox_api.dart +++ b/lib/features/mailbox/data/network/mailbox_api.dart @@ -12,7 +12,11 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/changes/changes_mailbox_respo import 'package:jmap_dart_client/jmap/mail/mailbox/get/get_mailbox_method.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/get/get_mailbox_response.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/set/set_mailbox_method.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/set/set_mailbox_response.dart'; +import 'package:model/model.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; class MailboxAPI { @@ -95,4 +99,33 @@ class MailboxAPI { hasMoreChanges: resultChanges?.hasMoreChanges ?? false, updatedProperties: resultChanges?.updatedProperties); } + + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest request) async { + final setMailboxMethod = SetMailboxMethod(accountId) + ..addCreate(request.creationId, Mailbox(name: request.newName, parentId: request.parentId)); + + final requestBuilder = JmapRequestBuilder(httpClient, ProcessingInvocation()); + + final setMailboxInvocation = requestBuilder.invocation(setMailboxMethod); + + final response = await (requestBuilder + ..usings(setMailboxMethod.requiredCapabilities)) + .build() + .execute(); + + final setMailboxResponse = response.parse( + setMailboxInvocation.methodCallId, + SetMailboxResponse.deserialize); + + return Future.sync(() async { + final newMailbox = setMailboxResponse?.created?[request.creationId]; + if (newMailbox != null) { + return newMailbox.addMailboxName(newMailbox, request.newName, parentId: request.parentId); + } else { + return null; + } + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart index 6b90c4db1..c14ea59d9 100644 --- a/lib/features/mailbox/data/repository/mailbox_repository_impl.dart +++ b/lib/features/mailbox/data/repository/mailbox_repository_impl.dart @@ -7,6 +7,7 @@ import 'package:model/model.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource/mailbox_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/datasource/state_datasource.dart'; import 'package:tmail_ui_user/features/mailbox/data/extensions/state_extension.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; import 'package:tmail_ui_user/features/mailbox/data/model/state_type.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; @@ -83,7 +84,7 @@ class MailboxRepositoryImpl extends MailboxRepository { if (updatedProperties == null) { return mailboxUpdated; } else { - final mailboxOld = mailboxCacheList?.findMailbox(mailboxUpdated.id); + final mailboxOld = mailboxCacheList?.findMailbox(mailboxUpdated.id!); if (mailboxOld != null) { return mailboxOld.combineMailbox(mailboxUpdated, updatedProperties); } else { @@ -134,4 +135,9 @@ class MailboxRepositoryImpl extends MailboxRepository { yield newMailboxResponse; } + + @override + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) { + return mapDataSource[DataSourceType.network]!.createNewMailbox(accountId, newMailboxRequest); + } } \ No newline at end of file diff --git a/lib/features/mailbox/domain/model/create_new_mailbox_request.dart b/lib/features/mailbox/domain/model/create_new_mailbox_request.dart new file mode 100644 index 000000000..280f232c9 --- /dev/null +++ b/lib/features/mailbox/domain/model/create_new_mailbox_request.dart @@ -0,0 +1,16 @@ + +import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; + +class CreateNewMailboxRequest with EquatableMixin { + + final MailboxName newName; + final Id creationId; + final MailboxId? parentId; + + CreateNewMailboxRequest(this.creationId, this.newName, {this.parentId}); + + @override + List get props => [creationId, newName, parentId]; +} \ No newline at end of file diff --git a/lib/features/mailbox/domain/repository/mailbox_repository.dart b/lib/features/mailbox/domain/repository/mailbox_repository.dart index 66d9cdbea..a5b072432 100644 --- a/lib/features/mailbox/domain/repository/mailbox_repository.dart +++ b/lib/features/mailbox/domain/repository/mailbox_repository.dart @@ -1,10 +1,14 @@ 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/state.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_response.dart'; abstract class MailboxRepository { Stream getAllMailbox(AccountId accountId, {Properties? properties}); Stream refresh(AccountId accountId, State currentState); + + Future createNewMailbox(AccountId accountId, CreateNewMailboxRequest newMailboxRequest); } \ No newline at end of file diff --git a/lib/features/mailbox/domain/state/create_new_mailbox_state.dart b/lib/features/mailbox/domain/state/create_new_mailbox_state.dart new file mode 100644 index 000000000..69ade3235 --- /dev/null +++ b/lib/features/mailbox/domain/state/create_new_mailbox_state.dart @@ -0,0 +1,21 @@ +import 'package:core/core.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; + +class CreateNewMailboxSuccess extends UIState { + + final Mailbox newMailbox; + + CreateNewMailboxSuccess(this.newMailbox); + + @override + List get props => [newMailbox]; +} + +class CreateNewMailboxFailure extends FeatureFailure { + final exception; + + CreateNewMailboxFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart b/lib/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart new file mode 100644 index 000000000..bdabfbe35 --- /dev/null +++ b/lib/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart @@ -0,0 +1,25 @@ +import 'package:core/core.dart'; +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_mailbox_request.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart'; + +class CreateNewMailboxInteractor { + final MailboxRepository mailboxRepository; + + CreateNewMailboxInteractor(this.mailboxRepository); + + Stream> execute(AccountId accountId, CreateNewMailboxRequest newMailboxRequest) async* { + try { + final newMailbox = await mailboxRepository.createNewMailbox(accountId, newMailboxRequest); + if (newMailbox != null) { + yield Right(CreateNewMailboxSuccess(newMailbox)); + } else { + yield Left(CreateNewMailboxFailure(null)); + } + } catch (e) { + yield Left(CreateNewMailboxFailure(e)); + } + } +} \ No newline at end of file diff --git a/lib/features/mailbox/presentation/mailbox_bindings.dart b/lib/features/mailbox/presentation/mailbox_bindings.dart index d1b44ca4f..ab0ba1b47 100644 --- a/lib/features/mailbox/presentation/mailbox_bindings.dart +++ b/lib/features/mailbox/presentation/mailbox_bindings.dart @@ -15,10 +15,12 @@ import 'package:tmail_ui_user/features/mailbox/data/network/mailbox_api.dart'; import 'package:tmail_ui_user/features/mailbox/data/local/mailbox_cache_manager.dart'; import 'package:tmail_ui_user/features/mailbox/data/repository/mailbox_repository_impl.dart'; import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/usecases/create_new_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/get_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/mailbox_controller.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; +import 'package:uuid/uuid.dart'; class MailboxBindings extends Bindings { @override @@ -42,11 +44,17 @@ class MailboxBindings extends Bindings { Get.lazyPut(() => GetAllMailboxInteractor(Get.find())); Get.lazyPut(() => RefreshAllMailboxInteractor(Get.find())); Get.lazyPut(() => TreeBuilder()); + Get.lazyPut(() => CreateNewMailboxInteractor(Get.find())); + Get.lazyPut(() => Uuid()); Get.put(MailboxController( Get.find(), Get.find(), Get.find(), + Get.find(), Get.find(), + Get.find(), + Get.find(), + Get.find(), Get.find(), Get.find())); } diff --git a/lib/features/mailbox/presentation/mailbox_controller.dart b/lib/features/mailbox/presentation/mailbox_controller.dart index 22e47aa8b..214ed5f16 100644 --- a/lib/features/mailbox/presentation/mailbox_controller.dart +++ b/lib/features/mailbox/presentation/mailbox_controller.dart @@ -4,25 +4,32 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart'; import 'package:tmail_ui_user/features/login/domain/usecases/delete_credential_interactor.dart'; +import 'package:tmail_ui_user/features/mailbox/domain/model/create_new_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/get_all_mailboxes_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/get_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/domain/usecases/refresh_all_mailbox_interactor.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_node.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_tree_builder.dart'; import 'package:tmail_ui_user/features/mailbox/presentation/extensions/list_mailbox_node_extension.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/mailbox_creator_arguments.dart'; +import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.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/move_multiple_email_to_mailbox_state.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'; import 'package:jmap_dart_client/jmap/core/state.dart' as jmapState; +import 'package:uuid/uuid.dart'; class MailboxController extends BaseController { @@ -30,7 +37,11 @@ class MailboxController extends BaseController { final GetAllMailboxInteractor _getAllMailboxInteractor; final DeleteCredentialInteractor _deleteCredentialInteractor; final RefreshAllMailboxInteractor _refreshAllMailboxInteractor; + final CreateNewMailboxInteractor _createNewMailboxInteractor; final TreeBuilder _treeBuilder; + final Uuid _uuid; + final AppToast _appToast; + final ImagePaths _imagePaths; final ResponsiveUtils responsiveUtils; final CachingManager _cachingManager; @@ -45,7 +56,11 @@ class MailboxController extends BaseController { this._getAllMailboxInteractor, this._deleteCredentialInteractor, this._refreshAllMailboxInteractor, + this._createNewMailboxInteractor, this._treeBuilder, + this._uuid, + this._appToast, + this._imagePaths, this.responsiveUtils, this._cachingManager, ); @@ -95,7 +110,20 @@ class MailboxController extends BaseController { } @override - void onDone() {} + void onDone() { + viewState.value.fold( + (failure) { + if (failure is CreateNewMailboxFailure) { + _createNewMailboxFailure(failure); + } + }, + (success) { + if (success is CreateNewMailboxSuccess) { + _createNewMailboxSuccess(success); + } + } + ); + } @override void onError(error) {} @@ -206,13 +234,47 @@ class MailboxController extends BaseController { await _cachingManager.clearAll(); } - void createNewMailbox() async { + void goToCreateNewMailboxView() async { final accountId = mailboxDashBoardController.accountId.value; if (accountId != null) { final newMailboxArguments = await push( AppRoutes.MAILBOX_CREATOR, arguments: MailboxCreatorArguments(accountId, allMailboxes) ); + + if (newMailboxArguments != null && newMailboxArguments is NewMailboxArguments) { + final generateCreateId = Id(_uuid.v1()); + _createNewMailboxAction(accountId, CreateNewMailboxRequest( + generateCreateId, + newMailboxArguments.newName, + parentId: newMailboxArguments.mailboxLocation?.id)); + } + } + } + + void _createNewMailboxAction(AccountId accountId, CreateNewMailboxRequest request) async { + consumeState(_createNewMailboxInteractor.execute(accountId, request)); + } + + void _createNewMailboxSuccess(CreateNewMailboxSuccess success) { + if (Get.overlayContext != null && Get.context != null) { + _appToast.showToastWithIcon( + Get.overlayContext!, + textColor: AppColor.toastSuccessBackgroundColor, + message: AppLocalizations.of(Get.context!).new_mailbox_is_created(success.newMailbox.name?.name ?? ''), + icon: _imagePaths.icFolderMailbox); + } + + refreshMailboxChanges(); + } + + void _createNewMailboxFailure(CreateNewMailboxFailure failure) { + if (Get.overlayContext != null && Get.context != null) { + _appToast.showToastWithIcon( + Get.overlayContext!, + textColor: AppColor.toastErrorBackgroundColor, + message: AppLocalizations.of(Get.context!).create_new_mailbox_failure, + icon: _imagePaths.icFolderMailbox); } } diff --git a/lib/features/mailbox/presentation/mailbox_view.dart b/lib/features/mailbox/presentation/mailbox_view.dart index 5d91a9921..451900307 100644 --- a/lib/features/mailbox/presentation/mailbox_view.dart +++ b/lib/features/mailbox/presentation/mailbox_view.dart @@ -83,8 +83,8 @@ class MailboxView extends GetWidget { return Padding( padding: EdgeInsets.only(left: 16, right: 16), child: IconButton( - key: Key('mailbox_add_new_folder_button'), - onPressed: () => controller.createNewMailbox(), + key: Key('create_new_mailbox_button'), + onPressed: () => controller.goToCreateNewMailboxView(), icon: SvgPicture.asset(imagePaths.icAddNewFolder, width: 30, height: 30, fit: BoxFit.fill))); } diff --git a/lib/features/mailbox/presentation/model/mailbox_action.dart b/lib/features/mailbox/presentation/model/mailbox_actions.dart similarity index 71% rename from lib/features/mailbox/presentation/model/mailbox_action.dart rename to lib/features/mailbox/presentation/model/mailbox_actions.dart index f7779785b..228a8b0ac 100644 --- a/lib/features/mailbox/presentation/model/mailbox_action.dart +++ b/lib/features/mailbox/presentation/model/mailbox_actions.dart @@ -2,18 +2,18 @@ import 'package:flutter/cupertino.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -enum MailboxAction { +enum MailboxActions { create, moveEmail, } -extension MailboxActionExtension on MailboxAction { +extension MailboxActionsExtension on MailboxActions { String getTitle(BuildContext context) { switch(this) { - case MailboxAction.create: + case MailboxActions.create: return AppLocalizations.of(context).mailbox_location; - case MailboxAction.moveEmail: + case MailboxActions.moveEmail: return AppLocalizations.of(context).move_to_mailbox; default: return ''; diff --git a/lib/features/mailbox_creator/domain/extensions/name_validator_string_extension.dart b/lib/features/mailbox_creator/domain/extensions/name_validator_string_extension.dart index a519d0b58..a8b2d9d0a 100644 --- a/lib/features/mailbox_creator/domain/extensions/name_validator_string_extension.dart +++ b/lib/features/mailbox_creator/domain/extensions/name_validator_string_extension.dart @@ -1,6 +1,6 @@ extension NameValidatorStringExtension on String { bool hasSpecialCharactersInName() { - return RegExp(r'^([@#%^$~!%&*()+=\|{}/<>:;?`])').hasMatch(this); + return RegExp(r'(?=.*?[#?!@$%^&*)(=+}{:;?/|\\><.,`~])').hasMatch(this); } } \ No newline at end of file diff --git a/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart b/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart index 6e2bc0809..09026af66 100644 --- a/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart +++ b/lib/features/mailbox_creator/presentation/mailbox_creator_controller.dart @@ -4,10 +4,11 @@ import 'package:dartz/dartz.dart'; import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/destination_picker/presentation/model/destination_picker_arguments.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/duplicate_name_validator.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/empty_name_validator.dart'; import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/special_character_validator.dart'; @@ -15,6 +16,7 @@ import 'package:tmail_ui_user/features/mailbox_creator/domain/state/verify_name_ import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart'; import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/mailbox_creator_arguments.dart'; +import 'package:tmail_ui_user/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/utils/app_logger.dart'; @@ -97,11 +99,21 @@ class MailboxCreatorController extends BaseController { if (accountId != null) { final destinationMailbox = await push( AppRoutes.DESTINATION_PICKER, - arguments: DestinationPickerArguments(accountId!, MailboxAction.create) + arguments: DestinationPickerArguments(accountId!, MailboxActions.create) ); - if (destinationMailbox != null && destinationMailbox is PresentationMailbox) { - selectedMailbox.value = destinationMailbox; - } + + selectedMailbox.value = destinationMailbox; + } + } + + void createNewMailbox(BuildContext context) { + FocusScope.of(context).unfocus(); + final nameMailbox = newNameMailbox.value; + if (nameMailbox != null && nameMailbox.isNotEmpty) { + final newMailboxArguments = NewMailboxArguments( + MailboxName(nameMailbox), + mailboxLocation: selectedMailbox.value); + popBack(result: newMailboxArguments); } } diff --git a/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart b/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart index 45f1dc68c..9ccf5df59 100644 --- a/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart +++ b/lib/features/mailbox_creator/presentation/mailbox_creator_view.dart @@ -98,7 +98,7 @@ class MailboxCreatorView extends GetWidget { title: AppLocalizations.of(context).new_mailbox, isValidated: controller.isCreateMailboxValidated(context)) ..addOnCancelActionClick(() => controller.closeMailboxCreator(context)) - ..addOnDoneActionClick(() => {})) + ..addOnDoneActionClick(() => controller.createNewMailbox(context))) .build()) ); } diff --git a/lib/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart b/lib/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart index 457a321a5..95b96fb38 100644 --- a/lib/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart +++ b/lib/features/mailbox_creator/presentation/model/new_mailbox_arguments.dart @@ -1,13 +1,14 @@ import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/mailbox/presentation_mailbox.dart'; -class NewMailboxArguments with EquatableMixin{ - final String nameMailbox; - final PresentationMailbox mailboxLocation; +class NewMailboxArguments with EquatableMixin { + final MailboxName newName; + final PresentationMailbox? mailboxLocation; - NewMailboxArguments(this.nameMailbox, this.mailboxLocation); + NewMailboxArguments(this.newName, {this.mailboxLocation}); @override - List get props => [nameMailbox, mailboxLocation]; + List get props => [newName, mailboxLocation]; } \ No newline at end of file diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index cd19ace92..0febc8d79 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -21,7 +21,7 @@ import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_sta import 'package:tmail_ui_user/features/email/domain/state/move_to_mailbox_state.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_star_email_interactor.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; -import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_action.dart'; +import 'package:tmail_ui_user/features/mailbox/presentation/model/mailbox_actions.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; @@ -480,7 +480,7 @@ class ThreadController extends BaseController { final listEmailIds = listEmail.map((email) => email.id).toList(); final destinationMailbox = await push( AppRoutes.DESTINATION_PICKER, - arguments: DestinationPickerArguments(_accountId!, MailboxAction.moveEmail) + arguments: DestinationPickerArguments(_accountId!, MailboxActions.moveEmail) ); if (destinationMailbox != null && destinationMailbox is PresentationMailbox) { diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index c8299e7e1..20343e851 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -634,4 +634,19 @@ class AppLocalizations { name: 'this_folder_name_is_already_taken', ); } + + String new_mailbox_is_created(String nameMailbox) { + return Intl.message( + '$nameMailbox is created', + name: 'new_mailbox_is_created', + args: [nameMailbox] + ); + } + + String get create_new_mailbox_failure { + return Intl.message( + 'Create new mailbox failure', + name: 'new_mailbox_is_created' + ); + } } \ No newline at end of file diff --git a/model/lib/extensions/mailbox_extension.dart b/model/lib/extensions/mailbox_extension.dart index 2e623c50e..f8f4ac645 100644 --- a/model/lib/extensions/mailbox_extension.dart +++ b/model/lib/extensions/mailbox_extension.dart @@ -8,7 +8,7 @@ extension MailboxExtension on Mailbox { PresentationMailbox toPresentationMailbox({SelectMode selectMode = SelectMode.INACTIVE}) { return PresentationMailbox( - id, + id!, name: name, parentId: parentId, role: role, @@ -25,17 +25,33 @@ extension MailboxExtension on Mailbox { Mailbox combineMailbox(Mailbox newMailbox, Properties updatedProperties) { return Mailbox( - newMailbox.id, - updatedProperties.contain(MailboxProperty.name) ? newMailbox.name : name, - updatedProperties.contain(MailboxProperty.parentId) ? newMailbox.parentId : parentId, - updatedProperties.contain(MailboxProperty.role) ? newMailbox.role : role, - updatedProperties.contain(MailboxProperty.sortOrder) ? newMailbox.sortOrder : sortOrder, - updatedProperties.contain(MailboxProperty.totalEmails) ? newMailbox.totalEmails : totalEmails, - updatedProperties.contain(MailboxProperty.unreadEmails) ? newMailbox.unreadEmails : unreadEmails, - updatedProperties.contain(MailboxProperty.totalThreads) ? newMailbox.totalThreads : totalThreads, - updatedProperties.contain(MailboxProperty.unreadThreads) ? newMailbox.unreadThreads : unreadThreads, - updatedProperties.contain(MailboxProperty.myRights) ? newMailbox.myRights : myRights, - updatedProperties.contain(MailboxProperty.isSubscribed) ? newMailbox.isSubscribed : isSubscribed, + id: newMailbox.id, + name: updatedProperties.contain(MailboxProperty.name) ? newMailbox.name : name, + parentId: updatedProperties.contain(MailboxProperty.parentId) ? newMailbox.parentId : parentId, + role: updatedProperties.contain(MailboxProperty.role) ? newMailbox.role : role, + sortOrder: updatedProperties.contain(MailboxProperty.sortOrder) ? newMailbox.sortOrder : sortOrder, + totalEmails: updatedProperties.contain(MailboxProperty.totalEmails) ? newMailbox.totalEmails : totalEmails, + unreadEmails: updatedProperties.contain(MailboxProperty.unreadEmails) ? newMailbox.unreadEmails : unreadEmails, + totalThreads: updatedProperties.contain(MailboxProperty.totalThreads) ? newMailbox.totalThreads : totalThreads, + unreadThreads: updatedProperties.contain(MailboxProperty.unreadThreads) ? newMailbox.unreadThreads : unreadThreads, + myRights: updatedProperties.contain(MailboxProperty.myRights) ? newMailbox.myRights : myRights, + isSubscribed: updatedProperties.contain(MailboxProperty.isSubscribed) ? newMailbox.isSubscribed : isSubscribed, + ); + } + + Mailbox addMailboxName(Mailbox newMailbox, MailboxName mailboxName, {MailboxId? parentId}) { + return Mailbox( + id: id, + name: mailboxName, + parentId: parentId, + role: role, + sortOrder: sortOrder, + totalEmails: totalEmails, + unreadEmails: unreadEmails, + totalThreads: totalThreads, + unreadThreads: unreadThreads, + myRights: myRights, + isSubscribed: isSubscribed, ); } } \ No newline at end of file diff --git a/model/lib/extensions/presentation_mailbox_extension.dart b/model/lib/extensions/presentation_mailbox_extension.dart index 9e63bfba6..191d027b3 100644 --- a/model/lib/extensions/presentation_mailbox_extension.dart +++ b/model/lib/extensions/presentation_mailbox_extension.dart @@ -23,17 +23,17 @@ extension PresentationMailboxExtension on PresentationMailbox { Mailbox toMailbox() { return Mailbox( - id, - name, - parentId, - role, - sortOrder, - totalEmails, - unreadEmails, - totalThreads, - unreadThreads, - myRights, - isSubscribed + id: id, + name: name, + parentId: parentId, + role: role, + sortOrder: sortOrder, + totalEmails: totalEmails, + unreadEmails: unreadEmails, + totalThreads: totalThreads, + unreadThreads: unreadThreads, + myRights: myRights, + isSubscribed: isSubscribed ); } } \ No newline at end of file diff --git a/test/fixtures/email_fixtures.dart b/test/fixtures/email_fixtures.dart index 1f537b014..401418a40 100644 --- a/test/fixtures/email_fixtures.dart +++ b/test/fixtures/email_fixtures.dart @@ -16,7 +16,7 @@ class EmailFixtures { sentAt: UTCDate(DateTime.parse("2021-08-11T04:25:34Z")), receivedAt: UTCDate(DateTime.parse("2021-08-11T04:25:55Z")), keywords: {KeyWordIdentifier.emailSeen : true}, - mailboxIds: {MailboxFixtures.inboxMailbox.id : true}, + mailboxIds: {MailboxFixtures.inboxMailbox.id! : true}, to: {EmailAddress("DatVu", "tdvu@linagora.com")}, ); @@ -28,7 +28,7 @@ class EmailFixtures { from: {EmailAddress(null, "noreply@qa.open-paas.org")}, sentAt: UTCDate(DateTime.parse("2021-08-10T09:45:01Z")), receivedAt: UTCDate(DateTime.parse("2021-08-10T04:00:59Z")), - mailboxIds: {MailboxFixtures.inboxMailbox.id : true}, + mailboxIds: {MailboxFixtures.inboxMailbox.id! : true}, to: {EmailAddress("DatVu", "tdvu@facebook.com")}, ); @@ -41,7 +41,7 @@ class EmailFixtures { sentAt: UTCDate(DateTime.parse("2021-08-09T03:00:00Z")), receivedAt: UTCDate(DateTime.parse("2021-08-09T04:00:55Z")), keywords: {KeyWordIdentifier.emailFlagged : true}, - mailboxIds: {MailboxFixtures.inboxMailbox.id : true}, + mailboxIds: {MailboxFixtures.inboxMailbox.id! : true}, to: {EmailAddress("DatVu", "tdvu@gmail.com")}, ); @@ -54,7 +54,7 @@ class EmailFixtures { sentAt: UTCDate(DateTime.parse("2021-08-08T06:46:25Z")), receivedAt: UTCDate(DateTime.parse("2021-08-08T06:46:26Z")), keywords: {KeyWordIdentifier.emailFlagged : true}, - mailboxIds: {MailboxFixtures.inboxMailbox.id : true}, + mailboxIds: {MailboxFixtures.inboxMailbox.id! : true}, to: {EmailAddress("DatVu", "tdvu@icloud.com")}, ); @@ -67,7 +67,7 @@ class EmailFixtures { sentAt: UTCDate(DateTime.parse("2021-08-07T04:34:13Z")), receivedAt: UTCDate(DateTime.parse("2021-08-07T04:34:17Z")), keywords: {KeyWordIdentifier.emailSeen : true}, - mailboxIds: {MailboxFixtures.inboxMailbox.id : true}, + mailboxIds: {MailboxFixtures.inboxMailbox.id! : true}, to: {EmailAddress("DatVu", "tdvu@yahoo.com")}, ); } \ No newline at end of file diff --git a/test/fixtures/mailbox_fixtures.dart b/test/fixtures/mailbox_fixtures.dart index 2476fa58a..d02446070 100644 --- a/test/fixtures/mailbox_fixtures.dart +++ b/test/fixtures/mailbox_fixtures.dart @@ -5,16 +5,16 @@ import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox_rights.dart'; class MailboxFixtures { static final inboxMailbox = Mailbox( - MailboxId(Id('1')), - MailboxName('Inbox'), - null, - Role('inbox'), - SortOrder(sortValue: 10), - TotalEmails(UnsignedInt(2758)), - UnreadEmails(UnsignedInt(34)), - TotalThreads(UnsignedInt(2758)), - UnreadThreads(UnsignedInt(34)), - MailboxRights( + id: MailboxId(Id('1')), + name: MailboxName('Inbox'), + parentId: null, + role: Role('inbox'), + sortOrder: SortOrder(sortValue: 10), + totalEmails: TotalEmails(UnsignedInt(2758)), + unreadEmails: UnreadEmails(UnsignedInt(34)), + totalThreads: TotalThreads(UnsignedInt(2758)), + unreadThreads: UnreadThreads(UnsignedInt(34)), + myRights: MailboxRights( true, true, true, @@ -24,20 +24,20 @@ class MailboxFixtures { true, true, true), - IsSubscribed(true) + isSubscribed: IsSubscribed(true) ); static final sentMailbox = Mailbox( - MailboxId(Id('2')), - MailboxName('Sent'), - null, - Role('sent'), - SortOrder(sortValue: 3), - TotalEmails(UnsignedInt(123)), - UnreadEmails(UnsignedInt(12)), - TotalThreads(UnsignedInt(123)), - UnreadThreads(UnsignedInt(12)), - MailboxRights( + id: MailboxId(Id('2')), + name: MailboxName('Sent'), + parentId: null, + role: Role('sent'), + sortOrder: SortOrder(sortValue: 3), + totalEmails: TotalEmails(UnsignedInt(123)), + unreadEmails: UnreadEmails(UnsignedInt(12)), + totalThreads: TotalThreads(UnsignedInt(123)), + unreadThreads: UnreadThreads(UnsignedInt(12)), + myRights: MailboxRights( true, true, true, @@ -47,20 +47,20 @@ class MailboxFixtures { true, true, true), - IsSubscribed(true) + isSubscribed: IsSubscribed(true) ); static final folder1 = Mailbox( - MailboxId(Id('b1')), - MailboxName('folder 1'), - null, - null, - SortOrder(sortValue: 1000), - TotalEmails(UnsignedInt(123)), - UnreadEmails(UnsignedInt(12)), - TotalThreads(UnsignedInt(123)), - UnreadThreads(UnsignedInt(12)), - MailboxRights( + id: MailboxId(Id('b1')), + name: MailboxName('folder 1'), + parentId: null, + role: null, + sortOrder: SortOrder(sortValue: 1000), + totalEmails: TotalEmails(UnsignedInt(123)), + unreadEmails: UnreadEmails(UnsignedInt(12)), + totalThreads: TotalThreads(UnsignedInt(123)), + unreadThreads: UnreadThreads(UnsignedInt(12)), + myRights: MailboxRights( true, true, true, @@ -70,20 +70,20 @@ class MailboxFixtures { true, true, true), - IsSubscribed(true) + isSubscribed: IsSubscribed(true) ); static final folder1_1 = Mailbox( - MailboxId(Id('b11')), - MailboxName('folder 1_1'), - MailboxId(Id("b1")), - null, - SortOrder(sortValue: 1000), - TotalEmails(UnsignedInt(123)), - UnreadEmails(UnsignedInt(12)), - TotalThreads(UnsignedInt(123)), - UnreadThreads(UnsignedInt(12)), - MailboxRights( + id: MailboxId(Id('b11')), + name: MailboxName('folder 1_1'), + parentId: MailboxId(Id("b1")), + role: null, + sortOrder: SortOrder(sortValue: 1000), + totalEmails: TotalEmails(UnsignedInt(123)), + unreadEmails: UnreadEmails(UnsignedInt(12)), + totalThreads: TotalThreads(UnsignedInt(123)), + unreadThreads: UnreadThreads(UnsignedInt(12)), + myRights: MailboxRights( true, true, true, @@ -93,6 +93,6 @@ class MailboxFixtures { true, true, true), - IsSubscribed(true) + isSubscribed: IsSubscribed(true) ); } \ No newline at end of file