From 292e6c8834b60e5a642517b574bb202458dfb355 Mon Sep 17 00:00:00 2001 From: krille-chan Date: Sun, 10 Mar 2024 14:56:45 +0100 Subject: [PATCH] design: Connect bubbles from same sender --- lib/pages/chat/chat_event_list.dart | 1 + lib/pages/chat/events/message.dart | 48 ++++++++++++------- .../settings_style/settings_style_view.dart | 9 ++-- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index b1e67f10e..a35acb234 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -144,6 +144,7 @@ class ChatEventList extends StatelessWidget { controller.readMarkerEventId == event.eventId && controller.timeline?.allowNewEvent == false, nextEvent: i + 1 < events.length ? events[i + 1] : null, + previousEvent: i > 0 ? events[i - 1] : null, avatarPresenceBackgroundColor: hasWallpaper ? Colors.transparent : null, ), diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 5c52d362f..23a532f35 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -21,6 +21,7 @@ import 'verification_request_content.dart'; class Message extends StatelessWidget { final Event event; final Event? nextEvent; + final Event? previousEvent; final bool displayReadMarker; final void Function(Event) onSelect; final void Function(Event) onAvatarTab; @@ -38,6 +39,7 @@ class Message extends StatelessWidget { const Message( this.event, { this.nextEvent, + this.previousEvent, this.displayReadMarker = false, this.longPressSelect = false, required this.onSelect, @@ -80,31 +82,39 @@ class Message extends StatelessWidget { final displayTime = event.type == EventTypes.RoomCreate || nextEvent == null || !event.originServerTs.sameEnvironment(nextEvent!.originServerTs); - final sameSender = nextEvent != null && + final nextEventSameSender = nextEvent != null && { EventTypes.Message, EventTypes.Sticker, EventTypes.Encrypted, }.contains(nextEvent!.type) && - nextEvent?.relationshipType == null && nextEvent!.senderId == event.senderId && !displayTime; + + final previousEventSameSender = previousEvent != null && + { + EventTypes.Message, + EventTypes.Sticker, + EventTypes.Encrypted, + }.contains(previousEvent!.type) && + previousEvent!.senderId == event.senderId; + final textColor = ownMessage - ? Theme.of(context).colorScheme.onPrimaryContainer - : Theme.of(context).colorScheme.onBackground; + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.onSurfaceVariant; final rowMainAxisAlignment = ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start; final displayEvent = event.getDisplayEvent(timeline); + const hardCorner = Radius.circular(4); + const roundedCorner = Radius.circular(AppConfig.borderRadius); final borderRadius = BorderRadius.only( - topLeft: !ownMessage - ? const Radius.circular(4) - : const Radius.circular(AppConfig.borderRadius), - topRight: const Radius.circular(AppConfig.borderRadius), - bottomLeft: const Radius.circular(AppConfig.borderRadius), - bottomRight: ownMessage - ? const Radius.circular(4) - : const Radius.circular(AppConfig.borderRadius), + topLeft: !ownMessage && nextEventSameSender ? hardCorner : roundedCorner, + topRight: ownMessage && nextEventSameSender ? hardCorner : roundedCorner, + bottomLeft: + !ownMessage && previousEventSameSender ? hardCorner : roundedCorner, + bottomRight: + ownMessage && previousEventSameSender ? hardCorner : roundedCorner, ); final noBubble = { MessageTypes.Video, @@ -120,7 +130,7 @@ class Message extends StatelessWidget { if (ownMessage) { color = displayEvent.status.isError ? Colors.redAccent - : Theme.of(context).colorScheme.primaryContainer; + : Theme.of(context).colorScheme.primary; } final resetAnimateIn = this.resetAnimateIn; @@ -152,7 +162,7 @@ class Message extends StatelessWidget { onChanged: (_) => onSelect(event), ), ) - else if (sameSender || ownMessage) + else if (nextEventSameSender || ownMessage) SizedBox( width: Avatar.defaultSize, child: Center( @@ -189,7 +199,7 @@ class Message extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - if (!sameSender) + if (!nextEventSameSender) Padding( padding: const EdgeInsets.only(left: 8.0, bottom: 4), child: ownMessage || event.room.isDirectChat @@ -454,9 +464,11 @@ class Message extends StatelessWidget { constraints: const BoxConstraints( maxWidth: FluffyThemes.columnWidth * 2.5, ), - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 4.0, + padding: EdgeInsets.only( + left: 8.0, + right: 8.0, + top: nextEventSameSender ? 1.0 : 4.0, + bottom: previousEventSameSender ? 1.0 : 4.0, ), child: container, ), diff --git a/lib/pages/settings_style/settings_style_view.dart b/lib/pages/settings_style/settings_style_view.dart index 5de60c133..ed80e8268 100644 --- a/lib/pages/settings_style/settings_style_view.dart +++ b/lib/pages/settings_style/settings_style_view.dart @@ -230,9 +230,7 @@ class SettingsStyleView extends StatelessWidget { bottom: 12, ), child: Material( - color: Theme.of(context) - .colorScheme - .primaryContainer, + color: Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular( AppConfig.borderRadius, ), @@ -244,9 +242,8 @@ class SettingsStyleView extends StatelessWidget { child: Text( 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onPrimaryContainer, + color: + Theme.of(context).colorScheme.onPrimary, fontSize: AppConfig.messageFontSize * AppConfig.fontSizeFactor, ),