feat: production-grade Live Activity with type-safe phases, decomposed views, previews, and alert transitions
- Replace raw string phase model with WorkoutPhase enum (Codable, Sendable, CaseIterable) with built-in .capitalized display name and SwiftUI .color per phase - Decompose WorkoutLiveActivity into reusable view structs: PhasePill, CountdownText, WorkoutProgressBar, MusicInfoRow, HeartRateBadge, PhaseIndicatorDot, WorkoutLockScreenView, WorkoutSmallView — following CraftingSwift iOS 26 architecture patterns - Add AlertConfiguration on work/rest/complete phase transitions so Dynamic Island expands and lights up at key moments - Add 13 #Preview blocks across both widgets covering all presentation types: lock screen, expanded, compact, minimal — for instant Xcode Canvas feedback - Add stale state handling (context.isStale shows 'Last updated' indicator) - MusicLiveActivity: 5 new #Preview blocks for playing/paused/expanded/compact/minimal
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
5A402D7E31059AB7107B625C /* MusicPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5505FBD6E001AE3AFD413ADA /* MusicPlayerViewModel.swift */; };
|
||||
5B01ABC32F9B8FFD006E707D /* MusicActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B01ABC22F9B8FFD006E707D /* MusicActivityAttributes.swift */; };
|
||||
5B01ABC82F9B90AF006E707D /* ActivityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B01ABC62F9B909E006E707D /* ActivityKit.framework */; };
|
||||
5B10095D2FB7B6EC0033DE89 /* MockPrograms 2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B10095C2FB7B6EC0033DE89 /* MockPrograms 2.swift */; };
|
||||
5B10095F2FB7C4080033DE89 /* MockPrograms.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B10095E2FB7C4080033DE89 /* MockPrograms.swift */; };
|
||||
5CE2F2210BEF17AC304F2AC2 /* HealthSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1DE8A4DAD846A879B8ED379 /* HealthSnapshot.swift */; };
|
||||
60503F963221C7FCF719C493 /* ActivityTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84123E854DE0BF3E0D4F0912 /* ActivityTab.swift */; };
|
||||
6060D95D485E4188EAABDDED /* WatchRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AEC37E6361DC4C7AE326139 /* WatchRootView.swift */; };
|
||||
@@ -183,7 +183,7 @@
|
||||
5ACBDB7D81F575AC5370E82F /* WatchL10n.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchL10n.swift; sourceTree = "<group>"; };
|
||||
5B01ABC22F9B8FFD006E707D /* MusicActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicActivityAttributes.swift; sourceTree = "<group>"; };
|
||||
5B01ABC62F9B909E006E707D /* ActivityKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActivityKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.4.sdk/System/Library/Frameworks/ActivityKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
5B10095C2FB7B6EC0033DE89 /* MockPrograms 2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MockPrograms 2.swift"; sourceTree = "<group>"; };
|
||||
5B10095E2FB7C4080033DE89 /* MockPrograms.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPrograms.swift; sourceTree = "<group>"; };
|
||||
5F5D3568A736B7A326874677 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
61E5AA44513F793EA7FEBA00 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
|
||||
63599808389B70FC2F6A43C3 /* HealthViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthViewModel.swift; sourceTree = "<group>"; };
|
||||
@@ -548,7 +548,7 @@
|
||||
DC96ED5F68F75A02548ECD40 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B10095C2FB7B6EC0033DE89 /* MockPrograms 2.swift */,
|
||||
5B10095E2FB7C4080033DE89 /* MockPrograms.swift */,
|
||||
F1DE8A4DAD846A879B8ED379 /* HealthSnapshot.swift */,
|
||||
2C6156C6E0E1A543DAC87A90 /* MusicTrack.swift */,
|
||||
7482C05380DE017FF582C28B /* PreviewData.swift */,
|
||||
@@ -818,7 +818,7 @@
|
||||
files = (
|
||||
22669D283A2B7C8D5F4FE19F /* ActivityRingView.swift in Sources */,
|
||||
60503F963221C7FCF719C493 /* ActivityTab.swift in Sources */,
|
||||
5B10095D2FB7B6EC0033DE89 /* MockPrograms 2.swift in Sources */,
|
||||
5B10095F2FB7C4080033DE89 /* MockPrograms.swift in Sources */,
|
||||
CCCCEFD2D61ED1D7DDB9040C /* AnalyticsService.swift in Sources */,
|
||||
EE6C591611D52C36ED5E03C6 /* AppState.swift in Sources */,
|
||||
14578A06877E3D67A49650A9 /* AudioService.swift in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user