Fixes 1864 - Message forwarding room list filtering and pagination problems (#1867)

* Fixes 1864 - Message forwarding room list filtering and pagination problems

* Fix SwiftFormat redundant closures body error

* Prevent crashes when writing to the localization bundle cache from different threads

* Fix unit tests

* Fix unit tests

* Address PR comments
This commit is contained in:
Stefan Ceriu
2023-10-09 14:59:31 +03:00
committed by GitHub
parent 8270a868a7
commit 1f12a7cb2f
14 changed files with 139 additions and 41 deletions
@@ -24,15 +24,6 @@ enum MessageForwardingScreenViewModelAction {
struct MessageForwardingScreenViewState: BindableState {
var rooms: [MessageForwardingRoom] = []
var selectedRoomID: String?
var visibleRooms: [MessageForwardingRoom] {
if bindings.searchQuery.isEmpty {
return rooms
}
return rooms.filter { $0.name.localizedStandardContains(bindings.searchQuery) }
}
var bindings = MessageForwardingScreenViewStateBindings()
}
@@ -44,6 +35,8 @@ enum MessageForwardingScreenViewAction {
case cancel
case send
case selectRoom(roomID: String)
case reachedTop
case reachedBottom
}
struct MessageForwardingRoom: Identifiable, Equatable {
@@ -43,6 +43,15 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me
}
.store(in: &cancellables)
context.$viewState
.map(\.bindings.searchQuery)
.removeDuplicates()
.sink { [weak self] searchQuery in
guard let self else { return }
self.roomSummaryProvider?.setFilter(.normalizedMatchRoomName(searchQuery))
}
.store(in: &cancellables)
updateRooms()
}
@@ -58,6 +67,10 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me
actionsSubject.send(.send(roomID: roomID))
case .selectRoom(let roomID):
state.selectedRoomID = roomID
case .reachedTop:
updateVisibleRange(edge: .top)
case .reachedBottom:
updateVisibleRange(edge: .bottom)
}
}
@@ -91,4 +104,26 @@ class MessageForwardingScreenViewModel: MessageForwardingScreenViewModelType, Me
MXLog.verbose("Finished updating rooms")
}
/// 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) {
guard let roomSummaryProvider else {
return
}
switch edge {
case .top:
roomSummaryProvider.updateVisibleRange(0..<0)
case .bottom:
let roomCount = roomSummaryProvider.roomListPublisher.value.count
roomSummaryProvider.updateVisibleRange(roomCount..<roomCount)
default:
break
}
}
}
@@ -22,10 +22,19 @@ struct MessageForwardingScreen: View {
var body: some View {
Form {
Section {
ForEach(context.viewState.visibleRooms) { room in
ForEach(context.viewState.rooms) { room in
MessageForwardingRoomCell(room: room, context: context)
.buttonStyle(FormButtonStyle(accessory: .singleSelection(isSelected: context.viewState.selectedRoomID == room.id)))
}
// Replace these with ScrollView's `scrollPosition` when dropping iOS 16.
} header: {
Rectangle().hidden().onAppear {
context.send(viewAction: .reachedTop)
}
} footer: {
Rectangle().hidden().onAppear {
context.send(viewAction: .reachedBottom)
}
}
.compoundFormSection()
}