- Replace #if os(watchOS) with #if canImport(WatchKit) for all .accessoryCorner
usages. When the CI builds with forced iphoneos SDK, os(watchOS) evaluates
to true (target platform is watchOS) but the SDK doesn't have WatchKit, so
accessoryCorner is unavailable. canImport(WatchKit) correctly checks SDK
availability rather than target platform.
- Wrap CornerComplicationView struct and its preview in #if canImport(WatchKit)
with @available(watchOS 10.0, *) annotation.
- Change CI build from -target TabataGo -sdk iphoneos to -scheme TabataGo
(without -sdk). This lets xcodebuild pick the correct SDK per target:
iphoneos for iOS, watchos for watchOS. The scheme already exists in
project.yml.
## What changed
### Player Redesign (video-first layout)
- New compact timer ring (110pt) with phase label, replaces 240pt ring
- Auto-hide top bar with block progress dots (3s auto-dismiss)
- Expandable now-playing music pill with skip control
- Bottom control bar with heart rate, play/pause, and skip
- Exercise caption with 'Next' preview during rest phases
- Compact round counter (capsule dots)
### Dynamic Island & Live Activities
- WorkoutLiveActivity widget: expanded, compact, and minimal views
- Phase-colored timers with Text(timerInterval:) countdown
- Shows exercise name, round progress, heart rate, music track
- MusicLiveActivity: standalone music now-playing widget
- LiveActivityMusicBars animated component
- Deep link from Dynamic Island back to app
### Timer Drift Fix (critical)
- Store a stable phaseEndDate once per phase instead of
recalculating Date() + timeRemaining on every update
- Prevents dynamic island countdown from rubber-banding
due to 5-second periodic update recalculation drift
- Reset phaseEndDate on phase change and resume from pause
- Guard Live Activity updates behind vm.isRunning to prevent
premature creation when music track loads before workout start
- Fixes timer showing 0 in Dynamic Island when expanding
from home screen
### New PlayerViewModel timer engine
- Full phase support: prep, warmup, work, rest,
interBlockRest, cooldown, complete
- 1-second countdown with audio cues at 3-2-1
- Phase transitions with spring animation and haptics
- HealthKit live session integration
- Workout session recording with completion
### Music Service
- New MusicPlayerViewModel with vibe-based playlist loading
- Track info exposed for Dynamic Island display
- Skip track support from Dynamic Island notification action
- Automatic play/pause based on phase and running state
### Additional
- ZoneHighlightIcon component for HomeTab zone cards
- Updated watchOS localizations with complication strings
- Info.plist updated for widget extension