From 3c85f1d5ed74aad5f2c94e72b5a4e2115035a50c Mon Sep 17 00:00:00 2001 From: ManhNTX Date: Sat, 20 Aug 2022 20:45:27 +0700 Subject: [PATCH] TF-831: implement Add a new recipient in forwarding --- env.file | 2 +- forward/lib/forward/forward_id.dart | 2 - .../emails_forward_creator_binding.dart | 2 +- .../emails_forward_creator_controller.dart | 34 +- .../emails_forward_creator_view.dart | 203 ++++++++++++ .../mails_forward_creator_arguments.dart | 0 .../email_forward_creator_item_widget.dart | 23 +- ...ails_forward_input_decoration_builder.dart | 0 ...rd_input_with_drop_list_field_builder.dart | 3 +- .../emails_forward_creator_view.dart | 313 ------------------ .../datasource/manage_account_datasource.dart | 4 + .../manage_account_datasource_impl.dart | 10 + .../manage_account_repository_impl.dart | 5 +- .../add_recipients_in_forwarding_request.dart | 23 ++ .../repository/manage_account_repository.dart | 3 + .../add_recipient_in_forwarding_state.dart | 21 ++ ...d_recipients_in_forwarding_interactor.dart | 28 ++ .../forward/forward_bindings.dart | 3 + .../forward/forward_controller.dart | 64 +++- .../widgets/forward_header_widget.dart | 82 ++--- .../widgets/list_email_forward_widget.dart | 2 +- .../manage_account_dashboard_controller.dart | 2 + .../manage_account_dashboard_view.dart | 267 +++++++-------- lib/l10n/intl_messages.arb | 20 +- lib/main/localizations/app_localizations.dart | 22 +- lib/main/pages/app_pages.dart | 4 +- lib/main/routes/app_routes.dart | 1 + ...ails_in_mailbox_interactor_test.mocks.dart | 4 +- ...ails_in_mailbox_interactor_test.mocks.dart | 4 +- 29 files changed, 615 insertions(+), 536 deletions(-) rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/emails_forward_creator_binding.dart (95%) rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/emails_forward_creator_controller.dart (77%) create mode 100644 lib/features/emails_forward_creator/presentation/emails_forward_creator_view.dart rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/model/mails_forward_creator_arguments.dart (100%) rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/widgets/email_forward_creator_item_widget.dart (60%) rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/widgets/emails_forward_input_decoration_builder.dart (100%) rename lib/features/{mails_forward_creator => emails_forward_creator}/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart (95%) delete mode 100644 lib/features/mails_forward_creator/presentation/emails_forward_creator_view.dart create mode 100644 lib/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart create mode 100644 lib/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart create mode 100644 lib/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart diff --git a/env.file b/env.file index f915cbf58..71638e979 100644 --- a/env.file +++ b/env.file @@ -1,3 +1,3 @@ -SERVER_URL=https://gateway.upn.integration-open-paas.org +SERVER_URL=http://localhost DOMAIN_REDIRECT_URL=http://localhost:3000 WEB_OIDC_CLIENT_ID=teammail-web \ No newline at end of file diff --git a/forward/lib/forward/forward_id.dart b/forward/lib/forward/forward_id.dart index 2311b41ea..f11f582a7 100644 --- a/forward/lib/forward/forward_id.dart +++ b/forward/lib/forward/forward_id.dart @@ -1,6 +1,4 @@ import 'package:equatable/equatable.dart'; -import 'package:forward/forward/converter/forward_id_coverter.dart'; -import 'package:jmap_dart_client/http/converter/id_converter.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; enum ForwardIdType { diff --git a/lib/features/mails_forward_creator/presentation/emails_forward_creator_binding.dart b/lib/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart similarity index 95% rename from lib/features/mails_forward_creator/presentation/emails_forward_creator_binding.dart rename to lib/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart index b9bdf7ca2..0553e26c9 100644 --- a/lib/features/mails_forward_creator/presentation/emails_forward_creator_binding.dart +++ b/lib/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart @@ -12,7 +12,7 @@ import 'package:tmail_ui_user/features/composer/domain/repository/contact_reposi import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/emails_forward_creator_controller.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_controller.dart'; class EmailsForwardCreatorBindings extends BaseBindings { diff --git a/lib/features/mails_forward_creator/presentation/emails_forward_creator_controller.dart b/lib/features/emails_forward_creator/presentation/emails_forward_creator_controller.dart similarity index 77% rename from lib/features/mails_forward_creator/presentation/emails_forward_creator_controller.dart rename to lib/features/emails_forward_creator/presentation/emails_forward_creator_controller.dart index 8de801c2a..b47ce7eaa 100644 --- a/lib/features/mails_forward_creator/presentation/emails_forward_creator_controller.dart +++ b/lib/features/emails_forward_creator/presentation/emails_forward_creator_controller.dart @@ -1,6 +1,7 @@ import 'package:core/utils/app_logger.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart'; @@ -11,7 +12,8 @@ import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_ import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart'; import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/model/mails_forward_creator_arguments.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/model/mails_forward_creator_arguments.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/features/composer/presentation/extensions/session_extension.dart'; @@ -19,18 +21,19 @@ class EmailsForwardCreatorController extends BaseController { final inputEmailForwardController = TextEditingController(); final ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact; + final _forwardController = Get.find(); late AccountId _accountId; late Session? _session; late GetAutoCompleteWithDeviceContactInteractor _getAutoCompleteWithDeviceContactInteractor; late GetAutoCompleteInteractor _getAutoCompleteInteractor; - final listEmailForwards = [].obs; + final listEmailForwards = RxSet(); EmailsForwardCreatorController( this._getAutoCompleteWithDeviceContactInteractor, this._getAutoCompleteInteractor, - ); + ); @override void onReady() { @@ -91,14 +94,33 @@ class EmailsForwardCreatorController extends BaseController { inputEmailForwardController.clear(); } + void _clearListEmailForwards() { + listEmailForwards.clear(); + } + void closeView(BuildContext context) { FocusScope.of(context).unfocus(); - popBack(); + if(kIsWeb) { + _clearListEmailForwards(); + _forwardController.accountDashBoardController.emailsForwardCreatorIsActive.toggle(); + } else { + popBack(); + } } void addEmailForwards(BuildContext context) { - inputEmailForwardController.clear(); FocusScope.of(context).unfocus(); - popBack(result: listEmailForwards.toList()); + if(inputEmailForwardController.text.trim().isNotEmpty) { + listEmailForwards.add(EmailAddress(null, inputEmailForwardController.text.trim())); + } + inputEmailForwardController.clear(); + + if(kIsWeb) { + _forwardController.accountDashBoardController.emailsForwardCreatorIsActive.toggle(); + _forwardController.handleAddRecipients(listEmailForwards.toList()); + _clearListEmailForwards(); + } else { + popBack(result: listEmailForwards.toList()); + } } } \ No newline at end of file diff --git a/lib/features/emails_forward_creator/presentation/emails_forward_creator_view.dart b/lib/features/emails_forward_creator/presentation/emails_forward_creator_view.dart new file mode 100644 index 000000000..2ae19674f --- /dev/null +++ b/lib/features/emails_forward_creator/presentation/emails_forward_creator_view.dart @@ -0,0 +1,203 @@ +import 'package:core/core.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:get/get.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/model.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_controller.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +class EmailsForwardCreatorView extends GetWidget { + + final _imagePaths = Get.find(); + final _responsiveUtils = Get.find(); + + EmailsForwardCreatorView({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ResponsiveWidget( + responsiveUtils: _responsiveUtils, + mobile: Scaffold( + backgroundColor: Colors.black38, + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: SafeArea( + child: Align( + alignment: Alignment.bottomCenter, + child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + )), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + )), + width: double.infinity, + height: _responsiveUtils.getSizeScreenHeight(context) - 70, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16)), + child: _buildEmailForwardCreatorList(context) + ) + ) + ) + ), + ), + ) + ), + tablet: Scaffold( + backgroundColor: Colors.black38, + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Align(alignment: Alignment.bottomCenter, child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + )), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + )), + width: double.infinity, + height: _responsiveUtils.getSizeScreenHeight(context) * 0.7, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16)), + child: _buildEmailForwardCreatorList(context) + ) + ) + )), + ) + ), + desktop: Scaffold( + backgroundColor: Colors.black38, + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Align(alignment: Alignment.center, child: Card( + color: Colors.transparent, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16))), + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16))), + width: _responsiveUtils.getSizeScreenWidth(context) * 0.6, + height: _responsiveUtils.getSizeScreenHeight(context) * 0.7, + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(16)), + child: _buildEmailForwardCreatorList(context) + ) + ) + ) + ), + ) + ) + ); + } + + Widget _buildEmailForwardCreatorList(BuildContext context) { + return Stack( + children: [ + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Container( + padding: const EdgeInsets.only(top: 16), + alignment: Alignment.center, + child: Text( + AppLocalizations.of(context).addRecipients, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20, + color: Colors.black))), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: (EmailsForwardInputWithDropListFieldBuilder( + AppLocalizations.of(context).recipientsLabel, + controller.inputEmailForwardController) + ..addOnSelectedSuggestionAction((newEmailAddress) { + controller.addToListEmailForwards(newEmailAddress); + controller.clearAll(); + }) + ..addOnSummitedCallbackAction((pattern) { + if (pattern != null && pattern.trim().isNotEmpty) { + controller.addToListEmailForwards(EmailAddress(null, pattern.trim())); + controller.clearAll(); + } + }) + ..addOnSuggestionCallbackAction((pattern) { + if (pattern != null) { + controller.getAutoCompleteSuggestion(word: pattern.trim()); + } + })) + .build(), + ), + Expanded( + child: Obx(() => ListView.builder( + itemCount: controller.listEmailForwards.length, + itemBuilder: (BuildContext context, int index) { + final item = controller.listEmailForwards.toList()[index]; + return EmailForwardCreatorItemWidget( + emailForward: item.emailAddress, + onDelete: () { + controller.listEmailForwards.remove(item); + } + ); + }, + )), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + child: _buildButtonAddNewEmailsForward(context), + ), + ]), + Positioned(top: 8, right: 8, + child: buildIconWeb( + icon: SvgPicture.asset( + _imagePaths.icCloseMailbox, + fit: BoxFit.fill), + tooltip: AppLocalizations.of(context).close, + onTap: () => controller.closeView(context))) + ], + ); + } + + Widget _buildButtonAddNewEmailsForward(BuildContext context) { + return (ButtonBuilder(_imagePaths.icAddEmailForward) + ..key(const Key('button_add_emails_forward_creator')) + ..decoration(BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppColor.colorTextButton)) + ..paddingIcon(const EdgeInsets.only(right: 8)) + ..iconColor(Colors.white) + ..size(20) + ..radiusSplash(10) + ..padding(const EdgeInsets.symmetric(vertical: 12)) + ..textStyle(const TextStyle( + fontSize: 17, + color: Colors.white, + fontWeight: FontWeight.w500, + )) + ..onPressActionClick(() => controller.addEmailForwards(context)) + ..text( + AppLocalizations.of(context).addRecipients, + isVertical: false, + )) + .build(); + } + +} \ No newline at end of file diff --git a/lib/features/mails_forward_creator/presentation/model/mails_forward_creator_arguments.dart b/lib/features/emails_forward_creator/presentation/model/mails_forward_creator_arguments.dart similarity index 100% rename from lib/features/mails_forward_creator/presentation/model/mails_forward_creator_arguments.dart rename to lib/features/emails_forward_creator/presentation/model/mails_forward_creator_arguments.dart diff --git a/lib/features/mails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart b/lib/features/emails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart similarity index 60% rename from lib/features/mails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart rename to lib/features/emails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart index 5b63db02f..3c070f509 100644 --- a/lib/features/mails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart +++ b/lib/features/emails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart @@ -4,7 +4,6 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; class EmailForwardCreatorItemWidget extends StatelessWidget { - final _responsiveUtils = Get.find(); final _imagePaths = Get.find(); final VoidCallback onDelete; final String emailForward; @@ -18,19 +17,25 @@ class EmailForwardCreatorItemWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - padding: EdgeInsets.only( - top: 15, - bottom: 15, - left: _responsiveUtils.isMobile(context) ? 16 : 24, - right: _responsiveUtils.isMobile(context) ? 0 : 24), + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), color: Colors.white, child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text(emailForward, + CircleAvatar( + backgroundColor: AppColor.colorTextButton, + radius: 16, + child: Text(emailForward[0].toUpperCase(), + style: const TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w500))), + const SizedBox(width: 10), + Expanded(child: Text(emailForward, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w400, - color: Colors.black)), - const Spacer(), + color: Colors.black))), buildIconWeb( icon: SvgPicture.asset( _imagePaths.icDeleteEmailAddress, diff --git a/lib/features/mails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart b/lib/features/emails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart similarity index 100% rename from lib/features/mails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart rename to lib/features/emails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart diff --git a/lib/features/mails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart b/lib/features/emails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart similarity index 95% rename from lib/features/mails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart rename to lib/features/emails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart index 3ef29bd99..19b3fe63f 100644 --- a/lib/features/mails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart +++ b/lib/features/emails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart @@ -3,13 +3,12 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/widgets/emails_forward_input_decoration_builder.dart'; typedef OnSelectedSuggestionAction = Function(EmailAddress emailAddress); typedef OnSuggestionCallbackAction = Function(String? pattern); typedef OnSummitedCallbackAction = Function(String? pattern); - class EmailsForwardInputWithDropListFieldBuilder { final String hintText; diff --git a/lib/features/mails_forward_creator/presentation/emails_forward_creator_view.dart b/lib/features/mails_forward_creator/presentation/emails_forward_creator_view.dart deleted file mode 100644 index 52bd41f83..000000000 --- a/lib/features/mails_forward_creator/presentation/emails_forward_creator_view.dart +++ /dev/null @@ -1,313 +0,0 @@ -import 'package:core/core.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:get/get.dart'; -import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -import 'package:model/model.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/emails_forward_creator_controller.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/widgets/email_forward_creator_item_widget.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/widgets/emails_forward_input_with_drop_list_field_builder.dart'; -import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; - -class EmailsForwardCreatorView extends GetWidget { - - final _imagePaths = Get.find(); - final _responsiveUtils = Get.find(); - - EmailsForwardCreatorView({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ResponsiveWidget( - responsiveUtils: _responsiveUtils, - mobile: Scaffold( - backgroundColor: Colors.black38, - body: GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - child: SafeArea( - child: Align( - alignment: Alignment.bottomCenter, - child: Card( - color: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - )), - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - )), - width: double.infinity, - height: _responsiveUtils.getSizeScreenHeight(context) - 70, - child: ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16)), - child: _buildRulesFilterFormOnMobile(context) - ) - ) - ) - ), - ), - ) - ), - tablet: Scaffold( - backgroundColor: Colors.black38, - body: GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - child: Align(alignment: Alignment.bottomCenter, child: Card( - color: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - )), - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - )), - width: double.infinity, - height: _responsiveUtils.getSizeScreenHeight(context) * 0.7, - child: ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16)), - child: _buildRulesFilterFormOnTablet(context) - ) - ) - )), - ) - ), - desktop: Scaffold( - backgroundColor: Colors.black38, - body: GestureDetector( - onTap: () => FocusScope.of(context).unfocus(), - child: Align(alignment: Alignment.center, child: Card( - color: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(16))), - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(16))), - width: _responsiveUtils.getSizeScreenWidth(context) * 0.6, - height: _responsiveUtils.getSizeScreenHeight(context) * 0.7, - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(16)), - child: _buildRulesFilterFormOnDesktop(context) - ) - ) - ) - ), - ) - ) - ); - } - - Widget _buildRulesFilterFormOnDesktop(BuildContext context) { - return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Align( - alignment: Alignment.centerRight, - child: buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icCloseMailbox, - fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: () => controller.closeView(context)), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: (EmailsForwardInputWithDropListFieldBuilder( - AppLocalizations.of(context).emailForwardLabel, - controller.inputEmailForwardController) - ..addOnSelectedSuggestionAction((newEmailAddress) { - controller.addToListEmailForwards(newEmailAddress); - controller.clearAll(); - }) - ..addOnSummitedCallbackAction((pattern) { - if (pattern != null && pattern.trim().isNotEmpty) { - controller.addToListEmailForwards(EmailAddress(null, pattern.trim())); - controller.clearAll(); - } - }) - ..addOnSuggestionCallbackAction((pattern) { - if (pattern != null) { - controller.getAutoCompleteSuggestion(word: pattern.trim()); - } - })) - .build(), - ), - Expanded( - child: Obx(() => ListView.builder( - itemCount: controller.listEmailForwards.length, - itemBuilder: (BuildContext context, int index) { - final item = controller.listEmailForwards[index]; - return EmailForwardCreatorItemWidget( - emailForward: item.emailAddress, - onDelete: () { - controller.listEmailForwards.removeAt(index); - } - ); - }, - )), - ), - ]); - } - - Widget _buildRulesFilterFormOnTablet(BuildContext context) { - return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Align( - alignment: Alignment.centerRight, - child: buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icCloseMailbox, - fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: () => controller.closeView(context)), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: (EmailsForwardInputWithDropListFieldBuilder( - AppLocalizations.of(context).emailForwardLabel, - controller.inputEmailForwardController) - ..addOnSelectedSuggestionAction((newEmailAddress) { - controller.addToListEmailForwards(newEmailAddress); - controller.clearAll(); - }) - ..addOnSummitedCallbackAction((pattern) { - if (pattern != null && pattern.trim().isNotEmpty) { - controller.addToListEmailForwards(EmailAddress(null, pattern.trim())); - controller.clearAll(); - } - }) - ..addOnSuggestionCallbackAction((pattern) { - if (pattern != null) { - controller.getAutoCompleteSuggestion(word: pattern.trim()); - } - })) - .build(), - ), - Expanded( - child: Obx(() => ListView.builder( - itemCount: controller.listEmailForwards.length, - itemBuilder: (BuildContext context, int index) { - final item = controller.listEmailForwards[index]; - return EmailForwardCreatorItemWidget( - emailForward: item.emailAddress, - onDelete: () { - controller.listEmailForwards.removeAt(index); - } - ); - }, - )), - ), - ]); - } - - Widget _buildRulesFilterFormOnMobile(BuildContext context) { - return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Align( - alignment: Alignment.centerRight, - child: buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icCloseMailbox, - fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).close, - onTap: () => controller.closeView(context)), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: (EmailsForwardInputWithDropListFieldBuilder( - AppLocalizations.of(context).emailForwardLabel, - controller.inputEmailForwardController) - ..addOnSelectedSuggestionAction((newEmailAddress) { - controller.addToListEmailForwards(newEmailAddress); - controller.clearAll(); - }) - ..addOnSummitedCallbackAction((pattern) { - if (pattern != null && pattern.trim().isNotEmpty) { - controller.addToListEmailForwards(EmailAddress(null, pattern.trim())); - controller.clearAll(); - } - }) - ..addOnSuggestionCallbackAction((pattern) { - if (pattern != null) { - controller.getAutoCompleteSuggestion(word: pattern.trim()); - } - })) - .build(), - ), - Expanded( - child: Obx(() => ListView.builder( - itemCount: controller.listEmailForwards.length, - itemBuilder: (BuildContext context, int index) { - final item = controller.listEmailForwards[index]; - return EmailForwardCreatorItemWidget( - emailForward: item.emailAddress, - onDelete: () { - controller.listEmailForwards.removeAt(index); - } - ); - }, - )), - ), - ]); - } - - Widget _buildButtonAddNewEmailsForward(BuildContext context) { - if (!_responsiveUtils.isMobile(context)) { - return (ButtonBuilder(_imagePaths.icAddEmailForward) - ..key(const Key('button_add_emails_forward_creator')) - ..decoration(BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: AppColor.colorTextButton)) - ..paddingIcon(const EdgeInsets.only(right: 8)) - ..iconColor(Colors.white) - ..maxWidth(130) - ..size(20) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric(vertical: 12)) - ..textStyle(const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.w500, - )) - ..onPressActionClick(() => controller.addEmailForwards(context)) - ..text( - AppLocalizations.of(context).addEmailForward, - isVertical: false, - )) - .build(); - } else { - return (ButtonBuilder(_imagePaths.icAddEmailForward) - ..key(const Key('button_add_emails_forward_creator')) - ..decoration(BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: AppColor.colorTextButton)) - ..paddingIcon(const EdgeInsets.only(right: 8)) - ..iconColor(Colors.white) - ..size(20) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric(vertical: 12)) - ..textStyle(const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.w500, - )) - ..onPressActionClick(() => controller.addEmailForwards(context)) - ..text( - AppLocalizations.of(context).addEmailForward, - isVertical: false, - )) - .build(); - } - } - -} \ No newline at end of file diff --git a/lib/features/manage_account/data/datasource/manage_account_datasource.dart b/lib/features/manage_account/data/datasource/manage_account_datasource.dart index 5fad38cad..2cb7dd6d0 100644 --- a/lib/features/manage_account/data/datasource/manage_account_datasource.dart +++ b/lib/features/manage_account/data/datasource/manage_account_datasource.dart @@ -6,6 +6,7 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/mail/vacation/vacation_response.dart'; import 'package:rule_filter/rule_filter/tmail_rule.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/delete_email_rule_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.dart'; @@ -40,4 +41,7 @@ abstract class ManageAccountDataSource { Future> updateVacation(AccountId accountId, VacationResponse vacationResponse); Future deleteRecipientInForwarding(AccountId accountId, DeleteRecipientInForwardingRequest deleteRequest); + + Future addRecipientsInForwarding(AccountId accountId, AddRecipientInForwardingRequest addRequest); + } \ No newline at end of file diff --git a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart index 6118dcf30..44975f0c1 100644 --- a/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart +++ b/lib/features/manage_account/data/datasource_impl/manage_account_datasource_impl.dart @@ -9,6 +9,7 @@ import 'package:rule_filter/rule_filter/tmail_rule.dart'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; import 'package:tmail_ui_user/features/manage_account/data/local/language_cache_manager.dart'; import 'package:tmail_ui_user/features/manage_account/data/network/manage_account_api.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/delete_email_rule_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.dart'; @@ -145,4 +146,13 @@ class ManageAccountDataSourceImpl extends ManageAccountDataSource { throw error; }); } + + @override + Future addRecipientsInForwarding(AccountId accountId, AddRecipientInForwardingRequest addRequest) { + return Future.sync(() async { + return await manageAccountAPI.updateForward(accountId, addRequest.newTMailForward); + }).catchError((error) { + throw error; + }); + } } \ No newline at end of file diff --git a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart index 7b4ed84b0..364443af9 100644 --- a/lib/features/manage_account/data/repository/manage_account_repository_impl.dart +++ b/lib/features/manage_account/data/repository/manage_account_repository_impl.dart @@ -7,6 +7,7 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/mail/vacation/vacation_response.dart'; import 'package:rule_filter/rule_filter/tmail_rule.dart'; import 'package:tmail_ui_user/features/manage_account/data/datasource/manage_account_datasource.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/delete_email_rule_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.dart'; @@ -88,7 +89,7 @@ class ManageAccountRepositoryImpl extends ManageAccountRepository { } @override - Future updateForward(AccountId accountId, TMailForward forward) { - return dataSource.updateForward(accountId, forward); + Future addRecipientsInForwarding(AccountId accountId, AddRecipientInForwardingRequest addRequest) { + return dataSource.addRecipientsInForwarding(accountId, addRequest); } } \ No newline at end of file diff --git a/lib/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart b/lib/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart new file mode 100644 index 000000000..57694b05c --- /dev/null +++ b/lib/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart @@ -0,0 +1,23 @@ +import 'package:equatable/equatable.dart'; +import 'package:forward/forward/tmail_forward.dart'; + +class AddRecipientInForwardingRequest with EquatableMixin { + final TMailForward currentForward; + final Set listRecipientAdded; + + AddRecipientInForwardingRequest({ + required this.currentForward, + required this.listRecipientAdded, + }); + + TMailForward get newTMailForward { + final newListRecipients = currentForward.forwards + .where((recipient) => !listRecipientAdded.contains(recipient)) + .toSet(); + newListRecipients.addAll(listRecipientAdded); + return currentForward.copyWith(forwards: newListRecipients); + } + + @override + List get props => [currentForward, listRecipientAdded]; +} \ No newline at end of file diff --git a/lib/features/manage_account/domain/repository/manage_account_repository.dart b/lib/features/manage_account/domain/repository/manage_account_repository.dart index e058eca74..bbb182c7d 100644 --- a/lib/features/manage_account/domain/repository/manage_account_repository.dart +++ b/lib/features/manage_account/domain/repository/manage_account_repository.dart @@ -6,6 +6,7 @@ import 'package:jmap_dart_client/jmap/core/properties/properties.dart'; import 'package:jmap_dart_client/jmap/identities/identity.dart'; import 'package:jmap_dart_client/jmap/mail/vacation/vacation_response.dart'; import 'package:rule_filter/rule_filter/tmail_rule.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_identity_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/delete_email_rule_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/create_new_email_rule_filter_request.dart'; @@ -40,4 +41,6 @@ abstract class ManageAccountRepository { Future> updateVacation(AccountId accountId, VacationResponse vacationResponse); Future deleteRecipientInForwarding(AccountId accountId, DeleteRecipientInForwardingRequest deleteRequest); + + Future addRecipientsInForwarding(AccountId accountId, AddRecipientInForwardingRequest addRequest); } \ No newline at end of file diff --git a/lib/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart b/lib/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart new file mode 100644 index 000000000..b47b00b55 --- /dev/null +++ b/lib/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart @@ -0,0 +1,21 @@ +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:forward/forward/tmail_forward.dart'; + +class AddRecipientsInForwardingSuccess extends UIState { + final TMailForward forward; + + AddRecipientsInForwardingSuccess(this.forward); + + @override + List get props => [forward]; +} + +class AddRecipientsInForwardingFailure extends FeatureFailure { + final dynamic exception; + + AddRecipientsInForwardingFailure(this.exception); + + @override + List get props => [exception]; +} \ No newline at end of file diff --git a/lib/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart b/lib/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart new file mode 100644 index 000000000..5e904f180 --- /dev/null +++ b/lib/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart @@ -0,0 +1,28 @@ +import 'dart:core'; + +import 'package:core/presentation/state/failure.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:dartz/dartz.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart'; + +class AddRecipientsInForwardingInteractor { + final ManageAccountRepository manageAccountRepository; + + AddRecipientsInForwardingInteractor(this.manageAccountRepository); + + Stream> execute( + AccountId accountId, + AddRecipientInForwardingRequest addRequest, + ) async* { + try { + yield Right(LoadingState()); + final result = await manageAccountRepository.addRecipientsInForwarding(accountId, addRequest); + yield Right(AddRecipientsInForwardingSuccess(result)); + } catch (exception) { + yield Left(AddRecipientsInForwardingFailure(exception)); + } + } +} diff --git a/lib/features/manage_account/presentation/forward/forward_bindings.dart b/lib/features/manage_account/presentation/forward/forward_bindings.dart index d7aefb41e..08d4e4ab0 100644 --- a/lib/features/manage_account/presentation/forward/forward_bindings.dart +++ b/lib/features/manage_account/presentation/forward/forward_bindings.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import 'package:tmail_ui_user/features/base/base_bindings.dart'; import 'package:tmail_ui_user/features/manage_account/domain/repository/manage_account_repository.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/delete_recipient_in_forwarding_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_forward_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; @@ -12,6 +13,7 @@ class ForwardBindings extends BaseBindings { Get.lazyPut(() => ForwardController( Get.find(), Get.find(), + Get.find(), )); } @@ -25,6 +27,7 @@ class ForwardBindings extends BaseBindings { void bindingsInteractor() { Get.lazyPut(() => GetForwardInteractor(Get.find())); Get.lazyPut(() => DeleteRecipientInForwardingInteractor(Get.find())); + Get.lazyPut(() => AddRecipientsInForwardingInteractor(Get.find())); } @override diff --git a/lib/features/manage_account/presentation/forward/forward_controller.dart b/lib/features/manage_account/presentation/forward/forward_controller.dart index f60f9c11b..b56c0192d 100644 --- a/lib/features/manage_account/presentation/forward/forward_controller.dart +++ b/lib/features/manage_account/presentation/forward/forward_controller.dart @@ -4,19 +4,24 @@ import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/views/bottom_popup/confirmation_dialog_action_sheet_builder.dart'; import 'package:core/presentation/views/dialog/confirmation_dialog_builder.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:forward/forward/tmail_forward.dart'; import 'package:get/get.dart'; +import 'package:model/extensions/email_address_extension.dart'; import 'package:model/mailbox/select_mode.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/model/add_recipients_in_forwarding_request.dart'; import 'package:tmail_ui_user/features/manage_account/domain/model/delete_recipient_in_forwarding_request.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/state/add_recipient_in_forwarding_state.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/delete_recipient_in_forwarding_state.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -import 'package:tmail_ui_user/features/base/base_controller.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/model/mails_forward_creator_arguments.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/model/mails_forward_creator_arguments.dart'; import 'package:tmail_ui_user/features/manage_account/domain/state/get_forward_state.dart'; +import 'package:tmail_ui_user/features/manage_account/domain/usecases/add_recipients_in_forwarding_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/delete_recipient_in_forwarding_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_forward_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/tmail_forward_extension.dart'; @@ -30,8 +35,9 @@ class ForwardController extends BaseController { final GetForwardInteractor _getForwardInteractor; final DeleteRecipientInForwardingInteractor _deleteRecipientInForwardingInteractor; + final AddRecipientsInForwardingInteractor _addRecipientsInForwardingInteractor; - final _accountDashBoardController = Get.find(); + final accountDashBoardController = Get.find(); final _responsiveUtils = Get.find(); final _imagePaths = Get.find(); final _appToast = Get.find(); @@ -41,9 +47,12 @@ class ForwardController extends BaseController { TMailForward? currentForward; + final listForwards = [].obs; + ForwardController( this._getForwardInteractor, this._deleteRecipientInForwardingInteractor, + this._addRecipientsInForwardingInteractor, ); @override @@ -60,6 +69,8 @@ class ForwardController extends BaseController { listRecipientForward.value = currentForward!.listRecipientForward; } else if (success is DeleteRecipientInForwardingSuccess) { _handleDeleteRecipientSuccess(success); + } else if (success is AddRecipientsInForwardingSuccess) { + _handleAddRecipientsSuccess(success); } }); } @@ -74,7 +85,7 @@ class ForwardController extends BaseController { } void _getForward() { - consumeState(_getForwardInteractor.execute(_accountDashBoardController.accountId.value!)); + consumeState(_getForwardInteractor.execute(accountDashBoardController.accountId.value!)); } void deleteRecipients(BuildContext context, String emailAddress) { @@ -116,7 +127,7 @@ class ForwardController extends BaseController { void _handleDeleteRecipientAction(Set listRecipients) { popBack(); - final accountId = _accountDashBoardController.accountId.value; + final accountId = accountDashBoardController.accountId.value; if (accountId != null && currentForward != null) { consumeState(_deleteRecipientInForwardingInteractor.execute( accountId, @@ -217,19 +228,48 @@ class ForwardController extends BaseController { } void goToAddEmailsForward() async { - final accountId = _accountDashBoardController.accountId.value; + final accountId = accountDashBoardController.accountId.value; if (accountId != null) { - final listEmail = await push( - AppRoutes.EMAILS_FORWARD_CREATOR, - arguments: MailsForwardCreatorArguments(accountId, _accountDashBoardController.sessionCurrent.value)); + if(kIsWeb) { + _openMailsForwardCreatorOverlay(); + } else { + final listEmail = await push( + AppRoutes.EMAILS_FORWARD_CREATOR, + arguments: MailsForwardCreatorArguments(accountId, accountDashBoardController.sessionCurrent.value)); - if (listEmail is List) { - _addEmailsForward(listEmail); + if (listEmail is List) { + handleAddRecipients(listEmail); + } } } } - void _addEmailsForward(List listEmailAddress) { + void _openMailsForwardCreatorOverlay() { + EmailsForwardCreatorBindings().dependencies(); + accountDashBoardController.emailsForwardCreatorIsActive.toggle(); + } + void handleAddRecipients(List listEmailAddress) { + final accountId = accountDashBoardController.accountId.value; + final listRecipients = listEmailAddress.map((e) => e.emailAddress).toSet(); + if (accountId != null && currentForward != null) { + consumeState(_addRecipientsInForwardingInteractor.execute( + accountId, + AddRecipientInForwardingRequest( + currentForward: currentForward!, + listRecipientAdded: listRecipients))); + } + } + + void _handleAddRecipientsSuccess(AddRecipientsInForwardingSuccess success) { + if (currentOverlayContext != null && currentContext != null) { + _appToast.showToastWithIcon( + currentOverlayContext!, + message: AppLocalizations.of(currentContext!).toastMessageAddRecipientsSuccessfully, + icon: _imagePaths.icSelected); + } + + currentForward = success.forward; + listRecipientForward.value = currentForward!.listRecipientForward; } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/widgets/forward_header_widget.dart b/lib/features/manage_account/presentation/forward/widgets/forward_header_widget.dart index 7266a0848..f3982a47d 100644 --- a/lib/features/manage_account/presentation/forward/widgets/forward_header_widget.dart +++ b/lib/features/manage_account/presentation/forward/widgets/forward_header_widget.dart @@ -42,49 +42,49 @@ class ForwardHeaderWidget extends StatelessWidget { Widget _buildButtonAddNewEmailsForward(BuildContext context) { if (!responsiveUtils.isMobile(context)) { return (ButtonBuilder(imagePaths.icAddEmailForward) - ..key(const Key('button_add_emails_forward')) - ..decoration(BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: AppColor.colorTextButton)) - ..paddingIcon(const EdgeInsets.only(right: 8)) - ..iconColor(Colors.white) - ..maxWidth(130) - ..size(20) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric(vertical: 12)) - ..textStyle(const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.w500, - )) - ..onPressActionClick(() => addEmailForward.call()) - ..text( - AppLocalizations.of(context).addEmailForward, - isVertical: false, - )) - .build(); + ..key(const Key('button_add_emails_forward')) + ..decoration(BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppColor.colorTextButton)) + ..paddingIcon(const EdgeInsets.only(right: 8)) + ..iconColor(Colors.white) + ..maxWidth(170) + ..size(20) + ..radiusSplash(10) + ..padding(const EdgeInsets.symmetric(vertical: 12)) + ..textStyle(const TextStyle( + fontSize: 17, + color: Colors.white, + fontWeight: FontWeight.w500, + )) + ..onPressActionClick(() => addEmailForward.call()) + ..text( + AppLocalizations.of(context).addRecipients, + isVertical: false, + )) + .build(); } else { return (ButtonBuilder(imagePaths.icAddEmailForward) - ..key(const Key('button_add_emails_forward')) - ..decoration(BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: AppColor.colorTextButton)) - ..paddingIcon(const EdgeInsets.only(right: 8)) - ..iconColor(Colors.white) - ..size(20) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric(vertical: 12)) - ..textStyle(const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.w500, - )) - ..onPressActionClick(() => addEmailForward.call()) - ..text( - AppLocalizations.of(context).addEmailForward, - isVertical: false, - )) - .build(); + ..key(const Key('button_add_emails_forward')) + ..decoration(BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: AppColor.colorTextButton)) + ..paddingIcon(const EdgeInsets.only(right: 8)) + ..iconColor(Colors.white) + ..size(20) + ..radiusSplash(10) + ..padding(const EdgeInsets.symmetric(vertical: 12)) + ..textStyle(const TextStyle( + fontSize: 17, + color: Colors.white, + fontWeight: FontWeight.w500, + )) + ..onPressActionClick(() => addEmailForward.call()) + ..text( + AppLocalizations.of(context).addRecipients, + isVertical: false, + )) + .build(); } } } diff --git a/lib/features/manage_account/presentation/forward/widgets/list_email_forward_widget.dart b/lib/features/manage_account/presentation/forward/widgets/list_email_forward_widget.dart index c0bdf988a..0cdd0a079 100644 --- a/lib/features/manage_account/presentation/forward/widgets/list_email_forward_widget.dart +++ b/lib/features/manage_account/presentation/forward/widgets/list_email_forward_widget.dart @@ -44,7 +44,7 @@ class ListEmailForwardsWidget extends GetWidget { : const EdgeInsets.symmetric(vertical: 13, horizontal: 24), child: Row(children: [ Expanded(child: Text( - AppLocalizations.of(context).headerEmailsForward, + AppLocalizations.of(context).headerRecipients, overflow: CommonTextStyle.defaultTextOverFlow, softWrap: CommonTextStyle.defaultSoftWrap, style: const TextStyle( diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart index decd800d1..a601449d3 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_controller.dart @@ -45,6 +45,8 @@ class ManageAccountDashBoardController extends ReloadableController { final sessionCurrent = Rxn(); final vacationResponse = Rxn(); + final emailsForwardCreatorIsActive = false.obs; + ManageAccountDashBoardController( LogoutOidcInteractor logoutOidcInteractor, DeleteAuthorityOidcInteractor deleteAuthorityOidcInteractor, diff --git a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart index 2774d9e84..1168a4e6e 100644 --- a/lib/features/manage_account/presentation/manage_account_dashboard_view.dart +++ b/lib/features/manage_account/presentation/manage_account_dashboard_view.dart @@ -3,6 +3,7 @@ import 'package:core/core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_view.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mixin/user_setting_popup_menu_mixin.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/extensions/vacation_response_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/vacation/widgets/vacation_notification_message_widget.dart'; @@ -33,136 +34,144 @@ class ManageAccountDashBoardView extends GetWidget FocusScope.of(context).unfocus(), - child: ResponsiveWidget( - responsiveUtils: _responsiveUtils, - desktop: Column(children: [ - Row(children: [ - Container(width: 256, color: Colors.white, - padding: const EdgeInsets.only(top: 25, bottom: 25, left: 32), - child: Row(children: [ - (SloganBuilder(arrangedByHorizontal: true) - ..setSloganText(AppLocalizations.of(context).app_name) - ..setSloganTextAlign(TextAlign.center) - ..setSloganTextStyle(const TextStyle(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)) - ..setSizeLogo(24) - ..addOnTapCallback(() => controller.backToMailboxDashBoard(context)) - ..setLogo(_imagePaths.icLogoTMail)) - .build(), - Obx(() { - if (controller.appInformation.value != null) { - return Padding(padding: const EdgeInsets.only(top: 6), - child: Text( - 'v.${controller.appInformation.value!.version}', - textAlign: TextAlign.center, - style: const TextStyle(fontSize: 13, color: AppColor.colorContentEmail, fontWeight: FontWeight.w500), - )); - } else { - return const SizedBox.shrink(); - } - }), - ]) - ), - Expanded(child: Padding( - padding: const EdgeInsets.only(right: 10, top: 16, bottom: 10, left: 48), - child: _buildRightHeader(context))) - ]), - Expanded(child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(child: ManageAccountMenuView(), width: _responsiveUtils.defaultSizeMenu), - Expanded(child: Container( - color: AppColor.colorBgDesktop, - child: Column(children: [ - Obx(() { - if (controller.vacationResponse.value?.vacationResponderIsValid == true) { - return VacationNotificationMessageWidget( - margin: const EdgeInsets.only( - top: 16, - left: BuildUtils.isWeb ? 24 : 16, - right: BuildUtils.isWeb ? 24 : 16), - vacationResponse: controller.vacationResponse.value!, - action: () => controller.disableVacationResponder()); - } else if ((controller.vacationResponse.value?.vacationResponderIsWaiting == true - || controller.vacationResponse.value?.vacationResponderIsStopped == true) - && controller.accountMenuItemSelected.value == AccountMenuItem.vacation) { - return VacationNotificationMessageWidget( - margin: const EdgeInsets.only( - top: 16, - left: BuildUtils.isWeb ? 24 : 16, - right: BuildUtils.isWeb ? 24 : 16), - vacationResponse: controller.vacationResponse.value!, - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - backgroundColor: Colors.yellow, - fontWeight: FontWeight.normal, - leadingIcon: const Padding( - padding: EdgeInsets.only(right: 16), - child: Icon(Icons.timer, size: 20), - )); - } else { - return const SizedBox.shrink(); - } - }), - Expanded(child: _viewDisplayedOfAccountMenuItem()) + return Obx( + () => Stack( + children: [ + Scaffold( + key: controller.menuDrawerKey, + backgroundColor: Colors.white, + drawer: ResponsiveWidget( + responsiveUtils: _responsiveUtils, + mobile: SizedBox(child: ManageAccountMenuView(), width: ResponsiveUtils.defaultSizeDrawer), + desktop: const SizedBox.shrink() + ), + drawerEnableOpenDragGesture: !_responsiveUtils.isDesktop(context), + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: ResponsiveWidget( + responsiveUtils: _responsiveUtils, + desktop: Column(children: [ + Row(children: [ + Container(width: 256, color: Colors.white, + padding: const EdgeInsets.only(top: 25, bottom: 25, left: 32), + child: Row(children: [ + (SloganBuilder(arrangedByHorizontal: true) + ..setSloganText(AppLocalizations.of(context).app_name) + ..setSloganTextAlign(TextAlign.center) + ..setSloganTextStyle(const TextStyle(color: Colors.black, fontSize: 20, fontWeight: FontWeight.bold)) + ..setSizeLogo(24) + ..addOnTapCallback(() => controller.backToMailboxDashBoard(context)) + ..setLogo(_imagePaths.icLogoTMail)) + .build(), + Obx(() { + if (controller.appInformation.value != null) { + return Padding(padding: const EdgeInsets.only(top: 6), + child: Text( + 'v.${controller.appInformation.value!.version}', + textAlign: TextAlign.center, + style: const TextStyle(fontSize: 13, color: AppColor.colorContentEmail, fontWeight: FontWeight.w500), + )); + } else { + return const SizedBox.shrink(); + } + }), + ]) + ), + Expanded(child: Padding( + padding: const EdgeInsets.only(right: 10, top: 16, bottom: 10, left: 48), + child: _buildRightHeader(context))) ]), - )) - ], - )) - ]), - mobile: SafeArea( - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: !BuildUtils.isWeb && _responsiveUtils.isPortraitMobile(context) - ? const EdgeInsets.only(left: 4, right: 8) - : const EdgeInsets.only(top: 16, left: 24, right: 32), - child: _buildAppbar(context)), - Obx(() { - if (controller.vacationResponse.value?.vacationResponderIsValid == true) { - return VacationNotificationMessageWidget( - margin: const EdgeInsets.only( - left: BuildUtils.isWeb ? 24 : 16, - right: BuildUtils.isWeb ? 24 : 16, - top: BuildUtils.isWeb ? 16 : 0), - vacationResponse: controller.vacationResponse.value!, - action: () => controller.disableVacationResponder()); - } else if ((controller.vacationResponse.value?.vacationResponderIsWaiting == true - || controller.vacationResponse.value?.vacationResponderIsStopped == true) - && controller.accountMenuItemSelected.value == AccountMenuItem.vacation) { - return VacationNotificationMessageWidget( - margin: const EdgeInsets.only( - left: BuildUtils.isWeb ? 24 : 16, - right: BuildUtils.isWeb ? 24 : 16, - top: BuildUtils.isWeb ? 16 : 0), - vacationResponse: controller.vacationResponse.value!, - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - fontWeight: FontWeight.normal, - backgroundColor: Colors.yellow, - leadingIcon: const Padding( - padding: EdgeInsets.only(right: 16), - child: Icon(Icons.timer, size: 20), - )); - } else { - return const SizedBox.shrink(); - } - }), - Expanded(child: Padding( - padding: !BuildUtils.isWeb && _responsiveUtils.isPortraitMobile(context) - ? const EdgeInsets.only(left: 8) - : const EdgeInsets.only(left: 24), - child: _viewDisplayedOfAccountMenuItem())) - ]) - ) - ), + Expanded(child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(child: ManageAccountMenuView(), width: _responsiveUtils.defaultSizeMenu), + Expanded(child: Container( + color: AppColor.colorBgDesktop, + child: Column(children: [ + Obx(() { + if (controller.vacationResponse.value?.vacationResponderIsValid == true) { + return VacationNotificationMessageWidget( + margin: const EdgeInsets.only( + top: 16, + left: BuildUtils.isWeb ? 24 : 16, + right: BuildUtils.isWeb ? 24 : 16), + vacationResponse: controller.vacationResponse.value!, + action: () => controller.disableVacationResponder()); + } else if ((controller.vacationResponse.value?.vacationResponderIsWaiting == true + || controller.vacationResponse.value?.vacationResponderIsStopped == true) + && controller.accountMenuItemSelected.value == AccountMenuItem.vacation) { + return VacationNotificationMessageWidget( + margin: const EdgeInsets.only( + top: 16, + left: BuildUtils.isWeb ? 24 : 16, + right: BuildUtils.isWeb ? 24 : 16), + vacationResponse: controller.vacationResponse.value!, + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), + backgroundColor: Colors.yellow, + fontWeight: FontWeight.normal, + leadingIcon: const Padding( + padding: EdgeInsets.only(right: 16), + child: Icon(Icons.timer, size: 20), + )); + } else { + return const SizedBox.shrink(); + } + }), + Expanded(child: _viewDisplayedOfAccountMenuItem()) + ]), + )) + ], + )) + ]), + mobile: SafeArea( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: !BuildUtils.isWeb && _responsiveUtils.isPortraitMobile(context) + ? const EdgeInsets.only(left: 4, right: 8) + : const EdgeInsets.only(top: 16, left: 24, right: 32), + child: _buildAppbar(context)), + Obx(() { + if (controller.vacationResponse.value?.vacationResponderIsValid == true) { + return VacationNotificationMessageWidget( + margin: const EdgeInsets.only( + left: BuildUtils.isWeb ? 24 : 16, + right: BuildUtils.isWeb ? 24 : 16, + top: BuildUtils.isWeb ? 16 : 0), + vacationResponse: controller.vacationResponse.value!, + action: () => controller.disableVacationResponder()); + } else if ((controller.vacationResponse.value?.vacationResponderIsWaiting == true + || controller.vacationResponse.value?.vacationResponderIsStopped == true) + && controller.accountMenuItemSelected.value == AccountMenuItem.vacation) { + return VacationNotificationMessageWidget( + margin: const EdgeInsets.only( + left: BuildUtils.isWeb ? 24 : 16, + right: BuildUtils.isWeb ? 24 : 16, + top: BuildUtils.isWeb ? 16 : 0), + vacationResponse: controller.vacationResponse.value!, + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), + fontWeight: FontWeight.normal, + backgroundColor: Colors.yellow, + leadingIcon: const Padding( + padding: EdgeInsets.only(right: 16), + child: Icon(Icons.timer, size: 20), + )); + } else { + return const SizedBox.shrink(); + } + }), + Expanded(child: Padding( + padding: !BuildUtils.isWeb && _responsiveUtils.isPortraitMobile(context) + ? const EdgeInsets.only(left: 8) + : const EdgeInsets.only(left: 24), + child: _viewDisplayedOfAccountMenuItem())) + ]) + ) + ), + ), + ), + if(controller.emailsForwardCreatorIsActive.isTrue) + EmailsForwardCreatorView(), + ] , ), ); } diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 77317d6c6..406f8055e 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-08-19T13:28:03.023650", + "@@last_modified": "2022-08-20T20:59:54.192845", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -2065,5 +2065,23 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "addEmailForward": "Add Email", + "@addEmailForward": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "emailForwardLabel": "Name or Email address", + "@emailForwardLabel": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "toastMessageAddRecipientsSuccessfully": "The emails has been added from the recipient list.", + "@toastMessageAddRecipientsSuccessfully": { + "type": "text", + "placeholders_order": [], + "placeholders": {} } } \ No newline at end of file diff --git a/lib/main/localizations/app_localizations.dart b/lib/main/localizations/app_localizations.dart index cf3fa2526..6cfc14330 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -1946,10 +1946,10 @@ class AppLocalizations { name: 'yourFilterHasBeenUpdated'); } - String get headerEmailsForward { + String get headerRecipients { return Intl.message( - 'Emails forward', - name: 'headerEmailsForward', + 'Recipients', + name: 'headerRecipients', ); } @@ -2134,17 +2134,23 @@ class AppLocalizations { ); } - String get addEmailForward { + String get addRecipients { return Intl.message( - 'Add Email', - name: 'addEmailForward', + 'Add Recipients', + name: 'addRecipients', ); } - String get emailForwardLabel { + String get recipientsLabel { return Intl.message( 'Name or Email address', - name: 'emailForwardLabel', + name: 'recipientsLabel', ); } + + String get toastMessageAddRecipientsSuccessfully { + return Intl.message( + 'The emails has been added from the recipient list.', + name: 'toastMessageAddRecipientsSuccessfully'); + } } \ No newline at end of file diff --git a/lib/main/pages/app_pages.dart b/lib/main/pages/app_pages.dart index 27744beb0..f6a9aa82c 100644 --- a/lib/main/pages/app_pages.dart +++ b/lib/main/pages/app_pages.dart @@ -9,8 +9,8 @@ import 'package:tmail_ui_user/features/home/presentation/home_bindings.dart'; import 'package:tmail_ui_user/features/home/presentation/home_view.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_bindings.dart'; import 'package:tmail_ui_user/features/identity_creator/presentation/identity_creator_view.dart' deferred as identity_creator; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/emails_forward_creator_binding.dart'; -import 'package:tmail_ui_user/features/mails_forward_creator/presentation/emails_forward_creator_view.dart' deferred as emails_forward_creator; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_binding.dart'; +import 'package:tmail_ui_user/features/emails_forward_creator/presentation/emails_forward_creator_view.dart' deferred as emails_forward_creator; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_bindings.dart'; import 'package:tmail_ui_user/features/rules_filter_creator/presentation/rules_filter_creator_view.dart' deferred as rules_filter_creator; import 'package:tmail_ui_user/features/login/presentation/login_bindings.dart'; diff --git a/lib/main/routes/app_routes.dart b/lib/main/routes/app_routes.dart index be0ad996e..8ea883e19 100644 --- a/lib/main/routes/app_routes.dart +++ b/lib/main/routes/app_routes.dart @@ -12,4 +12,5 @@ abstract class AppRoutes { static const MANAGE_ACCOUNT = '$MAILBOX_DASHBOARD/manage_account'; static const IDENTITY_CREATOR = '$MANAGE_ACCOUNT/identity_creator'; static const RULES_FILTER_CREATOR = '$MANAGE_ACCOUNT/rules_filter_creator'; + static const EMAILS_FORWARD_CREATOR = '$MANAGE_ACCOUNT/emails_forward_creator'; } \ No newline at end of file diff --git a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart index 3eac6cc39..2d60a94ff 100644 --- a/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart +++ b/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.mocks.dart @@ -1,8 +1,7 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.0.17 from annotations // in tmail_ui_user/test/features/thread/domain/usecases/get_emails_in_mailbox_interactor_test.dart. // Do not manually edit this file. -// ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; @@ -25,7 +24,6 @@ import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dar import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' as _i2; -// ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references diff --git a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart index c1b487099..ad6b718d8 100644 --- a/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart +++ b/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.mocks.dart @@ -1,8 +1,7 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.0.17 from annotations // in tmail_ui_user/test/features/thread/domain/usecases/refresh_changes_emails_in_mailbox_interactor_test.dart. // Do not manually edit this file. -// ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; import 'package:jmap_dart_client/jmap/account_id.dart' as _i5; @@ -25,7 +24,6 @@ import 'package:tmail_ui_user/features/thread/domain/model/get_email_request.dar import 'package:tmail_ui_user/features/thread/domain/repository/thread_repository.dart' as _i2; -// ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references