diff --git a/core/lib/presentation/extensions/color_extension.dart b/core/lib/presentation/extensions/color_extension.dart index 6c1e4f997..1f00a5271 100644 --- a/core/lib/presentation/extensions/color_extension.dart +++ b/core/lib/presentation/extensions/color_extension.dart @@ -61,5 +61,14 @@ extension AppColor on Color { static const backgroundCountAttachment = Color(0x681C1C1C); static const bgStatusResultSearch = Color(0xFFF5F5F7); static const bgWordSearch = Color(0xFFD7D6FC); + + static const mapGradientColor = [ + [Color(0xFF21D4FD), Color(0xFFB721FF)], + [Color(0xFF43E97B), Color(0xFF38F9D7)], + [Color(0xFF11E6F0), Color(0xFF4FACFE)], + [Color(0xFFE88395), Color(0xFFEF9C8F)], + [Color(0xFF8DDAD5), Color(0xFF00CDAC)], + [Color(0xFFDE9AF5), Color(0xFFD670EE)], + ]; } diff --git a/core/lib/presentation/views/image/avatar_builder.dart b/core/lib/presentation/views/image/avatar_builder.dart index b03cfdf5b..35cb7fd6e 100644 --- a/core/lib/presentation/views/image/avatar_builder.dart +++ b/core/lib/presentation/views/image/avatar_builder.dart @@ -10,21 +10,20 @@ class AvatarBuilder { double? _size; // String? _iconStatus; Color? _bgColor; + Color? _textColor; OnTapAvatarActionClick? _onTapAvatarActionClick; + List? _avatarColors; - AvatarBuilder key(Key key) { + void key(Key key) { _key = key; - return this; } - AvatarBuilder size(double size) { + void size(double size) { _size = size; - return this; } - AvatarBuilder text(String text) { + void text(String text) { _text = text; - return this; } // AvatarBuilder iconStatus(String iconStatus) { @@ -32,14 +31,20 @@ class AvatarBuilder { // return this; // } - AvatarBuilder backgroundColor(Color bgColor) { + void backgroundColor(Color bgColor) { _bgColor = bgColor; - return this; } - AvatarBuilder addOnTapActionClick(OnTapAvatarActionClick onTapAvatarActionClick) { + void textColor(Color textColor) { + _textColor = textColor; + } + + void avatarColor(List? avatarColors) { + _avatarColors = avatarColors; + } + + void addOnTapActionClick(OnTapAvatarActionClick onTapAvatarActionClick) { _onTapAvatarActionClick = onTapAvatarActionClick; - return this; } Widget build() { @@ -61,11 +66,17 @@ class AvatarBuilder { alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular((_size ?? 40) / 2), - border: Border.all(color: Colors.white), + border: Border.all(color: Colors.transparent), + gradient: _avatarColors?.isNotEmpty == true + ? LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: _avatarColors ?? []) + : null, color: _bgColor ?? AppColor.avatarColor), child: Text( '${_text ?? ''}', - style: TextStyle(fontSize: 20, color: AppColor.avatarTextColor, fontWeight: FontWeight.w500))), + style: TextStyle(fontSize: 20, color: _textColor ?? AppColor.avatarTextColor, fontWeight: FontWeight.w500))), // if (_iconStatus != null && _iconStatus!.isNotEmpty) // Align( // child: SvgPicture.asset(_iconStatus!, width: 12, height: 12, fit: BoxFit.fill), diff --git a/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart b/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart index 29fbe866a..e8f501bae 100644 --- a/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart +++ b/lib/features/email/presentation/widgets/sender_and_receiver_information_tile_builder.dart @@ -45,9 +45,9 @@ class SenderAndReceiverInformationTileBuilder { child: ListTile( leading: Transform( transform: Matrix4.translationValues(-15.0, -8.0, 0.0), - child: AvatarBuilder() - .text('${_presentationEmail!.getAvatarText()}') - .size(40) + child: (AvatarBuilder() + ..text('${_presentationEmail!.getAvatarText()}') + ..size(40)) // .iconStatus(_imagePaths.icOffline) .build()), title: Transform( diff --git a/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart b/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart index ea5e9b79e..fa6c6cdd6 100644 --- a/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart +++ b/lib/features/mailbox/presentation/widgets/user_information_widget_builder.dart @@ -38,9 +38,9 @@ class UserInformationWidgetBuilder { _onOpenUserInformationActionClick!(); } }, - leading: AvatarBuilder() - .text(_userProfile != null ? _userProfile!.getAvatarText() : '') - .size(40) + leading: (AvatarBuilder() + ..text(_userProfile != null ? _userProfile!.getAvatarText() : '') + ..size(40)) .build(), title: Transform( transform: Matrix4.translationValues(0.0, 0.0, 0.0), diff --git a/lib/features/thread/presentation/thread_controller.dart b/lib/features/thread/presentation/thread_controller.dart index aa224b610..d7a8ae1ed 100644 --- a/lib/features/thread/presentation/thread_controller.dart +++ b/lib/features/thread/presentation/thread_controller.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:core/core.dart'; import 'package:core/presentation/utils/responsive_utils.dart'; import 'package:dartz/dartz.dart'; @@ -63,6 +65,8 @@ class ThreadController extends BaseController { final emailListSearch = [].obs; final currentSelectMode = SelectMode.INACTIVE.obs; + final random = Random(); + bool canLoadMore = true; bool canSearchMore = true; MailboxId? _currentMailboxId; @@ -207,7 +211,10 @@ class ThreadController extends BaseController { void _getAllEmailSuccess(GetAllEmailSuccess success) { _currentEmailState = success.currentEmailState; - emailList.value = success.emailList; + final listEmailHaveAvatarGradientColor = success.emailList + .map((email) => email.asAvatarGradientColor(random)) + .toList(); + emailList.value = listEmailHaveAvatarGradientColor; } void _getAllEmailAction(AccountId accountId, {MailboxId? mailboxId}) { @@ -271,7 +278,10 @@ class ThreadController extends BaseController { void _loadMoreEmailsSuccess(LoadMoreEmailsSuccess success) { if (success.emailList.isNotEmpty) { - emailList.addAll(success.emailList); + final listEmailHaveAvatarGradientColor = success.emailList + .map((email) => email.asAvatarGradientColor(random)) + .toList(); + emailList.addAll(listEmailHaveAvatarGradientColor); } else { canLoadMore = false; } diff --git a/lib/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart b/lib/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart index a378b3e6a..a333375a1 100644 --- a/lib/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart +++ b/lib/features/thread/presentation/widgets/app_bar_thread_widget_builder.dart @@ -74,9 +74,9 @@ class AppBarThreadWidgetBuilder { }}, child: Padding( padding: EdgeInsets.zero, - child: AvatarBuilder() - .text(_userProfile != null ? _userProfile!.getAvatarText() : '') - .size(36) + child: (AvatarBuilder() + ..text(_userProfile != null ? _userProfile!.getAvatarText() : '') + ..size(36)) .build())); } diff --git a/lib/features/thread/presentation/widgets/email_tile_builder.dart b/lib/features/thread/presentation/widgets/email_tile_builder.dart index fd913d513..de0b3860b 100644 --- a/lib/features/thread/presentation/widgets/email_tile_builder.dart +++ b/lib/features/thread/presentation/widgets/email_tile_builder.dart @@ -81,7 +81,7 @@ class EmailTileBuilder { } }, leading: Transform( - transform: Matrix4.translationValues(-10.0, -10.0, 0.0), + transform: Matrix4.translationValues(-10.0, -2.0, 0.0), child: _buildAvatarIcon()), title: Transform( transform: Matrix4.translationValues(-10.0, 0.0, 0.0), @@ -216,7 +216,7 @@ class EmailTileBuilder { ); } - Widget _buildAvatarIcon () { + Widget _buildAvatarIcon() { if (_selectModeAll == SelectMode.ACTIVE) { return AnimatedSwitcher( duration: Duration(milliseconds: 600), @@ -228,20 +228,24 @@ class EmailTileBuilder { _onSelectEmailActionClick!(_presentationEmail); }})) .build() - : AvatarBuilder() - .text('${_presentationEmail.getAvatarText()}') - .size(40) - // .iconStatus(_imagePaths.icOffline) - .addOnTapActionClick(() { - if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) { - _onSelectEmailActionClick!(_presentationEmail); - }}) + : (AvatarBuilder() + ..text('${_presentationEmail.getAvatarText()}') + ..size(56) + ..textColor(Colors.white) + ..avatarColor(_presentationEmail.avatarColors) + // .iconStatus(_imagePaths.icOffline) + ..addOnTapActionClick(() { + if (_selectModeAll == SelectMode.ACTIVE && _onSelectEmailActionClick != null) { + _onSelectEmailActionClick!(_presentationEmail); + }})) .build() ); } else { - return AvatarBuilder() - .text('${_presentationEmail.getAvatarText()}') - .size(40) + return (AvatarBuilder() + ..text('${_presentationEmail.getAvatarText()}') + ..size(56) + ..textColor(Colors.white) + ..avatarColor(_presentationEmail.avatarColors)) // .iconStatus(_imagePaths.icOffline) .build(); } diff --git a/model/lib/email/presentation_email.dart b/model/lib/email/presentation_email.dart index 3961602b0..a84d6a3f1 100644 --- a/model/lib/email/presentation_email.dart +++ b/model/lib/email/presentation_email.dart @@ -1,4 +1,6 @@ +import 'dart:ui'; + 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'; @@ -26,6 +28,7 @@ class PresentationEmail with EquatableMixin { final Map? mailboxIds; final List? mailboxNames; final SelectMode selectMode; + final List? avatarColors; PresentationEmail( this.id, @@ -44,7 +47,8 @@ class PresentationEmail with EquatableMixin { this.replyTo, this.mailboxIds, this.mailboxNames, - this.selectMode = SelectMode.INACTIVE + this.selectMode = SelectMode.INACTIVE, + this.avatarColors, } ); @@ -52,9 +56,26 @@ class PresentationEmail with EquatableMixin { String getAvatarText() { if (getSenderName().isNotEmpty) { - final regexLetter = RegExp("([A-Za-z])"); - final firstLetter = regexLetter.firstMatch(getSenderName().trim())?.group(0); - return firstLetter != null ? firstLetter.toUpperCase() : ''; + 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 ''; } diff --git a/model/lib/extensions/presentation_email_extension.dart b/model/lib/extensions/presentation_email_extension.dart index 64c68e9f5..dd9f7d150 100644 --- a/model/lib/extensions/presentation_email_extension.dart +++ b/model/lib/extensions/presentation_email_extension.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:core/core.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:dartz/dartz.dart'; @@ -136,7 +138,32 @@ extension PresentationEmailExtension on PresentationEmail { replyTo: replyTo, mailboxIds: mailboxIds, mailboxNames: listMailboxName, - selectMode: selectMode + selectMode: selectMode, + avatarColors: avatarColors + ); + } + + PresentationEmail asAvatarGradientColor(Random random) { + final newAvatarColors = AppColor.mapGradientColor[random.nextInt(AppColor.mapGradientColor.length)]; + + return PresentationEmail( + this.id, + keywords: keywords, + size: size, + receivedAt: receivedAt, + hasAttachment: hasAttachment, + preview: preview, + subject: subject, + sentAt: sentAt, + from: from, + to: to, + cc: cc, + bcc: bcc, + replyTo: replyTo, + mailboxIds: mailboxIds, + mailboxNames: mailboxNames, + selectMode: selectMode, + avatarColors: avatarColors ?? newAvatarColors, ); } } \ No newline at end of file