Room list searching tweaks (#1800)

* Prevent the room list from flashing previous rooms when searching

* Remove reset diff chunking now that the whole list is limited

* Bump the Rust SDK to v1.1.19 and fix breaking API changes
This commit is contained in:
Stefan Ceriu
2023-09-26 14:33:15 +03:00
committed by GitHub
parent 68ea9acb36
commit dad6560ed4
13 changed files with 75 additions and 69 deletions
@@ -98,6 +98,7 @@ struct HomeScreenViewState: BindableState {
struct HomeScreenViewStateBindings {
var searchQuery = ""
var isSearchFieldFocused = false
var alertInfo: AlertInfo<UUID>?
var leaveRoomAlertItem: LeaveRoomAlertItem?
@@ -88,7 +88,17 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
.map(\.bindings.searchQuery)
.removeDuplicates()
.sink { [weak self] searchQuery in
self?.roomSummaryProvider?.updateFilterPattern(searchQuery)
guard let self else { return }
updateFilter(isSearchFieldFocused: state.bindings.isSearchFieldFocused, searchQuery: searchQuery)
}
.store(in: &cancellables)
context.$viewState
.map(\.bindings.isSearchFieldFocused)
.removeDuplicates()
.sink { [weak self] isSearchFieldFocused in
guard let self else { return }
updateFilter(isSearchFieldFocused: isSearchFieldFocused, searchQuery: state.bindings.searchQuery)
}
.store(in: &cancellables)
@@ -142,6 +152,16 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
// MARK: - Private
private func updateFilter(isSearchFieldFocused: Bool, searchQuery: String) {
if !isSearchFieldFocused {
roomSummaryProvider?.setFilter(.all)
} else if searchQuery.isEmpty {
roomSummaryProvider?.setFilter(.none)
} else {
roomSummaryProvider?.setFilter(.normalizedMatchRoomName(searchQuery))
}
}
private func setupRoomSummaryProviderSubscriptions() {
guard let roomSummaryProvider, let inviteSummaryProvider else {
MXLog.error("Room summary provider unavailable")
@@ -23,7 +23,6 @@ struct HomeScreen: View {
@ObservedObject var context: HomeScreenViewModel.Context
@State private var scrollViewAdapter = ScrollViewAdapter()
@State private var isSearching = false
// Bloom components
@State private var bloomView: UIView?
@@ -56,7 +55,7 @@ struct HomeScreen: View {
topSection
LazyVStack(spacing: 0) {
HomeScreenRoomList(context: context, isSearching: $isSearching)
HomeScreenRoomList(context: context)
}
.searchable(text: $context.searchQuery)
.compoundSearchField()
@@ -100,7 +99,7 @@ struct HomeScreen: View {
}
}
let isTopController = controller.navigationController?.topViewController != controller
let isHidden = isTopController || isSearching
let isHidden = isTopController || context.isSearchFieldFocused
if let bloomView {
bloomView.isHidden = isHidden
UIView.transition(with: bloomView, duration: 1.75, options: .curveEaseInOut) {
@@ -196,7 +195,7 @@ struct HomeScreen: View {
sessionVerificationBanner
}
if context.viewState.hasPendingInvitations, !isSearching {
if context.viewState.hasPendingInvitations, !context.isSearchFieldFocused {
HomeScreenInvitesButton(title: L10n.actionInvitesList, hasBadge: context.viewState.hasUnreadPendingInvitations) {
context.send(viewAction: .selectInvites)
}
@@ -20,39 +20,34 @@ struct HomeScreenRoomList: View {
@Environment(\.isSearching) var isSearchFieldFocused
@ObservedObject var context: HomeScreenViewModel.Context
@Binding var isSearching: Bool
var body: some View {
content
.onChange(of: isSearchFieldFocused) { isSearching = $0 }
.onChange(of: isSearchFieldFocused) { context.isSearchFieldFocused = $0 }
}
@ViewBuilder
private var content: some View {
if isSearchFieldFocused, context.searchQuery.count == 0 {
EmptyView()
} else {
ForEach(context.viewState.visibleRooms) { room in
if room.isPlaceholder {
HomeScreenRoomCell(room: room, context: context, isSelected: false)
.redacted(reason: .placeholder)
} else {
let isSelected = context.viewState.selectedRoomID == room.id
HomeScreenRoomCell(room: room, context: context, isSelected: isSelected)
.contextMenu {
Button {
context.send(viewAction: .showRoomDetails(roomIdentifier: room.id))
} label: {
Label(L10n.commonSettings, systemImage: "gearshape")
}
Button(role: .destructive) {
context.send(viewAction: .leaveRoom(roomIdentifier: room.id))
} label: {
Label(L10n.actionLeaveRoom, systemImage: "rectangle.portrait.and.arrow.right")
}
ForEach(context.viewState.visibleRooms) { room in
if room.isPlaceholder {
HomeScreenRoomCell(room: room, context: context, isSelected: false)
.redacted(reason: .placeholder)
} else {
let isSelected = context.viewState.selectedRoomID == room.id
HomeScreenRoomCell(room: room, context: context, isSelected: isSelected)
.contextMenu {
Button {
context.send(viewAction: .showRoomDetails(roomIdentifier: room.id))
} label: {
Label(L10n.commonSettings, systemImage: "gearshape")
}
}
Button(role: .destructive) {
context.send(viewAction: .leaveRoom(roomIdentifier: room.id))
} label: {
Label(L10n.actionLeaveRoom, systemImage: "rectangle.portrait.and.arrow.right")
}
}
}
}
}