diff --git a/tabatago-swift/TabataGo/ViewModels/PlayerViewModel.swift b/tabatago-swift/TabataGo/ViewModels/PlayerViewModel.swift index 38de8fc..69ba7b5 100644 --- a/tabatago-swift/TabataGo/ViewModels/PlayerViewModel.swift +++ b/tabatago-swift/TabataGo/ViewModels/PlayerViewModel.swift @@ -116,6 +116,8 @@ final class PlayerViewModel: ObservableObject { } func abandonWorkout() { + isRunning = false + isPaused = false timer?.invalidate() stopActivitySyncTimer() Task { try? await liveSession.end() } @@ -401,7 +403,8 @@ final class PlayerViewModel: ObservableObject { phaseElapsedSeconds: max(0, Double(totalPhaseTime) - Double(timeRemaining)) ) - if let existing = workoutActivity, existing.activityState != .active { + if let existing = workoutActivity, + existing.activityState == .ended || existing.activityState == .dismissed { workoutActivity = nil } @@ -449,12 +452,14 @@ final class PlayerViewModel: ObservableObject { } func endActivity() async { + stopActivitySyncTimer() guard let activity = workoutActivity else { return } workoutActivity = nil activityStateTask?.cancel() activityStateTask = nil nonisolated(unsafe) let safeActivity = activity - guard safeActivity.activityState == .active else { return } + guard safeActivity.activityState != .ended, + safeActivity.activityState != .dismissed else { return } let finalState = WorkoutActivityAttributes.ContentState( exerciseName: safeActivity.content.state.exerciseName, phase: .complete, @@ -497,7 +502,11 @@ final class PlayerViewModel: ObservableObject { activityStateTask = Task { @MainActor [weak self] in for await state in activity.activityStateUpdates { guard let self else { return } - if state == .stale || state == .ended || state == .dismissed { + if state == .stale { + // Stop sync timer, but keep the activity reference + // so endActivity() can still call .end() to properly dismiss it. + self.stopActivitySyncTimer() + } else if state == .ended || state == .dismissed { self.workoutActivity = nil self.stopActivitySyncTimer() }