Skip to content

Instantly share code, notes, and snippets.

@laevandus
Created December 12, 2024 09:39
Show Gist options
  • Save laevandus/2666164b9220f6af62e263768ba309a8 to your computer and use it in GitHub Desktop.
Save laevandus/2666164b9220f6af62e263768ba309a8 to your computer and use it in GitHub Desktop.
import Combine
import StreamChat
import SwiftUI
struct CustomChannelSearchView: View {
@StateObject var viewModel: ViewModel
init(client: ChatClient) {
_viewModel = StateObject(wrappedValue: ViewModel(client: client))
}
var body: some View {
NavigationView {
List(viewModel.results, id: \.cid) { channel in
VStack(alignment: .leading) {
Text(channel.name ?? "<Not set>")
.font(.headline)
Text(channel.cid.rawValue)
.font(.subheadline)
.foregroundColor(.secondary)
}
}
.navigationTitle("Channels")
.searchable(text: $viewModel.searchText, prompt: "Search for Channels")
// TODO: Implement pagination
}
}
}
extension CustomChannelSearchView {
@MainActor final class ViewModel: ObservableObject {
@Published private(set) var results = [ChatChannel]()
@Published var searchText = ""
private var cancellables = Set<AnyCancellable>()
private var channelList: ChannelList?
private let client: ChatClient
private var searchTask: Task<Void, Error>?
private var channelListCancellable: AnyCancellable?
init(client: ChatClient) {
self.client = client
$searchText
.removeDuplicates()
.sink { [weak self] text in
self?.search(text)
}
.store(in: &cancellables)
}
private func search(_ text: String) {
guard let currentUserId = client.currentUserId else { return }
searchTask?.cancel()
guard text.count > 2 else {
results = []
return
}
var query = ChannelListQuery(
filter: .and([
.autocomplete(.name, text: text),
.containMembers(userIds: [currentUserId])
])
)
query.options = [] // disable watching channels aka web-socket updates
let channelList = client.makeChannelList(with: query)
searchTask = Task {
do {
try await channelList.get()
guard !Task.isCancelled else { return }
setActiveChannelList(channelList)
} catch {
// TODO: handle errors
}
}
}
private func setActiveChannelList(_ channelList: ChannelList) {
self.channelList = channelList
channelListCancellable = channelList.state
.$channels
.sink { [weak self] results in
self?.results = Array(results)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment