From 5eed03c10ea4a6071a385f1e311341a894c2c6ac Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 6 Nov 2026 09:46:59 -0500 Subject: [PATCH] make thread roots more distinguishable, and always show them even when redacted --- lib/widgets/renderers/event.dart | 11 ++++++++++- lib/widgets/renderers/message.dart | 4 ++++ lib/widgets/room_chat/chat_timeline.dart | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index 6b31931..deff7f7 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -64,6 +64,10 @@ class const EventRenderer( /// If set, shows who in this chat has read up to this event, e.g. in the /// timeline. final ChatParams? readReceiptsChat, + + /// The root of the thread this is shown in, if any, to set it apart from the + /// replies. + final String? threadRoot, super.key, }) extends HookConsumerWidget { @override @@ -121,7 +125,9 @@ class const EventRenderer( if (isHidden && !textOnly) return SizedBox.shrink(); + final isThreadRoot = threadRoot != null && event.eventId == threadRoot; final isGrouped = + (threadRoot == null || previousEvent?.eventId != threadRoot) && (previousEvent?.isShownAsMessage ?? false) && event.sender == previousEvent?.sender && event.pmp?.id == previousEvent?.pmp?.id; @@ -166,7 +172,8 @@ class const EventRenderer( ), ); - final child = event.isShownAsMessage + final child = + event.isShownAsMessage || (isThreadRoot && event.redactedBy != null) ? MessageRenderer( event, onTapReply: jumpToEvent == null @@ -560,6 +567,8 @@ class const EventRenderer( ) else if (threadSummary != null) Padding(padding: .only(left: 4), child: threadSummary), + + if (isThreadRoot && !textOnly) Divider(height: 16), ], ); } diff --git a/lib/widgets/renderers/message.dart b/lib/widgets/renderers/message.dart index 7a4cd39..4e6a45a 100644 --- a/lib/widgets/renderers/message.dart +++ b/lib/widgets/renderers/message.dart @@ -55,6 +55,10 @@ class const MessageRenderer( ); final rendered = switch (event.content) { + _ when event.redactedBy != null => Text( + "Redacted event", + style: errorStyle, + ), EncryptedContent() => Text("Unable to decrypt event", style: errorStyle), StickerContent(:final body, :final url, :final info) => textOnly diff --git a/lib/widgets/room_chat/chat_timeline.dart b/lib/widgets/room_chat/chat_timeline.dart index 9501a17..40cc2e6 100644 --- a/lib/widgets/room_chat/chat_timeline.dart +++ b/lib/widgets/room_chat/chat_timeline.dart @@ -34,6 +34,7 @@ class const ChatTimeline({ getEventOptions: getEventOptions, onSwipe: onSwipe == null ? null : () => onSwipe!(eventRowId), readReceiptsChat: chat, + threadRoot: chat.threadRoot, ), key: key, isHighlighted: scroll.highlightedEvent == eventRowId,