Make the live run two-way: drive from either device
The propped-up iPhone now runs the real ExerciseProgressView for a live watch workout instead of a read-only mirror, and the live-run channel is symmetric — either device can drive the flow and the other follows. Each page transition is classified human / auto / remote: only human transitions (swipe, Start, One More, swipe-back reset) are broadcast and recorded by the actor; auto-advances (rest / timed-work countdown) record locally but aren't sent, since both devices reach them independently off the shared wall-clock anchors; an applied remote frame jumps the page without re-recording or re-broadcasting. That rule is also what stops an echo loop. - PhoneConnectivityBridge gains sendLiveProgress/sendLiveEnded (the missing phone->watch direction); WatchConnectivityBridge receives frames into an observable liveIncoming via a new didReceiveMessage route. Both share one increasing per-run version sequence so the stale-frame guard works across the two devices' counters. - Both ExerciseProgressViews gain an incomingFrame input + applyIncoming (syncing setCount for a remote One More); the iPhone one gains the liveSnapshot/broadcast machinery the watch already had. - New LiveRunCoverView wraps the real driver for the cover (resolves the workout, persists via SyncEngine, wires the live channel + close); ContentView presents it; LiveProgressMirrorView is removed. Claude-Session: https://claude.ai/code/session_01SCv7zvGFcKy47KSTnTLxRe
This commit is contained in:
@@ -91,7 +91,9 @@ struct WorkoutLogListView: View {
|
||||
logID: logID,
|
||||
onChange: { bridge.update(workout: doc) },
|
||||
onLive: { bridge.sendLiveProgress($0) },
|
||||
onLiveEnded: { bridge.sendLiveEnded(workoutID: doc.id, logID: logID) }
|
||||
onLiveEnded: { bridge.sendLiveEnded(workoutID: doc.id, logID: logID) },
|
||||
// Follow the phone when it drives this same run from its mirror.
|
||||
incomingFrame: bridge.liveIncoming.flatMap { $0.logID == logID ? $0 : nil }
|
||||
)
|
||||
}
|
||||
.sheet(isPresented: $showingExercisePicker) {
|
||||
|
||||
Reference in New Issue
Block a user