From a72d696f49ce05fcb9007b5807c2d38913e9056d Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Tue, 19 May 2026 21:44:03 -0400 Subject: [PATCH] working reply rendering --- lib/models/event.dart | 5 +++ lib/widgets/renderers/event.dart | 77 +++++++++++++++++++++----------- lib/widgets/room_chat.dart | 34 +++++++++----- 3 files changed, 81 insertions(+), 35 deletions(-) diff --git a/lib/models/event.dart b/lib/models/event.dart index 6f8d362..f647460 100644 --- a/lib/models/event.dart +++ b/lib/models/event.dart @@ -31,6 +31,7 @@ abstract class Event with _$Event { String? redactedBy, String? relatesTo, String? relationType, + String? replyTo, String? decryptionError, String? sendError, @Default(IMap.empty()) IMap reactions, @@ -43,6 +44,10 @@ abstract class Event with _$Event { factory Event.fromJson(Map json) => _$EventFromJson(json).copyWith( + replyTo: + ((json["decrypted"] ?? json["content"])["m.new_content"] ?? + json["decrypted"] ?? + json["content"])?["m.relates_to"]?["m.in_reply_to"]?["event_id"], content: Content.fromEventJson( (json["decrypted"] ?? json["content"])["m.new_content"] ?? json["decrypted"] ?? diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index 0814887..e053e90 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -21,7 +21,6 @@ import "package:nexus/models/event.dart"; import "package:nexus/models/requests/get_event_request.dart"; import "package:nexus/widgets/expandable_image.dart"; import "package:nexus/widgets/html/html.dart"; -import "package:nexus/widgets/html/quoted.dart"; import "package:nexus/widgets/lazy_loading/message_avatar.dart"; import "package:nexus/widgets/lazy_loading/message_displayname.dart"; import "package:nexus/widgets/link_preview.dart"; @@ -110,50 +109,76 @@ class EventRenderer extends ConsumerWidget { ], ), Card( - color: - ref.watch( - ClientStateController.provider.select( - (value) => value?.userId, - ), - ) == - event.sender + color: textOnly + ? Colors.transparent + : ref.watch( + ClientStateController.provider.select( + (value) => value?.userId, + ), + ) == + event.sender ? (event.eventId.startsWith("~") ? colorScheme.onPrimary : colorScheme.primaryContainer) : colorScheme.surfaceContainer, + elevation: textOnly ? 0 : null, child: Padding( - padding: EdgeInsets.all(12), + padding: textOnly + ? EdgeInsets.zero + : EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (event.relationType == "m.in_reply_to" && - event.relatesTo != null) - Quoted( - ref - .watch( + if (event.replyTo != null) + Card( + margin: EdgeInsets.only(bottom: 8), + color: theme.colorScheme.surfaceContainer, + child: InkWell( + onTap: onTapReply, + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + vertical: 8, + horizontal: 12, + ), + child: switch (ref.watch( EventController.provider( GetEventRequest( roomId: event.roomId, - eventId: event.relatesTo!, + eventId: event.replyTo!, ), ), - ) - .when( - data: (replyEvent) => replyEvent == null - ? SizedBox.shrink() - : EventRenderer( - replyEvent, + )) { + AsyncData(:final value?) || + AsyncLoading(:final value?) => Row( + spacing: 8, + children: [ + MessageAvatar(event, height: 24), + MessageDisplayname( + event, + style: TextStyle( + color: + theme.colorScheme.primary, + fontWeight: FontWeight.bold, + ), + ), + Expanded( + child: EventRenderer( + value, textOnly: true, maxLines: 1, ), - error: (_, _) => Text( + ), + ], + ), + AsyncError _ => Text( "An error occurred while fetching the reply", style: errorStyle, ), - loading: () => - Text("Fetching event..."), - ), + _ => Text("Fetching event..."), + }, + ), + ), ), switch (event.content) { EncryptedContent() => Text( @@ -408,6 +433,8 @@ class EventRenderer extends ConsumerWidget { ? textOnly ? Text("Unknown event type", style: errorStyle) : SizedBox.shrink() + : textOnly + ? child : GestureDetector( onSecondaryTapUp: contextMenuCallback, onLongPressStart: contextMenuCallback, diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index 5d9cf09..a531cdb 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -41,6 +41,7 @@ class RoomChat extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final relatedEvent = useState(null); final relationType = useState(RelationType.reply); + final flashingEvent = useState(null); final memberListOpened = useState(showMembersByDefault); @@ -329,21 +330,34 @@ class RoomChat extends HookConsumerWidget { value[index], EventRenderer( value[index], - onTapReply: () => - listController.value.animateToItem( - index: index, - scrollController: scrollController, - alignment: 0.5, - duration: (_) => - Duration(milliseconds: 250), - curve: (_) => Curves.easeInOut, + 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: 250), + 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, ), - // TODO: Reimplement flashing - isFlashing: false, + isFlashing: + flashingEvent.value == value[index].eventId, ), ), ],