diff --git a/lib/features/email/presentation/utils/email_utils.dart b/lib/features/email/presentation/utils/email_utils.dart index fd23e17cb..730866bef 100644 --- a/lib/features/email/presentation/utils/email_utils.dart +++ b/lib/features/email/presentation/utils/email_utils.dart @@ -71,10 +71,10 @@ class EmailUtils { static bool isSameDomain({ required String emailAddress, - required String serverDomain + required String internalDomain }) { - log('EmailUtils::isSameDomain: emailAddress = $emailAddress | serverDomain = $serverDomain'); + log('EmailUtils::isSameDomain: emailAddress = $emailAddress | internalDomain = $internalDomain'); return GetUtils.isEmail(emailAddress) && - emailAddress.split('@').last.toLowerCase() == serverDomain.toLowerCase(); + emailAddress.split('@').last.toLowerCase() == internalDomain.toLowerCase(); } } \ No newline at end of file diff --git a/lib/features/home/domain/extensions/session_extensions.dart b/lib/features/home/domain/extensions/session_extensions.dart index e253651e6..5afafc577 100644 --- a/lib/features/home/domain/extensions/session_extensions.dart +++ b/lib/features/home/domain/extensions/session_extensions.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:core/presentation/extensions/uri_extension.dart'; +import 'package:core/utils/app_logger.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/http/converter/state_converter.dart'; import 'package:jmap_dart_client/http/converter/user_name_converter.dart'; @@ -46,12 +47,17 @@ extension SessionExtensions on Session { } } - String get serverDomain { - if (GetUtils.isEmail(username.value)) { - return username.value.split('@').last; - } else if (GetUtils.isEmail(personalAccount.name.value)) { - return personalAccount.name.value.split('@').last; - } else { + String get internalDomain { + try { + if (GetUtils.isEmail(username.value)) { + return username.value.split('@').last; + } else if (GetUtils.isEmail(personalAccount.name.value)) { + return personalAccount.name.value.split('@').last; + } else { + return ''; + } + } catch (e) { + logError('SessionExtensions::internalDomain: Exception: $e'); return ''; } } diff --git a/lib/features/manage_account/presentation/forward/forward_controller.dart b/lib/features/manage_account/presentation/forward/forward_controller.dart index 92d6acd94..0e783cc88 100644 --- a/lib/features/manage_account/presentation/forward/forward_controller.dart +++ b/lib/features/manage_account/presentation/forward/forward_controller.dart @@ -177,10 +177,10 @@ class ForwardController extends BaseController { bool get _isExistRecipientSameServerDomain => listRecipientForward.any((recipient) { - final serverDomain = accountDashBoardController.sessionCurrent?.serverDomain ?? ''; + final internalDomain = accountDashBoardController.sessionCurrent?.internalDomain ?? ''; final isSameDomain = EmailUtils.isSameDomain( emailAddress: recipient.emailAddress.emailAddress, - serverDomain: serverDomain + internalDomain: internalDomain ); return !isSameDomain; }); diff --git a/lib/features/manage_account/presentation/forward/forward_view.dart b/lib/features/manage_account/presentation/forward/forward_view.dart index e76bed53a..abe75cd46 100644 --- a/lib/features/manage_account/presentation/forward/forward_view.dart +++ b/lib/features/manage_account/presentation/forward/forward_view.dart @@ -126,7 +126,7 @@ class ForwardView extends GetWidget with AppLoaderMixin { Widget _buildAddRecipientsFormWidget(BuildContext context) { return AutocompleteContactTextFieldWithTags( listEmailAddress: controller.recipientController.listRecipients, - serverDomain: controller.accountDashBoardController.sessionCurrent?.serverDomain ?? '', + internalDomain: controller.accountDashBoardController.sessionCurrent?.internalDomain ?? '', controller: controller.recipientController.inputRecipientController, onSuggestionCallback: controller.recipientController.getAutoCompleteSuggestion, hasAddContactButton: true, diff --git a/lib/features/manage_account/presentation/forward/widgets/autocomplete_contact_text_field_with_tags.dart b/lib/features/manage_account/presentation/forward/widgets/autocomplete_contact_text_field_with_tags.dart index 63321a0a9..6740433d3 100644 --- a/lib/features/manage_account/presentation/forward/widgets/autocomplete_contact_text_field_with_tags.dart +++ b/lib/features/manage_account/presentation/forward/widgets/autocomplete_contact_text_field_with_tags.dart @@ -35,12 +35,12 @@ class AutocompleteContactTextFieldWithTags extends StatefulWidget { final OnSuggestionContactCallbackAction? onSuggestionCallback; final OnAddListContactCallbackAction? onAddContactCallback; final OnExceptionAddListContactCallbackAction? onExceptionCallback; - final String serverDomain; + final String internalDomain; const AutocompleteContactTextFieldWithTags({ Key? key, required this.listEmailAddress, - required this.serverDomain, + required this.internalDomain, this.controller, this.hasAddContactButton = false, this.onSuggestionCallback, @@ -336,7 +336,7 @@ class _AutocompleteContactTextFieldWithTagsState extends State(); + + EmailForwardItemWidget({ Key? key, + required this.recipientForward, + required this.internalDomain, this.selectionMode = SelectMode.INACTIVE, this.onSelectRecipientCallback, this.onDeleteRecipientCallback, @@ -31,8 +39,6 @@ class EmailForwardItemWidget extends StatelessWidget { @override Widget build(BuildContext context) { - final imagePaths = Get.find(); - return Padding( padding: const EdgeInsets.only(top: 4), child: Material( @@ -53,23 +59,51 @@ class EmailForwardItemWidget extends StatelessWidget { recipientForward.selectMode == SelectMode.ACTIVE ? 12 : 0)) ), child: Row(children: [ - _buildAvatarIcon(imagePaths), + _buildAvatarIcon(_imagePaths), const SizedBox(width: 12), Expanded(child: Column( - mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - recipientForward.emailAddress.asString(), - overflow: CommonTextStyle.defaultTextOverFlow, - softWrap: CommonTextStyle.defaultSoftWrap, - maxLines: 1, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.normal, - color: Colors.black + if (EmailUtils.isSameDomain( + emailAddress: recipientForward.emailAddress.emailAddress, + internalDomain: internalDomain)) + Text( + recipientForward.emailAddress.asString(), + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: Theme.of(context).textTheme.labelSmall?.copyWith( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black + ) ) - ), + else + Row( + children: [ + Flexible( + child: Text( + recipientForward.emailAddress.asString(), + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 1, + style: Theme.of(context).textTheme.labelSmall?.copyWith( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.black + ) + ), + ), + TMailButtonWidget.fromIcon( + icon: _imagePaths.icInfoCircleOutline, + iconColor: AppColor.colorQuotaError, + iconSize: 20, + backgroundColor: Colors.transparent, + padding: const EdgeInsets.all(3), + tooltipMessage: AppLocalizations.of(context).externalDomain, + ) + ], + ), if (recipientForward.emailAddress.displayName.isNotEmpty) Padding( padding: const EdgeInsets.only(top: 4), @@ -92,7 +126,7 @@ class EmailForwardItemWidget extends StatelessWidget { buildIconWeb( iconSize: 30, splashRadius: 20, - icon: SvgPicture.asset(imagePaths.icDeleteRecipient), + icon: SvgPicture.asset(_imagePaths.icDeleteRecipient), onTap: () => onDeleteRecipientCallback?.call(recipientForward) ) ]), 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 99e05b52f..3b916a213 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 @@ -5,6 +5,7 @@ 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/home/domain/extensions/session_extensions.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'; import 'package:tmail_ui_user/features/manage_account/presentation/menu/settings_utils.dart'; @@ -34,10 +35,10 @@ class ListEmailForwardsWidget extends GetWidget { primary: false, itemCount: controller.listRecipientForward.length, padding: EdgeInsets.zero, - itemExtent: 75, itemBuilder: (context, index) { return EmailForwardItemWidget( - controller.listRecipientForward[index], + recipientForward: controller.listRecipientForward[index], + internalDomain: controller.accountDashBoardController.sessionCurrent?.internalDomain ?? '', selectionMode: controller.selectionMode.value, onSelectRecipientCallback: controller.selectRecipientForward, onDeleteRecipientCallback: (recipientForward) { diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 7393536ce..f01d69a86 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2024-02-29T10:18:57.883345", + "@@last_modified": "2024-02-29T11:49:16.217272", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", @@ -3647,5 +3647,11 @@ "type": "text", "placeholders_order": [], "placeholders": {} + }, + "externalDomain": "External domain", + "@externalDomain": { + "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 b6dfd3c05..07b228856 100644 --- a/lib/main/localizations/app_localizations.dart +++ b/lib/main/localizations/app_localizations.dart @@ -3800,4 +3800,10 @@ class AppLocalizations { name: 'messageWarningDialogForForwardsToOtherDomains' ); } + + String get externalDomain { + return Intl.message( + 'External domain', + name: 'externalDomain'); + } } \ No newline at end of file diff --git a/test/features/email/email_address_is_same_domain_test.dart b/test/features/email/email_address_is_same_domain_test.dart index ee3216d6c..7afac33db 100644 --- a/test/features/email/email_address_is_same_domain_test.dart +++ b/test/features/email/email_address_is_same_domain_test.dart @@ -5,27 +5,27 @@ void main() { group('EmailUtils', () { test('isSameDomain should return true when email is from the same domain as server', () { String emailAddress = 'user@example.com'; - String serverDomain = 'example.com'; + String internalDomain = 'example.com'; - bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, serverDomain: serverDomain); + bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, internalDomain: internalDomain); expect(result, true); }); test('isSameDomain should return false when email is not from the same domain as server', () { String emailAddress = 'user@example.com'; - String serverDomain = 'example2.com'; + String internalDomain = 'example2.com'; - bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, serverDomain: serverDomain); + bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, internalDomain: internalDomain); expect(result, false); }); test('isSameDomain should return false when email is invalid', () { String emailAddress = 'invalid_email'; - String serverDomain = 'example.com'; + String internalDomain = 'example.com'; - bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, serverDomain: serverDomain); + bool result = EmailUtils.isSameDomain(emailAddress: emailAddress, internalDomain: internalDomain); expect(result, false); }); diff --git a/test/features/session/get_internal_domain_in_session_test.dart b/test/features/session/get_internal_domain_in_session_test.dart new file mode 100644 index 000000000..7f6eabaad --- /dev/null +++ b/test/features/session/get_internal_domain_in_session_test.dart @@ -0,0 +1,88 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:jmap_dart_client/jmap/account_id.dart'; +import 'package:jmap_dart_client/jmap/core/account/account.dart'; +import 'package:jmap_dart_client/jmap/core/id.dart'; +import 'package:jmap_dart_client/jmap/core/session/session.dart'; +import 'package:jmap_dart_client/jmap/core/state.dart'; +import 'package:jmap_dart_client/jmap/core/user_name.dart'; +import 'package:tmail_ui_user/features/home/domain/extensions/session_extensions.dart'; + +void main() { + group('get internal domain in session test', () { + test('When username is valid email, internalDomain should be returns the domain', () { + final Session session = Session( + {}, + {}, + {}, + UserName('example@example.com'), + Uri.parse('http://domain.com/jmap'), + Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), + Uri.parse('http://domain.com/upload/{accountId}'), + Uri.parse('http://domain.com/eventSource?types={types}&closeAfter={closeafter}&ping={ping}'), + State('2c9f1b12-b35a-43e6-9af2-0106fb53a943') + ); + + String result = session.internalDomain; + + expect(result, equals('example.com')); + }); + + test('When personal account name is valid email, internalDomain should be returns the domain', () { + final Session session = Session( + {}, + { + AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')): Account(AccountName('example@example.com'), true, false, {}) + }, + {}, + UserName('example'), + Uri.parse('http://domain.com/jmap'), + Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), + Uri.parse('http://domain.com/upload/{accountId}'), + Uri.parse('http://domain.com/eventSource?types={types}&closeAfter={closeafter}&ping={ping}'), + State('2c9f1b12-b35a-43e6-9af2-0106fb53a943') + ); + + String result = session.internalDomain; + + expect(result, equals('example.com')); + }); + + test('When neither username nor personal account name is valid email, internalDomain should be returns an empty string', () { + final Session session = Session( + {}, + { + AccountId(Id('29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6')): Account(AccountName('example'), true, false, {}) + }, + {}, + UserName('example'), + Uri.parse('http://domain.com/jmap'), + Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), + Uri.parse('http://domain.com/upload/{accountId}'), + Uri.parse('http://domain.com/eventSource?types={types}&closeAfter={closeafter}&ping={ping}'), + State('2c9f1b12-b35a-43e6-9af2-0106fb53a943') + ); + + String result = session.internalDomain; + + expect(result, equals('')); + }); + + test('When personalAccount throw an exception, internalDomain should be returns an empty string', () { + final Session session = Session( + {}, + {}, + {}, + UserName('example'), + Uri.parse('http://domain.com/jmap'), + Uri.parse('http://domain.com/download/{accountId}/{blobId}/?type={type}&name={name}'), + Uri.parse('http://domain.com/upload/{accountId}'), + Uri.parse('http://domain.com/eventSource?types={types}&closeAfter={closeafter}&ping={ping}'), + State('2c9f1b12-b35a-43e6-9af2-0106fb53a943') + ); + + final result = session.internalDomain; + + expect(result, equals('')); + }); + }); +} \ No newline at end of file