A new 'Workouts Mac' target (same bundle ID as iOS, universal purchase) with a NavigationSplitView shell over the shared data/sync layers: routine management with starter gallery and seed-fork follow, schedule editing (reminders stay iPhone-scheduled), and a browse-only exercise library with the animated figures and reference guides. Multi-writer stance: the Mac writes only routine and schedule documents (whole-document last-writer-wins) and never workout documents, whose per-log merge exists only on the watch ingest path. The Mac reconciles on window activation (throttled) since iCloud syncs while the app is closed, and flushes pending writes on deactivation.
237 lines
7.9 KiB
YAML
237 lines
7.9 KiB
YAML
name: Workouts
|
|
options:
|
|
bundleIdPrefix: dev.rzen.indie
|
|
deploymentTarget:
|
|
iOS: "26.0"
|
|
watchOS: "26.0"
|
|
macOS: "26.0"
|
|
xcodeVersion: "26.0"
|
|
defaultConfig: Debug
|
|
|
|
settings:
|
|
base:
|
|
SWIFT_VERSION: "6.0"
|
|
DEVELOPMENT_TEAM: ${APPLE_TEAM_ID}
|
|
MARKETING_VERSION: "2.3"
|
|
CURRENT_PROJECT_VERSION: "1"
|
|
ENABLE_USER_SCRIPT_SANDBOXING: "NO"
|
|
DEAD_CODE_STRIPPING: "YES"
|
|
|
|
packages:
|
|
IndieAbout:
|
|
url: https://git.rzen.dev/rzen/indie-about.git
|
|
from: "0.2.2"
|
|
IndieSync:
|
|
url: https://git.rzen.dev/rzen/indie-sync.git
|
|
from: "0.3.0"
|
|
IndieBackup:
|
|
url: https://git.rzen.dev/rzen/indie-backup.git
|
|
from: "2.0.0"
|
|
|
|
# Shared post-build phase — stamps CFBundleVersion (git commit count), BuildDate, and
|
|
# BuildHash into each target's (and dSYM's) Info.plist. Aliased into every code-bearing
|
|
# target below so the app, watch app, and both widget extensions stamp identical metadata.
|
|
scriptAnchors:
|
|
updateBuildInfo: &updateBuildInfo
|
|
- script: '"${SRCROOT}/../indie-skills/skills/app-versioning/scripts/update_build_info.sh"'
|
|
name: Update Build Info
|
|
shell: /bin/sh
|
|
basedOnDependencyAnalysis: false
|
|
inputFiles:
|
|
- $(TARGET_BUILD_DIR)/$(INFOPLIST_PATH)
|
|
- $(DWARF_DSYM_FOLDER_PATH)/$(DWARF_DSYM_FILE_NAME)/Contents/Info.plist
|
|
|
|
targets:
|
|
# ---- iOS app (owns iCloud Drive sync; embeds the watch app) ----------------
|
|
Workouts:
|
|
type: application
|
|
platform: iOS
|
|
sources:
|
|
- path: Shared
|
|
- path: Workouts
|
|
excludes:
|
|
- "Resources/Info-*.plist"
|
|
- "Resources/*.entitlements"
|
|
- path: CHANGELOG.md
|
|
buildPhase: resources
|
|
type: file
|
|
- path: README.md
|
|
buildPhase: resources
|
|
type: file
|
|
- path: LICENSE.md
|
|
buildPhase: resources
|
|
type: file
|
|
# The Live Activity attributes are shared with the widget extension (which owns the
|
|
# folder); the app compiles just this one file so it can start / update / end the activity.
|
|
- path: "Workouts Widget/WorkoutActivityAttributes.swift"
|
|
dependencies:
|
|
- package: IndieAbout
|
|
- package: IndieSync
|
|
- package: IndieBackup
|
|
- target: Workouts Watch App
|
|
- target: Workouts Widget
|
|
embed: true
|
|
postBuildScripts: *updateBuildInfo
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts
|
|
INFOPLIST_FILE: Workouts/Resources/Info-iOS.plist
|
|
CODE_SIGN_ENTITLEMENTS: Workouts/Resources/Workouts-iOS.entitlements
|
|
GENERATE_INFOPLIST_FILE: false
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
IPHONEOS_DEPLOYMENT_TARGET: "26.0"
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
|
|
TARGETED_DEVICE_FAMILY: "1"
|
|
DEVELOPMENT_ASSET_PATHS: "\"Workouts/Preview Content\""
|
|
scheme:
|
|
testTargets:
|
|
- WorkoutsTests
|
|
|
|
# ---- unit tests (domain model / codec, against the iOS app target) --------
|
|
WorkoutsTests:
|
|
type: bundle.unit-test
|
|
platform: iOS
|
|
sources:
|
|
- WorkoutsTests
|
|
dependencies:
|
|
- target: Workouts
|
|
- package: IndieSync
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.WorkoutsTests
|
|
GENERATE_INFOPLIST_FILE: true
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
|
|
# ---- watchOS app (no iCloud; syncs through the phone via WatchConnectivity) -
|
|
Workouts Watch App:
|
|
type: application
|
|
platform: watchOS
|
|
sources:
|
|
- path: Shared
|
|
- path: Workouts Watch App
|
|
excludes:
|
|
- "Resources/Info-*.plist"
|
|
- "Resources/*.entitlements"
|
|
dependencies:
|
|
- package: IndieSync
|
|
- target: Workouts Watch Widget
|
|
embed: true
|
|
postBuildScripts: *updateBuildInfo
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.watchkitapp
|
|
INFOPLIST_FILE: "Workouts Watch App/Resources/Info-watchOS.plist"
|
|
CODE_SIGN_ENTITLEMENTS: "Workouts Watch App/Resources/Workouts-watchOS.entitlements"
|
|
GENERATE_INFOPLIST_FILE: false
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
WATCHOS_DEPLOYMENT_TARGET: "26.0"
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
|
|
TARGETED_DEVICE_FAMILY: "4"
|
|
DEVELOPMENT_ASSET_PATHS: "\"Workouts Watch App/Preview Content\""
|
|
scheme:
|
|
testTargets:
|
|
- Workouts Watch AppTests
|
|
|
|
# ---- watchOS unit tests (bridge apply/prune seam + watch-side helpers) ------
|
|
Workouts Watch AppTests:
|
|
type: bundle.unit-test
|
|
platform: watchOS
|
|
sources:
|
|
- Workouts Watch AppTests
|
|
dependencies:
|
|
- target: Workouts Watch App
|
|
- package: IndieSync
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.watchkitapp.tests
|
|
GENERATE_INFOPLIST_FILE: true
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
WATCHOS_DEPLOYMENT_TARGET: "26.0"
|
|
|
|
# ---- watchOS widget extension (a launcher complication for the watch face) --
|
|
Workouts Watch Widget:
|
|
type: app-extension
|
|
platform: watchOS
|
|
sources:
|
|
- path: Workouts Watch Widget
|
|
excludes:
|
|
- "Resources/Info-*.plist"
|
|
postBuildScripts: *updateBuildInfo
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.watchkitapp.widget
|
|
INFOPLIST_FILE: "Workouts Watch Widget/Resources/Info-WatchWidget.plist"
|
|
GENERATE_INFOPLIST_FILE: false
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
WATCHOS_DEPLOYMENT_TARGET: "26.0"
|
|
TARGETED_DEVICE_FAMILY: "4"
|
|
|
|
# ---- iOS widget extension (the active-workout Live Activity: lock screen + Dynamic Island) --
|
|
Workouts Widget:
|
|
type: app-extension
|
|
platform: iOS
|
|
sources:
|
|
- path: Workouts Widget
|
|
excludes:
|
|
- "Resources/Info-*.plist"
|
|
postBuildScripts: *updateBuildInfo
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts.widget
|
|
INFOPLIST_FILE: "Workouts Widget/Resources/Info-Widget.plist"
|
|
GENERATE_INFOPLIST_FILE: false
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
IPHONEOS_DEPLOYMENT_TARGET: "26.0"
|
|
TARGETED_DEVICE_FAMILY: "1"
|
|
|
|
# ---- macOS app (library management MVP: routines/schedules/exercises; no
|
|
# workout running/editing). Same bundle id as the iOS app (universal
|
|
# purchase); writes only Splits/ and Schedules/ documents. -------------
|
|
Workouts Mac:
|
|
type: application
|
|
platform: macOS
|
|
sources:
|
|
- path: Shared
|
|
excludes:
|
|
- "HealthKit/**"
|
|
- path: Workouts/Sync
|
|
- path: Workouts/Seed
|
|
- path: Workouts/ExerciseFigure
|
|
- path: Workouts/Views/Exercises/ExerciseCatalog.swift
|
|
- path: "Workouts/Views/Exercises/ExerciseDocument+PlanSummary.swift"
|
|
- path: Workouts/Views/Exercises/ExerciseInfoContent.swift
|
|
- path: Workouts/Views/Routines/RoutineOrdering.swift
|
|
- path: Workouts/Views/Library/StarterSeedState.swift
|
|
- path: Workouts/Assets.xcassets
|
|
- path: Workouts/Resources/ExerciseMotions
|
|
buildPhase: resources
|
|
- path: Workouts/Resources/StarterSplits
|
|
buildPhase: resources
|
|
- path: "Workouts Mac"
|
|
excludes:
|
|
- "Resources/Info-*.plist"
|
|
- "Resources/*.entitlements"
|
|
- path: CHANGELOG.md
|
|
buildPhase: resources
|
|
type: file
|
|
- path: LICENSE.md
|
|
buildPhase: resources
|
|
type: file
|
|
dependencies:
|
|
- package: IndieSync
|
|
- package: IndieAbout
|
|
postBuildScripts: *updateBuildInfo
|
|
settings:
|
|
base:
|
|
PRODUCT_BUNDLE_IDENTIFIER: dev.rzen.indie.Workouts
|
|
PRODUCT_NAME: Workouts
|
|
INFOPLIST_FILE: "Workouts Mac/Resources/Info-macOS.plist"
|
|
CODE_SIGN_ENTITLEMENTS: "Workouts Mac/Resources/Workouts-macOS.entitlements"
|
|
GENERATE_INFOPLIST_FILE: false
|
|
SWIFT_STRICT_CONCURRENCY: complete
|
|
MACOSX_DEPLOYMENT_TARGET: "26.0"
|
|
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
|