From f249f39972cb981d75cad19ce773e12441a8163c Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 26 Dec 2025 13:22:45 -0500 Subject: [PATCH] Fix state errors when dismissing replies --- lib/widgets/chat_page/chat_box.dart | 51 ++--------------- lib/widgets/chat_page/reply_preview.dart | 70 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 45 deletions(-) create mode 100644 lib/widgets/chat_page/reply_preview.dart diff --git a/lib/widgets/chat_page/chat_box.dart b/lib/widgets/chat_page/chat_box.dart index 1a03603..e38e5f5 100644 --- a/lib/widgets/chat_page/chat_box.dart +++ b/lib/widgets/chat_page/chat_box.dart @@ -12,6 +12,7 @@ import "package:nexus/controllers/room_chat_controller.dart"; import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/get_headers.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/chat_page/reply_preview.dart"; import "package:nexus/widgets/loading.dart"; class ChatBox extends HookConsumerWidget { @@ -69,51 +70,11 @@ class ChatBox extends HookConsumerWidget { borderRadius: BorderRadius.all(Radius.circular(12)), child: Column( children: [ - if (replyToMessage != null) - Container( - color: theme.colorScheme.surfaceContainerHigh, - padding: EdgeInsets.symmetric(horizontal: 8), - child: Row( - spacing: 8, - children: [ - SizedBox(width: 4), - AvatarOrHash( - ref - .watch( - AvatarController.provider( - replyToMessage!.metadata!["avatarUrl"], - ), - ) - .whenOrNull(data: (data) => data), - replyToMessage!.metadata!["displayName"].toString(), - headers: room.client.headers, - height: 16, - ), - Text( - replyToMessage!.metadata?["displayName"] ?? - replyToMessage!.authorId, - style: theme.textTheme.labelMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - Expanded( - child: (replyToMessage is TextMessage) - ? Text( - (replyToMessage as TextMessage).text, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.labelMedium, - maxLines: 1, - ) - : SizedBox(), - ), - IconButton( - onPressed: onDismiss, - icon: Icon(Icons.close), - iconSize: 20, - ), - ], - ), - ), + ReplyPreview( + replyToMessage: replyToMessage, + onDismiss: onDismiss, + room: room, + ), Container( color: theme.colorScheme.surfaceContainerHighest, padding: EdgeInsets.symmetric(horizontal: 8), diff --git a/lib/widgets/chat_page/reply_preview.dart b/lib/widgets/chat_page/reply_preview.dart new file mode 100644 index 0000000..4f1c1eb --- /dev/null +++ b/lib/widgets/chat_page/reply_preview.dart @@ -0,0 +1,70 @@ +import "package:flutter/material.dart"; +import "package:flutter_chat_core/flutter_chat_core.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:matrix/matrix.dart"; +import "package:nexus/controllers/avatar_controller.dart"; +import "package:nexus/helpers/extensions/get_headers.dart"; +import "package:nexus/widgets/avatar_or_hash.dart"; + +class ReplyPreview extends ConsumerWidget { + final Message? replyToMessage; + final VoidCallback onDismiss; + final Room room; + const ReplyPreview({ + required this.replyToMessage, + required this.onDismiss, + required this.room, + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = Theme.of(context); + + if (replyToMessage == null) return SizedBox.shrink(); + return Container( + color: theme.colorScheme.surfaceContainerHigh, + padding: EdgeInsets.symmetric(horizontal: 8), + child: Row( + spacing: 8, + children: [ + SizedBox(width: 4), + AvatarOrHash( + ref + .watch( + AvatarController.provider( + replyToMessage!.metadata!["avatarUrl"], + ), + ) + .whenOrNull(data: (data) => data), + replyToMessage!.metadata!["displayName"].toString(), + headers: room.client.headers, + height: 16, + ), + Text( + replyToMessage!.metadata?["displayName"] ?? + replyToMessage!.authorId, + style: theme.textTheme.labelMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Expanded( + child: (replyToMessage is TextMessage) + ? Text( + (replyToMessage as TextMessage).text, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.labelMedium, + maxLines: 1, + ) + : SizedBox(), + ), + IconButton( + onPressed: onDismiss, + icon: Icon(Icons.close), + iconSize: 20, + ), + ], + ), + ); + } +}