diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c93bca6..39c89350 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Expose `QuotedMessageViewContainer` [#1056](https://github.com/GetStream/stream-chat-swiftui/pull/1056) - Add `QuotedMessageContentView` and `ViewFactory.makeQuotedMessageContentView()` [#1056](https://github.com/GetStream/stream-chat-swiftui/pull/1056) - Allow customizing the attachment size and avatar size of the quoted message view [#1056](https://github.com/GetStream/stream-chat-swiftui/pull/1056) +### 🐞 Fixed +- Fix channel list skipping some updates on iPad [#1059](https://github.com/GetStream/stream-chat-swiftui/pull/1059) # [4.93.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.93.0) _November 18, 2025_ diff --git a/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift b/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift index d799d56c..c09941c3 100644 --- a/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift +++ b/Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift @@ -25,18 +25,24 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController /// Used when screen is shown from a deeplink. private var selectedChannelId: String? - - /// Temporarly holding changes while message list is shown. - private var queuedChannelsChanges = LazyCachedMapCollection() - + private var timer: Timer? /// Controls loading the channels. public private(set) var loadingNextChannels: Bool = false - /// Checks if the queued changes are completely applied. - private var markDirty = false - + /// True, if channel updates were skipped and are applied when selectedChannel is set to nil + private var skippedChannelUpdates = false + + /// True, if channel updates can be skipped for optimizing view refreshes while showing message list. + /// + /// - Important: Only meant for stacked navigation view style. + private var canSkipChannelUpdates: Bool { + guard isIphone || !utils.messageListConfig.iPadSplitViewEnabled else { return false } + guard selectedChannel != nil || !searchText.isEmpty else { return false } + return true + } + /// Index of the selected channel. private var selectedChannelIndex: Int? @@ -44,23 +50,15 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController @Published public var scrolledChannelId: String? /// Published variables. - @Published public var channels = LazyCachedMapCollection() { - didSet { - if !markDirty { - queuedChannelsChanges = [] - } else { - markDirty = false - } - } - } + @Published public var channels = LazyCachedMapCollection() @Published public var selectedChannel: ChannelSelectionInfo? { willSet { hideTabBar = newValue != nil if selectedChannel != nil && newValue == nil { // pop happened, apply the queued changes. - if !queuedChannelsChanges.isEmpty { - channels = queuedChannelsChanges + if skippedChannelUpdates { + updateChannels() } } if newValue == nil { @@ -317,8 +315,8 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController // MARK: - private private func handleChannelListChanges(_ controller: ChatChannelListController) { - if selectedChannel != nil || !searchText.isEmpty { - queuedChannelsChanges = controller.channels + if canSkipChannelUpdates { + skippedChannelUpdates = true updateChannelsIfNeeded() } else { channels = controller.channels @@ -537,15 +535,16 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController } private func updateChannels() { + skippedChannelUpdates = false channels = controller?.channels ?? LazyCachedMapCollection() } private func handleChannelAppearance() { - if !queuedChannelsChanges.isEmpty && selectedChannel == nil { - channels = queuedChannelsChanges - } else if !queuedChannelsChanges.isEmpty { - handleQueuedChanges() - } else if queuedChannelsChanges.isEmpty && selectedChannel != nil { + if skippedChannelUpdates && selectedChannel == nil { + updateChannels() + } else if skippedChannelUpdates { + updateSelectedChannelData() + } else if !skippedChannelUpdates && selectedChannel != nil { if selectedChannel?.injectedChannelInfo == nil { selectedChannel?.injectedChannelInfo = InjectedChannelInfo(unreadCount: 0) } @@ -562,10 +561,10 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController } } - private func handleQueuedChanges() { + private func updateSelectedChannelData() { let selected = selectedChannel?.channel var index: Int? - var temp = Array(queuedChannelsChanges) + var temp = Array(controller?.channels ?? []) for i in 0..