diff --git a/Tusker/TimelineLikeController.swift b/Tusker/TimelineLikeController.swift index 62758052..deea6c38 100644 --- a/Tusker/TimelineLikeController.swift +++ b/Tusker/TimelineLikeController.swift @@ -84,8 +84,11 @@ class TimelineLikeController { 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 { 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 { 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 { } 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 { 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 { } } + @MainActor class DeferredLoadingIndicator { private let owner: TimelineLikeController private let addedIndicatorState: State @@ -352,19 +356,18 @@ class TimelineLikeController { init(owner: TimelineLikeController, 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()