Fix older notifications not loading when initially visible set fits on one screen
Closes #346
This commit is contained in:
parent
53d43b5707
commit
c4bf5d406d
|
@ -539,6 +539,10 @@ extension NotificationsCollectionViewController: UICollectionViewDelegate {
|
|||
let itemsInSection = collectionView.numberOfItems(inSection: indexPath.section)
|
||||
if indexPath.row == itemsInSection - 1 {
|
||||
Task {
|
||||
// Because of grouping, all cells from the first load may fit on screen,
|
||||
// in which case, we try to load older while still in the loadingInitial state.
|
||||
// So, wait for that to finish before trying to load more.
|
||||
await controller.finishPendingOperation()
|
||||
await controller.loadOlder()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
import OSLog
|
||||
import Combine
|
||||
|
||||
protocol TimelineLikeControllerDelegate<TimelineItem>: AnyObject {
|
||||
associatedtype TimelineItem: Sendable
|
||||
|
@ -42,7 +43,7 @@ class TimelineLikeController<Item: Sendable> {
|
|||
private unowned var delegate: any TimelineLikeControllerDelegate<Item>
|
||||
private let ownerType: String
|
||||
|
||||
private(set) var state = State.notLoadedInitial {
|
||||
@AsyncObservable private(set) var state = State.notLoadedInitial {
|
||||
willSet {
|
||||
guard state.canTransition(to: newValue) else {
|
||||
logger.error("\(self.ownerType, privacy: .public) State \(self.state.debugDescription, privacy: .public) cannot transition to \(newValue.debugDescription, privacy: .public)")
|
||||
|
@ -57,6 +58,19 @@ class TimelineLikeController<Item: Sendable> {
|
|||
self.ownerType = ownerType
|
||||
}
|
||||
|
||||
/// Waits for the controller to finish the current operation and arrive at the idle state.
|
||||
///
|
||||
/// If the current state is `notLoadedInitial`, this will wait until the controller
|
||||
/// settles after the initial load.
|
||||
func finishPendingOperation() async {
|
||||
guard state != .idle else {
|
||||
return
|
||||
}
|
||||
for await state in $state where state == .idle {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func loadInitial() async {
|
||||
guard state == .notLoadedInitial || state == .idle else {
|
||||
return
|
||||
|
@ -369,3 +383,17 @@ enum TimelineGapDirection {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// I would love to be able to do this with @Observable, but it's not clear how to do so.
|
||||
@propertyWrapper
|
||||
private class AsyncObservable<Value>: ObservableObject {
|
||||
@Published var wrappedValue: Value
|
||||
|
||||
var projectedValue: AsyncPublisher<Published<Value>.Publisher> {
|
||||
$wrappedValue.values
|
||||
}
|
||||
|
||||
init(wrappedValue: Value) {
|
||||
self.wrappedValue = wrappedValue
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue