forked from shadowfacts/Tusker
Show loading indicator when restoring timeline state
This commit is contained in:
parent
9a2c24942a
commit
9d845bf6c1
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue