TF-3864 Support pasting multiple address with multiple format mixed
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
+20
-38
@@ -1,14 +1,12 @@
|
||||
|
||||
import 'package:core/utils/mail/mail_address.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/string_convert.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/email/prefix_email_address.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
import 'package:super_tag_editor/tag_editor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/named_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_named_address_extension.dart';
|
||||
|
||||
extension AutoCreateTagForRecipientsExtension on ComposerController {
|
||||
|
||||
@@ -42,36 +40,28 @@ extension AutoCreateTagForRecipientsExtension on ComposerController {
|
||||
};
|
||||
|
||||
void autoCreateEmailTagForType(PrefixEmailAddress type, String input) {
|
||||
final namedAddress = StringConvert.parseNamedAddress(input);
|
||||
Set<String> addressSet = {};
|
||||
final namedAddresses = StringConvert.extractNamedAddresses(input);
|
||||
List<EmailAddress> newListEmailAddress = [];
|
||||
final existingEmailList = _emailLists[type]!;
|
||||
|
||||
if (namedAddress == null) {
|
||||
addressSet = StringConvert.extractEmailAddress(input).toSet();
|
||||
if (addressSet.isEmpty) return;
|
||||
if (namedAddresses.isNotEmpty) {
|
||||
final emailAddressListFromNamed = namedAddresses
|
||||
.toFilteredEmailAddressList(existingEmailList);
|
||||
log('$runtimeType::autoCreateEmailTagForType: Create email tag from named address list with length ${emailAddressListFromNamed.length}');
|
||||
newListEmailAddress = emailAddressListFromNamed;
|
||||
}
|
||||
|
||||
final emailList = _emailLists[type]!;
|
||||
final keyEditor = _emailEditors[type]!;
|
||||
List<EmailAddress> listEmailAddress = [];
|
||||
|
||||
final emailSet = emailList.map((email) => email.emailAddress).toSet();
|
||||
|
||||
if (namedAddress != null && !emailSet.contains(namedAddress.address)) {
|
||||
listEmailAddress.add(namedAddress.toEmailAddress());
|
||||
} else if (addressSet.isNotEmpty) {
|
||||
final listEmailAddressRecord = addressSet
|
||||
.map(_generateEmailAddressFromString)
|
||||
.toList();
|
||||
|
||||
listEmailAddress = listEmailAddressRecord
|
||||
.where((emailRecord) => !emailSet.contains(emailRecord.$1))
|
||||
.map((emailRecord) => emailRecord.$2)
|
||||
.toList();
|
||||
if (newListEmailAddress.isEmpty) {
|
||||
List<String> addresses = StringConvert.extractEmailAddress(input);
|
||||
final emailAddressListFromAddress =
|
||||
addresses.toFilteredEmailAddressList(existingEmailList);
|
||||
log('$runtimeType::autoCreateEmailTagForType: Create email tag from address list with length ${emailAddressListFromAddress.length}');
|
||||
newListEmailAddress = emailAddressListFromAddress;
|
||||
}
|
||||
|
||||
if (listEmailAddress.isEmpty) return;
|
||||
if (newListEmailAddress.isEmpty) return;
|
||||
|
||||
emailList.addAll(listEmailAddress);
|
||||
existingEmailList.addAll(newListEmailAddress);
|
||||
|
||||
if (!isInitialRecipient.value) {
|
||||
isInitialRecipient.value = true;
|
||||
@@ -80,19 +70,11 @@ extension AutoCreateTagForRecipientsExtension on ComposerController {
|
||||
|
||||
updateStatusEmailSendButton();
|
||||
|
||||
final keyEditor = _emailEditors[type]!;
|
||||
keyEditor.currentState?.resetTextField();
|
||||
Future.delayed(
|
||||
const Duration(milliseconds: 300),
|
||||
keyEditor.currentState?.closeSuggestionBox,
|
||||
);
|
||||
}
|
||||
|
||||
(String email, EmailAddress emailAddress) _generateEmailAddressFromString(String input) {
|
||||
try {
|
||||
final mailAddress = MailAddress.validateAddress(input);
|
||||
return (mailAddress.asEncodedString(), mailAddress.asEmailAddress());
|
||||
} catch (e) {
|
||||
return (input, EmailAddress(null, input));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:core/utils/mail/mail_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart';
|
||||
|
||||
extension ListAddressExtension on List<String> {
|
||||
List<EmailAddress> toFilteredEmailAddressList(
|
||||
List<EmailAddress> existingEmails,
|
||||
) {
|
||||
final existingEmailSet = existingEmails.toNormalizedEmailSet();
|
||||
|
||||
final seen = <String>{};
|
||||
final result = <EmailAddress>[];
|
||||
|
||||
for (final address in this) {
|
||||
final emailAddress = _validateToEmailAddress(address);
|
||||
final lowerAddress = emailAddress.emailAddress.toLowerCase();
|
||||
|
||||
if (existingEmailSet.contains(lowerAddress) || !seen.add(lowerAddress)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(emailAddress);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
EmailAddress _validateToEmailAddress(String address) {
|
||||
try {
|
||||
final mailAddress = MailAddress.validateAddress(address);
|
||||
return mailAddress.asEmailAddress();
|
||||
} catch (_) {
|
||||
return EmailAddress(null, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:core/utils/mail/named_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/named_address_extension.dart';
|
||||
|
||||
extension ListNamedAddressExtension on List<NamedAddress> {
|
||||
List<EmailAddress> toFilteredEmailAddressList(
|
||||
List<EmailAddress> existingEmails,
|
||||
) {
|
||||
final existingEmailSet = existingEmails.toNormalizedEmailSet();
|
||||
final seen = <String>{};
|
||||
return where((named) {
|
||||
final normalized = named.normalizedAddress;
|
||||
return !existingEmailSet.contains(normalized) && seen.add(normalized);
|
||||
}).map((named) => named.validateToEmailAddress()).toList();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,25 @@
|
||||
|
||||
import 'package:core/utils/mail/mail_address.dart';
|
||||
import 'package:core/utils/mail/named_address.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart';
|
||||
|
||||
extension NamedAddressExtension on NamedAddress {
|
||||
bool get isValid => name.isNotEmpty && address.isNotEmpty;
|
||||
|
||||
String get normalizedAddress => address.toLowerCase();
|
||||
|
||||
EmailAddress toEmailAddress() => EmailAddress(name, address);
|
||||
|
||||
EmailAddress validateToEmailAddress() {
|
||||
try {
|
||||
if (isValid) {
|
||||
return toEmailAddress();
|
||||
} else {
|
||||
final mailAddress = MailAddress.validateAddress(address);
|
||||
return mailAddress.asEmailAddress();
|
||||
}
|
||||
} catch (_) {
|
||||
return toEmailAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,8 @@ import 'package:model/email/prefix_email_address.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
import 'package:model/mailbox/expand_mode.dart';
|
||||
import 'package:super_tag_editor/tag_editor.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/named_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/list_named_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/extensions/mail_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
|
||||
@@ -558,34 +559,33 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
|
||||
) => _createMailTag(value, stateSetter);
|
||||
|
||||
void _createMailTag(String value, StateSetter stateSetter) {
|
||||
final namedAddress = StringConvert.parseNamedAddress(value.trim());
|
||||
if (namedAddress != null) {
|
||||
if (!_isDuplicatedRecipient(namedAddress.address)) {
|
||||
final valueTrimmed = value.trim();
|
||||
final namedAddresses = StringConvert.extractNamedAddresses(valueTrimmed);
|
||||
if (namedAddresses.isNotEmpty) {
|
||||
final emailAddressListFromNamed = namedAddresses
|
||||
.toFilteredEmailAddressList(_currentListEmailAddress);
|
||||
log('$runtimeType::_createMailTag: Create email tag from named address list with length ${emailAddressListFromNamed.length}');
|
||||
if (emailAddressListFromNamed.isNotEmpty) {
|
||||
stateSetter(
|
||||
() => _currentListEmailAddress.add(namedAddress.toEmailAddress()),
|
||||
() => _currentListEmailAddress.addAll(emailAddressListFromNamed),
|
||||
);
|
||||
_updateListEmailAddressAction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final listString = StringConvert.extractEmailAddress(value.trim()).toSet();
|
||||
List<String> addresses = StringConvert.extractEmailAddress(valueTrimmed);
|
||||
final emailAddressListFromAddress =
|
||||
addresses.toFilteredEmailAddressList(_currentListEmailAddress);
|
||||
log('$runtimeType::_createMailTag: Create email tag from address list with length ${emailAddressListFromAddress.length}');
|
||||
|
||||
if (listString.isEmpty && !_isDuplicatedRecipient(value)) {
|
||||
if (emailAddressListFromAddress.isNotEmpty) {
|
||||
stateSetter(
|
||||
() => _currentListEmailAddress.addAll(emailAddressListFromAddress),
|
||||
);
|
||||
_updateListEmailAddressAction();
|
||||
} else if (!_isDuplicatedRecipient(valueTrimmed)) {
|
||||
_onEmailAddressReceived(value, stateSetter);
|
||||
} else if (listString.isNotEmpty) {
|
||||
final listStringNotExist = listString
|
||||
.where((text) => !_isDuplicatedRecipient(text))
|
||||
.toList();
|
||||
|
||||
if (listStringNotExist.isNotEmpty) {
|
||||
final listAddress = listStringNotExist
|
||||
.map((text) => EmailAddress(null, text))
|
||||
.toList();
|
||||
|
||||
stateSetter(() => _currentListEmailAddress.addAll(listAddress));
|
||||
_updateListEmailAddressAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user