mirror of
https://github.com/metabolist/metatext.git
synced 2024-12-22 21:46:28 +00:00
Fix inset adjustment
This commit is contained in:
parent
73fc2cd599
commit
d42642c079
5 changed files with 33 additions and 37 deletions
|
@ -291,14 +291,11 @@ private extension TableViewController {
|
|||
if
|
||||
let itemId = update.maintainScrollPositionItemId,
|
||||
let indexPath = self.dataSource.indexPath(itemId: itemId) {
|
||||
if self.viewModel.shouldAdjustContentInset {
|
||||
if update.shouldAdjustContentInset {
|
||||
self.tableView.contentInset.bottom = max(
|
||||
Self.bottomInset,
|
||||
self.tableView.frame.height
|
||||
- self.tableView.contentSize.height
|
||||
- self.tableView.safeAreaInsets.top
|
||||
- self.tableView.safeAreaInsets.bottom)
|
||||
+ self.tableView.rectForRow(at: indexPath).minY
|
||||
self.tableView.safeAreaLayoutGuide.layoutFrame.height
|
||||
- self.tableView.rectForRow(at: indexPath).height,
|
||||
Self.bottomInset)
|
||||
}
|
||||
|
||||
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
|
||||
|
|
|
@ -9,14 +9,16 @@ public final class CollectionItemsViewModel: ObservableObject {
|
|||
@Published public var alertItem: AlertItem?
|
||||
public private(set) var nextPageMaxId: String?
|
||||
|
||||
private let items = CurrentValueSubject<[[CollectionItem]], Never>([])
|
||||
@Published private var lastUpdate = CollectionUpdate(
|
||||
items: [],
|
||||
maintainScrollPositionItemId: nil,
|
||||
shouldAdjustContentInset: false)
|
||||
private let collectionService: CollectionService
|
||||
private let identification: Identification
|
||||
private var viewModelCache = [CollectionItem: (viewModel: CollectionItemViewModel, events: AnyCancellable)]()
|
||||
private let eventsSubject = PassthroughSubject<CollectionItemEvent, Never>()
|
||||
private let loadingSubject = PassthroughSubject<Bool, Never>()
|
||||
private let expandAllSubject: CurrentValueSubject<ExpandAllState, Never>
|
||||
private var maintainScrollPositionItemId: CollectionItem.Id?
|
||||
private var topVisibleIndexPath = IndexPath(item: 0, section: 0)
|
||||
private let lastReadId = CurrentValueSubject<String?, Never>(nil)
|
||||
private var lastSelectedLoadMore: LoadMore?
|
||||
|
@ -57,11 +59,7 @@ public final class CollectionItemsViewModel: ObservableObject {
|
|||
|
||||
extension CollectionItemsViewModel: CollectionViewModel {
|
||||
public var updates: AnyPublisher<CollectionUpdate, Never> {
|
||||
items.map { [weak self] in
|
||||
CollectionUpdate(items: $0,
|
||||
maintainScrollPositionItemId: self?.maintainScrollPositionItemId)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
$lastUpdate.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
public var title: AnyPublisher<String, Never> { collectionService.title }
|
||||
|
@ -80,8 +78,6 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
|
||||
public var events: AnyPublisher<CollectionItemEvent, Never> { eventsSubject.eraseToAnyPublisher() }
|
||||
|
||||
public var shouldAdjustContentInset: Bool { collectionService is ContextService }
|
||||
|
||||
public var preferLastPresentIdOverNextPageMaxId: Bool { collectionService.preferLastPresentIdOverNextPageMaxId }
|
||||
|
||||
public var canRefresh: Bool { collectionService.canRefresh }
|
||||
|
@ -120,7 +116,7 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
}
|
||||
|
||||
public func select(indexPath: IndexPath) {
|
||||
let item = items.value[indexPath.section][indexPath.item]
|
||||
let item = lastUpdate.items[indexPath.section][indexPath.item]
|
||||
|
||||
switch item {
|
||||
case let .status(status, _):
|
||||
|
@ -162,14 +158,14 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
topVisibleIndexPath = indexPath
|
||||
|
||||
if !shouldRestorePositionOfLocalLastReadId,
|
||||
items.value.count > indexPath.section,
|
||||
items.value[indexPath.section].count > indexPath.item {
|
||||
lastReadId.send(items.value[indexPath.section][indexPath.item].itemId)
|
||||
lastUpdate.items.count > indexPath.section,
|
||||
lastUpdate.items[indexPath.section].count > indexPath.item {
|
||||
lastReadId.send(lastUpdate.items[indexPath.section][indexPath.item].itemId)
|
||||
}
|
||||
}
|
||||
|
||||
public func canSelect(indexPath: IndexPath) -> Bool {
|
||||
switch items.value[indexPath.section][indexPath.item] {
|
||||
switch lastUpdate.items[indexPath.section][indexPath.item] {
|
||||
case let .status(_, configuration):
|
||||
return !configuration.isContextParent
|
||||
case .loadMore:
|
||||
|
@ -181,7 +177,7 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
|
||||
// swiftlint:disable:next function_body_length cyclomatic_complexity
|
||||
public func viewModel(indexPath: IndexPath) -> CollectionItemViewModel {
|
||||
let item = items.value[indexPath.section][indexPath.item]
|
||||
let item = lastUpdate.items[indexPath.section][indexPath.item]
|
||||
let cachedViewModel = viewModelCache[item]?.viewModel
|
||||
|
||||
switch item {
|
||||
|
@ -261,7 +257,7 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
}
|
||||
|
||||
public func toggleExpandAll() {
|
||||
let statusIds = Set(items.value.reduce([], +).compactMap { item -> Status.Id? in
|
||||
let statusIds = Set(lastUpdate.items.reduce([], +).compactMap { item -> Status.Id? in
|
||||
guard case let .status(status, _) = item else { return nil }
|
||||
|
||||
return status.id
|
||||
|
@ -287,6 +283,10 @@ extension CollectionItemsViewModel: CollectionViewModel {
|
|||
}
|
||||
|
||||
private extension CollectionItemsViewModel {
|
||||
var lastUpdateWasContextParentOnly: Bool {
|
||||
collectionService is ContextService && lastUpdate.items.map(\.count) == [0, 1, 0]
|
||||
}
|
||||
|
||||
func cache(viewModel: CollectionItemViewModel, forItem item: CollectionItem) {
|
||||
viewModelCache[item] = (viewModel, viewModel.events
|
||||
.flatMap { [weak self] events -> AnyPublisher<CollectionItemEvent, Never> in
|
||||
|
@ -299,10 +299,13 @@ private extension CollectionItemsViewModel {
|
|||
}
|
||||
|
||||
func process(items: [[CollectionItem]]) {
|
||||
maintainScrollPositionItemId = idForScrollPositionMaintenance(newItems: items)
|
||||
self.items.send(items)
|
||||
let flatItems = items.reduce([], +)
|
||||
let itemsSet = Set(flatItems)
|
||||
|
||||
let itemsSet = Set(items.reduce([], +))
|
||||
self.lastUpdate = .init(
|
||||
items: items,
|
||||
maintainScrollPositionItemId: idForScrollPositionMaintenance(newItems: items),
|
||||
shouldAdjustContentInset: lastUpdateWasContextParentOnly && flatItems.count > 1)
|
||||
|
||||
viewModelCache = viewModelCache.filter { itemsSet.contains($0.key) }
|
||||
}
|
||||
|
@ -312,14 +315,14 @@ private extension CollectionItemsViewModel {
|
|||
|
||||
guard let markerTimeline = collectionService.markerTimeline,
|
||||
identification.appPreferences.positionBehavior(markerTimeline: markerTimeline) == .rememberPosition,
|
||||
let lastItemId = items.value.last?.last?.itemId
|
||||
let lastItemId = lastUpdate.items.last?.last?.itemId
|
||||
else { return maxId }
|
||||
|
||||
return min(maxId, lastItemId)
|
||||
}
|
||||
|
||||
func idForScrollPositionMaintenance(newItems: [[CollectionItem]]) -> CollectionItem.Id? {
|
||||
let flatItems = items.value.reduce([], +)
|
||||
let flatItems = lastUpdate.items.reduce([], +)
|
||||
let flatNewItems = newItems.reduce([], +)
|
||||
|
||||
if shouldRestorePositionOfLocalLastReadId,
|
||||
|
@ -332,7 +335,7 @@ private extension CollectionItemsViewModel {
|
|||
}
|
||||
|
||||
if collectionService is ContextService,
|
||||
items.value.isEmpty || items.value.map(\.count) == [0, 1, 0],
|
||||
lastUpdate.items.isEmpty || lastUpdate.items.map(\.count) == [0, 1, 0],
|
||||
let contextParent = flatNewItems.first(where: {
|
||||
guard case let .status(_, configuration) = $0 else { return false }
|
||||
|
||||
|
@ -359,9 +362,9 @@ 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 lastUpdate.items.count > topVisibleIndexPath.section,
|
||||
lastUpdate.items[topVisibleIndexPath.section].count > topVisibleIndexPath.item {
|
||||
let topVisibleItem = lastUpdate.items[topVisibleIndexPath.section][topVisibleIndexPath.item]
|
||||
|
||||
if newItems.count > topVisibleIndexPath.section,
|
||||
let newIndex = newItems[topVisibleIndexPath.section]
|
||||
|
|
|
@ -11,7 +11,6 @@ public protocol CollectionViewModel {
|
|||
var alertItems: AnyPublisher<AlertItem, Never> { get }
|
||||
var loading: AnyPublisher<Bool, Never> { get }
|
||||
var events: AnyPublisher<CollectionItemEvent, Never> { get }
|
||||
var shouldAdjustContentInset: Bool { get }
|
||||
var nextPageMaxId: String? { get }
|
||||
var preferLastPresentIdOverNextPageMaxId: Bool { get }
|
||||
var canRefresh: Bool { get }
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
public struct CollectionUpdate: Hashable {
|
||||
public let items: [[CollectionItem]]
|
||||
public let maintainScrollPositionItemId: String?
|
||||
public let shouldAdjustContentInset: Bool
|
||||
}
|
||||
|
|
|
@ -95,10 +95,6 @@ extension ProfileViewModel: CollectionViewModel {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
public var shouldAdjustContentInset: Bool {
|
||||
collectionViewModel.value.shouldAdjustContentInset
|
||||
}
|
||||
|
||||
public var nextPageMaxId: String? {
|
||||
collectionViewModel.value.nextPageMaxId
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue