From ea1dc320765e0ebc0c30d60afe86634466e7eb6a Mon Sep 17 00:00:00 2001 From: Magellan Date: Mon, 27 Apr 2026 18:00:48 +0300 Subject: [PATCH 1/3] update date widget --- .../bloc/conversations_list_bloc.dart | 2 +- .../view/conversations_list.dart | 6 -- .../widgets/conversation_list_item.dart | 89 ++++++++++--------- 3 files changed, 48 insertions(+), 49 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart index ce95b566..065ff556 100644 --- a/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart +++ b/sama_chat_client/lib/src/features/conversations_list/bloc/conversations_list_bloc.dart @@ -52,7 +52,7 @@ class ConversationsBloc extends Bloc { add(ConversationsRefreshed()); if (state.typingStatuses.containsKey(chat.id)) { - add(TypingStatusStopReceived(chat.id, chat.lastMessage!.from!)); + add(TypingStatusStopReceived(chat.id, chat.lastMessage!.from)); } } }); diff --git a/sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart b/sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart index 59156c3e..ac8878fc 100644 --- a/sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart +++ b/sama_chat_client/lib/src/features/conversations_list/view/conversations_list.dart @@ -27,12 +27,6 @@ class _ConversationsListState extends State with RouteAware { routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); } - @override - void didPopNext() { - // TODO RP for now not using - // context.read().add(ConversationsRefreshed()); - } - @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart index 4a83b3e4..9d709192 100644 --- a/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart +++ b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart @@ -128,62 +128,67 @@ class DateUnreadWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only(right: 2), - child: Text( - DateFormatter().getVerboseDateTimeRepresentation( - (conversation.lastMessage?.t != null - ? DateTime.fromMillisecondsSinceEpoch( - conversation.lastMessage!.t! * 1000) - : conversation.updatedAt!)), - style: const TextStyle(color: whiteAluminum, fontSize: 15), - ), - ), - if (conversation.unreadMessagesCount != null && - conversation.unreadMessagesCount != 0) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 6), - decoration: BoxDecoration( - color: slateBlue, borderRadius: BorderRadius.circular(10.0)), + return Padding( + padding: const EdgeInsets.only(top: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(right: 2), child: Text( - conversation.unreadMessagesCount.toString(), - style: const TextStyle(color: white), + DateFormatter().getVerboseDateTimeRepresentation( + (conversation.lastMessage?.t != null + ? DateTime.fromMillisecondsSinceEpoch( + conversation.lastMessage!.t! * 1000) + : conversation.updatedAt)), + style: const TextStyle(color: whiteAluminum, fontSize: 13), ), ), - ), - ], - ); + if (conversation.unreadMessagesCount != null && + conversation.unreadMessagesCount != 0) + Padding( + padding: const EdgeInsets.only(top: 4), + child: Container( + padding: + const EdgeInsets.symmetric(vertical: 2, horizontal: 6), + decoration: BoxDecoration( + color: slateBlue, + borderRadius: BorderRadius.circular(10.0)), + child: Text( + conversation.unreadMessagesCount.toString(), + style: const TextStyle(color: white), + ), + ), + ), + ], + )); } } class DateFormatter { - String getVerboseDateTimeRepresentation(DateTime dateTime) { - DateTime now = DateTime.now(); - DateTime justNow = DateTime.now().subtract(const Duration(minutes: 1)); + String getVerboseDateTimeRepresentation(DateTime date) { + final now = DateTime.now(); + final difference = now.difference(date); - DateTime localDateTime = dateTime.toLocal(); + if (difference.inMinutes < 1) { + return 'Just now'; + } - if (!localDateTime.difference(justNow).isNegative) { - return DateFormat('jm').format(dateTime); + if (now.year == date.year && + now.month == date.month && + now.day == date.day) { + return DateFormat('HH:mm').format(date); } - String roughTimeString = DateFormat('jm').format(dateTime); - if (localDateTime.day == now.day && - localDateTime.month == now.month && - localDateTime.year == now.year) { - return roughTimeString; + final startOfWeek = now.subtract(Duration(days: now.weekday - 1)); + if (date.isAfter(startOfWeek)) { + return DateFormat('EEE').format(date).toLowerCase(); } - if (now.difference(localDateTime).inDays < 4) { - String weekday = DateFormat('EEEE').format(localDateTime); - return weekday.substring(0, 2); + if (now.year == date.year) { + return DateFormat('dd.MM').format(date); } - return DateFormat.yMd().format(dateTime); + return DateFormat('dd.MM.yy').format(date); } } From 3913437bdcda3c159be0f75bffa968c3627e3ead Mon Sep 17 00:00:00 2001 From: Magellan Date: Mon, 27 Apr 2026 20:20:57 +0300 Subject: [PATCH 2/3] update avatar color --- .../widgets/avatar_group_icon.dart | 7 +++--- .../widgets/avatar_letter_icon.dart | 11 +++++---- .../widgets/conversation_list_item.dart | 2 +- .../lib/src/shared/ui/colors.dart | 24 +++++++++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart index f8118d2f..4dd3f588 100644 --- a/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart +++ b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_group_icon.dart @@ -4,16 +4,17 @@ import '../../../db/models/avatar_model.dart'; import '../../../shared/ui/colors.dart'; class AvatarGroupIcon extends StatelessWidget { - const AvatarGroupIcon(this.avatar, {super.key}); + const AvatarGroupIcon(this.avatar, this.name, {super.key}); final AvatarModel? avatar; + final String name; final Size size = const Size(55, 60); @override Widget build(BuildContext context) { return Container( - decoration: const BoxDecoration( - color: black, + decoration: BoxDecoration( + color: getAvatarColor(name), shape: BoxShape.circle, ), height: size.height, diff --git a/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart index 5078004f..4e9028ff 100644 --- a/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart +++ b/sama_chat_client/lib/src/features/conversations_list/widgets/avatar_letter_icon.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import '../../../db/models/avatar_model.dart'; import '../../../shared/ui/colors.dart'; +import '../../../shared/utils/string_utils.dart'; class AvatarLetterIcon extends StatelessWidget { const AvatarLetterIcon({ @@ -10,8 +11,8 @@ class AvatarLetterIcon extends StatelessWidget { super.key, this.size = const Size(55, 55), this.padding = EdgeInsets.zero, - this.backgroundColor = black, - this.textColor = dullGray, + this.backgroundColor, + this.textColor = signalBlack, this.avatar, this.isDeleted, }); @@ -21,7 +22,7 @@ class AvatarLetterIcon extends StatelessWidget { final String? lastName; final Size size; final EdgeInsetsGeometry padding; - final Color backgroundColor; + final Color? backgroundColor; final Color textColor; final AvatarModel? avatar; final bool? isDeleted; @@ -38,7 +39,9 @@ class AvatarLetterIcon extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration( - color: backgroundColor, + color: isDeleted ?? false + ? black + : backgroundColor ?? getAvatarColor(name + (lastName ?? '')), shape: BoxShape.circle, // border: Border.all(color: whiteAluminum, width: 2), ), diff --git a/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart index 9d709192..715ab3cd 100644 --- a/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart +++ b/sama_chat_client/lib/src/features/conversations_list/widgets/conversation_list_item.dart @@ -32,7 +32,7 @@ class ConversationListItem extends StatelessWidget { avatar: conversation.avatar, isDeleted: isDeletedUser(conversation.opponent), ) - : AvatarGroupIcon(conversation.avatar), + : AvatarGroupIcon(conversation.avatar, conversation.name), title: Text( conversation.name, style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 20), diff --git a/sama_chat_client/lib/src/shared/ui/colors.dart b/sama_chat_client/lib/src/shared/ui/colors.dart index e6d520fc..2acd4ef6 100644 --- a/sama_chat_client/lib/src/shared/ui/colors.dart +++ b/sama_chat_client/lib/src/shared/ui/colors.dart @@ -1,5 +1,7 @@ import 'dart:ui'; +import 'package:flutter/material.dart'; + const Color white = Color(0xFFFFFFFF); const Color lightWhite = Color(0xFFF9F9F9); const Color smokyWhite = Color(0xFFF6F6F6); @@ -23,3 +25,25 @@ const Color lightPink = Color(0xFFFFB6C1); const Color orange = Color(0xFFFFA500); const Color redPurple = Color(0xFF68174D); const Color red = Color(0xFFDF2E38); + +const colors = [ + Color(0xFFe17076), // red + Color(0xFFf4a261), // orange + Color(0xFFe9c46a), // yellow + Color(0xFF2a9d8f), // teal + Color(0xFF4d96ff), // blue + Color(0xFF9b5de5), // purple + Color(0xFFf15bb5), // pink + Color(0xFF00bcd4), // cyan +]; + +Color getAvatarColor(String input) { + final hash = input.runes.fold(0, (prev, el) => prev * 31 + el); + final index = hash.abs() % colors.length; + + final saturation = 0.35 + ((hash >> 8) % 40) / 100; // 0.35–0.75 + final lightness = 0.55 + ((hash >> 16) % 20) / 100; // 0.55–0.75 + + final hsl = HSLColor.fromColor(colors[index]); + return hsl.withSaturation(saturation).withLightness(lightness).toColor(); +} From d0a26f934472aba0ac2ce1370feafa3f8e3c1318 Mon Sep 17 00:00:00 2001 From: Magellan Date: Mon, 4 May 2026 17:34:54 +0300 Subject: [PATCH 3/3] update profile bloc --- .../features/profile/bloc/profile_bloc.dart | 21 +++++++++---------- .../features/profile/bloc/profile_event.dart | 9 +------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart index 8c5ca4aa..7d94e1da 100644 --- a/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart +++ b/sama_chat_client/lib/src/features/profile/bloc/profile_bloc.dart @@ -29,26 +29,25 @@ class ProfileBloc extends Bloc { on(_onResetChanges); on(_onSubmitted); - _userRepository.getCurrentUser().then((user) { - add(ProfileUserReceived(user)); - }); + add(ProfileUserReceived()); } final UserRepository _userRepository; - void _onUserReceived( + Future _onUserReceived( ProfileUserReceived event, Emitter emit, - ) { + ) async { + var user = await _userRepository.getCurrentUser(); emit( state.copyWith( status: FormzSubmissionStatus.initial, - userLogin: event.user?.login, - userAvatar: UserAvatar.pure(event.user?.avatar?.imageUrl ?? ''), - userFirstname: UserFirstname.pure(event.user?.firstName ?? ''), - userLastname: UserLastname.pure(event.user?.lastName ?? ''), - userPhone: UserPhone.pure(event.user?.phone ?? ''), - userEmail: UserEmail.pure(event.user?.email ?? '')), + userLogin: user?.login, + userAvatar: UserAvatar.pure(user?.avatar?.imageUrl ?? ''), + userFirstname: UserFirstname.pure(user?.firstName ?? ''), + userLastname: UserLastname.pure(user?.lastName ?? ''), + userPhone: UserPhone.pure(user?.phone ?? ''), + userEmail: UserEmail.pure(user?.email ?? '')), ); } diff --git a/sama_chat_client/lib/src/features/profile/bloc/profile_event.dart b/sama_chat_client/lib/src/features/profile/bloc/profile_event.dart index 6b2c0f92..4358a49b 100644 --- a/sama_chat_client/lib/src/features/profile/bloc/profile_event.dart +++ b/sama_chat_client/lib/src/features/profile/bloc/profile_event.dart @@ -7,14 +7,7 @@ sealed class ProfileEvent extends Equatable { List get props => []; } -final class ProfileUserReceived extends ProfileEvent { - const ProfileUserReceived(this.user); - - final UserModel? user; - - @override - List get props => [user]; -} +final class ProfileUserReceived extends ProfileEvent {} final class ProfileAvatarPicked extends ProfileEvent {}