Show loading indicator when restoring timeline state

This commit is contained in:
Shadowfacts 2023-01-20 13:38:33 -05:00
parent 9a2c24942a
commit 9d845bf6c1
1 changed files with 17 additions and 14 deletions

View File

@ -84,8 +84,11 @@ class TimelineLikeController<Item> {
guard state == .notLoadedInitial || state == .idle else {
return
}
state = .restoringInitial
let token = LoadAttemptToken()
state = .restoringInitial(token, hasAddedLoadingIndicator: false)
let loadingIndicator = DeferredLoadingIndicator(owner: self, state: state, addedIndicatorState: .restoringInitial(token, hasAddedLoadingIndicator: true))
await doRestore()
await loadingIndicator.end()
state = .idle
}
@ -198,7 +201,7 @@ class TimelineLikeController<Item> {
enum State: Equatable, CustomDebugStringConvertible {
case notLoadedInitial
case idle
case restoringInitial
case restoringInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
case loadingInitial(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
case loadingNewer(LoadAttemptToken)
case loadingOlder(LoadAttemptToken, hasAddedLoadingIndicator: Bool)
@ -210,8 +213,8 @@ class TimelineLikeController<Item> {
return "notLoadedInitial"
case .idle:
return "idle"
case .restoringInitial:
return "restoringInitial"
case .restoringInitial(let token, let hasAddedLoadingIndicator):
return "restoringInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
case .loadingInitial(let token, let hasAddedLoadingIndicator):
return "loadingInitial(\(ObjectIdentifier(token)), hasAddedLoadingIndicator: \(hasAddedLoadingIndicator))"
case .loadingNewer(let token):
@ -234,13 +237,13 @@ class TimelineLikeController<Item> {
}
case .idle:
switch to {
case .restoringInitial, .loadingInitial(_, _), .loadingNewer(_), .loadingOlder(_, _), .loadingGap(_, _):
case .restoringInitial(_, _), .loadingInitial(_, _), .loadingNewer(_), .loadingOlder(_, _), .loadingGap(_, _):
return true
default:
return false
}
case .restoringInitial:
return to == .idle
case .restoringInitial(let token, let hasAddedLoadingIndicator):
return to == .idle || (!hasAddedLoadingIndicator && to == .restoringInitial(token, hasAddedLoadingIndicator: true))
case .loadingInitial(let token, let hasAddedLoadingIndicator):
return to == .notLoadedInitial || to == .idle || (!hasAddedLoadingIndicator && to == .loadingInitial(token, hasAddedLoadingIndicator: true))
case .loadingNewer(_):
@ -256,14 +259,14 @@ class TimelineLikeController<Item> {
switch event {
case .addLoadingIndicator:
switch self {
case .loadingInitial(_, _), .loadingOlder(_, _):
case .restoringInitial(_, _), .loadingInitial(_, _), .loadingOlder(_, _):
return true
default:
return false
}
case .removeLoadingIndicator:
switch self {
case .loadingInitial(_, hasAddedLoadingIndicator: true), .loadingOlder(_, hasAddedLoadingIndicator: true):
case .restoringInitial(_, hasAddedLoadingIndicator: true), .loadingInitial(_, hasAddedLoadingIndicator: true), .loadingOlder(_, hasAddedLoadingIndicator: true):
return true
default:
return false
@ -344,6 +347,7 @@ class TimelineLikeController<Item> {
}
}
@MainActor
class DeferredLoadingIndicator {
private let owner: TimelineLikeController<Item>
private let addedIndicatorState: State
@ -352,19 +356,18 @@ class TimelineLikeController<Item> {
init(owner: TimelineLikeController<Item>, state: State, addedIndicatorState: State) {
self.owner = owner
self.addedIndicatorState = addedIndicatorState
self.task = Task {
self.task = Task { @MainActor in
try await Task.sleep(nanoseconds: 150 * NSEC_PER_MSEC)
guard await state == owner.state else {
guard state == owner.state else {
return
}
await owner.emit(event: .addLoadingIndicator)
await owner.transition(to: addedIndicatorState)
owner.transition(to: addedIndicatorState)
}
}
func end() async {
let state = await owner.state
if state == addedIndicatorState {
if owner.state == addedIndicatorState {
await owner.emit(event: .removeLoadingIndicator)
} else {
task.cancel()