From c26fd7bbd3e57ad0c1342480dbdd1913f346330c Mon Sep 17 00:00:00 2001 From: Nan Date: Fri, 6 Jan 2023 02:10:45 -0800 Subject: [PATCH 1/5] permission + subscription state: description/toDictionary * Before, printing a permission state or subscription state gave good information. Let's make sure they have the `description` method overridden still. --- .../OneSignalNotifications/OSPermission.m | 41 +++++++++++-------- .../Source/OSSubscriptionModel.swift | 12 +++++- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.m b/iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.m index 020701643..a586dbda9 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.m +++ b/iOS_SDK/OneSignalSDK/OneSignalNotifications/OSPermission.m @@ -159,22 +159,6 @@ - (OSNotificationPermission)status { return OSNotificationPermissionNotDetermined; } -- (NSString*)statusAsString { - switch(self.status) { - case OSNotificationPermissionNotDetermined: - return @"NotDetermined"; - case OSNotificationPermissionAuthorized: - return @"Authorized"; - case OSNotificationPermissionDenied: - return @"Denied"; - case OSNotificationPermissionProvisional: - return @"Provisional"; - case OSNotificationPermissionEphemeral: - return @"Ephemeral"; - } - return @"NotDetermined"; -} - - (BOOL)compare:(OSPermissionStateInternal*)from { return self.accepted != from.accepted || self.ephemeral != from.ephemeral || @@ -187,8 +171,8 @@ - (OSPermissionState *)getExternalState { } - (NSString*)description { - static NSString* format = @""; - return [NSString stringWithFormat:format, self.hasPrompted, self.statusAsString, self.provisional]; + static NSString* format = @""; + return [NSString stringWithFormat:format, self.hasPrompted, self.status, self.provisional]; } @@ -206,6 +190,27 @@ - (instancetype)initWithStatus:(OSNotificationPermission)status reachable:(BOOL) return self; } +- (NSString*)statusAsString { + switch(self.status) { + case OSNotificationPermissionNotDetermined: + return @"NotDetermined"; + case OSNotificationPermissionAuthorized: + return @"Authorized"; + case OSNotificationPermissionDenied: + return @"Denied"; + case OSNotificationPermissionProvisional: + return @"Provisional"; + case OSNotificationPermissionEphemeral: + return @"Ephemeral"; + } + return @"NotDetermined"; +} + +- (NSString*)description { + static NSString* format = @""; + return [NSString stringWithFormat:format, self.hasPrompted, self.statusAsString, self.provisional]; +} + - (NSDictionary*)toDictionary { return @{@"hasPrompted": @(self.hasPrompted), @"status": @(self.status), diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionModel.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionModel.swift index 5299a9bf9..931883391 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionModel.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSSubscriptionModel.swift @@ -42,13 +42,17 @@ public class OSPushSubscriptionState: NSObject { @objc public let token: String? @objc public let optedIn: Bool + @objc public override var description: String { + return "" + } + init(id: String?, token: String?, optedIn: Bool) { self.id = id self.token = token self.optedIn = optedIn } - func toDictionary() -> NSDictionary { + @objc public func toDictionary() -> NSDictionary { let id = self.id ?? "nil" let token = self.token ?? "nil" return [ @@ -64,12 +68,16 @@ public class OSPushSubscriptionStateChanges: NSObject { @objc public let to: OSPushSubscriptionState @objc public let from: OSPushSubscriptionState + @objc public override var description: String { + return "" + } + init(to: OSPushSubscriptionState, from: OSPushSubscriptionState) { self.to = to self.from = from } - func toDictionary() -> NSDictionary { + @objc public func toDictionary() -> NSDictionary { return ["from": from.toDictionary(), "to": to.toDictionary()] } } From 3d2818ce0f6dff069648e2d4db70da2da95ab420 Mon Sep 17 00:00:00 2001 From: Nan Date: Fri, 6 Jan 2023 02:13:39 -0800 Subject: [PATCH 2/5] push sub store won't remove models from user defaults * As a model store, the push subscription model store was also clearing user defaults when the user will change. Don't do that, but all other stores still will. --- .../OneSignalOSCore/Source/OSModelStore.swift | 5 ++++- .../OneSignalUser/Source/OneSignalUserManagerImpl.swift | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSModelStore.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSModelStore.swift index f2930e27d..edfc9203f 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSModelStore.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/OSModelStore.swift @@ -49,10 +49,13 @@ open class OSModelStore: NSObject { for model in self.models.values { model.changeNotifier.subscribe(self) } + } - // register as user observer + public func registerAsUserObserver() -> OSModelStore { + // This method was taken out of the initializer as the push subscription model store should not be clearing its user defaults NotificationCenter.default.addObserver(self, selector: #selector(self.removeModelsFromUserDefaults), name: Notification.Name(OS_ON_USER_WILL_CHANGE), object: nil) + return self } deinit { diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift index 10fd21537..96eb53694 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OneSignalUserManagerImpl.swift @@ -140,11 +140,11 @@ public class OneSignalUserManagerImpl: NSObject, OneSignalUserManager { return pushSubscriptionStateChangesObserver } - // has Identity, Properties, Subscription, and Push Subscription Model Stores - let identityModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_IDENTITY_MODEL_STORE_KEY) - let propertiesModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_PROPERTIES_MODEL_STORE_KEY) + // Model Stores + let identityModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_IDENTITY_MODEL_STORE_KEY).registerAsUserObserver() + let propertiesModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_PROPERTIES_MODEL_STORE_KEY).registerAsUserObserver() // Holds email and sms subscription models - let subscriptionModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_SUBSCRIPTION_MODEL_STORE_KEY) + let subscriptionModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_SUBSCRIPTION_MODEL_STORE_KEY).registerAsUserObserver() // Holds a single push subscription model let pushSubscriptionModelStore = OSModelStore(changeSubscription: OSEventProducer(), storeKey: OS_PUSH_SUBSCRIPTION_MODEL_STORE_KEY) From a5808c48a7e131152d239f85df23e9bfd7456f70 Mon Sep 17 00:00:00 2001 From: Nan Date: Fri, 6 Jan 2023 02:14:10 -0800 Subject: [PATCH 3/5] [nits] --- iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift | 1 + iOS_SDK/OneSignalSDK/Source/OneSignal.m | 1 + 2 files changed, 2 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift index 0f2f91b94..44cf50428 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift @@ -209,6 +209,7 @@ class OSUserExecutor { static func executeIdentifyUserRequest(_ request: OSRequestIdentifyUser) { OneSignalClient.shared().execute(request) { _ in // the anonymous user has been identified, still need to Fetch User + // TODO: Is the above true, do we need to Fetch? If the anon user is identified, then no user with this external_id existed, correct? fetchUser(aliasLabel: OS_EXTERNAL_ID, aliasId: request.aliasId, identityModel: request.identityModelToUpdate) executePendingRequests() // TODO: Here or after fetch or after transfer? diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 341ab7b66..5ddc6f12b 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -331,6 +331,7 @@ + (void)setLaunchOptions:(nullable NSDictionary*)newLaunchOptions { [OSNotificationsManager setColdStartFromTapOnNotification:YES]; } +// TODO: Should this be in the InAppMessages namespace? + (void)setLaunchURLsInApp:(BOOL)launchInApp { NSMutableDictionary *newSettings = [[NSMutableDictionary alloc] initWithDictionary:appSettings]; newSettings[kOSSettingsKeyInAppLaunchURL] = launchInApp ? @true : @false; From e1ed60a39034b00ea8120c19976e472028d6a6ea Mon Sep 17 00:00:00 2001 From: Nan Date: Fri, 6 Jan 2023 03:35:34 -0800 Subject: [PATCH 4/5] explicitly check for `409` on Identify User response * We were switching to the user when the Identify User request returns any failure, but we should really check that the code is `409` to go down this path. It could be some other error. --- .../OneSignalUser/Source/OSUserRequests.swift | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift index 44cf50428..f4e9dcce6 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/OSUserRequests.swift @@ -214,16 +214,19 @@ class OSUserExecutor { executePendingRequests() // TODO: Here or after fetch or after transfer? - } onFailure: { _ in - // TODO: Actually account for error code when processing this failure response + } onFailure: { error in // Returns 409 if any provided (label, id) pair exists on another User, so the SDK will switch to this user. - // If 409: - fetchUser(aliasLabel: OS_EXTERNAL_ID, aliasId: request.aliasId, identityModel: request.identityModelToUpdate) - // TODO: Link ^ to the new user - transferPushSubscriptionTo(aliasLabel: request.aliasLabel, aliasId: request.aliasId, retainPreviousUser: true) // update logic to determine flag - executePendingRequests() // Here or after fetch or after transfer? + if error?._code == 409 { + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "executeIdentifyUserRequest returned 409, failed due to alias already assigned to a different user. Now switch to this user.") - // If not 409, we retry, depending on what the error is? + fetchUser(aliasLabel: OS_EXTERNAL_ID, aliasId: request.aliasId, identityModel: request.identityModelToUpdate) + // TODO: Link ^ to the new user... what was this todo for? + transferPushSubscriptionTo(aliasLabel: request.aliasLabel, aliasId: request.aliasId, retainPreviousUser: true) // update logic to determine flag + executePendingRequests() // Here or after fetch or after transfer? + } else { + // If not 409, we retry, depending on what the error is? + OneSignalLog.onesignalLog(.LL_VERBOSE, message: "executeIdentifyUserRequest failed without returning a 409.") + } } } From c0e7b8fc4fb0f5e7dd145646018c6cf986261cae Mon Sep 17 00:00:00 2001 From: Nan Date: Fri, 6 Jan 2023 11:54:33 -0800 Subject: [PATCH 5/5] no longer use a staging app * We already pointed requests to production * But now revert the app back to bundle ID `com.onesignal.example` --- .../OneSignalDevApp/OneSignalDevApp/AppDelegate.m | 4 ++-- .../OneSignalDevApp/OneSignalDevApp.entitlements | 2 +- .../OneSignalDevAppClip.entitlements | 2 +- .../OneSignalExample.xcodeproj/project.pbxproj | 12 ++++++------ ...neSignalNotificationServiceExtension.entitlements | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m b/iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m index d1457a8f8..3eea33e6f 100644 --- a/iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m +++ b/iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m @@ -105,8 +105,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( return YES; } -#define ONESIGNAL_APP_ID_DEFAULT @"1688d8f2-da7f-4815-8ee3-9d13788482c8" -#define ONESIGNAL_APP_ID_KEY_FOR_TESTING @"1688d8f2-da7f-4815-8ee3-9d13788482c8" +#define ONESIGNAL_APP_ID_DEFAULT @"YOUR_APP_ID_HERE" +#define ONESIGNAL_APP_ID_KEY_FOR_TESTING @"YOUR_APP_ID_HERE" + (NSString*)getOneSignalAppId { NSString* userDefinedAppId = [[NSUserDefaults standardUserDefaults] objectForKey:ONESIGNAL_APP_ID_KEY_FOR_TESTING]; diff --git a/iOS_SDK/OneSignalDevApp/OneSignalDevApp/OneSignalDevApp.entitlements b/iOS_SDK/OneSignalDevApp/OneSignalDevApp/OneSignalDevApp.entitlements index 5388fb2fe..28007cfd9 100644 --- a/iOS_SDK/OneSignalDevApp/OneSignalDevApp/OneSignalDevApp.entitlements +++ b/iOS_SDK/OneSignalDevApp/OneSignalDevApp/OneSignalDevApp.entitlements @@ -11,7 +11,7 @@ com.apple.security.application-groups - group.com.onesignal.example.staging.onesignal + group.com.onesignal.example.onesignal diff --git a/iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/OneSignalDevAppClip.entitlements b/iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/OneSignalDevAppClip.entitlements index 89d4647e8..be2597206 100644 --- a/iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/OneSignalDevAppClip.entitlements +++ b/iOS_SDK/OneSignalDevApp/OneSignalDevAppClip/OneSignalDevAppClip.entitlements @@ -11,7 +11,7 @@ com.apple.developer.parent-application-identifiers - $(AppIdentifierPrefix)com.onesignal.example.staging + $(AppIdentifierPrefix)com.onesignal.example diff --git a/iOS_SDK/OneSignalDevApp/OneSignalExample.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalDevApp/OneSignalExample.xcodeproj/project.pbxproj index 80cd41a55..e533904f1 100644 --- a/iOS_SDK/OneSignalDevApp/OneSignalExample.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalDevApp/OneSignalExample.xcodeproj/project.pbxproj @@ -745,7 +745,7 @@ ); MARKETING_VERSION = 1.4.4; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; PRODUCT_NAME = OneSignalExample; SUPPORTS_MACCATALYST = YES; SWIFT_OBJC_BRIDGING_HEADER = "OneSignalDevApp/OneSignalExample-Bridging-Header.h"; @@ -776,7 +776,7 @@ ); MARKETING_VERSION = 1.4.4; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example; PRODUCT_NAME = OneSignalExample; SUPPORTS_MACCATALYST = YES; SWIFT_OBJC_BRIDGING_HEADER = "OneSignalDevApp/OneSignalExample-Bridging-Header.h"; @@ -804,7 +804,7 @@ ); MARKETING_VERSION = 1.4.4; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging.OneSignalNotificationServiceExtensionA; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.OneSignalNotificationServiceExtensionA; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SUPPORTS_MACCATALYST = YES; @@ -832,7 +832,7 @@ ); MARKETING_VERSION = 1.4.4; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging.OneSignalNotificationServiceExtensionA; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.OneSignalNotificationServiceExtensionA; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SUPPORTS_MACCATALYST = YES; @@ -877,7 +877,7 @@ MARKETING_VERSION = 1.4.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging.Clip; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.Clip; PRODUCT_NAME = OneSignalExampleClip; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -915,7 +915,7 @@ ); MARKETING_VERSION = 1.4.4; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.staging.Clip; + PRODUCT_BUNDLE_IDENTIFIER = com.onesignal.example.Clip; PRODUCT_NAME = OneSignalExampleClip; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/iOS_SDK/OneSignalDevApp/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements b/iOS_SDK/OneSignalDevApp/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements index fa1031a37..c70461e82 100644 --- a/iOS_SDK/OneSignalDevApp/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements +++ b/iOS_SDK/OneSignalDevApp/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements @@ -4,7 +4,7 @@ com.apple.security.application-groups - group.com.onesignal.example.staging.onesignal + group.com.onesignal.example.onesignal