mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
Update room suggestions and search when space membership changes (#6316)
* Avoid repeated space membership scans in room search Signed-off-by: Ivan Magda <imagda15@gmail.com> * Refresh room candidates when space membership changes Keep known space room IDs in a set updated by the room publisher and by successful additions. Filter both suggestions and search results through that set, retaining exclusions while the space list resets and reloads. Preserve the initial recent-room eligibility filter so existing children do not consume the five suggestion slots. Cover live membership updates and partial-save filtering in both candidate lists. --------- Signed-off-by: Ivan Magda <imagda15@gmail.com>
This commit is contained in:
+21
-16
@@ -17,9 +17,8 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
private var suggestedRooms: [SpaceAddRoomsScreenRoom] = []
|
||||
/// A place to track rooms that were sucessfully added to the space in order to filter them out from
|
||||
/// the roomsSection when a failure occurs part way through the array.
|
||||
private var addedRoomIDs: Set<String> = []
|
||||
/// Keep known children excluded while the space list resets and reloads after saving.
|
||||
private var existingRoomIDs: Set<String>
|
||||
|
||||
private var actionsSubject: PassthroughSubject<SpaceAddRoomsScreenViewModelAction, Never> = .init()
|
||||
var actions: AnyPublisher<SpaceAddRoomsScreenViewModelAction, Never> {
|
||||
@@ -31,6 +30,7 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
roomSummaryProvider: RoomSummaryProviderProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.spaceRoomListProxy = spaceRoomListProxy
|
||||
existingRoomIDs = Set(spaceRoomListProxy.spaceRoomsPublisher.value.map(\.id))
|
||||
spaceServiceProxy = userSession.clientProxy.spaceService
|
||||
self.roomSummaryProvider = roomSummaryProvider
|
||||
self.userIndicatorController = userIndicatorController
|
||||
@@ -38,6 +38,15 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
super.init(initialViewState: SpaceAddRoomsScreenViewState(roomsSection: .init(type: .suggestions, rooms: [])),
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
spaceRoomListProxy.spaceRoomsPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] spaceRooms in
|
||||
guard let self else { return }
|
||||
existingRoomIDs.formUnion(spaceRooms.map(\.id))
|
||||
updateRooms()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
roomSummaryProvider.roomListPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] _ in
|
||||
@@ -45,20 +54,18 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
let existingRooms = spaceRoomListProxy.spaceRoomsPublisher.value
|
||||
Task { [existingRoomIDs] in
|
||||
// Filter before the recent-room limit so existing children do not displace suggestions.
|
||||
suggestedRooms = await userSession.clientProxy
|
||||
.recentlyVisitedRooms { @MainActor roomProxy in
|
||||
!roomProxy.infoPublisher.value.isDirect
|
||||
&& !roomProxy.infoPublisher.value.isSpace
|
||||
&& roomProxy.infoPublisher.value.membership == .joined
|
||||
&& !existingRooms.contains { $0.id == roomProxy.id }
|
||||
&& !existingRoomIDs.contains(roomProxy.id)
|
||||
}
|
||||
.map { .init(roomProxy: $0) }
|
||||
|
||||
if state.roomsSection.type == .suggestions {
|
||||
state.roomsSection = .init(type: .suggestions, rooms: suggestedRooms)
|
||||
}
|
||||
updateRooms()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,16 +97,14 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
|
||||
private func updateRooms() {
|
||||
guard !state.bindings.searchQuery.isEmpty else {
|
||||
state.roomsSection = .init(type: .suggestions, rooms: suggestedRooms)
|
||||
state.roomsSection = .init(type: .suggestions, rooms: suggestedRooms.filter { !existingRoomIDs.contains($0.id) })
|
||||
return
|
||||
}
|
||||
|
||||
let existingRooms = spaceRoomListProxy.spaceRoomsPublisher.value
|
||||
|
||||
let rooms = roomSummaryProvider.roomListPublisher.value
|
||||
.lazy
|
||||
.filter { [addedRoomIDs] summary in
|
||||
!summary.isDirect && !existingRooms.contains { $0.id == summary.id } && !addedRoomIDs.contains(summary.id)
|
||||
.filter { [existingRoomIDs] summary in
|
||||
!summary.isDirect && !existingRoomIDs.contains(summary.id)
|
||||
}
|
||||
.map(SpaceAddRoomsScreenRoom.init)
|
||||
|
||||
@@ -142,13 +147,13 @@ class SpaceAddRoomsScreenViewModel: SpaceAddRoomsScreenViewModelType, SpaceAddRo
|
||||
for room in state.selectedRooms {
|
||||
switch await spaceServiceProxy.addChild(room.id, to: spaceRoomListProxy.id) {
|
||||
case .success:
|
||||
addedRoomIDs.insert(room.id)
|
||||
existingRoomIDs.insert(room.id)
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed adding room to space: \(error)")
|
||||
showErrorIndicator()
|
||||
|
||||
// Hide rooms that were successfully added.
|
||||
state.selectedRooms.removeAll { addedRoomIDs.contains($0.id) }
|
||||
state.selectedRooms.removeAll { existingRoomIDs.contains($0.id) }
|
||||
updateRooms()
|
||||
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user