From 5c49def7bd57a2187e4a5ae12e1982dfd21c2d4d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 9 May 2023 17:01:02 +0530 Subject: [PATCH 1/5] 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 = []; From f5f475567f189034a1001f0781f8aaecf04f3553 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 9 May 2023 17:03:02 +0530 Subject: [PATCH 2/5] chore: update CHANGELOG.md Signed-off-by: xsahil03x --- packages/stream_chat/CHANGELOG.md | 2 ++ packages/stream_chat_flutter/CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index df72ed55..4177cd15 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -4,6 +4,8 @@ - [[#1355]](https://github.com/GetStream/stream-chat-flutter/issues/1355) Fixed error while hiding channel and clearing message history. +- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed removing message not removing quoted + message reference. ✅ Added diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index 778c162d..f3ea52da 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -13,6 +13,8 @@ used in message edit widget. - [[#1523]](https://github.com/GetStream/stream-chat-flutter/issues/1523) Fixed `StreamMessageThemeData` not being applied correctly. +- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed removing message not removing quoted + message reference. ✅ Added From b607fd9733d5367a58eee96749ed9c92ab0212f8 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 9 May 2023 17:09:50 +0530 Subject: [PATCH 3/5] chore: update CHANGELOG.md Signed-off-by: xsahil03x --- packages/stream_chat_flutter/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_flutter/CHANGELOG.md b/packages/stream_chat_flutter/CHANGELOG.md index f3ea52da..fc8b653f 100644 --- a/packages/stream_chat_flutter/CHANGELOG.md +++ b/packages/stream_chat_flutter/CHANGELOG.md @@ -13,8 +13,8 @@ used in message edit widget. - [[#1523]](https://github.com/GetStream/stream-chat-flutter/issues/1523) Fixed `StreamMessageThemeData` not being applied correctly. -- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed removing message not removing quoted - message reference. +- [[#1525]](https://github.com/GetStream/stream-chat-flutter/issues/1525) Fixed `StreamQuotedMessageWidget` message for + deleted messages not being shown correctly. ✅ Added From 89b9e957b9cb343852c373f45f655ff7c194664e Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 10 May 2023 17:57:57 +0530 Subject: [PATCH 4/5] fix: visible footnote spacing and visibility. Signed-off-by: xsahil03x --- .../src/message_input/quoted_message_widget.dart | 13 +++---------- .../src/message_list_view/message_list_view.dart | 14 ++++++++++---- .../lib/src/message_widget/bottom_row.dart | 14 +++++++++----- .../lib/src/message_widget/message_widget.dart | 3 +-- .../lib/src/message_widget/quoted_message.dart | 1 - 5 files changed, 23 insertions(+), 22 deletions(-) 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 795154ca..33145852 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 @@ -22,7 +22,6 @@ class StreamQuotedMessageWidget extends StatelessWidget { this.padding = const EdgeInsets.all(8), this.onTap, this.onQuotedMessageClear, - this.composing = true, }); /// The message @@ -53,9 +52,6 @@ class StreamQuotedMessageWidget extends StatelessWidget { /// Callback for clearing quoted messages. final VoidCallback? onQuotedMessageClear; - /// True if the message is being composed - final bool composing; - @override Widget build(BuildContext context) { final children = [ @@ -63,11 +59,10 @@ class StreamQuotedMessageWidget extends StatelessWidget { child: _QuotedMessage( message: message, textLimit: textLimit, - composing: composing, - onQuotedMessageClear: onQuotedMessageClear, messageTheme: messageTheme, showBorder: showBorder, reverse: reverse, + onQuotedMessageClear: onQuotedMessageClear, attachmentThumbnailBuilders: attachmentThumbnailBuilders, ), ), @@ -104,17 +99,15 @@ class _QuotedMessage extends StatelessWidget { const _QuotedMessage({ required this.message, required this.textLimit, - required this.composing, - required this.onQuotedMessageClear, required this.messageTheme, required this.showBorder, required this.reverse, + this.onQuotedMessageClear, this.attachmentThumbnailBuilders, }); final Message message; final int textLimit; - final bool composing; final VoidCallback? onQuotedMessageClear; final StreamMessageThemeData messageTheme; final bool showBorder; @@ -161,7 +154,7 @@ class _QuotedMessage extends StatelessWidget { } else { // Show quoted message children = [ - if (composing) + if (onQuotedMessageClear != null) PlatformWidgetBuilder( web: (context, child) => child, desktop: (context, child) => child, diff --git a/packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart b/packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart index 5435e95c..89db51dd 100644 --- a/packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/message_list_view/message_list_view.dart @@ -282,9 +282,14 @@ class StreamMessageListView extends StatefulWidget { BuildContext context, List spacingTypes, ) { - if (!spacingTypes.contains(SpacingType.defaultSpacing)) { + if (spacingTypes.contains(SpacingType.otherUser)) { + return const SizedBox(height: 8); + } else if (spacingTypes.contains(SpacingType.thread)) { + return const SizedBox(height: 8); + } else if (spacingTypes.contains(SpacingType.timeDiff)) { return const SizedBox(height: 8); } + return const SizedBox(height: 2); } @@ -644,7 +649,8 @@ class _StreamMessageListViewState extends State { Widget separator; - final isThread = message.replyCount! > 0; + final isPartOfThread = message.replyCount! > 0 || + message.showInChannel == true; if (!Jiffy(message.createdAt.toLocal()).isSame( nextMessage.createdAt.toLocal(), @@ -666,7 +672,7 @@ class _StreamMessageListViewState extends State { final spacingRules = [ if (hasTimeDiff) SpacingType.timeDiff, if (!isNextUserSame) SpacingType.otherUser, - if (isThread) SpacingType.thread, + if (isPartOfThread) SpacingType.thread, if (isDeleted) SpacingType.deleted, ]; @@ -680,7 +686,7 @@ class _StreamMessageListViewState extends State { ); } - if (!isThread && + if (!isPartOfThread && unreadCount > 0 && _oldestUnreadMessage?.id == nextMessage.id) { final unreadMessagesSeparator = 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 04cb4f33..5d5bbc0d 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 @@ -147,11 +147,15 @@ class BottomRow extends StatelessWidget { @override Widget build(BuildContext context) { if (isDeleted) { - return deletedBottomRowBuilder?.call( - context, - message, - ) ?? - const StreamVisibleFootnote(); + final deletedBottomRowBuilder = this.deletedBottomRowBuilder; + if (deletedBottomRowBuilder != null) { + return deletedBottomRowBuilder(context, message); + } + + // Only show visible footnote for ownUser. + final currentUser = streamChat.currentUser; + final isOwnUser = message.user?.id == currentUser?.id; + if (isOwnUser) return const StreamVisibleFootnote(); } final children = []; diff --git a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart index 267c96d4..a2a3b55f 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget/message_widget.dart @@ -794,8 +794,7 @@ class _StreamMessageWidgetState extends State showUsername || showTimeStamp || showInChannel || - showSendingIndicator || - isDeleted; + showSendingIndicator; /// {@template isPinned} /// Whether [StreamMessageWidget.message] is pinned or not. diff --git a/packages/stream_chat_flutter/lib/src/message_widget/quoted_message.dart b/packages/stream_chat_flutter/lib/src/message_widget/quoted_message.dart index 028cc443..f75bdbe7 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget/quoted_message.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget/quoted_message.dart @@ -65,7 +65,6 @@ class _QuotedMessageState extends State { top: 8, bottom: widget.hasNonUrlAttachments ? 8 : 0, ), - composing: false, ); } } From bc6283e30c52b9a381e03b68f28f16ffc3da6957 Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Wed, 10 May 2023 23:57:59 +0530 Subject: [PATCH 5/5] chore: don't use a fallback for deleteBottomRowBuilder Signed-off-by: xsahil03x --- .../lib/src/message_widget/bottom_row.dart | 5 ----- 1 file changed, 5 deletions(-) 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 5d5bbc0d..8d650f5c 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,11 +151,6 @@ class BottomRow extends StatelessWidget { if (deletedBottomRowBuilder != null) { return deletedBottomRowBuilder(context, message); } - - // Only show visible footnote for ownUser. - final currentUser = streamChat.currentUser; - final isOwnUser = message.user?.id == currentUser?.id; - if (isOwnUser) return const StreamVisibleFootnote(); } final children = [];