mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Fix back pagination (#432)
* Use pagination and start items for view state. isBackPaginating and canBackPaginate are updated each time the timeline is rebuilt * Update some timeline snapshots The top section has gone, which has altered the layout slightly.
This commit is contained in:
@@ -19,8 +19,6 @@ import Combine
|
||||
struct MockRoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
var itemsPublisher = CurrentValueSubject<[TimelineItemProxy], Never>([])
|
||||
|
||||
var backPaginationPublisher = CurrentValueSubject<Bool, Never>(false)
|
||||
|
||||
private var itemProxies = [TimelineItemProxy]()
|
||||
|
||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineProviderError> {
|
||||
|
||||
@@ -32,15 +32,10 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
let itemsPublisher = CurrentValueSubject<[TimelineItemProxy], Never>([])
|
||||
let backPaginationPublisher = CurrentValueSubject<Bool, Never>(false)
|
||||
|
||||
private var itemProxies: [TimelineItemProxy] {
|
||||
didSet {
|
||||
itemsPublisher.send(itemProxies)
|
||||
|
||||
if backPaginationPublisher.value == true {
|
||||
backPaginationPublisher.send(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +64,6 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
}
|
||||
|
||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineProviderError> {
|
||||
// Set this back to false after actually updating the items or if failed
|
||||
backPaginationPublisher.send(true)
|
||||
|
||||
MXLog.info("Started back pagination request")
|
||||
switch await roomProxy.paginateBackwards(requestSize: requestSize, untilNumberOfItems: untilNumberOfItems) {
|
||||
case .success:
|
||||
@@ -79,7 +71,6 @@ class RoomTimelineProvider: RoomTimelineProviderProtocol {
|
||||
return .success(())
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed back pagination request with error: \(error)")
|
||||
backPaginationPublisher.send(false)
|
||||
|
||||
if error == .noMoreMessagesToBackPaginate {
|
||||
return .failure(.noMoreMessagesToBackPaginate)
|
||||
|
||||
@@ -29,8 +29,6 @@ enum RoomTimelineProviderError: Error {
|
||||
protocol RoomTimelineProviderProtocol {
|
||||
var itemsPublisher: CurrentValueSubject<[TimelineItemProxy], Never> { get }
|
||||
|
||||
var backPaginationPublisher: CurrentValueSubject<Bool, Never> { get }
|
||||
|
||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineProviderError>
|
||||
|
||||
func sendMessage(_ message: String, inReplyToItemId: String?) async -> Result<Void, RoomTimelineProviderError>
|
||||
|
||||
+3
-15
@@ -42,20 +42,7 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
|
||||
func paginateBackwards(requestSize: UInt, untilNumberOfItems: UInt) async -> Result<Void, RoomTimelineControllerError> {
|
||||
callbacks.send(.startedBackPaginating)
|
||||
|
||||
guard !backPaginationResponses.isEmpty else {
|
||||
callbacks.send(.finishedBackPaginating)
|
||||
return .failure(.generic)
|
||||
}
|
||||
|
||||
let newItems = backPaginationResponses.removeFirst()
|
||||
|
||||
try? await Task.sleep(for: backPaginationDelay)
|
||||
timelineItems.insert(contentsOf: newItems, at: 0)
|
||||
callbacks.send(.updatedTimelineItems)
|
||||
callbacks.send(.finishedBackPaginating)
|
||||
|
||||
callbacks.send(.canBackPaginate(false))
|
||||
return .success(())
|
||||
}
|
||||
|
||||
@@ -125,11 +112,12 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
|
||||
/// Prepends the next chunk of items to the `timelineItems` array.
|
||||
private func simulateBackPagination() async throws {
|
||||
guard !backPaginationResponses.isEmpty else { return }
|
||||
callbacks.send(.isBackPaginating(true))
|
||||
|
||||
let newItems = backPaginationResponses.removeFirst()
|
||||
timelineItems.insert(contentsOf: newItems, at: 0)
|
||||
callbacks.send(.updatedTimelineItems)
|
||||
callbacks.send(.finishedBackPaginating)
|
||||
callbacks.send(.isBackPaginating(false))
|
||||
|
||||
try? await connection?.send(.success)
|
||||
}
|
||||
|
||||
@@ -61,18 +61,6 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
self.timelineProvider
|
||||
.backPaginationPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] value in
|
||||
if value {
|
||||
self?.callbacks.send(.startedBackPaginating)
|
||||
} else {
|
||||
self?.callbacks.send(.finishedBackPaginating)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
updateTimelineItems()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
@@ -230,6 +218,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
private func asyncUpdateTimelineItems() async {
|
||||
var newTimelineItems = [RoomTimelineItemProtocol]()
|
||||
var canBackPaginate = true
|
||||
var isBackPaginating = false
|
||||
|
||||
for (index, itemProxy) in timelineProvider.itemsPublisher.value.enumerated() {
|
||||
if Task.isCancelled {
|
||||
@@ -262,8 +252,10 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
}
|
||||
case .loadingIndicator:
|
||||
newTimelineItems.append(PaginationIndicatorRoomTimelineItem())
|
||||
isBackPaginating = true
|
||||
case .timelineStart:
|
||||
newTimelineItems.append(TimelineStartRoomTimelineItem(name: roomProxy.displayName ?? roomProxy.name))
|
||||
canBackPaginate = false
|
||||
}
|
||||
default:
|
||||
break
|
||||
@@ -277,6 +269,8 @@ class RoomTimelineController: RoomTimelineControllerProtocol {
|
||||
timelineItems = newTimelineItems
|
||||
|
||||
callbacks.send(.updatedTimelineItems)
|
||||
callbacks.send(.canBackPaginate(canBackPaginate))
|
||||
callbacks.send(.isBackPaginating(isBackPaginating))
|
||||
}
|
||||
|
||||
private func computeGroupState(for itemProxy: TimelineItemProxy,
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@ import UIKit
|
||||
enum RoomTimelineControllerCallback {
|
||||
case updatedTimelineItems
|
||||
case updatedTimelineItem(_ itemId: String)
|
||||
case startedBackPaginating
|
||||
case finishedBackPaginating
|
||||
case canBackPaginate(Bool)
|
||||
case isBackPaginating(Bool)
|
||||
}
|
||||
|
||||
enum RoomTimelineControllerAction {
|
||||
|
||||
Reference in New Issue
Block a user