Scroll position maintenance

This commit is contained in:
Justin Mazzocchi 2020-10-06 16:12:11 -07:00
parent a124c44eb1
commit c589c74052
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
4 changed files with 27 additions and 0 deletions

View file

@ -210,6 +210,12 @@ private extension TableViewController {
self.sizeTableHeaderFooterViews() self.sizeTableHeaderFooterViews()
} }
.store(in: &cancellables) .store(in: &cancellables)
tableView.publisher(for: \.contentOffset)
.compactMap { [weak self] _ in self?.tableView.indexPathsForVisibleRows?.first }
.removeDuplicates()
.sink { [weak self] in self?.viewModel.viewedAtTop(indexPath: $0) }
.store(in: &cancellables)
} }
func update(items: [[CollectionItemIdentifier]]) { func update(items: [[CollectionItemIdentifier]]) {

View file

@ -15,6 +15,7 @@ final public class CollectionItemsViewModel: ObservableObject {
private var viewModelCache = [CollectionItem: (CollectionItemViewModel, AnyCancellable)]() private var viewModelCache = [CollectionItem: (CollectionItemViewModel, AnyCancellable)]()
private let navigationEventsSubject = PassthroughSubject<NavigationEvent, Never>() private let navigationEventsSubject = PassthroughSubject<NavigationEvent, Never>()
private let loadingSubject = PassthroughSubject<Bool, Never>() private let loadingSubject = PassthroughSubject<Bool, Never>()
private var topVisibleIndexPath = IndexPath(item: 0, section: 0)
private var lastSelectedLoadMore: LoadMore? private var lastSelectedLoadMore: LoadMore?
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
@ -80,6 +81,10 @@ extension CollectionItemsViewModel: CollectionViewModel {
} }
} }
public func viewedAtTop(indexPath: IndexPath) {
topVisibleIndexPath = indexPath
}
public func canSelect(indexPath: IndexPath) -> Bool { public func canSelect(indexPath: IndexPath) -> Bool {
switch items.value[indexPath.section][indexPath.item] { switch items.value[indexPath.section][indexPath.item] {
case let .status(_, configuration): case let .status(_, configuration):
@ -180,6 +185,17 @@ private extension CollectionItemsViewModel {
} }
} }
} }
if items.value.count > topVisibleIndexPath.section,
items.value[topVisibleIndexPath.section].count > topVisibleIndexPath.item {
let topVisibleItem = items.value[topVisibleIndexPath.section][topVisibleIndexPath.item]
if newItems.count > topVisibleIndexPath.section,
let newIndex = newItems[topVisibleIndexPath.section].firstIndex(of: topVisibleItem),
newIndex > topVisibleIndexPath.item {
return .init(item: topVisibleItem)
}
}
} }
return nil return nil

View file

@ -12,6 +12,7 @@ public protocol CollectionViewModel {
var nextPageMaxId: String? { get } var nextPageMaxId: String? { get }
var maintainScrollPositionOfItem: CollectionItemIdentifier? { get } var maintainScrollPositionOfItem: CollectionItemIdentifier? { get }
func request(maxId: String?, minId: String?) func request(maxId: String?, minId: String?)
func viewedAtTop(indexPath: IndexPath)
func select(indexPath: IndexPath) func select(indexPath: IndexPath)
func canSelect(indexPath: IndexPath) -> Bool func canSelect(indexPath: IndexPath) -> Bool
func viewModel(indexPath: IndexPath) -> CollectionItemViewModel func viewModel(indexPath: IndexPath) -> CollectionItemViewModel

View file

@ -85,6 +85,10 @@ extension ProfileViewModel: CollectionViewModel {
collectionViewModel.value.request(maxId: maxId, minId: minId) collectionViewModel.value.request(maxId: maxId, minId: minId)
} }
public func viewedAtTop(indexPath: IndexPath) {
collectionViewModel.value.viewedAtTop(indexPath: indexPath)
}
public func select(indexPath: IndexPath) { public func select(indexPath: IndexPath) {
collectionViewModel.value.select(indexPath: indexPath) collectionViewModel.value.select(indexPath: indexPath)
} }