From b153de5c908f0d8bb4d9d7af3e7bd1064697f386 Mon Sep 17 00:00:00 2001 From: dab246 Date: Fri, 4 Nov 2022 00:33:59 +0700 Subject: [PATCH] TF-1118 Apply new design for Forwarding on web --- assets/images/ic_cancel_selection.svg | 3 + .../extensions/color_extension.dart | 5 +- .../extensions/string_extension.dart | 13 +- .../presentation/resources/image_paths.dart | 1 + .../mixin/message_dialog_action_mixin.dart | 27 ++- .../validator_failure_extension.dart | 10 + .../extensions/tmail_forward_extension.dart | 3 +- .../forward/bindings/forward_bindings.dart | 4 +- .../forward_recipient_controller.dart | 97 +++++++++ .../forward/forward_controller.dart | 192 +++++++++--------- .../presentation/forward/forward_view.dart | 175 ++++++++++++++-- .../widgets/email_forward_item_widget.dart | 120 +++++++---- .../email_forward_item_widget_for_web.dart | 148 ++++++++++---- .../widgets/forward_header_widget.dart | 117 +++-------- .../widgets/list_email_forward_widget.dart | 171 ++++++++-------- .../recipient_input_decoration_builder.dart | 41 ++++ .../recipient_input_field_builder.dart | 81 ++++++++ .../presentation/menu/settings_utils.dart | 51 ++++- .../presentation/model/recipient_forward.dart | 5 +- .../presentation/profiles/profiles_view.dart | 12 +- lib/l10n/intl_messages.arb | 42 +++- lib/main/localizations/app_localizations.dart | 32 ++- 22 files changed, 936 insertions(+), 414 deletions(-) create mode 100644 assets/images/ic_cancel_selection.svg create mode 100644 lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart create mode 100644 lib/features/manage_account/presentation/forward/widgets/recipient_input_decoration_builder.dart create mode 100644 lib/features/manage_account/presentation/forward/widgets/recipient_input_field_builder.dart diff --git a/assets/images/ic_cancel_selection.svg b/assets/images/ic_cancel_selection.svg new file mode 100644 index 000000000..9f3afc68c --- /dev/null +++ b/assets/images/ic_cancel_selection.svg @@ -0,0 +1,3 @@ + + + diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 77d34b6aa..4c038291a 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -133,7 +133,7 @@ extension AppColor on Color { static const colorBackgroundSnackBar = Color(0xFF343438); static const colorBackgroundHeaderListRuleFilter = Color(0xFFFAF7F7); static const colorBorderListRuleFilter = Color(0xFFE7E8EC); - static const colorBackgroundHeaderListForwards = Color(0xFFFAF7F7); + static const colorBackgroundHeaderListForwards = Color(0xFFF8F9FA); static const colorBorderListForwardsFilter = Color(0xFFE7E8EC); static const colorBackgroundFieldConditionRulesFilter = Color(0xFFF2F3F5); static const colorDividerRuleFilter = Color(0xFFE7E8EC); @@ -157,6 +157,9 @@ extension AppColor on Color { static const colorDividerDestinationPicker = Color(0x1F000000); static const colorItemAlreadySelected = Color(0xFF818C99); static const colorItemSelected = Color(0xFFF2F3F5); + static const colorBorderSettingContentWeb = Color(0xFFE7E8EC); + static const colorDividerHeaderSetting = Color(0xFFE4E4E4); + static const colorSettingExplanation = Color(0xFF686E76); static const mapGradientColor = [ [Color(0xFF21D4FD), Color(0xFFB721FF)], diff --git a/core/lib/presentation/extensions/string_extension.dart b/core/lib/presentation/extensions/string_extension.dart index d0f234102..f74060f8f 100644 --- a/core/lib/presentation/extensions/string_extension.dart +++ b/core/lib/presentation/extensions/string_extension.dart @@ -19,8 +19,17 @@ extension StringExtension on String { } } else { final regexLetter = RegExp("([A-Za-z])"); - final firstLetter = regexLetter.firstMatch(trim())?.group(0); - return firstLetter != null ? '${firstLetter.toUpperCase()}${firstLetter.toUpperCase()}' : ''; + final listMatch = regexLetter.allMatches(trim()).toList(); + if (listMatch.length > 1) { + final firstLetter = listMatch[0].group(0); + final secondLetter = listMatch[1].group(0); + return firstLetter != null && secondLetter != null + ? '${firstLetter.toUpperCase()}${secondLetter.toUpperCase()}' + : ''; + } else { + final firstLetter = listMatch[0].group(0); + return firstLetter != null ? firstLetter.toUpperCase() : ''; + } } } } \ No newline at end of file diff --git a/core/lib/presentation/resources/image_paths.dart b/core/lib/presentation/resources/image_paths.dart index e08929e29..dc9674b21 100644 --- a/core/lib/presentation/resources/image_paths.dart +++ b/core/lib/presentation/resources/image_paths.dart @@ -169,6 +169,7 @@ class ImagePaths { String get icCreateNewFolder => _getImagePath('ic_create_new_folder.svg'); String get icOlder => _getImagePath('ic_older.svg'); String get icNewer => _getImagePath('ic_newer.svg'); + String get icCancelSelection => _getImagePath('ic_cancel_selection.svg'); String _getImagePath(String imageName) { return AssetsPaths.images + imageName; diff --git a/lib/features/base/mixin/message_dialog_action_mixin.dart b/lib/features/base/mixin/message_dialog_action_mixin.dart index e13e6c891..943e85b92 100644 --- a/lib/features/base/mixin/message_dialog_action_mixin.dart +++ b/lib/features/base/mixin/message_dialog_action_mixin.dart @@ -21,7 +21,12 @@ mixin MessageDialogActionMixin { String? cancelTitle, bool hasCancelButton = true, bool showAsBottomSheet = false, - Widget? icon + Widget? icon, + TextStyle? titleStyle, + TextStyle? actionStyle, + TextStyle? cancelStyle, + Color? actionButtonColor, + Color? cancelButtonColor, } ) { if (_responsiveUtils.isMobile(context)) { @@ -40,16 +45,16 @@ mixin MessageDialogActionMixin { ..addIcon(icon) ..margin(const EdgeInsets.symmetric(vertical: 42, horizontal: 16)) ..widthDialog(_responsiveUtils.getSizeScreenWidth(context)) - ..colorConfirmButton(AppColor.colorTextButton) - ..colorCancelButton(AppColor.colorCancelButton) + ..colorConfirmButton(actionButtonColor ?? AppColor.colorTextButton) + ..colorCancelButton(cancelButtonColor ?? AppColor.colorCancelButton) ..paddingTitle(icon != null ? const EdgeInsets.only(top: 34) : EdgeInsets.zero) ..marginIcon(EdgeInsets.zero) ..paddingContent(const EdgeInsets.only(left: 44, right: 44, bottom: 24, top: 8)) ..paddingButton(hasCancelButton ? null : const EdgeInsets.only(bottom: 16, left: 44, right: 44)) - ..styleTitle(const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black)) + ..styleTitle(titleStyle ?? const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black)) ..styleContent(const TextStyle(fontSize: 14, fontWeight: FontWeight.normal, color: AppColor.colorContentEmail)) - ..styleTextCancelButton(const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton)) - ..styleTextConfirmButton(const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white)) + ..styleTextCancelButton(cancelStyle ?? const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton)) + ..styleTextConfirmButton(actionStyle ?? const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white)) ..onConfirmButtonAction(actionName, () { popBack(); onConfirmAction?.call(); @@ -76,16 +81,16 @@ mixin MessageDialogActionMixin { ..title(title ?? '') ..content(message) ..addIcon(icon) - ..colorConfirmButton(AppColor.colorTextButton) - ..colorCancelButton(AppColor.colorCancelButton) + ..colorConfirmButton(actionButtonColor ?? AppColor.colorTextButton) + ..colorCancelButton(cancelButtonColor ?? AppColor.colorCancelButton) ..paddingTitle(icon != null ? const EdgeInsets.only(top: 34) : EdgeInsets.zero) ..marginIcon(EdgeInsets.zero) ..paddingContent(const EdgeInsets.only(left: 44, right: 44, bottom: 24, top: 8)) ..paddingButton(hasCancelButton ? null : const EdgeInsets.only(bottom: 16, left: 44, right: 44)) - ..styleTitle(const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black)) + ..styleTitle(titleStyle ?? const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black)) ..styleContent(const TextStyle(fontSize: 14, fontWeight: FontWeight.normal, color: AppColor.colorContentEmail)) - ..styleTextCancelButton(const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton)) - ..styleTextConfirmButton(const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white)) + ..styleTextCancelButton(cancelStyle ?? const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: AppColor.colorTextButton)) + ..styleTextConfirmButton(actionStyle ?? const TextStyle(fontSize: 17, fontWeight: FontWeight.w500, color: Colors.white)) ..onConfirmButtonAction(actionName, () { popBack(); onConfirmAction?.call(); diff --git a/lib/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart b/lib/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart index f916e449c..e6483697a 100644 --- a/lib/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart +++ b/lib/features/mailbox_creator/presentation/extensions/validator_failure_extension.dart @@ -50,4 +50,14 @@ extension ValicatorFailureExtension on VerifyNameFailure { return ''; } } + + String getMessageForwarding(BuildContext context) { + if (exception is EmptyNameException) { + return AppLocalizations.of(context).this_field_cannot_be_blank; + } else if (exception is EmailAddressInvalidException) { + return AppLocalizations.of(context).incorrectEmailFormat; + } else { + return ''; + } + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/extensions/tmail_forward_extension.dart b/lib/features/manage_account/presentation/extensions/tmail_forward_extension.dart index 134250fb2..4beac2de5 100644 --- a/lib/features/manage_account/presentation/extensions/tmail_forward_extension.dart +++ b/lib/features/manage_account/presentation/extensions/tmail_forward_extension.dart @@ -1,12 +1,13 @@ import 'package:forward/forward/tmail_forward.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/recipient_forward.dart'; extension TMailForwardExtension on TMailForward { List get listRecipientForward { return forwards - .map((emailAddress) => RecipientForward(emailAddress)) + .map((emailAddress) => RecipientForward(EmailAddress(emailAddress, emailAddress))) .toList(); } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/bindings/forward_bindings.dart b/lib/features/manage_account/presentation/forward/bindings/forward_bindings.dart index c110c80d0..63a7c7406 100644 --- a/lib/features/manage_account/presentation/forward/bindings/forward_bindings.dart +++ b/lib/features/manage_account/presentation/forward/bindings/forward_bindings.dart @@ -1,10 +1,12 @@ import 'package:get/get.dart'; +import 'package:tmail_ui_user/features/mailbox_creator/domain/usecases/verify_name_interactor.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; class ForwardBindings extends Bindings { @override void dependencies() { - Get.lazyPut(() => ForwardController()); + Get.lazyPut(() => VerifyNameInteractor()); + Get.lazyPut(() => ForwardController(Get.find())); } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart b/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart new file mode 100644 index 000000000..07ba4c15a --- /dev/null +++ b/lib/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart @@ -0,0 +1,97 @@ + +import 'package:contact/contact/model/capability_contact.dart'; +import 'package:core/utils/app_logger.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/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; +import 'package:model/autocomplete/auto_complete_pattern.dart'; +import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; +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/mailbox_dashboard/presentation/bindings/contact_autocomplete_bindings.dart'; +import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/bindings/tmail_autocomplete_bindings.dart'; +import 'package:tmail_ui_user/main/error/capability_validator.dart'; + +class ForwardRecipientController { + + final ContactSuggestionSource _contactSuggestionSource = ContactSuggestionSource.tMailContact; + final TextEditingController inputEmailForwardController = TextEditingController(); + + GetAutoCompleteWithDeviceContactInteractor? _getAutoCompleteWithDeviceContactInteractor; + GetAutoCompleteInteractor? _getAutoCompleteInteractor; + AccountId? _accountId; + Session? _session; + EmailAddress? _emailAddressSelected; + + ForwardRecipientController({AccountId? accountId, Session? session}) { + _accountId = accountId; + _session = session; + injectAutoCompleteBindings(_session, _accountId); + } + + EmailAddress? get emailAddressSelected => _emailAddressSelected; + + void onClose() { + clearAll(); + _disposeWidget(); + } + + void injectAutoCompleteBindings(Session? session, AccountId? accountId) { + try { + ContactAutoCompleteBindings().dependencies(); + requireCapability(session!, accountId!, [tmailContactCapabilityIdentifier]); + TMailAutoCompleteBindings().dependencies(); + _getAutoCompleteWithDeviceContactInteractor = Get.find(); + _getAutoCompleteInteractor = Get.find(); + } catch (e) { + logError('ForwardRecipientController::injectAutoCompleteBindings(): exception: $e'); + } + } + + Future> getAutoCompleteSuggestion(String word) async { + log('ForwardRecipientController::getAutoCompleteSuggestion(): $word'); + if (_contactSuggestionSource == ContactSuggestionSource.all) { + if (_getAutoCompleteWithDeviceContactInteractor == null || _getAutoCompleteInteractor == null) { + log('ForwardRecipientController::getAutoCompleteSuggestion(): _getAutoCompleteWithDeviceContactInteractor is NULL'); + return []; + } else { + return await _getAutoCompleteWithDeviceContactInteractor! + .execute(AutoCompletePattern(word: word, accountId: _accountId)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetAutoCompleteSuccess + ? success.listEmailAddress + : [])); + } + } else { + if (_getAutoCompleteInteractor == null) { + log('ForwardRecipientController::getAutoCompleteSuggestion(): _getAutoCompleteInteractor is NULL'); + return []; + } else { + return await _getAutoCompleteInteractor! + .execute(AutoCompletePattern(word: word, accountId: _accountId)) + .then((value) => value.fold( + (failure) => [], + (success) => success is GetAutoCompleteSuccess + ? success.listEmailAddress + : [])); + } + } + } + + void selectEmailAddress(EmailAddress? emailAddress) { + _emailAddressSelected = emailAddress; + } + + void clearAll() { + inputEmailForwardController.clear(); + _emailAddressSelected = null; + } + + void _disposeWidget() { + inputEmailForwardController.dispose(); + } +} \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/forward_controller.dart b/lib/features/manage_account/presentation/forward/forward_controller.dart index 445e0d79c..1f3ea3a25 100644 --- a/lib/features/manage_account/presentation/forward/forward_controller.dart +++ b/lib/features/manage_account/presentation/forward/forward_controller.dart @@ -1,11 +1,7 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; 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:core/utils/app_logger.dart'; -import 'package:core/utils/build_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:forward/forward/tmail_forward.dart'; @@ -13,9 +9,12 @@ import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/account_id.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/model/email_forward_creator_arguments.dart'; +import 'package:tmail_ui_user/features/mailbox_creator/domain/model/verification/email_address_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/state/verify_name_view_state.dart'; +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/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/model/edit_local_copy_in_forwarding_request.dart'; @@ -29,33 +28,39 @@ import 'package:tmail_ui_user/features/manage_account/domain/usecases/delete_rec import 'package:tmail_ui_user/features/manage_account/domain/usecases/edit_local_copy_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'; +import 'package:tmail_ui_user/features/manage_account/presentation/forward/controller/forward_recipient_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/manage_account_dashboard_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/recipient_forward.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'; class ForwardController extends BaseController { + final VerifyNameInteractor _verifyNameInteractor; + GetForwardInteractor? _getForwardInteractor; DeleteRecipientInForwardingInteractor? _deleteRecipientInForwardingInteractor; AddRecipientsInForwardingInteractor? _addRecipientsInForwardingInteractor; EditLocalCopyInForwardingInteractor? _editLocalCopyInForwardingInteractor; final accountDashBoardController = Get.find(); - final _responsiveUtils = Get.find(); final _imagePaths = Get.find(); final _appToast = Get.find(); final selectionMode = Rx(SelectMode.INACTIVE); final listRecipientForward = RxList(); final currentForward = Rxn(); - - final listForwards = [].obs; + final errorRecipientInputText = RxnString(); bool get currentForwardLocalCopyState => currentForward.value?.localCopy ?? false; - ForwardController(); + late ForwardRecipientController recipientController; + + ForwardController(this._verifyNameInteractor) { + recipientController = ForwardRecipientController( + accountId: accountDashBoardController.accountId.value, + session: accountDashBoardController.sessionCurrent.value); + } @override void onInit() { @@ -70,6 +75,12 @@ class ForwardController extends BaseController { } } + @override + void onClose() { + recipientController.onClose(); + super.onClose(); + } + @override void onDone() { viewState.value.fold( @@ -105,39 +116,28 @@ class ForwardController extends BaseController { } void deleteRecipients(BuildContext context, String emailAddress) { - if (_responsiveUtils.isMobile(context)) { - (ConfirmationDialogActionSheetBuilder(context) - ..messageText(AppLocalizations.of(context) - .messageConfirmationDialogDeleteRecipientForward(emailAddress)) - ..onCancelAction(AppLocalizations.of(context).cancel, () => - popBack()) - ..onConfirmAction(AppLocalizations.of(context).delete, () => - _handleDeleteRecipientAction({emailAddress}))) - .show(); - } else { - showDialog( - context: context, - barrierColor: AppColor.colorDefaultCupertinoActionSheet, - builder: (BuildContext context) => - PointerInterceptor(child: (ConfirmDialogBuilder(_imagePaths) - ..title(AppLocalizations.of(context).deleteRecipient) - ..content(AppLocalizations.of(context) - .messageConfirmationDialogDeleteRecipientForward(emailAddress)) - ..addIcon(SvgPicture.asset(_imagePaths.icRemoveDialog, - fit: BoxFit.fill)) - ..marginIcon(EdgeInsets.zero) - ..colorConfirmButton(AppColor.colorConfirmActionDialog) - ..styleTextConfirmButton(const TextStyle( - fontSize: 17, - fontWeight: FontWeight.w500, - color: AppColor.colorActionDeleteConfirmDialog)) - ..onCloseButtonAction(() => popBack()) - ..onConfirmButtonAction(AppLocalizations.of(context).delete, () => - _handleDeleteRecipientAction({emailAddress})) - ..onCancelButtonAction(AppLocalizations.of(context).cancel, () => - popBack())) - .build())); - } + showConfirmDialogAction(currentContext!, + title: AppLocalizations.of(context).deleteRecipient, + AppLocalizations.of(context).messageConfirmationDialogDeleteRecipientForward(emailAddress), + AppLocalizations.of(currentContext!).remove, + onConfirmAction: () => _handleDeleteRecipientAction({emailAddress}), + showAsBottomSheet: true, + icon: SvgPicture.asset(_imagePaths.icDeleteDialogIdentity, fit: BoxFit.fill), + titleStyle: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: AppColor.colorDeletePermanentlyButton), + actionStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: Colors.white), + cancelStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: AppColor.colorTextButton), + actionButtonColor: AppColor.colorDeletePermanentlyButton, + cancelButtonColor: AppColor.colorButtonCancelDialog, + ); } void _handleDeleteRecipientAction(Set listRecipients) { @@ -201,39 +201,28 @@ class ForwardController extends BaseController { } void deleteMultipleRecipients(BuildContext context, Set listEmailAddress) { - if (_responsiveUtils.isMobile(context)) { - (ConfirmationDialogActionSheetBuilder(context) - ..messageText(AppLocalizations.of(context).messageConfirmationDialogDeleteAllRecipientForward) - ..onCancelAction(AppLocalizations.of(context).cancel, () => - popBack()) - ..onConfirmAction(AppLocalizations.of(context).delete, () { - _handleDeleteRecipientAction(listEmailAddress); - })) - .show(); - } else { - showDialog( - context: context, - barrierColor: AppColor.colorDefaultCupertinoActionSheet, - builder: (BuildContext context) => - PointerInterceptor(child: (ConfirmDialogBuilder(_imagePaths) - ..title(AppLocalizations.of(context).deleteRecipient) - ..content(AppLocalizations.of(context).messageConfirmationDialogDeleteAllRecipientForward) - ..addIcon(SvgPicture.asset(_imagePaths.icRemoveDialog, - fit: BoxFit.fill)) - ..marginIcon(EdgeInsets.zero) - ..colorConfirmButton(AppColor.colorConfirmActionDialog) - ..styleTextConfirmButton(const TextStyle( - fontSize: 17, - fontWeight: FontWeight.w500, - color: AppColor.colorActionDeleteConfirmDialog)) - ..onCloseButtonAction(() => popBack()) - ..onConfirmButtonAction(AppLocalizations.of(context).delete, () { - _handleDeleteRecipientAction(listEmailAddress); - }) - ..onCancelButtonAction(AppLocalizations.of(context).cancel, () => - popBack())) - .build())); - } + showConfirmDialogAction(currentContext!, + title: AppLocalizations.of(context).deleteRecipient, + AppLocalizations.of(context).messageConfirmationDialogDeleteAllRecipientForward, + AppLocalizations.of(currentContext!).remove, + onConfirmAction: () => _handleDeleteRecipientAction(listEmailAddress), + showAsBottomSheet: true, + icon: SvgPicture.asset(_imagePaths.icDeleteDialogIdentity, fit: BoxFit.fill), + titleStyle: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: AppColor.colorDeletePermanentlyButton), + actionStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: Colors.white), + cancelStyle: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + color: AppColor.colorTextButton), + actionButtonColor: AppColor.colorDeletePermanentlyButton, + cancelButtonColor: AppColor.colorButtonCancelDialog, + ); } void selectAllRecipientForward() { @@ -246,26 +235,19 @@ class ForwardController extends BaseController { .toList(); } - void goToAddEmailsForward(BuildContext context) async { + void addRecipientAction(BuildContext context) { final accountId = accountDashBoardController.accountId.value; - final session = accountDashBoardController.sessionCurrent.value; - if (accountId != null && session != null) { - final arguments = EmailForwardCreatorArguments(accountId, session); + final emailAddressSelected = recipientController.emailAddressSelected; - if (BuildUtils.isWeb) { - showDialogEmailForwardCreator( - context: context, - arguments: arguments, - onAddEmailForward: (listEmailAddress) => _handleAddRecipients(accountId, listEmailAddress)); - } else { - final newListEmailAddress = await push( - AppRoutes.emailsForwardCreator, - arguments: arguments); + updateErrorRecipientInputText(context, emailAddressSelected?.email); - if (newListEmailAddress is List && newListEmailAddress.isNotEmpty) { - _handleAddRecipients(accountId, newListEmailAddress); - } - } + if (errorRecipientInputText.value != null) { + return; + } + + log('ForwardController::addRecipientAction():emailAddressSelected: $emailAddressSelected'); + if (emailAddressSelected != null && accountId != null) { + _handleAddRecipients(accountId, [emailAddressSelected]); } } @@ -291,6 +273,8 @@ class ForwardController extends BaseController { currentForward.value = success.forward; listRecipientForward.value = currentForward.value!.listRecipientForward; + + recipientController.clearAll(); } void handleEditLocalCopy() { @@ -320,4 +304,24 @@ class ForwardController extends BaseController { currentForward.value = success.forward; listRecipientForward.value = currentForward.value!.listRecipientForward; } + + void updateErrorRecipientInputText(BuildContext context, String? emailAddress) { + errorRecipientInputText.value = _getErrorRecipientInputString(context, emailAddress); + } + + String? _getErrorRecipientInputString(BuildContext context, String? emailAddress) { + return _verifyNameInteractor.execute( + emailAddress, + [EmptyNameValidator(), EmailAddressValidator()] + ).fold( + (failure) { + if (failure is VerifyNameFailure) { + return failure.getMessageForwarding(context); + } else { + return null; + } + }, + (success) => null + ); + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/forward_view.dart b/lib/features/manage_account/presentation/forward/forward_view.dart index 1ca80bae5..87ebfefe5 100644 --- a/lib/features/manage_account/presentation/forward/forward_view.dart +++ b/lib/features/manage_account/presentation/forward/forward_view.dart @@ -1,11 +1,20 @@ -import 'package:core/core.dart'; +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/state/success.dart'; +import 'package:core/presentation/utils/responsive_utils.dart'; +import 'package:core/presentation/utils/style_utils.dart'; +import 'package:core/presentation/views/button/button_builder.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:tmail_ui_user/features/base/mixin/app_loader_mixin.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/widgets/forward_header_widget.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/widgets/list_email_forward_widget.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/forward/widgets/recipient_input_field_builder.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class ForwardView extends GetWidget with AppLoaderMixin { final _responsiveUtils = Get.find(); @@ -16,38 +25,162 @@ class ForwardView extends GetWidget with AppLoaderMixin { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: _responsiveUtils.isWebDesktop(context) - ? AppColor.colorBgDesktop - : Colors.white, + backgroundColor: SettingsUtils.getBackgroundColor(context, _responsiveUtils), body: Container( width: double.infinity, + height: double.infinity, + color: SettingsUtils.getContentBackgroundColor(context, _responsiveUtils), + decoration: SettingsUtils.getBoxDecorationForContent(context, _responsiveUtils), margin: SettingsUtils.getMarginViewForSettingDetails(context, _responsiveUtils), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ForwardHeaderWidget( - imagePaths: _imagePaths, - responsiveUtils: _responsiveUtils, - ), - SizedBox(height: _responsiveUtils.isWebDesktop(context) ? 24 : 16), - _buildLoadingView(), - ListEmailForwardsWidget() - ], - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ForwardHeaderWidget(imagePaths: _imagePaths, responsiveUtils: _responsiveUtils), + Container(height: 1, color: AppColor.colorDividerHeaderSetting), + Expanded(child: SingleChildScrollView( + child: Column(children: [ + _buildLoadingView(), + Obx(() { + if (controller.currentForward.value != null) { + return Column(children: [ + _buildKeepLocalSwitchButton(context), + _buildAddRecipientsFormWidget(context), + ListEmailForwardsWidget() + ]); + } else { + return const SizedBox.shrink(); + } + }) + ]) + )) + ], ), ), ); } + Widget _buildKeepLocalSwitchButton(BuildContext context) { + return Container( + color: Colors.transparent, + padding: const EdgeInsets.only(left: 24, top: 24, right: 24, bottom: 11), + child: Row(children: [ + Obx(() { + return InkWell( + onTap: controller.handleEditLocalCopy, + child: SvgPicture.asset( + controller.currentForwardLocalCopyState + ? _imagePaths.icSwitchOn + : _imagePaths.icSwitchOff, + fit: BoxFit.fill, + width: 24, + height: 24) + ); + }), + const SizedBox(width: 16), + Expanded( + child: Text( + AppLocalizations.of(context).keepLocalCopyForwardLabel, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black) + ), + ) + ]), + ); + } + Widget _buildLoadingView() { return Obx(() => controller.viewState.value.fold( (failure) => const SizedBox.shrink(), (success) => success is LoadingState - ? Padding( - padding: const EdgeInsets.only(bottom: 24), - child: loadingWidget) - : const SizedBox.shrink() + ? Padding( + padding: const EdgeInsets.all(24), + child: loadingWidget) + : const SizedBox.shrink() )); } + + Widget _buildAddRecipientInputField() { + return Obx(() => RecipientInputFieldBuilder( + editingController: controller.recipientController.inputEmailForwardController, + onSelectedSuggestionAction: (newEmailAddress) { + controller.recipientController.selectEmailAddress(newEmailAddress); + controller.recipientController.inputEmailForwardController.text = newEmailAddress.email ?? ''; + }, + onRecipientInputTextChange: (pattern) { + if (pattern.trim().isNotEmpty) { + controller.recipientController.selectEmailAddress(EmailAddress(null, pattern.trim())); + } else { + controller.recipientController.selectEmailAddress(null); + } + controller.errorRecipientInputText.value = null; + }, + onSummitedCallbackAction: (pattern) { + if (pattern.trim().isNotEmpty) { + controller.recipientController.selectEmailAddress(EmailAddress(null, pattern.trim())); + } else { + controller.recipientController.selectEmailAddress(null); + } + }, + onSuggestionCallbackAction: controller.recipientController.getAutoCompleteSuggestion, + errorText: controller.errorRecipientInputText.value, + )); + } + + Widget _buildAddRecipientButton(BuildContext context) { + return (ButtonBuilder(_imagePaths.icAddIdentity) + ..key(const Key('button_add_recipient')) + ..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(() => controller.addRecipientAction(context)) + ..text(AppLocalizations.of(context).addRecipientButton, isVertical: false) + ).build(); + } + + Widget _buildAddRecipientsFormWidget(BuildContext context) { + if (_responsiveUtils.isPortraitMobile(context)) { + return Container( + color: Colors.transparent, + width: double.infinity, + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildAddRecipientInputField(), + const SizedBox(height: 16), + _buildAddRecipientButton(context) + ], + ), + ); + } else { + return Container( + color: Colors.transparent, + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: _buildAddRecipientInputField()), + Padding( + padding: const EdgeInsets.only(left: 24, right: 12), + child: _buildAddRecipientButton(context)) + ], + ), + ); + } + } } diff --git a/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget.dart b/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget.dart index 38a7bb335..159a8ea82 100644 --- a/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget.dart +++ b/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget.dart @@ -2,6 +2,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:model/extensions/email_address_extension.dart'; import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/recipient_forward.dart'; @@ -13,10 +14,12 @@ class EmailForwardItemWidget extends StatelessWidget { final RecipientForward recipientForward; final SelectMode selectionMode; + final bool isLast; EmailForwardItemWidget({ Key? key, required this.recipientForward, + this.isLast = false, this.selectionMode = SelectMode.INACTIVE, }) : super(key: key); @@ -30,32 +33,70 @@ class EmailForwardItemWidget extends StatelessWidget { } }, child: Container( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - color: Colors.white, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: recipientForward.selectMode == SelectMode.ACTIVE + ? AppColor.colorItemEmailSelectedDesktop + : Colors.white, + borderRadius: BorderRadius.only( + bottomLeft: isLast ? const Radius.circular(12) : Radius.zero, + bottomRight: isLast ? const Radius.circular(12) : Radius.zero, + ) + ), child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( - width: 32, - height: 32, - color: Colors.transparent, - alignment: Alignment.center, - child: _buildAvatarIcon()), - const SizedBox(width: 10), - Expanded(child: Text(recipientForward.emailAddress, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Colors.black))), + width: 54, + height: 54, + color: Colors.transparent, + alignment: Alignment.center, + child: _buildAvatarIcon() + ), + const SizedBox(width: 12), + Expanded(child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (recipientForward.emailAddress.displayName.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: Text( + recipientForward.emailAddress.displayName, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black + ) + ), + ), + Text( + recipientForward.emailAddress.email ?? '', + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: AppColor.colorContentEmail + ) + ) + ], + )), + const SizedBox(width: 12), buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icDeleteEmailForward, - fit: BoxFit.fill, - width: 18, - height: 18, - ), - onTap: () => - _emailForwardController.deleteRecipients(context, recipientForward.emailAddress)), + icon: SvgPicture.asset( + _imagePaths.icDeleteEmailForward, + fit: BoxFit.fill, + width: 18, + height: 18, + ), + onTap: () => _emailForwardController.deleteRecipients( + context, + recipientForward.emailAddress.email ?? '' + ) + ), ]), ), ); @@ -64,22 +105,25 @@ class EmailForwardItemWidget extends StatelessWidget { Widget _buildAvatarIcon() { if (selectionMode == SelectMode.ACTIVE) { return Container( - alignment: Alignment.center, - child: SvgPicture.asset( - recipientForward.selectMode == SelectMode.ACTIVE - ? _imagePaths.icSelected - : _imagePaths.icUnSelected, - width: 24, - height: 24)); + alignment: Alignment.center, + child: SvgPicture.asset( + recipientForward.selectMode == SelectMode.ACTIVE + ? _imagePaths.icSelected + : _imagePaths.icUnSelected, + width: 24, + height: 24 + ) + ); } else { - return CircleAvatar( - backgroundColor: AppColor.colorTextButton, - radius: 16, - child: Text(recipientForward.emailAddress[0].toUpperCase(), - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500))); + return (AvatarBuilder() + ..text(recipientForward.emailAddress.asString().firstLetterToUpperCase) + ..size(54) + ..addTextStyle(const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 20, + color: Colors.white)) + ..avatarColor(recipientForward.emailAddress.avatarColors) + ).build(); } } } diff --git a/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget_for_web.dart b/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget_for_web.dart index 221a67989..87d1277dd 100644 --- a/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget_for_web.dart +++ b/lib/features/manage_account/presentation/forward/widgets/email_forward_item_widget_for_web.dart @@ -1,8 +1,14 @@ -import 'package:core/core.dart'; +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/extensions/string_extension.dart'; +import 'package:core/presentation/resources/image_paths.dart'; +import 'package:core/presentation/utils/style_utils.dart'; +import 'package:core/presentation/views/button/icon_button_web.dart'; +import 'package:core/presentation/views/image/avatar_builder.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:html_editor_enhanced/utils/utils.dart'; +import 'package:model/extensions/email_address_extension.dart'; import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/recipient_forward.dart'; @@ -11,10 +17,12 @@ class EmailForwardItemWidget extends StatefulWidget { final RecipientForward recipientForward; final SelectMode selectionMode; + final bool isLast; const EmailForwardItemWidget({ Key? key, required this.recipientForward, + this.isLast = false, this.selectionMode = SelectMode.INACTIVE, }) : super(key: key); @@ -28,48 +36,97 @@ class _EmailForwardItemWidgetState extends State { final _emailForwardController = Get.find(); bool isHoverIcon = false; + bool isHoverItem = false; @override Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16), - color: Colors.white, - child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ - InkWell( - onTap: () { - if (isHoverIcon) { - _emailForwardController.selectRecipientForward(widget.recipientForward); - } - }, - onHover: (value) { - setState(mounted, this.setState, () { - isHoverIcon = value; - }); - }, - child: Container( - width: 32, - height: 32, + return InkWell( + onTap: () => {}, + onHover: (value) { + setState(mounted, this.setState, () { + isHoverItem = value; + }); + }, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: widget.recipientForward.selectMode == SelectMode.ACTIVE + ? AppColor.colorItemEmailSelectedDesktop + : Colors.white, + borderRadius: BorderRadius.only( + bottomLeft: widget.isLast ? const Radius.circular(12) : Radius.zero, + bottomRight: widget.isLast ? const Radius.circular(12) : Radius.zero, + ) + ), + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + InkWell( + onTap: () { + if (isHoverIcon) { + _emailForwardController.selectRecipientForward(widget.recipientForward); + } + }, + onHover: (value) { + setState(mounted, this.setState, () { + isHoverIcon = value; + }); + }, + child: Container( + width: 54, + height: 54, color: Colors.transparent, alignment: Alignment.center, - child: _buildAvatarIcon())), - const SizedBox(width: 10), - Expanded(child: Text(widget.recipientForward.emailAddress, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Colors.black))), - buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icDeleteEmailForward, - fit: BoxFit.fill, - width: 18, - height: 18, + child: _buildAvatarIcon() + ) + ), + const SizedBox(width: 12), + Expanded(child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.recipientForward.emailAddress.displayName.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: Text( + widget.recipientForward.emailAddress.displayName, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black + ) + ), + ), + Text( + widget.recipientForward.emailAddress.email ?? '', + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: AppColor.colorContentEmail + ) + ) + ], + )), + const SizedBox(width: 12), + if (isHoverItem) + buildIconWeb( + icon: SvgPicture.asset( + _imagePaths.icDeleteEmailForward, + fit: BoxFit.fill, + width: 18, + height: 18, + ), + onTap: () => _emailForwardController.deleteRecipients( + context, + widget.recipientForward.emailAddress.email ?? '' + ) ), - onTap: () => - _emailForwardController.deleteRecipients(context, widget.recipientForward.emailAddress)), - ]), + ]), + ), ); } @@ -84,14 +141,15 @@ class _EmailForwardItemWidgetState extends State { width: 24, height: 24)); } else { - return CircleAvatar( - backgroundColor: AppColor.colorTextButton, - radius: 16, - child: Text(widget.recipientForward.emailAddress[0].toUpperCase(), - style: const TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w500))); + return (AvatarBuilder() + ..text(widget.recipientForward.emailAddress.asString().firstLetterToUpperCase) + ..size(54) + ..addTextStyle(const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 20, + color: Colors.white)) + ..avatarColor(widget.recipientForward.emailAddress.avatarColors) + ).build(); } } } 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 d13a740ee..2c4d20d9f 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 @@ -2,13 +2,10 @@ import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/resources/image_paths.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/presentation/utils/style_utils.dart'; -import 'package:core/presentation/views/button/button_builder.dart'; import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; -class ForwardHeaderWidget extends GetWidget { +class ForwardHeaderWidget extends StatelessWidget { const ForwardHeaderWidget({ Key? key, required this.imagePaths, @@ -21,97 +18,29 @@ class ForwardHeaderWidget extends GetWidget { @override Widget build(BuildContext context) { return Container( - width: double.infinity, - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: AppColor.colorBackgroundWrapIconStyleCode, - borderRadius: BorderRadius.circular(16), - ), + color: Colors.transparent, + padding: const EdgeInsets.only(top: 24, left: 24, right: 24, bottom: 11), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(AppLocalizations.of(context).forwarding, - style: const TextStyle( - fontSize: 17, - fontWeight: FontWeight.bold, - color: Colors.black)), - const SizedBox(height: 24), - _buildButtonAddNewEmailsForward(context), - const SizedBox(height: 24), - Obx(() => _buildButtonSwitchKeepLocalCopy(context)), + Text( + AppLocalizations.of(context).forwarding, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Colors.black)), + const SizedBox(height: 8), + Text( + AppLocalizations.of(context).forwardingSettingExplanation, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 3, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + color: AppColor.colorSettingExplanation)), ]), ); } - - 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(170) - ..size(20) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric(vertical: 12)) - ..textStyle(const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.w500, - )) - ..onPressActionClick(() => controller.goToAddEmailsForward(context)) - ..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(() => controller.goToAddEmailsForward(context)) - ..text( - AppLocalizations.of(context).addRecipients, - isVertical: false, - )) - .build(); - } - } - - Widget _buildButtonSwitchKeepLocalCopy(BuildContext context) { - if(controller.currentForward.value != null) { - return SizedBox( - width: 250, - child: SwitchListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 0), - title: Text(AppLocalizations.of(context).keepLocalCopyForwardLabel, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Colors.black)), - value: controller.currentForwardLocalCopyState, - onChanged: (_) { - controller.handleEditLocalCopy(); - }, - controlAffinity: ListTileControlAffinity.trailing, - ), - ); - } else { - return const SizedBox.shrink(); - } - } -} +} \ No newline at end of file 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 867ed2a9c..22bda1925 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 @@ -6,79 +6,29 @@ import 'package:model/mailbox/select_mode.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/forward_controller.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/forward/widgets/email_forward_item_widget.dart' if (dart.library.html) 'package:tmail_ui_user/features/manage_account/presentation/forward/widgets/email_forward_item_widget_for_web.dart'; +import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/recipient_forward.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; class ListEmailForwardsWidget extends GetWidget { final _imagePaths = Get.find(); + final _responsiveUtils = Get.find(); ListEmailForwardsWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( - decoration: BoxDecoration( - color: AppColor.colorBackgroundWrapIconStyleCode, - borderRadius: BorderRadius.circular(16), - border: Border.all( - width: 1, - color: AppColor.colorBorderListForwardsFilter) - ), + decoration: SettingsUtils.getBoxDecorationForListRecipient(context, _responsiveUtils), + margin: SettingsUtils.getPaddingListRecipientForwarding(context, _responsiveUtils), child: ClipRRect( - borderRadius: BorderRadius.circular(16), + borderRadius: BorderRadius.circular(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - Obx(() => Container( - width: double.infinity, - decoration: const BoxDecoration( - color: AppColor.colorBackgroundHeaderListForwards, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16)), - ), - padding: controller.selectionMode.value == SelectMode.INACTIVE - ? const EdgeInsets.symmetric(vertical: 17, horizontal: 24) - : const EdgeInsets.symmetric(vertical: 13, horizontal: 24), - child: Row(children: [ - Expanded(child: Text( - AppLocalizations.of(context).headerRecipients, - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: AppColor.colorTextButtonHeaderThread))), - Obx(() { - if (controller.selectionMode.value == SelectMode.ACTIVE) { - return _buildListButtonSelection(context); - } else { - if (controller.listRecipientForward.isNotEmpty) { - return (ButtonBuilder(_imagePaths.icSelectAll) - ..decoration(BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: AppColor.colorButtonHeaderThread)) - ..paddingIcon(const EdgeInsets.only(right: 8)) - ..size(16) - ..radiusSplash(10) - ..padding(const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8)) - ..textStyle(const TextStyle( - fontSize: 12, - color: AppColor.colorTextButtonHeaderThread)) - ..onPressActionClick(() => controller.selectAllRecipientForward()) - ..text(AppLocalizations.of(context).select_all, isVertical: false)) - .build(); - } else { - return const SizedBox.shrink(); - } - } - }) - ]), - )), + _buildTitleHeader(context), const Divider( color: AppColor.lineItemListColor, height: 1, @@ -92,13 +42,20 @@ class ListEmailForwardsWidget extends GetWidget { final recipientForward = controller.listRecipientForward[index]; return EmailForwardItemWidget( recipientForward: recipientForward, + isLast: index == controller.listRecipientForward.length - 1, selectionMode: controller.selectionMode.value); }, - separatorBuilder: (context, index) => const Divider( - color: AppColor.lineItemListColor, - height: 1, - thickness: 0.2, - ), + separatorBuilder: (context, index) { + if (index != controller.listRecipientForward.length - 1) { + return const Divider( + color: AppColor.lineItemListColor, + height: 1, + thickness: 0.2, + ); + } else { + return const SizedBox.shrink(); + } + }, ); }), ]), @@ -106,26 +63,76 @@ class ListEmailForwardsWidget extends GetWidget { ); } - Widget _buildListButtonSelection(BuildContext context) { - return Row(mainAxisSize: MainAxisSize.min, children: [ - buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icCloseComposer, - color: AppColor.colorTextButton, - fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).cancel, - onTap: () => controller.cancelSelectionMode()), - const SizedBox(width: 5), - buildIconWeb( - icon: SvgPicture.asset( - _imagePaths.icDelete, - color: AppColor.colorActionDeleteConfirmDialog, - fit: BoxFit.fill), - tooltip: AppLocalizations.of(context).delete_all, - onTap: () => - controller.deleteMultipleRecipients( - context, - controller.listRecipientForwardSelected.listEmailAddress)) - ]); + Widget _buildTitleHeader(BuildContext context) { + return Obx(() => Container( + width: double.infinity, + decoration: const BoxDecoration( + color: AppColor.colorBackgroundHeaderListForwards, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16) + ), + ), + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12), + child: Row(children: [ + _buildSelectAllButton(), + const SizedBox(width: 12), + Expanded(child: Text( + AppLocalizations.of(context).headerRecipients, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: AppColor.colorTextButtonHeaderThread + ) + )), + const SizedBox(width: 12), + if (controller.listRecipientForwardSelected.isNotEmpty) + _buildDeleteAllButton(context) + ]), + )); + } + + Widget _buildSelectAllButton() { + return Material( + child: InkWell( + customBorder: const CircleBorder(), + child: Padding( + padding: const EdgeInsets.all(16), + child: SvgPicture.asset( + controller.selectionMode.value == SelectMode.ACTIVE + ? _imagePaths.icCancelSelection + : _imagePaths.icUnSelected, + width: 24, + height: 24 + ), + ), + onTap: () { + if (controller.selectionMode.value == SelectMode.ACTIVE) { + controller.cancelSelectionMode(); + } else { + controller.selectAllRecipientForward(); + } + }, + ), + color: Colors.transparent, + ); + } + + Widget _buildDeleteAllButton(BuildContext context) { + return buildIconWeb( + icon: SvgPicture.asset( + _imagePaths.icDeleteEmailForward, + fit: BoxFit.fill, + width: 18, + height: 18, + ), + tooltip: AppLocalizations.of(context).delete_all, + onTap: () => controller.deleteMultipleRecipients( + context, + controller.listRecipientForwardSelected.listEmailAddress + ) + ); } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/widgets/recipient_input_decoration_builder.dart b/lib/features/manage_account/presentation/forward/widgets/recipient_input_decoration_builder.dart new file mode 100644 index 000000000..5547ede7a --- /dev/null +++ b/lib/features/manage_account/presentation/forward/widgets/recipient_input_decoration_builder.dart @@ -0,0 +1,41 @@ + +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/views/text/input_decoration_builder.dart'; +import 'package:core/utils/build_utils.dart'; +import 'package:flutter/material.dart'; + +class RecipientInputDecorationBuilder extends InputDecorationBuilder { + + @override + InputDecoration build() { + return InputDecoration( + enabledBorder: enabledBorder ?? const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + borderSide: BorderSide(width: 0.5, color: AppColor.colorInputBorderCreateMailbox)), + focusedBorder: enabledBorder ?? const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + borderSide: BorderSide(width: 0.5, color: AppColor.colorTextButton)), + errorBorder: errorBorder ?? const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + borderSide: BorderSide(width: 0.5, color: AppColor.colorInputBorderErrorVerifyName)), + focusedErrorBorder: errorBorder ?? const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + borderSide: BorderSide(width: 0.5, color: AppColor.colorInputBorderErrorVerifyName)), + prefixText: prefixText, + labelText: labelText, + floatingLabelBehavior: FloatingLabelBehavior.never, + labelStyle: labelStyle ?? const TextStyle(color: Colors.black, fontSize: 16), + hintText: hintText, + isDense: true, + hintStyle: hintStyle ?? const TextStyle(color: AppColor.colorEmailAddressFull, fontSize: 16), + contentPadding: const EdgeInsets.symmetric( + vertical: BuildUtils.isWeb ? 16 : 12, + horizontal: 12), + errorText: errorText, + errorStyle: errorTextStyle ?? const TextStyle(color: AppColor.colorInputBorderErrorVerifyName, fontSize: 13), + filled: true, + fillColor: errorText?.isNotEmpty == true + ? AppColor.colorInputBackgroundErrorVerifyName + : AppColor.colorInputBackgroundCreateMailbox); + } +} \ No newline at end of file diff --git a/lib/features/manage_account/presentation/forward/widgets/recipient_input_field_builder.dart b/lib/features/manage_account/presentation/forward/widgets/recipient_input_field_builder.dart new file mode 100644 index 000000000..912bbecd1 --- /dev/null +++ b/lib/features/manage_account/presentation/forward/widgets/recipient_input_field_builder.dart @@ -0,0 +1,81 @@ + +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/manage_account/presentation/forward/widgets/recipient_input_decoration_builder.dart'; +import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; + +typedef OnSelectedSuggestionAction = Function(EmailAddress emailAddress); +typedef OnSuggestionCallbackAction = Function(String pattern); +typedef OnSummitedCallbackAction = Function(String pattern); +typedef OnRecipientInputTextChange = Function(String pattern); + +class RecipientInputFieldBuilder extends StatelessWidget { + + final TextEditingController? editingController; + final OnSelectedSuggestionAction? onSelectedSuggestionAction; + final OnSuggestionCallbackAction? onSuggestionCallbackAction; + final OnSummitedCallbackAction? onSummitedCallbackAction; + final OnRecipientInputTextChange? onRecipientInputTextChange; + final String? errorText; + + const RecipientInputFieldBuilder({ + Key? key, + this.editingController, + this.onSelectedSuggestionAction, + this.onSuggestionCallbackAction, + this.onSummitedCallbackAction, + this.onRecipientInputTextChange, + this.errorText + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return TypeAheadFormField( + textFieldConfiguration: TextFieldConfiguration( + controller: editingController, + onSubmitted: (pattern) { + if (onSummitedCallbackAction != null) { + onSummitedCallbackAction!(pattern); + } + }, + onChanged: onRecipientInputTextChange, + textInputAction: TextInputAction.done, + decoration: (RecipientInputDecorationBuilder() + ..setHintText(AppLocalizations.of(context).recipientsLabel) + ..setErrorText(errorText) + ).build() + ), + debounceDuration: const Duration(milliseconds: 500), + suggestionsCallback: (pattern) async { + if (onSuggestionCallbackAction != null) { + return onSuggestionCallbackAction!(pattern); + } else { + return []; + } + }, + itemBuilder: (BuildContext context, emailAddress) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Text(emailAddress.email ?? '', + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Colors.black)), + ); + }, + onSuggestionSelected: (emailSelected) { + if (onSelectedSuggestionAction != null) { + onSelectedSuggestionAction!(emailSelected); + } + }, + suggestionsBoxDecoration: SuggestionsBoxDecoration( + borderRadius: BorderRadius.circular(14) + ), + noItemsFoundBuilder: (context) => const SizedBox(), + hideOnEmpty: true, + hideOnError: true, + hideOnLoading: true, + ); + } +} \ No newline at end of file diff --git a/lib/features/manage_account/presentation/menu/settings_utils.dart b/lib/features/manage_account/presentation/menu/settings_utils.dart index 2a45ef92c..244e0cc81 100644 --- a/lib/features/manage_account/presentation/menu/settings_utils.dart +++ b/lib/features/manage_account/presentation/menu/settings_utils.dart @@ -1,6 +1,7 @@ +import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:core/utils/build_utils.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; class SettingsUtils { static double getHorizontalPadding(BuildContext context, ResponsiveUtils responsiveUtils) { @@ -30,7 +31,7 @@ class SettingsUtils { static EdgeInsets getMarginViewForSettingDetails(BuildContext context, ResponsiveUtils responsiveUtils) { if (BuildUtils.isWeb) { if (responsiveUtils.isDesktop(context)) { - return const EdgeInsets.only(left: 16, top: 16, right: 24, bottom: 24); + return const EdgeInsets.all(16); } else if (responsiveUtils.isTabletLarge(context) || responsiveUtils.isTablet(context)) { return const EdgeInsets.only(right: 32, top: 16, bottom: 16, left: 32); @@ -49,4 +50,50 @@ class SettingsUtils { } } } + + static BoxDecoration? getBoxDecorationForContent(BuildContext context, ResponsiveUtils responsiveUtils) { + if (responsiveUtils.isWebDesktop(context)) { + return BoxDecoration( + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.colorBorderSettingContentWeb, width: 1), + color: Colors.white); + } else { + return null; + } + } + + static Color? getContentBackgroundColor(BuildContext context, ResponsiveUtils responsiveUtils) { + if (responsiveUtils.isWebDesktop(context)) { + return null; + } else { + return Colors.white; + } + } + + static Color? getBackgroundColor(BuildContext context, ResponsiveUtils responsiveUtils) { + if (responsiveUtils.isWebDesktop(context)) { + return AppColor.colorBgDesktop; + } else { + return Colors.white; + } + } + + static EdgeInsets getPaddingListRecipientForwarding(BuildContext context, ResponsiveUtils responsiveUtils) { + if (responsiveUtils.isPortraitMobile(context)) { + return const EdgeInsets.all(12); + } else { + return const EdgeInsets.symmetric(horizontal: 24, vertical: 12); + } + } + + static BoxDecoration? getBoxDecorationForListRecipient(BuildContext context, ResponsiveUtils responsiveUtils) { + if (responsiveUtils.isWebDesktop(context)) { + return BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all(color: AppColor.colorBorderSettingContentWeb, width: 1), + color: Colors.white); + } else { + return null; + } + } } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/model/recipient_forward.dart b/lib/features/manage_account/presentation/model/recipient_forward.dart index 878896528..36921c666 100644 --- a/lib/features/manage_account/presentation/model/recipient_forward.dart +++ b/lib/features/manage_account/presentation/model/recipient_forward.dart @@ -1,9 +1,10 @@ import 'package:equatable/equatable.dart'; +import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/mailbox/select_mode.dart'; class RecipientForward with EquatableMixin { - final String emailAddress; + final EmailAddress emailAddress; final SelectMode selectMode; RecipientForward(this.emailAddress, {this.selectMode = SelectMode.INACTIVE}); @@ -35,5 +36,5 @@ extension RecipientForwardExtension on RecipientForward { extension ListRecipientForwardExtension on List { Set get listEmailAddress => - map((recipient) => recipient.emailAddress).toSet(); + map((recipient) => recipient.emailAddress.email!).toSet(); } \ No newline at end of file diff --git a/lib/features/manage_account/presentation/profiles/profiles_view.dart b/lib/features/manage_account/presentation/profiles/profiles_view.dart index 9f84c8793..142b695e0 100644 --- a/lib/features/manage_account/presentation/profiles/profiles_view.dart +++ b/lib/features/manage_account/presentation/profiles/profiles_view.dart @@ -16,23 +16,21 @@ class ProfilesView extends GetWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: _responsiveUtils.isWebDesktop(context) - ? AppColor.colorBgDesktop - : Colors.white, + backgroundColor: SettingsUtils.getBackgroundColor(context, _responsiveUtils), body: Container( margin: _responsiveUtils.isWebDesktop(context) - ? const EdgeInsets.all(24) + ? const EdgeInsets.all(16) : EdgeInsets.symmetric(horizontal: SettingsUtils.getHorizontalPadding(context, _responsiveUtils)), color: _responsiveUtils.isWebDesktop(context) ? null : Colors.white, decoration: _responsiveUtils.isWebDesktop(context) ? BoxDecoration( - borderRadius: BorderRadius.circular(20), - border: Border.all(color: AppColor.colorBorderBodyThread, width: 1), + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColor.colorBorderSettingContentWeb, width: 1), color: Colors.white) : null, child: ClipRRect( borderRadius: BorderRadius.circular( - _responsiveUtils.isWebDesktop(context) ? 20 : 0), + _responsiveUtils.isWebDesktop(context) ? 16 : 0), child: Padding( padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10), child: DefaultTabController( diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 6a84665f2..6f774bfbe 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-10-28T13:12:30.889722", + "@@last_modified": "2022-11-04T00:32:44.924510", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -2022,7 +2022,7 @@ "emailAddress": {} } }, - "deleteRecipient": "Delete recipient", + "deleteRecipient": "Remove recipients", "@deleteRecipient": { "type": "text", "placeholders_order": [], @@ -2034,7 +2034,7 @@ "placeholders_order": [], "placeholders": {} }, - "messageConfirmationDialogDeleteAllRecipientForward": "Do you want to delete all email?", + "messageConfirmationDialogDeleteAllRecipientForward": "Are you sure you want to remove those recipients? Doing this will remove them from the email chain.", "@messageConfirmationDialogDeleteAllRecipientForward": { "type": "text", "placeholders_order": [], @@ -2046,7 +2046,7 @@ "placeholders_order": [], "placeholders": {} }, - "recipientsLabel": "Name or Email address", + "recipientsLabel": "Enter name or email address", "@recipientsLabel": { "type": "text", "placeholders_order": [], @@ -2070,7 +2070,7 @@ "placeholders_order": [], "placeholders": {} }, - "keepLocalCopyForwardLabel": "Keep local copy", + "keepLocalCopyForwardLabel": "Keep a copy of the email in Inbox", "@keepLocalCopyForwardLabel": { "type": "text", "placeholders_order": [], @@ -2400,14 +2400,14 @@ "placeholders_order": [], "placeholders": {} }, - "newer": "Newer", - "@newer": { + "createNewMailbox": "Create new mailbox", + "@createNewMailbox": { "type": "text", "placeholders_order": [], "placeholders": {} }, - "createNewMailbox": "Create new mailbox", - "@createNewMailbox": { + "newer": "Newer", + "@newer": { "type": "text", "placeholders_order": [], "placeholders": {} @@ -2417,5 +2417,29 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "forwardingSettingExplanation": "Allows a new recipient to see the email sent if they were not originally included in the email chain.", + "@forwardingSettingExplanation": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "addRecipientButton": "Add recipient", + "@addRecipientButton": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "incorrectEmailFormat": "Incorrect email format", + "@incorrectEmailFormat": { + "type": "text", + "placeholders_order": [], + "placeholders": {} + }, + "remove": "Remove", + "@remove": { + "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 514df2f0a..d4379a2c7 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -2083,7 +2083,7 @@ class AppLocalizations { String get deleteRecipient { return Intl.message( - 'Delete recipient', + 'Remove recipients', name: 'deleteRecipient'); } @@ -2095,7 +2095,7 @@ class AppLocalizations { String get messageConfirmationDialogDeleteAllRecipientForward { return Intl.message( - 'Do you want to delete all email?', + 'Are you sure you want to remove those recipients? Doing this will remove them from the email chain.', name: 'messageConfirmationDialogDeleteAllRecipientForward' ); } @@ -2109,7 +2109,7 @@ class AppLocalizations { String get recipientsLabel { return Intl.message( - 'Name or Email address', + 'Enter name or email address', name: 'recipientsLabel', ); } @@ -2134,7 +2134,7 @@ class AppLocalizations { String get keepLocalCopyForwardLabel { return Intl.message( - 'Keep local copy', + 'Keep a copy of the email in Inbox', name: 'keepLocalCopyForwardLabel', ); } @@ -2487,4 +2487,28 @@ class AppLocalizations { 'Older', name: 'older'); } + + String get forwardingSettingExplanation { + return Intl.message( + 'Allows a new recipient to see the email sent if they were not originally included in the email chain.', + name: 'forwardingSettingExplanation'); + } + + String get addRecipientButton { + return Intl.message( + 'Add recipient', + name: 'addRecipientButton'); + } + + String get incorrectEmailFormat { + return Intl.message( + 'Incorrect email format', + name: 'incorrectEmailFormat'); + } + + String get remove { + return Intl.message( + 'Remove', + name: 'remove'); + } } \ No newline at end of file