Some checks failed
Apple Platform CI / smoke-and-tests (push) Has been cancelled
Deep audit (issues 2-14): - Add missing WCSession handlers for applicationContext and userInfo - Fix BoundedFIFOQueue race condition with serial dispatch queue - Fix timer race condition with main thread guarantee - Fix watch pause state divergence — phone is now source of truth - Fix wrong notification posted on logout (createdNewWorkout → userLoggedOut) - Fix POST status check to accept any 2xx (was exact match) - Fix @StateObject → @ObservedObject for injected viewModel - Add pull-to-refresh to CompletedWorkoutsView - Fix typos: RefreshUserInfoFetcable, defualtPackageModle - Replace string concatenation with interpolation - Replace 6 @StateObject with @ObservedObject for BridgeModule.shared - Replace 7 hardcoded AVPlayer URLs with BaseURLs.currentBaseURL UI audit (issues 1-15): - Fix GeometryReader eating VStack space — replaced with .overlay - Fix refreshable continuation resuming before fetch completes - Remove duplicate @State workouts — derive from DataStore - Decouple leaf views from BridgeModule (pass discrete values) - Convert selectedIds from Array to Set for O(1) lookups - Extract .sorted() from var body into computed properties - Move search filter out of ForEach render loop - Replace import SwiftUI with import Combine in non-UI classes - Mark all @State properties private - Extract L/R exercise auto-add logic to WorkoutViewModel - Use enumerated() instead of .indices in ForEach - Make AddSupersetView frame flexible instead of fixed 300pt - Hoist Set construction out of per-exercise filter loop - Move ViewModel network fetch from init to load() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.0 KiB
Swift
97 lines
3.0 KiB
Swift
//
|
|
// WatchMainViewMoel.swift
|
|
// Werkout_watch Watch App
|
|
//
|
|
// Created by Trey Tartt on 6/22/23.
|
|
//
|
|
|
|
import Foundation
|
|
import WatchConnectivity
|
|
import SwiftUI
|
|
import HealthKit
|
|
import os
|
|
import SharedCore
|
|
|
|
class WatchMainViewModel: NSObject, ObservableObject {
|
|
static let shared = WatchMainViewModel()
|
|
let logger = Logger(subsystem: "com.werkout.watch", category: "session")
|
|
|
|
var session: WCSession
|
|
|
|
@Published var watchPackageModel = WatchMainViewModel.defaultPackageModel
|
|
|
|
static var defaultPackageModel: WatchPackageModel {
|
|
WatchPackageModel(currentExerciseName: "", currentExerciseID: -1, currentTimeLeft: -1, workoutStartDate: Date())
|
|
}
|
|
|
|
override init() {
|
|
session = WCSession.default
|
|
super.init()
|
|
|
|
session.delegate = self
|
|
session.activate()
|
|
|
|
}
|
|
|
|
private func send(_ action: WatchActions) {
|
|
do {
|
|
let data = try JSONEncoder().encode(action)
|
|
DataSender.send(data)
|
|
} catch {
|
|
logger.error("Failed to encode watch action: \(error.localizedDescription, privacy: .public)")
|
|
}
|
|
}
|
|
|
|
// actions from view
|
|
func nextExercise() {
|
|
send(.nextExercise)
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
|
|
func restartExercise() {
|
|
send(.restartExercise)
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
|
|
func previousExercise() {
|
|
send(.previousExercise)
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
|
|
func completeWorkout() {
|
|
send(.stopWorkout)
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
|
|
func pauseWorkout() {
|
|
send(.pauseWorkout)
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
|
|
func dataToAction(messageData: Data) {
|
|
do {
|
|
let model = try WatchPayloadValidation.decode(PhoneToWatchActions.self, from: messageData)
|
|
DispatchQueue.main.async {
|
|
switch model {
|
|
case .inExercise(let newWatchPackageModel):
|
|
WatchWorkout.shared.startWorkout()
|
|
if self.watchPackageModel.currentExerciseID != newWatchPackageModel.currentExerciseID {
|
|
WKInterfaceDevice.current().play(.start)
|
|
}
|
|
self.watchPackageModel = newWatchPackageModel
|
|
case .reset:
|
|
self.watchPackageModel = WatchMainViewModel.defaultPackageModel
|
|
WatchWorkout.shared.stopWorkout(sendDetails: false)
|
|
case .endWorkout:
|
|
self.watchPackageModel = WatchMainViewModel.defaultPackageModel
|
|
WatchWorkout.shared.stopWorkout(sendDetails: true)
|
|
case .startWorkout:
|
|
WatchWorkout.shared.startWorkout()
|
|
}
|
|
}
|
|
} catch {
|
|
logger.error("Rejected PhoneToWatchActions payload: \(error.localizedDescription, privacy: .public)")
|
|
}
|
|
}
|
|
}
|