Address search PR review comments

- Drop the redundant searchService coordinator/view model parameter; derive it from the client proxy.
- Rename the globalSearch avatar size to search.
- Lift the query observation streams out of their tasks.
- Restore the appeared and updateVisibleRange comments.
- Use CompoundIcon defaults and a scaledFrame for media previews.
- Simplify the result mapping with compactMap(makeResult) and drop unsupported events by returning nil.
- Move the preview helpers beneath the previews.
This commit is contained in:
Stefan Ceriu
2026-07-03 11:57:23 +03:00
parent 4c2243cda1
commit 02d9ed1f0e
7 changed files with 50 additions and 50 deletions
@@ -25,14 +25,13 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
}
init(roomSummaryProvider: RoomSummaryProviderProtocol,
searchService: SearchServiceProxyProtocol,
clientProxy: ClientProxyProtocol,
mediaProvider: MediaProviderProtocol,
initialSearchQuery: String = "",
initialSearchMode: SearchScreenMode = .rooms) {
self.roomSummaryProvider = roomSummaryProvider
self.searchService = searchService
self.clientProxy = clientProxy
searchService = clientProxy.searchService
super.init(initialViewState: SearchScreenViewState(bindings: .init(searchQuery: initialSearchQuery, searchMode: initialSearchMode)),
mediaProvider: mediaProvider)
@@ -68,18 +67,18 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
}
.store(in: &cancellables)
let debouncedSearchQueryStream = context.observe(\.viewState.bindings.searchQuery).debounce(for: .milliseconds(250)).removeDuplicates()
searchQueryObservationTask = Task { [weak self] in
guard let stream = self?.context.observe(\.viewState.bindings.searchQuery).debounce(for: .milliseconds(250)).removeDuplicates() else { return }
for await searchQuery in stream {
for await searchQuery in debouncedSearchQueryStream {
self?.updateFilter(for: searchQuery)
}
}
// Flip the loading indicator on the moment the user starts typing, ahead of the debounced
// query above, so the empty state doesn't flash while the first search is still pending.
let searchQueryStream = context.observe(\.viewState.bindings.searchQuery).removeDuplicates()
loadingObservationTask = Task { [weak self] in
guard let stream = self?.context.observe(\.viewState.bindings.searchQuery).removeDuplicates() else { return }
for await searchQuery in stream {
for await searchQuery in searchQueryStream {
self?.state.isLoadingRooms = !searchQuery.isEmpty
self?.state.isLoadingMessages = !searchQuery.isEmpty
}
@@ -101,6 +100,8 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
switch viewAction {
case .appeared:
// The provider is shared, so other consumers may have changed its filter while we were off-screen.
// Re-apply ours on every appearance to keep the displayed results in sync with the query.
updateFilter(for: state.bindings.searchQuery)
case .selectRoom(let roomID):
actionsSubject.send(.presentRoom(roomID: roomID, eventID: nil))
@@ -156,6 +157,12 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
}
}
/// The actual range values don't matter as long as they contain the lower
/// or upper bounds. updateVisibleRange is a hybrid API that powers both
/// sliding sync visible range update and list paginations.
/// For lists other than the home screen one we don't care about visible ranges,
/// we just need the respective bounds to be there to trigger a next page load or
/// a reset to just one page.
private func updateVisibleRange(edge: UIRectEdge) {
switch edge {
case .top: