fix: table reload in the background cannot keep scroll position issue
This commit is contained in:
parent
206fe8d3bd
commit
9561b58a70
|
@ -155,8 +155,14 @@ extension HomeTimelineViewModel {
|
||||||
) -> Difference<T>? {
|
) -> Difference<T>? {
|
||||||
guard let sourceIndexPath = (tableView.indexPathsForVisibleRows ?? []).sorted().first else { return nil }
|
guard let sourceIndexPath = (tableView.indexPathsForVisibleRows ?? []).sorted().first else { return nil }
|
||||||
let rectForSourceItemCell = tableView.rectForRow(at: sourceIndexPath)
|
let rectForSourceItemCell = tableView.rectForRow(at: sourceIndexPath)
|
||||||
let sourceDistanceToTableViewTopEdge = tableView.convert(rectForSourceItemCell, to: nil).origin.y - tableView.safeAreaInsets.top
|
let sourceDistanceToTableViewTopEdge: CGFloat = {
|
||||||
|
if tableView.window != nil {
|
||||||
|
return tableView.convert(rectForSourceItemCell, to: nil).origin.y - tableView.safeAreaInsets.top
|
||||||
|
} else {
|
||||||
|
return rectForSourceItemCell.origin.y - tableView.contentOffset.y - tableView.safeAreaInsets.top
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
guard sourceIndexPath.section < oldSnapshot.numberOfSections,
|
guard sourceIndexPath.section < oldSnapshot.numberOfSections,
|
||||||
sourceIndexPath.row < oldSnapshot.numberOfItems(inSection: oldSnapshot.sectionIdentifiers[sourceIndexPath.section])
|
sourceIndexPath.row < oldSnapshot.numberOfItems(inSection: oldSnapshot.sectionIdentifiers[sourceIndexPath.section])
|
||||||
else { return nil }
|
else { return nil }
|
||||||
|
|
|
@ -139,130 +139,6 @@ extension ThreadViewModel {
|
||||||
} // end Task
|
} // end Task
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
|
||||||
// Publishers.CombineLatest3(
|
|
||||||
// rootItem.removeDuplicates(),
|
|
||||||
// ancestorItems.removeDuplicates(),
|
|
||||||
// descendantItems.removeDuplicates()
|
|
||||||
// )
|
|
||||||
// .receive(on: RunLoop.main)
|
|
||||||
// .sink { [weak self] rootItem, ancestorItems, descendantItems in
|
|
||||||
// guard let self = self else { return }
|
|
||||||
// var items: [Item] = []
|
|
||||||
// rootItem.flatMap { items.append($0) }
|
|
||||||
// items.append(contentsOf: ancestorItems)
|
|
||||||
// items.append(contentsOf: descendantItems)
|
|
||||||
// self.updateDeletedStatus(for: items)
|
|
||||||
// }
|
|
||||||
// .store(in: &disposeBag)
|
|
||||||
//
|
|
||||||
// Publishers.CombineLatest4(
|
|
||||||
// rootItem,
|
|
||||||
// ancestorItems,
|
|
||||||
// descendantItems,
|
|
||||||
// existStatusFetchedResultsController.objectIDs
|
|
||||||
// )
|
|
||||||
// .debounce(for: .milliseconds(100), scheduler: RunLoop.main) // some magic to avoid jitter
|
|
||||||
// .sink { [weak self] rootItem, ancestorItems, descendantItems, existObjectIDs in
|
|
||||||
// guard let self = self else { return }
|
|
||||||
// guard let tableView = self.tableView,
|
|
||||||
// let navigationBar = self.contentOffsetAdjustableTimelineViewControllerDelegate?.navigationBar()
|
|
||||||
// else { return }
|
|
||||||
//
|
|
||||||
// guard let diffableDataSource = self.diffableDataSource else { return }
|
|
||||||
// let oldSnapshot = diffableDataSource.snapshot()
|
|
||||||
//
|
|
||||||
// var newSnapshot = NSDiffableDataSourceSnapshot<StatusSection, Item>()
|
|
||||||
// newSnapshot.appendSections([.main])
|
|
||||||
//
|
|
||||||
// let currentState = self.loadThreadStateMachine.currentState
|
|
||||||
//
|
|
||||||
// // reply to
|
|
||||||
// if self.rootNode.value?.replyToID != nil, !(currentState is LoadThreadState.NoMore) {
|
|
||||||
// newSnapshot.appendItems([.topLoader], toSection: .main)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// let ancestorItems = ancestorItems.filter { item in
|
|
||||||
// guard case let .reply(statusObjectID, _) = item else { return false }
|
|
||||||
// return existObjectIDs.contains(statusObjectID)
|
|
||||||
// }
|
|
||||||
// newSnapshot.appendItems(ancestorItems, toSection: .main)
|
|
||||||
//
|
|
||||||
// // root
|
|
||||||
// if let rootItem = rootItem,
|
|
||||||
// case let .root(objectID, _) = rootItem,
|
|
||||||
// existObjectIDs.contains(objectID) {
|
|
||||||
// newSnapshot.appendItems([rootItem], toSection: .main)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // leaf
|
|
||||||
// if !(currentState is LoadThreadState.NoMore) {
|
|
||||||
// newSnapshot.appendItems([.bottomLoader], toSection: .main)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// let descendantItems = descendantItems.filter { item in
|
|
||||||
// switch item {
|
|
||||||
// case .leaf(let statusObjectID, _):
|
|
||||||
// return existObjectIDs.contains(statusObjectID)
|
|
||||||
// default:
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// newSnapshot.appendItems(descendantItems, toSection: .main)
|
|
||||||
//
|
|
||||||
// // difference for first visible item exclude .topLoader
|
|
||||||
// guard let difference = self.calculateReloadSnapshotDifference(navigationBar: navigationBar, tableView: tableView, oldSnapshot: oldSnapshot, newSnapshot: newSnapshot) else {
|
|
||||||
// diffableDataSource.apply(newSnapshot)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // additional margin for .topLoader
|
|
||||||
// let oldTopMargin: CGFloat = {
|
|
||||||
// let marginHeight = TimelineTopLoaderTableViewCell.cellHeight
|
|
||||||
// if oldSnapshot.itemIdentifiers.contains(.topLoader) {
|
|
||||||
// return marginHeight
|
|
||||||
// }
|
|
||||||
// if !ancestorItems.isEmpty {
|
|
||||||
// return marginHeight
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return .zero
|
|
||||||
// }()
|
|
||||||
//
|
|
||||||
// let oldRootCell: UITableViewCell? = {
|
|
||||||
// guard let rootItem = rootItem else { return nil }
|
|
||||||
// guard let index = oldSnapshot.indexOfItem(rootItem) else { return nil }
|
|
||||||
// guard let cell = tableView.cellForRow(at: IndexPath(row: index, section: 0)) else { return nil }
|
|
||||||
// return cell
|
|
||||||
// }()
|
|
||||||
// // save height before cell reuse
|
|
||||||
// let oldRootCellHeight = oldRootCell?.frame.height
|
|
||||||
//
|
|
||||||
// diffableDataSource.reloadData(snapshot: newSnapshot) {
|
|
||||||
// guard let _ = rootItem else {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if let oldRootCellHeight = oldRootCellHeight {
|
|
||||||
// // set bottom inset. Make root item pin to top (with margin).
|
|
||||||
// let bottomSpacing = tableView.safeAreaLayoutGuide.layoutFrame.height - oldRootCellHeight - oldTopMargin
|
|
||||||
// tableView.contentInset.bottom = max(0, bottomSpacing)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // set scroll position
|
|
||||||
// tableView.scrollToRow(at: difference.targetIndexPath, at: .top, animated: false)
|
|
||||||
// let contentOffsetY: CGFloat = {
|
|
||||||
// var offset: CGFloat = tableView.contentOffset.y - difference.offset
|
|
||||||
// if tableView.contentInset.bottom != 0.0 && descendantItems.isEmpty {
|
|
||||||
// // needs restore top margin if bottom inset adjusted AND no descendantItems
|
|
||||||
// offset += oldTopMargin
|
|
||||||
// }
|
|
||||||
// return offset
|
|
||||||
// }()
|
|
||||||
// tableView.setContentOffset(CGPoint(x: 0, y: contentOffsetY), animated: false)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// .store(in: &disposeBag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -379,7 +255,13 @@ extension ThreadViewModel {
|
||||||
let sourceIndexPath = IndexPath(row: index, section: 0)
|
let sourceIndexPath = IndexPath(row: index, section: 0)
|
||||||
|
|
||||||
let rectForSourceItemCell = tableView.rectForRow(at: sourceIndexPath)
|
let rectForSourceItemCell = tableView.rectForRow(at: sourceIndexPath)
|
||||||
let sourceDistanceToTableViewTopEdge = tableView.convert(rectForSourceItemCell, to: nil).origin.y - tableView.safeAreaInsets.top
|
let sourceDistanceToTableViewTopEdge: CGFloat = {
|
||||||
|
if tableView.window != nil {
|
||||||
|
return tableView.convert(rectForSourceItemCell, to: nil).origin.y - tableView.safeAreaInsets.top
|
||||||
|
} else {
|
||||||
|
return rectForSourceItemCell.origin.y - tableView.contentOffset.y - tableView.safeAreaInsets.top
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
guard sourceIndexPath.section < oldSnapshot.numberOfSections,
|
guard sourceIndexPath.section < oldSnapshot.numberOfSections,
|
||||||
sourceIndexPath.row < oldSnapshot.numberOfItems(inSection: oldSnapshot.sectionIdentifiers[sourceIndexPath.section])
|
sourceIndexPath.row < oldSnapshot.numberOfItems(inSection: oldSnapshot.sectionIdentifiers[sourceIndexPath.section])
|
||||||
|
@ -403,33 +285,3 @@ extension ThreadViewModel {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//extension ThreadViewModel {
|
|
||||||
// private func updateDeletedStatus(for items: [Item]) {
|
|
||||||
// let parentManagedObjectContext = context.managedObjectContext
|
|
||||||
// let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
|
||||||
// managedObjectContext.parent = parentManagedObjectContext
|
|
||||||
// managedObjectContext.perform {
|
|
||||||
// var statusIDs: [Status.ID] = []
|
|
||||||
// for item in items {
|
|
||||||
// switch item {
|
|
||||||
// case .root(let objectID, _):
|
|
||||||
// guard let status = managedObjectContext.object(with: objectID) as? Status else { continue }
|
|
||||||
// statusIDs.append(status.id)
|
|
||||||
// case .reply(let objectID, _):
|
|
||||||
// guard let status = managedObjectContext.object(with: objectID) as? Status else { continue }
|
|
||||||
// statusIDs.append(status.id)
|
|
||||||
// case .leaf(let objectID, _):
|
|
||||||
// guard let status = managedObjectContext.object(with: objectID) as? Status else { continue }
|
|
||||||
// statusIDs.append(status.id)
|
|
||||||
// default:
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// DispatchQueue.main.async { [weak self] in
|
|
||||||
// guard let self = self else { return }
|
|
||||||
// self.existStatusFetchedResultsController.statusIDs.value = statusIDs
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
Loading…
Reference in New Issue