Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel was sometimes not selected when setting selectedChannelId #611

Merged
merged 12 commits into from
Oct 3, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Rare crash when accessing frame of the view [#607](https://github.com/GetStream/stream-chat-swiftui/pull/607)
- `ChatChannelListView` navigation did not trigger when using a custom container and its body reloaded [#609](https://github.com/GetStream/stream-chat-swiftui/pull/609)
- Channel was sometimes not marked as read when tapping the x on the unread message pill in the message list [#610](https://github.com/GetStream/stream-chat-swiftui/pull/610)
- Channel was sometimes not selected if `ChatChannelViewModel.selectedChannelId` was set to a channel created a moments ago [#611](https://github.com/GetStream/stream-chat-swiftui/pull/611)

# [4.63.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.63.0)
_September 12, 2024_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
} else {
markDirty = false
}
checkForDeeplinks()
}
}

Expand Down Expand Up @@ -117,7 +118,13 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
public var isSearching: Bool {
!searchText.isEmpty
}


/// Creates a view model for the `ChatChannelListView`.
///
/// - Parameters:
/// - channelListController: A controller providing the list of channels. If nil, a controller with default `ChannelListQuery` is created.
/// - selectedChannelId: The id of a channel to select. If the channel is not part of the channel list query, no channel is selected.
/// Consider using ``ChatChannelScreen`` for presenting channels what might not be part of the initial page of channels.
public init(
channelListController: ChatChannelListController? = nil,
selectedChannelId: String? = nil
Expand Down Expand Up @@ -265,15 +272,16 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
}
}

/// Checks for currently loaded channels for opening a channel with id.
private func checkForDeeplinks() {
if let selectedChannelId = selectedChannelId,
let channelId = try? ChannelId(cid: selectedChannelId) {
let chatController = chatClient.channelController(
for: channelId,
messageOrdering: .topToBottom
)
selectedChannel = chatController.channel?.channelSelectionInfo
guard let selectedChannelId else { return }
do {
let channelId = try ChannelId(cid: selectedChannelId)
guard let selectedChannel = channels.first(where: { $0.cid == channelId })?.channelSelectionInfo else { return }
self.selectedChannelId = nil
self.selectedChannel = selectedChannel
} catch {
log.error("Failed to select a channel with id \(selectedChannelId) (\(error))")
}
}

Expand Down Expand Up @@ -307,7 +315,6 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
if self.selectedChannel == nil {
self.updateChannels()
}
self.checkForDeeplinks()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,55 @@ class ChatChannelListViewModel_Tests: StreamChatTestCase {
// Then
XCTAssert(viewModel.hideTabBar == true)
}

func test_channelListVM_deeplinkToExistingChannel() {
// Given
let channels = (0..<3).map { ChatChannel.mock(cid: ChannelId(type: .messaging, id: "\($0)")) }
let channelListController = makeChannelListController(channels: channels)
let selectedId = channels[1].cid
let viewModel = ChatChannelListViewModel(
channelListController: channelListController,
selectedChannelId: selectedId.rawValue
)

// Then
let expectation = XCTestExpectation(description: "SelectedChannel")
let cancellable = viewModel.$selectedChannel
.filter { $0?.channel.cid == selectedId }
.sink { _ in
expectation.fulfill()
}
wait(for: [expectation], timeout: defaultTimeout)
cancellable.cancel()
}

func test_channelListVM_deeplinkToIncomingChannel() {
// Given
let channels = (0..<3).map { ChatChannel.mock(cid: ChannelId(type: .messaging, id: "\($0)")) }
let channelListController = makeChannelListController(channels: channels)
let selectedId = ChannelId(type: .messaging, id: "3")
let viewModel = ChatChannelListViewModel(
channelListController: channelListController,
selectedChannelId: selectedId.rawValue
)

// When
let expectation = XCTestExpectation(description: "SelectedChannel")
let cancellable = viewModel.$selectedChannel
.filter { $0?.channel.cid == selectedId }
.sink { _ in
expectation.fulfill()
}
let insertedChannel = ChatChannel.mock(cid: selectedId)
channelListController.simulate(
channels: channels + [insertedChannel],
changes: [.insert(insertedChannel, index: IndexPath(item: 0, section: 0))]
)

// Then
wait(for: [expectation], timeout: defaultTimeout)
cancellable.cancel()
}

// MARK: - private

Expand Down
Loading