From 2350e93db33d18f247491f9ba635c4e16a7c56e1 Mon Sep 17 00:00:00 2001 From: Nuno Vieira Date: Fri, 6 Dec 2024 16:14:04 +0000 Subject: [PATCH] Fix message thread reply footnote view not shown if parent message not in cache (#681) * First solution: Provide the reply in the parentMessage parameter and do workaround * Revert "First solution: Provide the reply in the parentMessage parameter and do workaround" This reverts commit cfb4b2ed9eeee59c066a54f47577e5c17b52f097. * Final solution: Create a Lazy view that waits for the parent message to be fetched This solution requires the least amount of changes and there is also no breaking change * Update CHANGELOG.md * Remove unused properties * PR feedback * Fix Xcode 15 * Fix Xcode 15 * Use on appear instead * Please.... --- CHANGELOG.md | 2 + .../MessageList/MessageContainerView.swift | 14 +++++++ .../MessageList/MessageRepliesView.swift | 42 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83acba62..8cf27ff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Upcoming +### 🐞 Fixed +- Fix message thread reply footnote view not shown if parent message not in cache [#681](https://github.com/GetStream/stream-chat-swiftui/pull/681) ### ⚡ Performance - Improve message search performance [#680](https://github.com/GetStream/stream-chat-swiftui/pull/680) diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift index ea39a48d..594fb3bf 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageContainerView.swift @@ -185,6 +185,20 @@ public struct MessageContainerView: View { ) .accessibilityElement(children: .contain) .accessibility(identifier: "MessageRepliesView") + } else if message.showReplyInChannel, let parentId = message.parentMessageId { + /// In case the parent message is not available in the local cache, we need to fetch it from the remote server. + /// The lazy view uses the `factory.makeMessageRepliesShownInChannelView` internally once the parent message is fetched. + LazyMessageRepliesView( + factory: factory, + channel: channel, + message: message, + parentMessageController: chatClient.messageController( + cid: channel.cid, + messageId: parentId + ) + ) + .accessibilityElement(children: .contain) + .accessibility(identifier: "MessageRepliesView") } } diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageRepliesView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageRepliesView.swift index 8aec642c..69dcd7ab 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageRepliesView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/MessageRepliesView.swift @@ -116,3 +116,45 @@ public struct MessageRepliesView: View { } } } + +/// Lazy view that uses the message controller to fetch the parent message before creating message replies view. +/// This is needed when the parent message is not available in the local cache. +/// Changing the `parentMessage` to `nil` in the `MessageRepliesView` would case multiple changes including breaking changes. +struct LazyMessageRepliesView: View { + @StateObject private var parentMessageObserver: ChatMessageController.ObservableObject + + var factory: Factory + var channel: ChatChannel + var message: ChatMessage + + init( + factory: Factory, + channel: ChatChannel, + message: ChatMessage, + parentMessageController: ChatMessageController + ) { + _parentMessageObserver = StateObject(wrappedValue: parentMessageController.observableObject) + self.factory = factory + self.channel = channel + self.message = message + } + + var body: some View { + VStack { + if let parentMessage = parentMessageObserver.message { + factory.makeMessageRepliesShownInChannelView( + channel: channel, + message: message, + parentMessage: parentMessage, + replyCount: parentMessage.replyCount + ) + } else { + EmptyView() + } + }.onAppear { + if parentMessageObserver.message == nil { + parentMessageObserver.controller.synchronize() + } + } + } +}