diff --git a/core/lib/core.dart b/core/lib/core.dart index f1a44a380..93a316b6a 100644 --- a/core/lib/core.dart +++ b/core/lib/core.dart @@ -9,6 +9,7 @@ export 'domain/extensions/datetime_extension.dart'; export 'presentation/extensions/html_extension.dart'; export 'presentation/extensions/compare_string_extension.dart'; export 'presentation/extensions/compare_list_extensions.dart'; +export 'presentation/extensions/string_extension.dart'; export 'domain/extensions/media_type_extension.dart'; // Exceptions diff --git a/core/lib/presentation/extensions/string_extension.dart b/core/lib/presentation/extensions/string_extension.dart new file mode 100644 index 000000000..d0f234102 --- /dev/null +++ b/core/lib/presentation/extensions/string_extension.dart @@ -0,0 +1,26 @@ + +extension StringExtension on String { + + String get firstLetterToUpperCase { + final listWord = split(' '); + if (listWord.length > 1) { + final regexLetter = RegExp("([A-Za-z])"); + final firstLetterOfFirstWord = regexLetter.firstMatch(listWord[0].trim())?.group(0); + final firstLetterOfSecondWord = regexLetter.firstMatch(listWord[1].trim())?.group(0); + + if (firstLetterOfFirstWord != null && firstLetterOfSecondWord != null) { + return '${firstLetterOfFirstWord.toUpperCase()}${firstLetterOfSecondWord.toUpperCase()}'; + } else if (firstLetterOfFirstWord != null && firstLetterOfSecondWord == null) { + return '${firstLetterOfFirstWord.toUpperCase()}${firstLetterOfFirstWord.toUpperCase()}'; + } else if (firstLetterOfFirstWord == null && firstLetterOfSecondWord != null) { + return '${firstLetterOfSecondWord.toUpperCase()}${firstLetterOfSecondWord.toUpperCase()}'; + } else { + return ''; + } + } else { + final regexLetter = RegExp("([A-Za-z])"); + final firstLetter = regexLetter.firstMatch(trim())?.group(0); + return firstLetter != null ? '${firstLetter.toUpperCase()}${firstLetter.toUpperCase()}' : ''; + } + } +} \ No newline at end of file diff --git a/lib/features/email/presentation/email_controller.dart b/lib/features/email/presentation/email_controller.dart index 781732ce1..a5697439b 100644 --- a/lib/features/email/presentation/email_controller.dart +++ b/lib/features/email/presentation/email_controller.dart @@ -626,11 +626,14 @@ class EmailController extends BaseController with AppLoaderMixin { showDialog( context: context, barrierColor: AppColor.colorDefaultCupertinoActionSheet, - builder: (BuildContext context) => PointerInterceptor(child: (EmailAddressDialogBuilder(context, imagePaths, emailAddress) - ..addOnCloseContextMenuAction(() => popBack()) - ..addOnCopyEmailAddressAction((emailAddress) => copyEmailAddress(context, emailAddress)) - ..addOnComposeEmailAction((emailAddress) => composeEmailFromEmailAddress(emailAddress))) - .build())); + builder: (BuildContext context) => PointerInterceptor( + child: EmailAddressDialogBuilder( + emailAddress, + onCloseDialogAction: () => popBack(), + onCopyEmailAddressAction: (emailAddress) => + copyEmailAddress(context, emailAddress), + onComposeEmailAction: (emailAddress) => + composeEmailFromEmailAddress(emailAddress)))); } } diff --git a/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart b/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart index e685fada9..92e81c102 100644 --- a/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart +++ b/lib/features/email/presentation/widgets/email_address_bottom_sheet_builder.dart @@ -72,25 +72,51 @@ class EmailAddressBottomSheetBuilder { child: IconButton( padding: const EdgeInsets.only(top: 16, right: 16), onPressed: () => _onCloseBottomSheetAction?.call(), - icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))), + icon: SvgPicture.asset( + _imagePaths.icCloseMailbox, + width: 24, height: 24, + fit: BoxFit.fill))), (AvatarBuilder() - ..text(_emailAddress.asString().characters.first.toUpperCase()) + ..text(_emailAddress.asString().firstLetterToUpperCase) ..size(64) - ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white)) + ..addTextStyle(const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 23, + color: Colors.white)) ..avatarColor(_emailAddress.avatarColors)) .build(), if (_emailAddress.displayName.isNotEmpty) Padding( - padding: const EdgeInsets.only(left: 16, right: 16, top: 16), + padding: const EdgeInsets.only( + left: 16, + right: 16, + top: 16), child: Text( - _emailAddress.asString(), - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail), + _emailAddress.displayName, + textAlign: TextAlign.center, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 2, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: AppColor.colorNameEmail), )), Padding( - padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16), + padding: EdgeInsets.only( + left: 16, + right: 16, + top: _emailAddress.displayName.isNotEmpty ? 12 : 16), child: Text( _emailAddress.emailAddress, - style: const TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog), + textAlign: TextAlign.center, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 2, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.normal, + color: AppColor.colorMessageConfirmDialog), )), Material( borderRadius: BorderRadius.circular(20), @@ -98,7 +124,10 @@ class EmailAddressBottomSheetBuilder { child: TextButton( child: Text( AppLocalizations.of(_context).copy_email_address, - style: const TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal), + style: const TextStyle( + fontSize: 13, + color: AppColor.colorTextButton, + fontWeight: FontWeight.normal), ), onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress) ) @@ -112,12 +141,21 @@ class EmailAddressBottomSheetBuilder { height: 48, child: ElevatedButton( style: ButtonStyle( - foregroundColor: MaterialStateProperty.resolveWith((Set states) => Colors.white), - backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.colorTextButton), + foregroundColor: MaterialStateProperty.resolveWith( + (Set states) => Colors.white), + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) => AppColor.colorTextButton), shape: MaterialStateProperty.all(RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), - side: const BorderSide(width: 0, color: AppColor.colorTextButton)))), - child: Text(AppLocalizations.of(_context).compose_email, style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)), + side: const BorderSide( + width: 0, + color: AppColor.colorTextButton)))), + child: Text( + AppLocalizations.of(_context).compose_email, + style: const TextStyle( + fontSize: 16, + color: Colors.white, + fontWeight: FontWeight.w500)), onPressed: () => _onComposeEmailAction?.call(_emailAddress)), ) ) diff --git a/lib/features/email/presentation/widgets/email_address_dialog_builder.dart b/lib/features/email/presentation/widgets/email_address_dialog_builder.dart index fcf23c551..3d0223b85 100644 --- a/lib/features/email/presentation/widgets/email_address_dialog_builder.dart +++ b/lib/features/email/presentation/widgets/email_address_dialog_builder.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:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:model/model.dart'; import 'package:tmail_ui_user/main/localizations/app_localizations.dart'; @@ -10,38 +11,31 @@ typedef OnCloseDialogAction = void Function(); typedef OnCopyEmailAddressDialogAction = void Function(EmailAddress); typedef OnComposeEmailDialogAction = void Function(EmailAddress); -class EmailAddressDialogBuilder { +class EmailAddressDialogBuilder extends StatelessWidget { - final BuildContext _context; - final ImagePaths _imagePaths; final EmailAddress _emailAddress; + final OnCloseDialogAction? onCloseDialogAction; + final OnCopyEmailAddressDialogAction? onCopyEmailAddressAction; + final OnComposeEmailDialogAction? onComposeEmailAction; - OnCloseDialogAction? _onCloseDialogAction; - OnCopyEmailAddressDialogAction? _onCopyEmailAddressAction; - OnComposeEmailDialogAction? _onComposeEmailAction; + const EmailAddressDialogBuilder( + this._emailAddress, { + Key? key, + this.onCloseDialogAction, + this.onCopyEmailAddressAction, + this.onComposeEmailAction, + }) : super(key: key); - EmailAddressDialogBuilder( - this._context, - this._imagePaths, - this._emailAddress - ); + @override + Widget build(BuildContext context) { + final imagePaths = Get.find(); - void addOnCloseContextMenuAction(OnCloseDialogAction onCloseDialogAction) { - _onCloseDialogAction = onCloseDialogAction; - } - - void addOnCopyEmailAddressAction(OnCopyEmailAddressDialogAction onCopyEmailAddressAction) { - _onCopyEmailAddressAction = onCopyEmailAddressAction; - } - - void addOnComposeEmailAction(OnComposeEmailDialogAction onComposeEmailAction) { - _onComposeEmailAction = onComposeEmailAction; - } - - Widget build() { return Dialog( - shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), - insetPadding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(16))), + insetPadding: const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 16.0), child: Container( margin: EdgeInsets.zero, padding: EdgeInsets.zero, @@ -55,28 +49,55 @@ class EmailAddressDialogBuilder { alignment: Alignment.centerRight, child: IconButton( padding: const EdgeInsets.only(top: 16, right: 16), - onPressed: () => _onCloseDialogAction?.call(), - icon: SvgPicture.asset(_imagePaths.icCloseMailbox, width: 24, height: 24, fit: BoxFit.fill))), + onPressed: () => onCloseDialogAction?.call(), + icon: SvgPicture.asset( + imagePaths.icCloseMailbox, + width: 24, + height: 24, + fit: BoxFit.fill))), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: Center(child: (AvatarBuilder() - ..text(_emailAddress.asString().characters.first.toUpperCase()) + ..text(_emailAddress.asString().firstLetterToUpperCase) ..size(64) - ..addTextStyle(const TextStyle(fontWeight: FontWeight.w600, fontSize: 23, color: Colors.white)) + ..addTextStyle(const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 23, + color: Colors.white)) ..avatarColor(_emailAddress.avatarColors)) .build())), if (_emailAddress.displayName.isNotEmpty) Padding( - padding: const EdgeInsets.only(left: 16, right: 16, top: 16), + padding: const EdgeInsets.only( + left: 16, + right: 16, + top: 16), child: Center(child: Text( - _emailAddress.asString(), - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: AppColor.colorNameEmail), + _emailAddress.displayName, + textAlign: TextAlign.center, + maxLines: 2, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: AppColor.colorNameEmail), )) ), Padding( - padding: EdgeInsets.only(left: 16, right: 16, top: _emailAddress.displayName.isNotEmpty ? 12 : 16), + padding: EdgeInsets.only( + left: 16, + right: 16, + top: _emailAddress.displayName.isNotEmpty ? 12 : 16), child: Center(child: Text( _emailAddress.emailAddress, - style: const TextStyle(fontSize: 17, fontWeight: FontWeight.normal, color: AppColor.colorMessageConfirmDialog), + textAlign: TextAlign.center, + overflow: CommonTextStyle.defaultTextOverFlow, + softWrap: CommonTextStyle.defaultSoftWrap, + maxLines: 2, + style: const TextStyle( + fontSize: 17, + fontWeight: FontWeight.normal, + color: AppColor.colorMessageConfirmDialog), )) ), Padding(padding: const EdgeInsets.symmetric(horizontal: 16), @@ -85,10 +106,13 @@ class EmailAddressDialogBuilder { color: Colors.transparent, child: TextButton( child: Text( - AppLocalizations.of(_context).copy_email_address, - style: const TextStyle(fontSize: 13, color: AppColor.colorTextButton, fontWeight: FontWeight.normal), + AppLocalizations.of(context).copy_email_address, + style: const TextStyle( + fontSize: 13, + color: AppColor.colorTextButton, + fontWeight: FontWeight.normal), ), - onPressed: () => _onCopyEmailAddressAction?.call(_emailAddress) + onPressed: () => onCopyEmailAddressAction?.call(_emailAddress) ) ))), SizedBox(height: _emailAddress.displayName.isNotEmpty ? 100 : 130), @@ -100,13 +124,22 @@ class EmailAddressDialogBuilder { height: 48, child: ElevatedButton( style: ButtonStyle( - foregroundColor: MaterialStateProperty.resolveWith((Set states) => Colors.white), - backgroundColor: MaterialStateProperty.resolveWith((Set states) => AppColor.colorTextButton), + foregroundColor: MaterialStateProperty.resolveWith( + (Set states) => Colors.white), + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) => AppColor.colorTextButton), shape: MaterialStateProperty.all(RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), - side: const BorderSide(width: 0, color: AppColor.colorTextButton)))), - child: Text(AppLocalizations.of(_context).compose_email, style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500)), - onPressed: () => _onComposeEmailAction?.call(_emailAddress)), + side: const BorderSide( + width: 0, + color: AppColor.colorTextButton)))), + child: Text( + AppLocalizations.of(context).compose_email, + style: const TextStyle( + fontSize: 16, + color: Colors.white, + fontWeight: FontWeight.w500)), + onPressed: () => onComposeEmailAction?.call(_emailAddress)), ) ) ], diff --git a/model/lib/email/presentation_email.dart b/model/lib/email/presentation_email.dart index 54d72994a..19811086b 100644 --- a/model/lib/email/presentation_email.dart +++ b/model/lib/email/presentation_email.dart @@ -1,4 +1,5 @@ +import 'package:core/core.dart'; import 'package:equatable/equatable.dart'; import 'package:jmap_dart_client/jmap/core/unsigned_int.dart'; import 'package:jmap_dart_client/jmap/core/utc_date.dart'; @@ -52,26 +53,7 @@ class PresentationEmail with EquatableMixin { String getAvatarText() { if (getSenderName().isNotEmpty) { - final listWord = getSenderName().split(' '); - if (listWord.length > 1) { - final regexLetter = RegExp("([A-Za-z])"); - final firstLetterOfFirstWord = regexLetter.firstMatch(listWord[0].trim())?.group(0); - final firstLetterOfSecondWord = regexLetter.firstMatch(listWord[1].trim())?.group(0); - - if (firstLetterOfFirstWord != null && firstLetterOfSecondWord != null) { - return '${firstLetterOfFirstWord.toUpperCase()}${firstLetterOfSecondWord.toUpperCase()}'; - } else if (firstLetterOfFirstWord != null && firstLetterOfSecondWord == null) { - return '${firstLetterOfFirstWord.toUpperCase()}${firstLetterOfFirstWord.toUpperCase()}'; - } else if (firstLetterOfFirstWord == null && firstLetterOfSecondWord != null) { - return '${firstLetterOfSecondWord.toUpperCase()}${firstLetterOfSecondWord.toUpperCase()}'; - } else { - return ''; - } - } else { - final regexLetter = RegExp("([A-Za-z])"); - final firstLetter = regexLetter.firstMatch(getSenderName().trim())?.group(0); - return firstLetter != null ? '${firstLetter.toUpperCase()}${firstLetter.toUpperCase()}' : ''; - } + return getSenderName().firstLetterToUpperCase; } return ''; }