feat(watch): display water lock status indicator during workout

This commit is contained in:
2026-08-09 18:33:23 +02:00
parent 383f641ac2
commit a17ae0dea5
3 changed files with 320 additions and 240 deletions
+287 -240
View File
@@ -417,7 +417,63 @@
}
},
"End Workout" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Workout beenden"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Afslut træning"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "End Workout"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Finalizar entrenamiento"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terminer l'entraînement"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Termina allenamento"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Workout beëindigen"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Zakończ trening"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terminar treino"
}
}
}
},
"kcal" : {
"extractionState" : "manual",
@@ -843,7 +899,63 @@
}
},
"Pause" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pauze"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pauza"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
}
}
},
"Recent" : {
"extractionState" : "manual",
@@ -974,10 +1086,122 @@
}
},
"Rest %@" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause %@"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hvile %@"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Rest %@"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Descanso %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Repos %@"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Recupero %@"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Rust %@"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Odpoczynek %@"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Descanso %@"
}
}
}
},
"Resume" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fortsetzen"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Forsæt"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Resume"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reanudar"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reprendre"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Riprendi"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hervatten"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Wznów"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Retomar"
}
}
}
},
"Saved Workouts" : {
"extractionState" : "manual",
@@ -1287,6 +1511,65 @@
}
}
},
"Water Lock" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Wassersperre"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Vandlås"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Water Lock"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Bloqueo de agua"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Verrouillage eau"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Blocco acqua"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Watermodus"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Blokada wody"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Bloqueio de água"
}
}
}
},
"Workout" : {
"extractionState" : "manual",
"localizations" : {
@@ -1346,242 +1629,6 @@
}
}
},
"End Workout" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Workout beenden"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Afslut træning"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "End Workout"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Finalizar entrenamiento"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terminer l'entraînement"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Termina allenamento"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Workout beëindigen"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Zakończ trening"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terminar treino"
}
}
}
},
"Pause" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pauze"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pauza"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pausa"
}
}
}
},
"Resume" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fortsetzen"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Forsæt"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Resume"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reanudar"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Reprendre"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Riprendi"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hervatten"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Wznów"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Retomar"
}
}
}
},
"Rest %@" : {
"extractionState" : "manual",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pause %@"
}
},
"dk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hvile %@"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Rest %@"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Descanso %@"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Repos %@"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "Recupero %@"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Rust %@"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Odpoczynek %@"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "Descanso %@"
}
}
}
},
"Workout complete!" : {
"extractionState" : "manual",
"localizations" : {
@@ -199,6 +199,17 @@ struct ControlsPage: View {
var body: some View {
VStack(spacing: 16) {
if workoutManager.isWaterLockEnabled {
HStack(spacing: 4) {
Image(systemName: "drop.fill")
.foregroundColor(.cyan)
.font(.caption)
Text("Water Lock")
.font(.caption)
.foregroundColor(.cyan)
}
}
Spacer()
Button {
+22
View File
@@ -41,6 +41,9 @@ class WorkoutManager: NSObject, ObservableObject, HKLiveWorkoutBuilderDelegate {
@Published var lapDetected = false
@Published var healthKitAuthorized = false
@Published var isPaused = false
@Published var isWaterLockEnabled = false
private var waterLockCheckTimer: Timer?
override init() {
super.init()
@@ -163,6 +166,7 @@ class WorkoutManager: NSObject, ObservableObject, HKLiveWorkoutBuilderDelegate {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
WKInterfaceDevice.current().enableWaterLock()
}
startWaterLockCheck()
WKInterfaceDevice.current().play(.start)
}
@@ -189,6 +193,7 @@ class WorkoutManager: NSObject, ObservableObject, HKLiveWorkoutBuilderDelegate {
restTimer?.invalidate()
isWorkoutActive = false
stopWaterLockCheck()
stopLapDetection()
stopHeartRateQuery()
stopCalorieQuery()
@@ -199,6 +204,23 @@ class WorkoutManager: NSObject, ObservableObject, HKLiveWorkoutBuilderDelegate {
WKInterfaceDevice.current().play(.success)
}
// MARK: - Water Lock Check
private func startWaterLockCheck() {
isWaterLockEnabled = WKInterfaceDevice.current().isWaterLockEnabled
waterLockCheckTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { [weak self] _ in
DispatchQueue.main.async {
self?.isWaterLockEnabled = WKInterfaceDevice.current().isWaterLockEnabled
}
}
}
private func stopWaterLockCheck() {
waterLockCheckTimer?.invalidate()
waterLockCheckTimer = nil
isWaterLockEnabled = false
}
// MARK: - Workout Summary
private func createWorkoutSummary() {