TF-2613 Handle display forward warning icon in recipient item

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2024-02-29 12:07:48 +07:00
committed by Dat H. Pham
parent 33f32783aa
commit 86991b5168
11 changed files with 181 additions and 40 deletions
@@ -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();
}
}
@@ -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 '';
}
}
@@ -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;
});
@@ -126,7 +126,7 @@ class ForwardView extends GetWidget<ForwardController> 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,
@@ -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<AutocompleteConta
final validateSameDomain = EmailUtils.isSameDomain(
emailAddress: emailAddress.emailAddress,
serverDomain: widget.serverDomain
internalDomain: widget.internalDomain
);
if (!validateSameDomain) {
@@ -3,6 +3,7 @@ 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/button/tmail_button_widget.dart';
import 'package:core/presentation/views/image/avatar_builder.dart';
import 'package:core/utils/platform_info.dart';
import 'package:flutter/material.dart';
@@ -10,7 +11,9 @@ 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/email/presentation/utils/email_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';
typedef OnSelectRecipientCallbackAction = Function(RecipientForward recipientForward);
typedef OnDeleteRecipientCallbackAction = Function(RecipientForward recipientForward);
@@ -19,11 +22,16 @@ class EmailForwardItemWidget extends StatelessWidget {
final RecipientForward recipientForward;
final SelectMode selectionMode;
final String internalDomain;
final OnSelectRecipientCallbackAction? onSelectRecipientCallback;
final OnDeleteRecipientCallbackAction? onDeleteRecipientCallback;
const EmailForwardItemWidget(this.recipientForward, {
final ImagePaths _imagePaths = Get.find<ImagePaths>();
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<ImagePaths>();
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)
)
]),
@@ -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<ForwardController> {
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) {
+7 -1
View File
@@ -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": {}
}
}
@@ -3800,4 +3800,10 @@ class AppLocalizations {
name: 'messageWarningDialogForForwardsToOtherDomains'
);
}
String get externalDomain {
return Intl.message(
'External domain',
name: 'externalDomain');
}
}
@@ -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);
});
@@ -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(''));
});
});
}