design: Connect bubbles from same sender
This commit is contained in:
parent
ca79beeddb
commit
292e6c8834
3 changed files with 34 additions and 24 deletions
|
|
@ -144,6 +144,7 @@ class ChatEventList extends StatelessWidget {
|
||||||
controller.readMarkerEventId == event.eventId &&
|
controller.readMarkerEventId == event.eventId &&
|
||||||
controller.timeline?.allowNewEvent == false,
|
controller.timeline?.allowNewEvent == false,
|
||||||
nextEvent: i + 1 < events.length ? events[i + 1] : null,
|
nextEvent: i + 1 < events.length ? events[i + 1] : null,
|
||||||
|
previousEvent: i > 0 ? events[i - 1] : null,
|
||||||
avatarPresenceBackgroundColor:
|
avatarPresenceBackgroundColor:
|
||||||
hasWallpaper ? Colors.transparent : null,
|
hasWallpaper ? Colors.transparent : null,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import 'verification_request_content.dart';
|
||||||
class Message extends StatelessWidget {
|
class Message extends StatelessWidget {
|
||||||
final Event event;
|
final Event event;
|
||||||
final Event? nextEvent;
|
final Event? nextEvent;
|
||||||
|
final Event? previousEvent;
|
||||||
final bool displayReadMarker;
|
final bool displayReadMarker;
|
||||||
final void Function(Event) onSelect;
|
final void Function(Event) onSelect;
|
||||||
final void Function(Event) onAvatarTab;
|
final void Function(Event) onAvatarTab;
|
||||||
|
|
@ -38,6 +39,7 @@ class Message extends StatelessWidget {
|
||||||
const Message(
|
const Message(
|
||||||
this.event, {
|
this.event, {
|
||||||
this.nextEvent,
|
this.nextEvent,
|
||||||
|
this.previousEvent,
|
||||||
this.displayReadMarker = false,
|
this.displayReadMarker = false,
|
||||||
this.longPressSelect = false,
|
this.longPressSelect = false,
|
||||||
required this.onSelect,
|
required this.onSelect,
|
||||||
|
|
@ -80,31 +82,39 @@ class Message extends StatelessWidget {
|
||||||
final displayTime = event.type == EventTypes.RoomCreate ||
|
final displayTime = event.type == EventTypes.RoomCreate ||
|
||||||
nextEvent == null ||
|
nextEvent == null ||
|
||||||
!event.originServerTs.sameEnvironment(nextEvent!.originServerTs);
|
!event.originServerTs.sameEnvironment(nextEvent!.originServerTs);
|
||||||
final sameSender = nextEvent != null &&
|
final nextEventSameSender = nextEvent != null &&
|
||||||
{
|
{
|
||||||
EventTypes.Message,
|
EventTypes.Message,
|
||||||
EventTypes.Sticker,
|
EventTypes.Sticker,
|
||||||
EventTypes.Encrypted,
|
EventTypes.Encrypted,
|
||||||
}.contains(nextEvent!.type) &&
|
}.contains(nextEvent!.type) &&
|
||||||
nextEvent?.relationshipType == null &&
|
|
||||||
nextEvent!.senderId == event.senderId &&
|
nextEvent!.senderId == event.senderId &&
|
||||||
!displayTime;
|
!displayTime;
|
||||||
|
|
||||||
|
final previousEventSameSender = previousEvent != null &&
|
||||||
|
{
|
||||||
|
EventTypes.Message,
|
||||||
|
EventTypes.Sticker,
|
||||||
|
EventTypes.Encrypted,
|
||||||
|
}.contains(previousEvent!.type) &&
|
||||||
|
previousEvent!.senderId == event.senderId;
|
||||||
|
|
||||||
final textColor = ownMessage
|
final textColor = ownMessage
|
||||||
? Theme.of(context).colorScheme.onPrimaryContainer
|
? Theme.of(context).colorScheme.onPrimary
|
||||||
: Theme.of(context).colorScheme.onBackground;
|
: Theme.of(context).colorScheme.onSurfaceVariant;
|
||||||
final rowMainAxisAlignment =
|
final rowMainAxisAlignment =
|
||||||
ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start;
|
ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start;
|
||||||
|
|
||||||
final displayEvent = event.getDisplayEvent(timeline);
|
final displayEvent = event.getDisplayEvent(timeline);
|
||||||
|
const hardCorner = Radius.circular(4);
|
||||||
|
const roundedCorner = Radius.circular(AppConfig.borderRadius);
|
||||||
final borderRadius = BorderRadius.only(
|
final borderRadius = BorderRadius.only(
|
||||||
topLeft: !ownMessage
|
topLeft: !ownMessage && nextEventSameSender ? hardCorner : roundedCorner,
|
||||||
? const Radius.circular(4)
|
topRight: ownMessage && nextEventSameSender ? hardCorner : roundedCorner,
|
||||||
: const Radius.circular(AppConfig.borderRadius),
|
bottomLeft:
|
||||||
topRight: const Radius.circular(AppConfig.borderRadius),
|
!ownMessage && previousEventSameSender ? hardCorner : roundedCorner,
|
||||||
bottomLeft: const Radius.circular(AppConfig.borderRadius),
|
bottomRight:
|
||||||
bottomRight: ownMessage
|
ownMessage && previousEventSameSender ? hardCorner : roundedCorner,
|
||||||
? const Radius.circular(4)
|
|
||||||
: const Radius.circular(AppConfig.borderRadius),
|
|
||||||
);
|
);
|
||||||
final noBubble = {
|
final noBubble = {
|
||||||
MessageTypes.Video,
|
MessageTypes.Video,
|
||||||
|
|
@ -120,7 +130,7 @@ class Message extends StatelessWidget {
|
||||||
if (ownMessage) {
|
if (ownMessage) {
|
||||||
color = displayEvent.status.isError
|
color = displayEvent.status.isError
|
||||||
? Colors.redAccent
|
? Colors.redAccent
|
||||||
: Theme.of(context).colorScheme.primaryContainer;
|
: Theme.of(context).colorScheme.primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
final resetAnimateIn = this.resetAnimateIn;
|
final resetAnimateIn = this.resetAnimateIn;
|
||||||
|
|
@ -152,7 +162,7 @@ class Message extends StatelessWidget {
|
||||||
onChanged: (_) => onSelect(event),
|
onChanged: (_) => onSelect(event),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (sameSender || ownMessage)
|
else if (nextEventSameSender || ownMessage)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: Avatar.defaultSize,
|
width: Avatar.defaultSize,
|
||||||
child: Center(
|
child: Center(
|
||||||
|
|
@ -189,7 +199,7 @@ class Message extends StatelessWidget {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (!sameSender)
|
if (!nextEventSameSender)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 8.0, bottom: 4),
|
padding: const EdgeInsets.only(left: 8.0, bottom: 4),
|
||||||
child: ownMessage || event.room.isDirectChat
|
child: ownMessage || event.room.isDirectChat
|
||||||
|
|
@ -454,9 +464,11 @@ class Message extends StatelessWidget {
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: FluffyThemes.columnWidth * 2.5,
|
maxWidth: FluffyThemes.columnWidth * 2.5,
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: EdgeInsets.only(
|
||||||
horizontal: 8.0,
|
left: 8.0,
|
||||||
vertical: 4.0,
|
right: 8.0,
|
||||||
|
top: nextEventSameSender ? 1.0 : 4.0,
|
||||||
|
bottom: previousEventSameSender ? 1.0 : 4.0,
|
||||||
),
|
),
|
||||||
child: container,
|
child: container,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -230,9 +230,7 @@ class SettingsStyleView extends StatelessWidget {
|
||||||
bottom: 12,
|
bottom: 12,
|
||||||
),
|
),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context).colorScheme.primary,
|
||||||
.colorScheme
|
|
||||||
.primaryContainer,
|
|
||||||
borderRadius: BorderRadius.circular(
|
borderRadius: BorderRadius.circular(
|
||||||
AppConfig.borderRadius,
|
AppConfig.borderRadius,
|
||||||
),
|
),
|
||||||
|
|
@ -244,9 +242,8 @@ class SettingsStyleView extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor',
|
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color:
|
||||||
.colorScheme
|
Theme.of(context).colorScheme.onPrimary,
|
||||||
.onPrimaryContainer,
|
|
||||||
fontSize: AppConfig.messageFontSize *
|
fontSize: AppConfig.messageFontSize *
|
||||||
AppConfig.fontSizeFactor,
|
AppConfig.fontSizeFactor,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue