-
Notifications
You must be signed in to change notification settings - Fork 265
feat: [SDK-5032] enable Mac Catalyst demo builds #1716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: fadi/sdk-5022
Are you sure you want to change the base?
Changes from all commits
4ef3147
2dc947f
7664bd5
864c6aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,8 @@ settings: | |
| CODE_SIGN_STYLE: Automatic | ||
| DEVELOPMENT_TEAM: "" | ||
| GENERATE_INFOPLIST_FILE: NO | ||
| SUPPORTS_MACCATALYST: YES | ||
| DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER: YES | ||
|
Comment on lines
+21
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Act on (A/B/C/D): With That breaks the shared App Group / NSE path this PR is meant to validate, and matches the “macOS App Group authorization prompt” note in the PR body. Pin |
||
| projectReferences: | ||
| OneSignalSDK: | ||
| path: ../../iOS_SDK/OneSignalSDK/OneSignal.xcodeproj | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,27 +59,45 @@ public final class OSResilientStorage: NSObject { | |
| /// the NSE can read the same file. Falls back to the app's private | ||
| /// Application Support directory when no App Group is entitled. | ||
| private static func fileURL() -> URL? { | ||
| let fm = FileManager.default | ||
| let fileManager = FileManager.default | ||
|
|
||
| let groupName = OneSignalUserDefaults.appGroupName() | ||
| if let container = fm.containerURL(forSecurityApplicationGroupIdentifier: groupName) { | ||
| return container.appendingPathComponent(fileName) | ||
| if let container = fileManager.containerURL(forSecurityApplicationGroupIdentifier: groupName) { | ||
| do { | ||
| return try preparedFileURL(in: container, fileManager: fileManager) | ||
| } catch { | ||
| OneSignalLog.onesignalLog( | ||
| .LL_WARN, | ||
| message: "OSResilientStorage could not prepare the App Group container: \(error)" | ||
| ) | ||
| } | ||
|
Comment on lines
+65
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Act on (A/C/D): After a non-nil App Group Previously the group URL was always returned and a write failure stayed on that path. Silent private rehoming breaks the documented app↔NSE single-file contract and can make Catalyst storage checks look green without touching the entitled group. Once a container URL is selected, fail closed (return |
||
| } | ||
|
|
||
| do { | ||
| let support = try fm.url( | ||
| let support = try fileManager.url( | ||
| for: .applicationSupportDirectory, | ||
| in: .userDomainMask, | ||
| appropriateFor: nil, | ||
| create: true | ||
| ) | ||
| return support.appendingPathComponent(fileName) | ||
| return try preparedFileURL(in: support, fileManager: fileManager) | ||
| } catch { | ||
| OneSignalLog.onesignalLog(.LL_ERROR, message: "OSResilientStorage could not resolve a container URL: \(error)") | ||
| return nil | ||
| } | ||
| } | ||
|
|
||
| static func preparedFileURL( | ||
| in directory: URL, | ||
| fileManager: FileManager = .default | ||
| ) throws -> URL { | ||
| try fileManager.createDirectory( | ||
| at: directory, | ||
| withIntermediateDirectories: true | ||
| ) | ||
| return directory.appendingPathComponent(fileName) | ||
| } | ||
|
|
||
| /// Reads the cache file. Caller is responsible for queue-serialization. | ||
| /// Returns an empty dict if the file is missing or unreadable. | ||
| private static func loadUnsafe() -> [String: String] { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,18 @@ final class OSResilientStorageTests: XCTestCase { | |
| XCTAssertNil(OSResilientStorage.string(forKey: "never_written_\(UUID().uuidString)")) | ||
| } | ||
|
|
||
| func testPreparedFileURL_createsMissingContainerForAtomicWrites() throws { | ||
| let root = FileManager.default.temporaryDirectory | ||
| .appendingPathComponent(UUID().uuidString, isDirectory: true) | ||
| let container = root.appendingPathComponent("group.example", isDirectory: true) | ||
| defer { try? FileManager.default.removeItem(at: root) } | ||
|
|
||
| let fileURL = try OSResilientStorage.preparedFileURL(in: container) | ||
| try Data("value".utf8).write(to: fileURL, options: .atomic) | ||
|
|
||
| XCTAssertTrue(FileManager.default.fileExists(atPath: fileURL.path)) | ||
|
Comment on lines
+67
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider (A/C/D): This asserts Cover prepare-failure semantics (no private fallback once a group URL was selected), or drop the helper-only assertion. |
||
| } | ||
|
|
||
| func testSetWithNil_removesKey() { | ||
| OSResilientStorage.setString("alpha", forKey: keyA) | ||
| XCTAssertEqual(OSResilientStorage.string(forKey: keyA), "alpha") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| */ | ||
|
|
||
| #import <stdatomic.h> | ||
| #import <TargetConditionals.h> | ||
| #import "OneSignalFramework.h" | ||
| #import <OneSignalOSCore/OneSignalOSCore-Swift.h> | ||
| #import "OneSignalInternal.h" | ||
|
|
@@ -206,13 +207,17 @@ + (void)logout { | |
| } | ||
|
|
||
| + (Class<OSLiveActivities>)LiveActivities { | ||
| #if TARGET_OS_MACCATALYST | ||
| return [OSStubLiveActivities liveActivities]; | ||
|
Comment on lines
+210
to
+211
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider (A/D): Prefer one platform-aware stub/message owned by the LiveActivities module rather than a third dispatch path in |
||
| #else | ||
| let oneSignalLiveActivities = NSClassFromString(ONE_SIGNAL_LIVE_ACTIVITIES_CLASS_NAME); | ||
| if (oneSignalLiveActivities != nil && [oneSignalLiveActivities respondsToSelector:@selector(liveActivities)]) { | ||
| return [oneSignalLiveActivities performSelector:@selector(liveActivities)]; | ||
| } else { | ||
| [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:@"oneSignalLiveActivities not found. In order to use OneSignal's LiveActivities features the OneSignalLiveActivities module must be added."]; | ||
| return [OSStubLiveActivities liveActivities]; | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| + (Class<OSLocation>)Location { | ||
|
|
@@ -440,12 +445,16 @@ + (void)startUserManager { | |
| } | ||
|
|
||
| + (void)startLiveActivitiesManager { | ||
| #if TARGET_OS_MACCATALYST | ||
| return; | ||
| #else | ||
| let oneSignalLiveActivities = NSClassFromString(ONE_SIGNAL_LIVE_ACTIVITIES_CLASS_NAME); | ||
| if (oneSignalLiveActivities != nil && [oneSignalLiveActivities respondsToSelector:@selector(start)]) { | ||
| [oneSignalLiveActivities performSelector:@selector(start)]; | ||
| } else { | ||
| [OneSignalLog onesignalLog:ONE_S_LL_ERROR message:@"oneSignalLiveActivities not found. In order to use OneSignal's LiveActivities features the OneSignalLiveActivities module must be added."]; | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| + (void)delayInitializationForPrivacyConsent { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Act on (A/B/C/D): Only
setup/startare compiled out.LiveActivitySectionstill mounts on Catalyst (ContentView), Start silently no-ops, andupdate/endbelow still hit the Live Activities REST API for an activity that cannot exist locally.Hide/disable the section on Catalyst (mirror the widget’s “unavailable” copy), and gate all controller operations consistently.