From f99b607f080025bcc01b5c7238889050e3a73a9f Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Mon, 12 Oct 2026 10:39:19 +0200 Subject: [PATCH] Fix room pickers not loading more than the first page of rooms The forward, share, add-to-space and search pickers signal reaching the bottom of the list with an empty `roomCount.. 0, range.upperBound >= rooms.count - Int(roomListPageSize) / 2, rooms.count != roomCountOnLastPageAddRequest else { return diff --git a/UnitTests/Sources/RoomSummaryProviderTests.swift b/UnitTests/Sources/RoomSummaryProviderTests.swift index c76e37852..99676d9f8 100644 --- a/UnitTests/Sources/RoomSummaryProviderTests.swift +++ b/UnitTests/Sources/RoomSummaryProviderTests.swift @@ -22,6 +22,10 @@ final class RoomSummaryProviderTests { var dynamicEntriesController: RoomListDynamicEntriesControllerSDKMock! var roomSummaryProvider: RoomSummaryProvider! + enum TestError: Error { + case missingRoomInfo + } + @Test func defaultRustFilters() async { // Given a new room provider. @@ -119,9 +123,63 @@ final class RoomSummaryProviderTests { #expect(dynamicEntriesController.setFilterKindReceivedInvocations.last == .all(filters: [.all(filters: [.favourite, .joined])] + baseFilters + [.identifiers(identifiers: ["SomeRoom"])])) } + @Test + func reachingTheBottomAddsAPage() async throws { + // Given a provider showing its first page of rooms. + setup(roomListPageSize: 10) + try await loadRooms(count: 10) + + // When a picker reports reaching the bottom with an empty range at the end of the list. + roomSummaryProvider.updateVisibleRange(10..<10) + + // Then the next page should be requested. + #expect(dynamicEntriesController.addOnePageCallsCount == 1) + + // When reaching the bottom again before that page has loaded. + roomSummaryProvider.updateVisibleRange(10..<10) + + // Then the request shouldn't be repeated. + #expect(dynamicEntriesController.addOnePageCallsCount == 1) + } + + @Test + func scrollingNearTheBottomPrefetchesAPage() async throws { + // Given a provider showing its first page of rooms. + setup(roomListPageSize: 10) + try await loadRooms(count: 10) + + // When scrolling to more than half a page away from the bottom. + roomSummaryProvider.updateVisibleRange(0..<4) + + // Then no page should be requested yet. + #expect(dynamicEntriesController.addOnePageCallsCount == 0) + + // When scrolling to half a page away from the bottom. + roomSummaryProvider.updateVisibleRange(1..<5) + + // Then the next page should be requested. + #expect(dynamicEntriesController.addOnePageCallsCount == 1) + } + + @Test + func reachingTheTopDoesNotAddAPage() async throws { + // Given a provider with fewer rooms than half a page. + setup(roomListPageSize: 10) + try await loadRooms(count: 4) + + // When a picker reports reaching the top with an empty range at the start of the list. + roomSummaryProvider.updateVisibleRange(0..<0) + + // Then no page should be requested. + #expect(dynamicEntriesController.addOnePageCallsCount == 0) + } + // MARK: - Helpers - private func setup(isLowPriorityFilterEnabled: Bool = false, includesOnlyJoinedRooms: Bool = false, setsRoomList: Bool = true) { + private func setup(isLowPriorityFilterEnabled: Bool = false, + includesOnlyJoinedRooms: Bool = false, + roomListPageSize: UInt32 = 100, + setsRoomList: Bool = true) { userSettings = UserSettings.mock() userSettings.app.lowPriorityFilterEnabled = isLowPriorityFilterEnabled @@ -136,6 +194,7 @@ final class RoomSummaryProviderTests { eventStringBuilder: eventStringBuilder, name: "Test", includesOnlyJoinedRooms: includesOnlyJoinedRooms, + roomListPageSize: roomListPageSize, notificationSettings: NotificationSettingsProxyMock(with: .init()), userSettings: userSettings) @@ -151,4 +210,20 @@ final class RoomSummaryProviderTests { roomSummaryProvider.setRoomList(roomList) } } + + private func loadRooms(count: Int) async throws { + let listener = try #require(roomList.entriesWithDynamicAdaptersPageSizeListenerReceivedArguments?.listener) + let rooms = (0..