From 5c49def7bd57a2187e4a5ae12e1982dfd21c2d4d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 9 May 2023 17:01:02 +0530 Subject: [PATCH] fix(llc, ui): fix removing message not removing quoted reference. Signed-off-by: xsahil03x --- .../stream_chat/lib/src/client/channel.dart | 52 +++++++++--- .../message_input/quoted_message_widget.dart | 79 +++++++++++-------- .../lib/src/message_widget/bottom_row.dart | 2 +- 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 8152753d..3b249fca 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -746,6 +746,7 @@ class Channel { state!.deleteMessage( message.copyWith( type: 'deleted', + deletedAt: message.deletedAt ?? DateTime.now(), status: MessageSendingStatus.sent, ), hardDelete: hardDelete, @@ -1928,11 +1929,9 @@ class ChannelClientState { void _listenMessageDeleted() { _subscriptions.add(_channel.on(EventType.messageDeleted).listen((event) { final message = event.message!; - if (event.hardDelete == true) { - removeMessage(message); - } else { - updateMessage(message); - } + final hardDelete = event.hardDelete ?? false; + + deleteMessage(message, hardDelete: hardDelete); })); } @@ -1957,18 +1956,35 @@ class ChannelClientState { /// Updates the [message] in the state if it exists. Adds it otherwise. void updateMessage(Message message) { + // Regular messages, which are shown in channel. if (message.parentId == null || message.showInChannel == true) { - final newMessages = [...messages]; + var newMessages = [...messages]; final oldIndex = newMessages.indexWhere((m) => m.id == message.id); if (oldIndex != -1) { - Message? m; + var updatedMessage = message; + // Add quoted message to the message if it is not present. if (message.quotedMessageId != null && message.quotedMessage == null) { final oldMessage = newMessages[oldIndex]; - m = message.copyWith( + updatedMessage = updatedMessage.copyWith( quotedMessage: oldMessage.quotedMessage, ); } - newMessages[oldIndex] = m ?? message; + newMessages[oldIndex] = updatedMessage; + + // Update quoted message reference for every message if available. + newMessages = [...newMessages].map((it) { + // Early return if the message doesn't have a quoted message. + if (it.quotedMessageId != message.id) return it; + + // Setting it to null will remove the quoted message from the message + // So, we are setting the same message but with the deleted state. + return it.copyWith( + quotedMessage: updatedMessage.copyWith( + type: 'deleted', + deletedAt: updatedMessage.deletedAt ?? DateTime.now(), + ), + ); + }).toList(); } else { newMessages.add(message); } @@ -1997,6 +2013,7 @@ class ChannelClientState { ); } + // Thread messages, which are shown in thread page. if (message.parentId != null) { updateThreadInfo(message.parentId!, [message]); } @@ -2026,9 +2043,22 @@ class ChannelClientState { } // Remove regular message, thread message shown in channel - final allMessages = [...messages]; + var updatedMessages = [...messages]..removeWhere((e) => e.id == message.id); + + // Remove quoted message reference from every message if available. + updatedMessages = [...updatedMessages].map((it) { + // Early return if the message doesn't have a quoted message. + if (it.quotedMessageId != message.id) return it; + + // Setting it to null will remove the quoted message from the message. + return it.copyWith( + quotedMessage: null, + quotedMessageId: null, + ); + }).toList(); + _channelState = _channelState.copyWith( - messages: allMessages..removeWhere((e) => e.id == message.id), + messages: updatedMessages, ); } diff --git a/packages/stream_chat_flutter/lib/src/message_input/quoted_message_widget.dart b/packages/stream_chat_flutter/lib/src/message_input/quoted_message_widget.dart index 08152a58..795154ca 100644 --- a/packages/stream_chat_flutter/lib/src/message_input/quoted_message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_input/quoted_message_widget.dart @@ -134,6 +134,8 @@ class _QuotedMessage extends StatelessWidget { bool get _isGiphy => message.attachments.any((element) => element.type == 'giphy'); + bool get _isDeleted => message.isDeleted || message.deletedAt != null; + @override Widget build(BuildContext context) { final isOnlyEmoji = message.text!.isOnlyEmoji; @@ -144,39 +146,54 @@ class _QuotedMessage extends StatelessWidget { msg = msg.copyWith(text: '${msg.text!.substring(0, textLimit - 3)}...'); } - final children = [ - if (composing) - PlatformWidgetBuilder( - web: (context, child) => child, - desktop: (context, child) => child, - child: ClearInputItemButton( - onTap: onQuotedMessageClear, + List children; + if (_isDeleted) { + // Show deleted message text + children = [ + Text( + context.translations.messageDeletedLabel, + style: messageTheme.messageTextStyle?.copyWith( + fontStyle: FontStyle.italic, + color: messageTheme.createdAtStyle?.color, ), ), - if (_hasAttachments) - _ParseAttachments( - message: message, - messageTheme: messageTheme, - attachmentThumbnailBuilders: attachmentThumbnailBuilders, - ), - if (msg.text!.isNotEmpty && !_isGiphy) - Flexible( - child: StreamMessageText( - message: msg, - messageTheme: isOnlyEmoji && _containsText - ? messageTheme.copyWith( - messageTextStyle: messageTheme.messageTextStyle?.copyWith( - fontSize: 32, - ), - ) - : messageTheme.copyWith( - messageTextStyle: messageTheme.messageTextStyle?.copyWith( - fontSize: 12, - ), - ), + ]; + } else { + // Show quoted message + children = [ + if (composing) + PlatformWidgetBuilder( + web: (context, child) => child, + desktop: (context, child) => child, + child: ClearInputItemButton( + onTap: onQuotedMessageClear, + ), ), - ), - ].insertBetween(const SizedBox(width: 8)); + if (_hasAttachments) + _ParseAttachments( + message: message, + messageTheme: messageTheme, + attachmentThumbnailBuilders: attachmentThumbnailBuilders, + ), + if (msg.text!.isNotEmpty && !_isGiphy) + Flexible( + child: StreamMessageText( + message: msg, + messageTheme: isOnlyEmoji && _containsText + ? messageTheme.copyWith( + messageTextStyle: messageTheme.messageTextStyle?.copyWith( + fontSize: 32, + ), + ) + : messageTheme.copyWith( + messageTextStyle: messageTheme.messageTextStyle?.copyWith( + fontSize: 12, + ), + ), + ), + ), + ].insertBetween(const SizedBox(width: 8)); + } return Container( decoration: BoxDecoration( @@ -204,7 +221,7 @@ class _QuotedMessage extends StatelessWidget { } Color? _getBackgroundColor(BuildContext context) { - if (_containsLinkAttachment) { + if (_containsLinkAttachment && !_isDeleted) { return messageTheme.urlAttachmentBackgroundColor; } return messageTheme.messageBackgroundColor; diff --git a/packages/stream_chat_flutter/lib/src/message_widget/bottom_row.dart b/packages/stream_chat_flutter/lib/src/message_widget/bottom_row.dart index 289088af..04cb4f33 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget/bottom_row.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget/bottom_row.dart @@ -151,7 +151,7 @@ class BottomRow extends StatelessWidget { context, message, ) ?? - const Offstage(); + const StreamVisibleFootnote(); } final children = [];