From 5c6cc1d584e89359e261872ee7cf0c07c00a70db Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Tue, 19 May 2026 22:55:29 -0400 Subject: [PATCH] fix PMP rendering, add grouping --- lib/models/event.dart | 12 +++--- lib/widgets/renderers/event.dart | 4 +- lib/widgets/room_chat.dart | 71 +++++++++++++++++--------------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/lib/models/event.dart b/lib/models/event.dart index c74e2f3..c54dbc5 100644 --- a/lib/models/event.dart +++ b/lib/models/event.dart @@ -8,11 +8,6 @@ part "event.g.dart"; @freezed abstract class Event with _$Event { - static Profile? pmpFromJson(Map? json) { - final pmp = json?["content"]?["com.beeper.per_message_profile"]; - return pmp == null ? null : Profile.fromJsonWithCatch(pmp); - } - static String typeJsonFromJson(Map json, _) => json["decrypted_type"] ?? json["type"]; @@ -43,7 +38,7 @@ abstract class Event with _$Event { @Default(IMap.empty()) IMap reactions, @JsonKey(name: "last_edit_rowid") @Default(0) int lastEditRowId, @UnreadTypeConverter() UnreadType? unreadType, - @JsonKey(fromJson: Event.pmpFromJson) Profile? pmp, + Profile? pmp, required Content content, required Content? previousContent, }) = _Event; @@ -53,6 +48,11 @@ abstract class Event with _$Event { replyTo: getContentFromJson( json, )["m.relates_to"]?["m.in_reply_to"]?["event_id"], + pmp: json["content"]?["com.beeper.per_message_profile"] == null + ? null + : Profile.fromJsonWithCatch( + json["content"]?["com.beeper.per_message_profile"], + ), content: Content.fromEventJson( getContentFromJson(json), json["decrypted_type"] ?? json["type"], diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index cfc865f..4097759 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -441,7 +441,9 @@ class EventRenderer extends ConsumerWidget { onSecondaryTapUp: contextMenuCallback, onLongPressStart: contextMenuCallback, child: Padding( - padding: EdgeInsets.symmetric(vertical: 8), + padding: isGrouped + ? EdgeInsets.zero + : EdgeInsets.symmetric(vertical: 8), child: child, ), ); diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 7d28838..696642e 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -333,39 +333,44 @@ class RoomChat extends HookConsumerWidget { SuperSliverList.builder( listController: listController.value, itemCount: value.length, - itemBuilder: (_, index) => EventWrapper( - value[index], - EventRenderer( - value[index], - onTapReply: () async { - final replyId = value[index].replyTo; - listController.value.animateToItem( - index: value.indexWhere( - (element) => element.eventId == replyId, - ), - scrollController: scrollController, - alignment: 0.5, - duration: (_) => - Duration(milliseconds: 700), - curve: (_) => Curves.easeInOut, - ); - flashingEvent.value = replyId; - await Future.delayed( - Duration(seconds: 1), - () { - if (flashingEvent.value == replyId) { - flashingEvent.value = null; - } - }, - ); - }, - getEventOptions: getEventOptions, - // TODO: Reimplement grouping - isGrouped: false, - ), - isFlashing: - flashingEvent.value == value[index].eventId, - ), + itemBuilder: (_, index) { + final event = value[index]; + final previousEvent = value.getOrNull(index - 1); + return EventWrapper( + event, + EventRenderer( + event, + onTapReply: () async { + final replyId = event.replyTo; + listController.value.animateToItem( + index: value.indexWhere( + (element) => element.eventId == replyId, + ), + scrollController: scrollController, + alignment: 0.5, + duration: (_) => + Duration(milliseconds: 700), + curve: (_) => Curves.easeInOut, + ); + flashingEvent.value = replyId; + await Future.delayed( + Duration(seconds: 1), + () { + if (flashingEvent.value == replyId) { + flashingEvent.value = null; + } + }, + ); + }, + getEventOptions: getEventOptions, + isGrouped: + "${event.sender}${event.pmp?.id}" == + "${previousEvent?.sender}${previousEvent?.pmp?.id}", + ), + isFlashing: + flashingEvent.value == event.eventId, + ); + }, ), ], ),