From 7bc3ce0de333e5cae074e393688f60fac29babdc Mon Sep 17 00:00:00 2001 From: Justin Mazzocchi <2831158+jzzocc@users.noreply.github.com> Date: Sat, 16 Jan 2021 11:41:01 -0800 Subject: [PATCH] Fix pagination issues --- .../Services/CollectionService.swift | 3 +++ .../Services/TimelineService.swift | 1 + View Controllers/TableViewController.swift | 18 +++++++++++------- .../ViewModels/CollectionItemsViewModel.swift | 2 ++ .../ViewModels/CollectionViewModel.swift | 1 + .../Sources/ViewModels/ProfileViewModel.swift | 4 ++++ 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift b/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift index 2265fac..96670b2 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/CollectionService.swift @@ -6,6 +6,7 @@ import Mastodon public protocol CollectionService { var sections: AnyPublisher<[[CollectionItem]], Error> { get } var nextPageMaxId: AnyPublisher { get } + var preferLastPresentIdOverNextPageMaxId: Bool { get } var title: AnyPublisher { get } var titleLocalizationComponents: AnyPublisher<[String], Never> { get } var navigationService: NavigationService { get } @@ -16,6 +17,8 @@ public protocol CollectionService { extension CollectionService { public var nextPageMaxId: AnyPublisher { Empty().eraseToAnyPublisher() } + public var preferLastPresentIdOverNextPageMaxId: Bool { false } + public var title: AnyPublisher { Empty().eraseToAnyPublisher() } public var titleLocalizationComponents: AnyPublisher<[String], Never> { Empty().eraseToAnyPublisher() } diff --git a/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift b/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift index 0b051ce..a5ac402 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/TimelineService.swift @@ -10,6 +10,7 @@ public struct TimelineService { public let sections: AnyPublisher<[[CollectionItem]], Error> public let navigationService: NavigationService public let nextPageMaxId: AnyPublisher + public let preferLastPresentIdOverNextPageMaxId = true public let title: AnyPublisher private let timeline: Timeline diff --git a/View Controllers/TableViewController.swift b/View Controllers/TableViewController.swift index 992a47a..4c6546b 100644 --- a/View Controllers/TableViewController.swift +++ b/View Controllers/TableViewController.swift @@ -16,6 +16,7 @@ class TableViewController: UITableViewController { private let identification: Identification private let loadingTableFooterView = LoadingTableFooterView() private let webfingerIndicatorView = WebfingerIndicatorView() + @Published private var loading = false private var cancellables = Set() private var cellHeightCaches = [CGFloat: [CollectionItem: CGFloat]]() private var shouldKeepPlayingVideoAfterDismissal = false @@ -234,7 +235,9 @@ private extension TableViewController { .sink { [weak self] in self?.set(expandAllState: $0) } .store(in: &cancellables) - viewModel.loading.receive(on: RunLoop.main).sink { [weak self] in + viewModel.loading.receive(on: DispatchQueue.main).assign(to: &$loading) + + $loading.sink { [weak self] in guard let self = self else { return } self.tableView.tableFooterView = $0 ? self.loadingTableFooterView : UIView() @@ -244,7 +247,6 @@ private extension TableViewController { viewModel.alertItems .compactMap { $0 } - .handleEvents(receiveOutput: { print($0.error) }) .sink { [weak self] in self?.present(alertItem: $0) } .store(in: &cancellables) @@ -433,11 +435,13 @@ private extension TableViewController { } func paginateIfLastIndexPathPresent(indexPaths: [IndexPath]) { - guard - let maxId = viewModel.nextPageMaxId, - let indexPath = indexPaths.last, - indexPath.section == dataSource.numberOfSections(in: tableView) - 1, - indexPath.row == dataSource.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1 + guard !loading, + let indexPath = indexPaths.last, + indexPath.section == dataSource.numberOfSections(in: tableView) - 1, + indexPath.row == dataSource.tableView(tableView, numberOfRowsInSection: indexPath.section) - 1, + let maxId = viewModel.preferLastPresentIdOverNextPageMaxId + ? dataSource.itemIdentifier(for: indexPath)?.itemId + : viewModel.nextPageMaxId else { return } viewModel.request(maxId: maxId, minId: nil) diff --git a/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift b/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift index 03bf067..f2473cd 100644 --- a/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift +++ b/ViewModels/Sources/ViewModels/CollectionItemsViewModel.swift @@ -82,6 +82,8 @@ extension CollectionItemsViewModel: CollectionViewModel { public var shouldAdjustContentInset: Bool { collectionService is ContextService } + public var preferLastPresentIdOverNextPageMaxId: Bool { collectionService.preferLastPresentIdOverNextPageMaxId } + public func request(maxId: String? = nil, minId: String? = nil) { let publisher: AnyPublisher diff --git a/ViewModels/Sources/ViewModels/CollectionViewModel.swift b/ViewModels/Sources/ViewModels/CollectionViewModel.swift index ad40407..fc90338 100644 --- a/ViewModels/Sources/ViewModels/CollectionViewModel.swift +++ b/ViewModels/Sources/ViewModels/CollectionViewModel.swift @@ -13,6 +13,7 @@ public protocol CollectionViewModel { var events: AnyPublisher { get } var shouldAdjustContentInset: Bool { get } var nextPageMaxId: String? { get } + var preferLastPresentIdOverNextPageMaxId: Bool { get } func request(maxId: String?, minId: String?) func viewedAtTop(indexPath: IndexPath) func select(indexPath: IndexPath) diff --git a/ViewModels/Sources/ViewModels/ProfileViewModel.swift b/ViewModels/Sources/ViewModels/ProfileViewModel.swift index de5dc72..f7ea651 100644 --- a/ViewModels/Sources/ViewModels/ProfileViewModel.swift +++ b/ViewModels/Sources/ViewModels/ProfileViewModel.swift @@ -103,6 +103,10 @@ extension ProfileViewModel: CollectionViewModel { collectionViewModel.value.nextPageMaxId } + public var preferLastPresentIdOverNextPageMaxId: Bool { + collectionViewModel.value.preferLastPresentIdOverNextPageMaxId + } + public func request(maxId: String?, minId: String?) { if case .statuses = collection, maxId == nil { profileService.fetchPinnedStatuses()