Proper 1.0 release for iOS. Pending App Store submission.

This commit is contained in:
2025-09-15 21:01:02 -06:00
parent 127c25f506
commit 363fbd676a
24 changed files with 1848 additions and 2 deletions

View File

@@ -0,0 +1,50 @@
import ActivityKit
import Foundation
@MainActor
final class LiveActivityManager {
static let shared = LiveActivityManager()
private init() {}
private var currentActivity: Activity<SessionActivityAttributes>?
/// Call this when a ClimbSession starts to begin a Live Activity
func startLiveActivity(for session: ClimbSession, gymName: String) async {
await endLiveActivity()
let attributes = SessionActivityAttributes(
gymName: gymName, startTime: session.startTime ?? session.date)
let initialContentState = SessionActivityAttributes.ContentState(
elapsed: 0,
totalAttempts: 0,
completedProblems: 0
)
do {
currentActivity = try Activity<SessionActivityAttributes>.request(
attributes: attributes,
contentState: initialContentState,
pushType: nil
)
} catch {
print("Failed to start live activity: \(error)")
}
}
/// Call this to update the Live Activity with new session progress
func updateLiveActivity(elapsed: TimeInterval, totalAttempts: Int, completedProblems: Int) async
{
guard let currentActivity else { return }
let updatedContentState = SessionActivityAttributes.ContentState(
elapsed: elapsed,
totalAttempts: totalAttempts,
completedProblems: completedProblems
)
await currentActivity.update(using: updatedContentState, alertConfiguration: nil)
}
/// Call this when a ClimbSession ends to end the Live Activity
func endLiveActivity() async {
guard let currentActivity else { return }
await currentActivity.end(using: nil, dismissalPolicy: .immediate)
self.currentActivity = nil
}
}

View File

@@ -6,8 +6,44 @@
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
D2FE94822E78E95C008CDB25 /* ActivityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FE94802E78E958008CDB25 /* ActivityKit.framework */; };
D2FE948D2E78FEE0008CDB25 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FE948C2E78FEE0008CDB25 /* WidgetKit.framework */; };
D2FE948F2E78FEE0008CDB25 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FE948E2E78FEE0008CDB25 /* SwiftUI.framework */; };
D2FE94A02E78FEE1008CDB25 /* SessionStatusLiveExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D2FE948B2E78FEE0008CDB25 /* SessionStatusLiveExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
D2FE94A82E78FFB7008CDB25 /* ActivityKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2FE94802E78E958008CDB25 /* ActivityKit.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D2FE949E2E78FEE1008CDB25 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D24C19602E75002A0045894C /* Project object */;
proxyType = 1;
remoteGlobalIDString = D2FE948A2E78FEE0008CDB25;
remoteInfo = SessionStatusLiveExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
D2FE94A52E78FEE1008CDB25 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
D2FE94A02E78FEE1008CDB25 /* SessionStatusLiveExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
D24C19682E75002A0045894C /* OpenClimb.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenClimb.app; sourceTree = BUILT_PRODUCTS_DIR; };
D2FE94802E78E958008CDB25 /* ActivityKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActivityKit.framework; path = System/Library/Frameworks/ActivityKit.framework; sourceTree = SDKROOT; };
D2FE948B2E78FEE0008CDB25 /* SessionStatusLiveExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionStatusLiveExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
D2FE948C2E78FEE0008CDB25 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
D2FE948E2E78FEE0008CDB25 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
@@ -18,6 +54,13 @@
);
target = D24C19672E75002A0045894C /* OpenClimb */;
};
D2FE94A42E78FEE1008CDB25 /* Exceptions for "SessionStatusLive" folder in "SessionStatusLiveExtension" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = D2FE948A2E78FEE0008CDB25 /* SessionStatusLiveExtension */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -29,6 +72,14 @@
path = OpenClimb;
sourceTree = "<group>";
};
D2FE94902E78FEE0008CDB25 /* SessionStatusLive */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
D2FE94A42E78FEE1008CDB25 /* Exceptions for "SessionStatusLive" folder in "SessionStatusLiveExtension" target */,
);
path = SessionStatusLive;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
@@ -36,6 +87,17 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D2FE94822E78E95C008CDB25 /* ActivityKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D2FE94882E78FEE0008CDB25 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D2FE94A82E78FFB7008CDB25 /* ActivityKit.framework in Frameworks */,
D2FE948F2E78FEE0008CDB25 /* SwiftUI.framework in Frameworks */,
D2FE948D2E78FEE0008CDB25 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -46,6 +108,8 @@
isa = PBXGroup;
children = (
D24C196A2E75002A0045894C /* OpenClimb */,
D2FE94902E78FEE0008CDB25 /* SessionStatusLive */,
D2FE947F2E78E958008CDB25 /* Frameworks */,
D24C19692E75002A0045894C /* Products */,
);
sourceTree = "<group>";
@@ -54,10 +118,21 @@
isa = PBXGroup;
children = (
D24C19682E75002A0045894C /* OpenClimb.app */,
D2FE948B2E78FEE0008CDB25 /* SessionStatusLiveExtension.appex */,
);
name = Products;
sourceTree = "<group>";
};
D2FE947F2E78E958008CDB25 /* Frameworks */ = {
isa = PBXGroup;
children = (
D2FE94802E78E958008CDB25 /* ActivityKit.framework */,
D2FE948C2E78FEE0008CDB25 /* WidgetKit.framework */,
D2FE948E2E78FEE0008CDB25 /* SwiftUI.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -68,10 +143,12 @@
D24C19642E75002A0045894C /* Sources */,
D24C19652E75002A0045894C /* Frameworks */,
D24C19662E75002A0045894C /* Resources */,
D2FE94A52E78FEE1008CDB25 /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
D2FE949F2E78FEE1008CDB25 /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
D24C196A2E75002A0045894C /* OpenClimb */,
@@ -83,6 +160,28 @@
productReference = D24C19682E75002A0045894C /* OpenClimb.app */;
productType = "com.apple.product-type.application";
};
D2FE948A2E78FEE0008CDB25 /* SessionStatusLiveExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = D2FE94A12E78FEE1008CDB25 /* Build configuration list for PBXNativeTarget "SessionStatusLiveExtension" */;
buildPhases = (
D2FE94872E78FEE0008CDB25 /* Sources */,
D2FE94882E78FEE0008CDB25 /* Frameworks */,
D2FE94892E78FEE0008CDB25 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
D2FE94902E78FEE0008CDB25 /* SessionStatusLive */,
);
name = SessionStatusLiveExtension;
packageProductDependencies = (
);
productName = SessionStatusLiveExtension;
productReference = D2FE948B2E78FEE0008CDB25 /* SessionStatusLiveExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -96,6 +195,9 @@
D24C19672E75002A0045894C = {
CreatedOnToolsVersion = 26.0;
};
D2FE948A2E78FEE0008CDB25 = {
CreatedOnToolsVersion = 26.0;
};
};
};
buildConfigurationList = D24C19632E75002A0045894C /* Build configuration list for PBXProject "OpenClimb" */;
@@ -113,6 +215,7 @@
projectRoot = "";
targets = (
D24C19672E75002A0045894C /* OpenClimb */,
D2FE948A2E78FEE0008CDB25 /* SessionStatusLiveExtension */,
);
};
/* End PBXProject section */
@@ -125,6 +228,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
D2FE94892E78FEE0008CDB25 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -135,8 +245,23 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
D2FE94872E78FEE0008CDB25 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D2FE949F2E78FEE1008CDB25 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D2FE948A2E78FEE0008CDB25 /* SessionStatusLiveExtension */;
targetProxy = D2FE949E2E78FEE1008CDB25 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
D24C19712E75002A0045894C /* Debug */ = {
isa = XCBuildConfiguration;
@@ -335,6 +460,64 @@
};
name = Release;
};
D2FE94A22E78FEE1008CDB25 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = SessionStatusLive/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SessionStatusLive;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb.SessionStatusLive;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
D2FE94A32E78FEE1008CDB25 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 4BC9Y2LL4B;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = SessionStatusLive/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SessionStatusLive;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb.SessionStatusLive;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -356,6 +539,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D2FE94A12E78FEE1008CDB25 /* Build configuration list for PBXNativeTarget "SessionStatusLiveExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D2FE94A22E78FEE1008CDB25 /* Debug */,
D2FE94A32E78FEE1008CDB25 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D24C19602E75002A0045894C /* Project object */;

View File

@@ -4,4 +4,10 @@
<FileRef
location = "self:">
</FileRef>
<FileRef
location = "group:LiveActivityManager.swift">
</FileRef>
<FileRef
location = "group:SessionLiveActivityWidget.swift">
</FileRef>
</Workspace>

View File

@@ -9,6 +9,11 @@
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>SessionStatusLiveExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>