From 6c6760c4d41324e1ec073a19bcc7425b0175e904 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Thu, 3 Nov 2022 14:43:33 -0700 Subject: [PATCH 01/10] Update OneSignal.h to include headers for new customer facing methods. --- iOS_SDK/OneSignalSDK/Source/OneSignal.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.h b/iOS_SDK/OneSignalSDK/Source/OneSignal.h index b787ef03c..430863892 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.h @@ -293,6 +293,17 @@ typedef void (^OSFailureBlock)(NSError* error); + (void)setLaunchURLsInApp:(BOOL)launchInApp; + (void)setProvidesNotificationSettingsView:(BOOL)providesView; + +#pragma mark Live Activity +typedef void (^OSLiveActivitySuccessBlock)(); +typedef void (^OSLiveActivityFailureBlock)(NSError *error); + ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token; ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; + ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId; ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; + #pragma mark Logging + (void)setLogLevel:(ONE_S_LOG_LEVEL)logLevel visualLevel:(ONE_S_LOG_LEVEL)visualLogLevel; + (void)onesignalLog:(ONE_S_LOG_LEVEL)logLevel message:(NSString* _Nonnull)message; From e8808b872bc956d4a3f3a2c906b429aeb51f24e7 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Thu, 3 Nov 2022 14:48:49 -0700 Subject: [PATCH 02/10] Adding interfaces to OSRequest.h --- .../OneSignalCore/Source/API/OSRequests.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h index 269cc143e..26b575c2f 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h @@ -135,10 +135,22 @@ NS_ASSUME_NONNULL_END + (instancetype _Nonnull)withUserId:(NSString * _Nullable)externalId withUserIdHashToken:(NSString * _Nullable)hashToken withOneSignalUserId:(NSString * _Nonnull)userId withSMSHashToken:(NSString * _Nullable)smsHashToken appId:(NSString * _Nonnull)appId; @end - @interface OSRequestTrackV1 : OneSignalRequest + (instancetype _Nonnull)trackUsageData:(NSString * _Nonnull)osUsageData appId:(NSString * _Nonnull)appId; @end + +@interface OSRequestLiveActivityEnter: OneSignalRequest ++ (instancetype _Nonnull)withUserId:(NSString * _Nonnull)userId + appId:(NSString * _Nonnull)appId + activityId:(NSString * _Nonnull)activityId + token:(NSString * _Nullable)token; +@end + +@interface OSRequestLiveActivityExit: OneSignalRequest ++ (instancetype _Nonnull)withUserId:(NSString * _Nonnull)userId + appId:(NSString * _Nonnull)appId + activityId:(NSString * _Nonnull)activityId; +@end #endif /* Requests_h */ From a0d8656cd24027f1a04c97cd5076f93f6d817cd6 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Thu, 3 Nov 2022 17:12:34 -0700 Subject: [PATCH 03/10] Adding implementation for the new OSRequest subclasses in OSRequests.m --- .../OneSignalCore/Source/API/OSRequests.m | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m index 39577b103..340ce0b49 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m @@ -492,3 +492,33 @@ + (instancetype)trackUsageData:(NSString *)osUsageData appId:(NSString *)appId { return request; } @end + +@implementation OSRequestLiveActivityEnter ++ (instancetype)withUserId:(NSString * _Nonnull)userId + appId:(NSString * _Nonnull)appId + activityId:(NSString * _Nonnull)activityId + token:(NSString * _Nullable)token { + let request = [OSRequestLiveActivityEnter new]; + let params = [NSMutableDictionary new]; + params[@"subscription_id"] = appId; // pre-5.X.X + params[@"push_token"] = token; + request.parameters = params; + request.method = POST; + request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/enter", appId, activityId]; + return request; +} +@end + +@implementation OSRequestLiveActivityExit ++ (instancetype)withUserId:(NSString * _Nonnull)userId + appId:(NSString * _Nonnull)appId + activityId:(NSString * _Nonnull)activityId{ + let request = [OSRequestLiveActivityExit new]; + let params = [NSMutableDictionary new]; + params[@"subscription_id"] = appId; // pre-5.X.X + request.parameters = params; + request.method = POST; + request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/exit", appId, activityId]; + return request; +} +@end From 55c87d82b28f0e15380bd09e15019c19e0ee66d0 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Fri, 4 Nov 2022 16:38:31 -0700 Subject: [PATCH 04/10] Adding impl for new SDK API in OneSignal.m --- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 4561f7525..a86a19e99 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -664,6 +664,33 @@ + (void)setProvidesNotificationSettingsView:(BOOL)providesView { appSettings = newSettings; } ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token { + [self enterLiveActivity:activityId withToken:token withSuccess:nil withFailure:nil]; +} ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ + + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId token:token] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:successBlock]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:failureBlock withError:error]; + }]; +} + ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId{ + [self exitLiveActivity:activityId withSuccess:nil withFailure:nil]; +} + ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ + + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:successBlock]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:failureBlock withError:error]; + }]; +} + + (void)setNotificationWillShowInForegroundHandler:(OSNotificationWillShowInForegroundBlock)block { [OneSignal onesignalLog:ONE_S_LL_VERBOSE message:@"Notification will show in foreground handler set successfully"]; [OneSignalHelper setNotificationWillShowInForegroundBlock:block]; From 3e76f6f48cf4cf32cadaf1c1e7ef51052b31fd52 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Tue, 15 Nov 2022 10:32:08 -0800 Subject: [PATCH 05/10] updating request path --- .../OneSignalCore/Source/API/OSRequests.m | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m index 340ce0b49..7e7723099 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m @@ -500,11 +500,11 @@ + (instancetype)withUserId:(NSString * _Nonnull)userId token:(NSString * _Nullable)token { let request = [OSRequestLiveActivityEnter new]; let params = [NSMutableDictionary new]; - params[@"subscription_id"] = appId; // pre-5.X.X params[@"push_token"] = token; + params[@"subscription_id"] = userId; // pre-5.X.X subscription_id = player_id = userId request.parameters = params; request.method = POST; - request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/enter", appId, activityId]; + request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token", appId, activityId]; return request; } @end @@ -514,11 +514,8 @@ + (instancetype)withUserId:(NSString * _Nonnull)userId appId:(NSString * _Nonnull)appId activityId:(NSString * _Nonnull)activityId{ let request = [OSRequestLiveActivityExit new]; - let params = [NSMutableDictionary new]; - params[@"subscription_id"] = appId; // pre-5.X.X - request.parameters = params; - request.method = POST; - request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/exit", appId, activityId]; + request.method = DELETE; + request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token/%@", appId, activityId, userId]; return request; } @end From 9451da5fc3a4d9000e999f283a38730e128f4c34 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Tue, 15 Nov 2022 13:50:03 -0800 Subject: [PATCH 06/10] Adding tests --- iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m b/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m index 49e2dc445..28c83e4e0 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m @@ -57,6 +57,8 @@ @implementation RequestTests { NSString *testInAppMessageAppId; NSString *testInAppMessageVariantId; NSString *testInAppMessagePageId; + NSString *testLiveActivityId; + NSString *testLiveActivityToken; NSString *testNotificationId; OSOutcomeEvent *testOutcome; NSNumber *testDeviceType; @@ -84,6 +86,8 @@ - (void)setUp { testInAppMessageAppId = @"test_in_app_message_app_id"; testInAppMessageVariantId = @"test_in_app_message_variant_id"; testInAppMessagePageId = @"test_in_app_message_page_id"; + testLiveActivityId = @"test_live_activity_id"; + testLiveActivityToken = @"test_live_activity_token"; testNotificationId = @"test_notification_id"; testOutcome = [[OSOutcomeEvent new] initWithSession:UNATTRIBUTED @@ -106,6 +110,7 @@ - (void)setUp { testAction = testBridgeEvent.userAction; testAction.firstClick = true; + } /* @@ -763,6 +768,39 @@ - (void)testSendTrackUsageRequest { })); } +- (void)testEnterLiveActivity { + let request = [OSRequestLiveActivityEnter withUserId:testUserId appId:testAppId activityId:testLiveActivityId token:testLiveActivityToken]; + + let testEnterLiveActivityUrlPath = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token", + testAppId, + testLiveActivityId]; + + let correctUrl = correctUrlWithPath(testEnterLiveActivityUrlPath); + + XCTAssertTrue([correctUrl isEqualToString:request.urlRequest.URL.absoluteString]); + XCTAssertTrue(checkHttpBody(request.urlRequest.HTTPBody, @{@"push_token" : testLiveActivityToken, @"subscription_id" : testUserId })); + + XCTAssertEqualObjects(request.urlRequest.HTTPMethod, @"POST"); + XCTAssertEqualObjects(request.urlRequest.allHTTPHeaderFields[@"Accept"], @"application/vnd.onesignal.v1+json"); +} + +- (void)testExitLiveActivity { + let request = [OSRequestLiveActivityExit withUserId:testUserId appId:testAppId activityId:testLiveActivityId]; + + let testExitLiveActivityUrlPath = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token/%@", + testAppId, + testLiveActivityId, + testUserId]; + + let correctUrl = correctUrlWithPath(testExitLiveActivityUrlPath); + + XCTAssertTrue([correctUrl isEqualToString:request.urlRequest.URL.absoluteString]); + + XCTAssertEqualObjects(request.urlRequest.HTTPBody, nil); + XCTAssertEqualObjects(request.urlRequest.HTTPMethod, @"DELETE"); + XCTAssertEqualObjects(request.urlRequest.allHTTPHeaderFields[@"Accept"], @"application/vnd.onesignal.v1+json"); +} + - (void)testAdditionalHeaders { // Create a fake request let request = [OneSignalRequest new]; From e3a4435e95939a68a2a382f61a808c5c69a1d795 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Tue, 15 Nov 2022 14:55:27 -0800 Subject: [PATCH 07/10] Adding further tests --- iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index b88166e28..a52adc551 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -3435,4 +3435,58 @@ - (void) testParseCollapseIdFromNotificationRequestWithOSData { XCTAssertEqualObjects(content.userInfo[@"os_data"][@"collapse_id"], @"test_id"); } +- (void)testEnterLiveActivity { + + NSString *testAppId = @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"; + NSString *testLiveActivity = @"onesignal-01012022"; + NSString *testLiveActivityToken = @"8076f335e7a8f865607949b02e95ba49268cf98a633f3963256e53172c19f299d312f09950d25c4e711260a65157446aba0b47d6120d53d67f6f6946b706f9ce4a0c883d3e0b1391f67fe4a8cc2ca381"; + NSString *testUserId = @"1234"; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + [OneSignal enterLiveActivity:testLiveActivity + withToken:testLiveActivityToken + withSuccess:nil + withFailure:nil]; + + [UnitTestCommonMethods runBackgroundThreads]; + + //check to make sure the OSRequestEnterLiveActivity HTTP call was made, and was formatted correctly + XCTAssertTrue([NSStringFromClass([OSRequestLiveActivityEnter class]) isEqualToString:OneSignalClientOverrider.lastHTTPRequestType]); + XCTAssertEqual(OneSignalClientOverrider.lastHTTPRequest[@"push_token"],testLiveActivityToken); + XCTAssertEqual(OneSignalClientOverrider.lastHTTPRequest[@"subscription_id"], testUserId); + + let testEnterLiveActivityCorrectURL = [NSString stringWithFormat:@"https://api.onesignal.com/apps/%@/live_activities/%@/token", + testAppId, + testLiveActivity]; + + XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testEnterLiveActivityCorrectURL); +} + +- (void)testExitLiveActivity { + + NSString *testAppId = @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"; + NSString *testLiveActivity = @"onesignal-01012022"; + NSString *testUserId = @"1234"; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + [OneSignal exitLiveActivity:testLiveActivity + withSuccess:nil + withFailure:nil]; + + [UnitTestCommonMethods runBackgroundThreads]; + + //check to make sure the OSRequestExitLiveActivity HTTP call was made, and was formatted correctly + XCTAssertTrue([NSStringFromClass([OSRequestLiveActivityExit class]) isEqualToString:OneSignalClientOverrider.lastHTTPRequestType]); + + let testExitLiveActivityCorrectURL = [NSString stringWithFormat:@"https://api.onesignal.com/apps/%@/live_activities/%@/token/%@", + testAppId, + testLiveActivity, + testUserId]; + + XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testExitLiveActivityCorrectURL); + +} + @end From a6178873749e5a2aa051eded28b216aae9299f17 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Tue, 15 Nov 2022 15:31:03 -0800 Subject: [PATCH 08/10] PR feedback NONULL, Privacy consent, nits --- .../OneSignalCore/Source/API/OSRequests.m | 2 +- iOS_SDK/OneSignalSDK/Source/OneSignal.h | 4 +-- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 28 +++++++++++++++++-- iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m | 1 - 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m index 7e7723099..184c0c477 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m @@ -512,7 +512,7 @@ + (instancetype)withUserId:(NSString * _Nonnull)userId @implementation OSRequestLiveActivityExit + (instancetype)withUserId:(NSString * _Nonnull)userId appId:(NSString * _Nonnull)appId - activityId:(NSString * _Nonnull)activityId{ + activityId:(NSString * _Nonnull)activityId { let request = [OSRequestLiveActivityExit new]; request.method = DELETE; request.path = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token/%@", appId, activityId, userId]; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.h b/iOS_SDK/OneSignalSDK/Source/OneSignal.h index 430863892..9d3a7577d 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.h @@ -298,8 +298,8 @@ typedef void (^OSFailureBlock)(NSError* error); typedef void (^OSLiveActivitySuccessBlock)(); typedef void (^OSLiveActivityFailureBlock)(NSError *error); -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token; -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token; ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; + (void)exitLiveActivity:(NSString * _Nonnull)activityId; + (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index a86a19e99..6cd94d970 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -664,10 +664,22 @@ + (void)setProvidesNotificationSettingsView:(BOOL)providesView { appSettings = newSettings; } -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token { ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token { + + if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:"]) + return; + [self enterLiveActivity:activityId withToken:token withSuccess:nil withFailure:nil]; } -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nullable)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ + + if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:onSuccess:onFailure:"]) { + if (failureBlock) { + NSError *error = [NSError errorWithDomain:@"com.onesignal.tags" code:0 userInfo:@{@"error" : @"Your application has called enterLiveActivity:onSuccess:onFailure: before the user granted privacy permission. Please call `consentGranted(bool)` in order to provide user privacy consent"}]; + failureBlock(error); + } + return; + } [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId token:token] onSuccess:^(NSDictionary *result) { @@ -678,11 +690,23 @@ + (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * } + (void)exitLiveActivity:(NSString * _Nonnull)activityId{ + + if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:"]) + return; + [self exitLiveActivity:activityId withSuccess:nil withFailure:nil]; } + (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ + if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"exitLiveActivity:onSuccess:onFailure:"]) { + if (failureBlock) { + NSError *error = [NSError errorWithDomain:@"com.onesignal.tags" code:0 userInfo:@{@"error" : @"Your application has called exitLiveActivity:onSuccess:onFailure: before the user granted privacy permission. Please call `consentGranted(bool)` in order to provide user privacy consent"}]; + failureBlock(error); + } + return; + } + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId] onSuccess:^(NSDictionary *result) { [self callSuccessBlockOnMainThread:successBlock]; diff --git a/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m b/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m index 28c83e4e0..280e3bc2b 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/RequestTests.m @@ -110,7 +110,6 @@ - (void)setUp { testAction = testBridgeEvent.userAction; testAction.firstClick = true; - } /* From 63a1b9c8828216a2b54be7f1d9bb475aeffa2de5 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Tue, 15 Nov 2022 17:07:44 -0800 Subject: [PATCH 09/10] Add pending live activity update support --- iOS_SDK/OneSignalSDK/Source/OneSignal.h | 7 +- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 133 +++++++++++++++++---- iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m | 69 +++++++++++ 3 files changed, 183 insertions(+), 26 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.h b/iOS_SDK/OneSignalSDK/Source/OneSignal.h index 9d3a7577d..a85aa7bd7 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.h @@ -295,14 +295,11 @@ typedef void (^OSFailureBlock)(NSError* error); #pragma mark Live Activity -typedef void (^OSLiveActivitySuccessBlock)(); -typedef void (^OSLiveActivityFailureBlock)(NSError *error); - + (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token; -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock; + (void)exitLiveActivity:(NSString * _Nonnull)activityId; -+ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock; ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock; #pragma mark Logging + (void)setLogLevel:(ONE_S_LOG_LEVEL)logLevel visualLevel:(ONE_S_LOG_LEVEL)visualLogLevel; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 6cd94d970..9f305b7ea 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -111,6 +111,34 @@ - (NSDictionary*)toDictionary { } @end +@interface OSPendingLiveActivityUpdate: NSObject + @property NSString* token; + @property NSString* activityId; + @property BOOL isEnter; + @property OSResultSuccessBlock successBlock; + @property OSFailureBlock failureBlock; + - (id)initWith:(NSString * _Nonnull)activityId + withToken:(NSString * _Nonnull)token + isEnter:(BOOL)isEnter + withSuccess:(OSResultSuccessBlock _Nullable)successBlock + withFailure:(OSFailureBlock _Nullable)failureBlock; +@end +@implementation OSPendingLiveActivityUpdate + +- (id)initWith:(NSString *)activityId + withToken:(NSString *)token + isEnter:(BOOL)isEnter + withSuccess:(OSResultSuccessBlock)successBlock + withFailure:(OSFailureBlock)failureBlock { + self.token = token; + self.activityId = activityId; + self.isEnter = isEnter; + self.successBlock = successBlock; + self.failureBlock = failureBlock; + return self; +}; +@end + @interface OneSignal (SessionStatusDelegate) @end @@ -138,6 +166,8 @@ + (OneSignalSetSMSParameters *)delayedSMSParameters { static OSResultSuccessBlock pendingGetTagsSuccessBlock; static OSFailureBlock pendingGetTagsFailureBlock; +static NSMutableArray* pendingLiveActivityUpdates; + // Has attempted to register for push notifications with Apple since app was installed. static BOOL registeredWithApple = NO; @@ -671,7 +701,52 @@ + (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * [self enterLiveActivity:activityId withToken:token withSuccess:nil withFailure:nil]; } -+ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ + +#pragma mark: LIVE ACTIVITIES + + ++ (void)addPendingLiveActivityUpdate:(NSString * _Nonnull)activityId + withToken:(NSString * _Nullable)token + isEnter:(BOOL)isEnter + withSuccess:(OSResultSuccessBlock _Nullable)successBlock + withFailure:(OSFailureBlock _Nullable)failureBlock { + OSPendingLiveActivityUpdate *pendingLiveActivityUpdate = [[OSPendingLiveActivityUpdate alloc] initWith:activityId withToken:token isEnter:isEnter withSuccess:successBlock withFailure:failureBlock]; + + if (!pendingLiveActivityUpdates){ + pendingLiveActivityUpdates = [NSMutableArray new]; + } + [pendingLiveActivityUpdates addObject:pendingLiveActivityUpdate]; +} + ++ (void)executePendingLiveActivityUpdates{ + if(pendingLiveActivityUpdates.count <= 0){ + return; + } + + OSPendingLiveActivityUpdate * updateToProcess = [pendingLiveActivityUpdates objectAtIndex:0]; + [pendingLiveActivityUpdates removeObjectAtIndex: 0]; + if (updateToProcess.isEnter) { + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:updateToProcess.activityId token:updateToProcess.token] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:updateToProcess.successBlock withResult:result]; + [self executePendingLiveActivityUpdates]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:updateToProcess.failureBlock withError:error]; + [self executePendingLiveActivityUpdates]; + }]; + } else { + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:updateToProcess.activityId] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:updateToProcess.successBlock withResult:result]; + [self executePendingLiveActivityUpdates]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:updateToProcess.failureBlock withError:error]; + [self executePendingLiveActivityUpdates]; + }]; + } +} + ++ (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * _Nonnull)token withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock{ if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"enterLiveActivity:onSuccess:onFailure:"]) { if (failureBlock) { @@ -680,13 +755,18 @@ + (void)enterLiveActivity:(NSString * _Nonnull)activityId withToken:(NSString * } return; } + - [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId token:token] - onSuccess:^(NSDictionary *result) { - [self callSuccessBlockOnMainThread:successBlock]; - } onFailure:^(NSError *error) { - [self callFailureBlockOnMainThread:failureBlock withError:error]; - }]; + if(self.currentSubscriptionState.userId) { + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityEnter withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId token:token] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:successBlock withResult:result]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:failureBlock withError:error]; + }]; + } else { + [self addPendingLiveActivityUpdate:activityId withToken:token isEnter:true withSuccess:successBlock withFailure:failureBlock]; + } } + (void)exitLiveActivity:(NSString * _Nonnull)activityId{ @@ -697,7 +777,7 @@ + (void)exitLiveActivity:(NSString * _Nonnull)activityId{ [self exitLiveActivity:activityId withSuccess:nil withFailure:nil]; } -+ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActivitySuccessBlock _Nullable)successBlock withFailure:(OSLiveActivityFailureBlock _Nullable)failureBlock{ ++ (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSResultSuccessBlock _Nullable)successBlock withFailure:(OSFailureBlock _Nullable)failureBlock{ if ([OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:@"exitLiveActivity:onSuccess:onFailure:"]) { if (failureBlock) { @@ -706,13 +786,16 @@ + (void)exitLiveActivity:(NSString * _Nonnull)activityId withSuccess:(OSLiveActi } return; } - - [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId] - onSuccess:^(NSDictionary *result) { - [self callSuccessBlockOnMainThread:successBlock]; - } onFailure:^(NSError *error) { - [self callFailureBlockOnMainThread:failureBlock withError:error]; - }]; + if(self.currentSubscriptionState.userId) { + [OneSignalClient.sharedClient executeRequest:[OSRequestLiveActivityExit withUserId:self.currentSubscriptionState.userId appId:appId activityId:activityId] + onSuccess:^(NSDictionary *result) { + [self callSuccessBlockOnMainThread:successBlock withResult:result]; + } onFailure:^(NSError *error) { + [self callFailureBlockOnMainThread:failureBlock withError:error]; + }]; + } else { + [self addPendingLiveActivityUpdate:activityId withToken:nil isEnter:false withSuccess:successBlock withFailure:failureBlock]; + } } + (void)setNotificationWillShowInForegroundHandler:(OSNotificationWillShowInForegroundBlock)block { @@ -1260,7 +1343,7 @@ + (void)sendTags:(NSDictionary*)keyValuePair onSuccess:(OSResultSuccessBlock)suc [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(sendTagsToServer) object:nil]; - // Can't send tags yet as their isn't a player_id. + // Can't send tags yet as there isn't a player_id. // tagsToSend will be sent with the POST create player call later in this case. if (self.currentSubscriptionState.userId) [OneSignalHelper performSelector:@selector(sendTagsToServer) onMainThreadOnObject:self withObject:nil afterDelay:5]; @@ -1891,7 +1974,7 @@ + (void)registerUserInternal { pendingGetTagsSuccessBlock = nil; pendingGetTagsFailureBlock = nil; } - + [self executePendingLiveActivityUpdates]; } if (results[@"push"][@"in_app_messages"]) { @@ -2354,7 +2437,15 @@ + (void)callFailureBlockOnMainThread:(OSFailureBlock)failureBlock withError:(NSE } } -+ (void)callSuccessBlockOnMainThread:(OSEmailSuccessBlock)successBlock { ++ (void)callSuccessBlockOnMainThread:(OSResultSuccessBlock)successBlock withResult:(NSDictionary *)result{ + if (successBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + successBlock(result); + }); + } +} + ++ (void)callEmailSuccessBlockOnMainThread:(OSEmailSuccessBlock)successBlock { if (successBlock) { dispatch_async(dispatch_get_main_queue(), ^{ successBlock(); @@ -2437,7 +2528,7 @@ + (void)setEmail:(NSString * _Nonnull)email withEmailAuthHashToken:(NSString * _ // Since developers may be making UI changes when this call finishes, we will call callbacks on the main thread. if (self.currentEmailSubscriptionState.emailUserId) { [OneSignalClient.sharedClient executeRequest:[OSRequestUpdateDeviceToken withUserId:self.currentEmailSubscriptionState.emailUserId appId:self.appId deviceToken:email withParentId:nil emailAuthToken:emailAuthToken email:nil externalIdAuthToken:[self mExternalIdAuthToken]] onSuccess:^(NSDictionary *result) { - [self callSuccessBlockOnMainThread:successBlock]; + [self callEmailSuccessBlockOnMainThread:successBlock]; } onFailure:^(NSError *error) { [self callFailureBlockOnMainThread:failureBlock withError:error]; }]; @@ -2449,7 +2540,7 @@ + (void)setEmail:(NSString * _Nonnull)email withEmailAuthHashToken:(NSString * _ if (emailPlayerId) { [OneSignal saveEmailAddress:email withAuthToken:emailAuthToken userId:emailPlayerId]; [OneSignalClient.sharedClient executeRequest:[OSRequestUpdateDeviceToken withUserId:self.currentSubscriptionState.userId appId:self.appId deviceToken:nil withParentId:self.currentEmailSubscriptionState.emailUserId emailAuthToken:hashToken email:email externalIdAuthToken:[self mExternalIdAuthToken] ] onSuccess:^(NSDictionary *result) { - [self callSuccessBlockOnMainThread:successBlock]; + [self callEmailSuccessBlockOnMainThread:successBlock]; } onFailure:^(NSError *error) { [self callFailureBlockOnMainThread:failureBlock withError:error]; }]; @@ -2490,7 +2581,7 @@ + (void)logoutEmailWithSuccess:(OSEmailSuccessBlock _Nullable)successBlock withF [OneSignalUserDefaults.initStandard removeValueForKey:OSUD_EMAIL_PLAYER_ID]; [OneSignal saveEmailAddress:nil withAuthToken:nil userId:nil]; - [self callSuccessBlockOnMainThread:successBlock]; + [self callEmailSuccessBlockOnMainThread:successBlock]; } onFailure:^(NSError *error) { [self callFailureBlockOnMainThread:failureBlock withError:error]; }]; diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index a52adc551..4dcc3b357 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -3463,6 +3463,50 @@ - (void)testEnterLiveActivity { XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testEnterLiveActivityCorrectURL); } +- (void)testPendingLiveActivityUpdates { + + NSString *testAppId = @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"; + NSString *testLiveActivity = @"onesignal-01012022"; + NSString *testLiveActivityToken = @"8076f335e7a8f865607949b02e95ba49268cf98a633f3963256e53172c19f299d312f09950d25c4e711260a65157446aba0b47d6120d53d67f6f6946b706f9ce4a0c883d3e0b1391f67fe4a8cc2ca381"; + NSString *testUserId = @"1234"; + + [OneSignal enterLiveActivity:testLiveActivity + withToken:testLiveActivityToken + withSuccess:nil + withFailure:nil]; + + [OneSignal exitLiveActivity:testLiveActivity + withSuccess:nil + withFailure:nil]; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + [UnitTestCommonMethods runBackgroundThreads]; + + //check to make sure the OSRequestEnterLiveActivity HTTP call was made, and was formatted correctly + OneSignalRequest *enterRequest = OneSignalClientOverrider.executedRequests[OneSignalClientOverrider.executedRequests.count-2]; + XCTAssertTrue([NSStringFromClass([OSRequestLiveActivityEnter class]) isEqualToString:NSStringFromClass([enterRequest class])]); + XCTAssertEqual(enterRequest.parameters[@"push_token"],testLiveActivityToken); + XCTAssertEqual(enterRequest.parameters[@"subscription_id"], testUserId); + + let testEnterLiveActivityCorrectURL = [NSString stringWithFormat:@"apps/%@/live_activities/%@/token", + testAppId, + testLiveActivity]; + + XCTAssertEqualObjects(enterRequest.path, testEnterLiveActivityCorrectURL); + + //check to make sure the OSRequestExitLiveActivity HTTP call was made, and was formatted correctly + XCTAssertTrue([NSStringFromClass([OSRequestLiveActivityExit class]) isEqualToString:OneSignalClientOverrider.lastHTTPRequestType]); + + let testExitLiveActivityCorrectURL = [NSString stringWithFormat:@"https://api.onesignal.com/apps/%@/live_activities/%@/token/%@", + testAppId, + testLiveActivity, + testUserId]; + + XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testExitLiveActivityCorrectURL); + +} + - (void)testExitLiveActivity { NSString *testAppId = @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"; @@ -3487,6 +3531,31 @@ - (void)testExitLiveActivity { XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testExitLiveActivityCorrectURL); +} +- (void)testExitLiveActivityEarly { + + NSString *testAppId = @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"; + NSString *testLiveActivity = @"onesignal-01012022"; + NSString *testUserId = @"1234"; + + [OneSignal exitLiveActivity:testLiveActivity + withSuccess:nil + withFailure:nil]; + + [UnitTestCommonMethods initOneSignal_andThreadWait]; + + [UnitTestCommonMethods runBackgroundThreads]; + + //check to make sure the OSRequestExitLiveActivity HTTP call was made, and was formatted correctly + XCTAssertTrue([NSStringFromClass([OSRequestLiveActivityExit class]) isEqualToString:OneSignalClientOverrider.lastHTTPRequestType]); + + let testExitLiveActivityCorrectURL = [NSString stringWithFormat:@"https://api.onesignal.com/apps/%@/live_activities/%@/token/%@", + testAppId, + testLiveActivity, + testUserId]; + + XCTAssertEqualObjects(OneSignalClientOverrider.lastUrl, testExitLiveActivityCorrectURL); + } @end From 720d1f4647100e988c4ab06777920f0441bbe135 Mon Sep 17 00:00:00 2001 From: fhboswell Date: Wed, 16 Nov 2022 08:14:40 -0800 Subject: [PATCH 10/10] token should be _Nonull in OSRequest --- iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h | 2 +- iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m | 2 +- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h index 26b575c2f..43bf0348b 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.h @@ -144,7 +144,7 @@ NS_ASSUME_NONNULL_END + (instancetype _Nonnull)withUserId:(NSString * _Nonnull)userId appId:(NSString * _Nonnull)appId activityId:(NSString * _Nonnull)activityId - token:(NSString * _Nullable)token; + token:(NSString * _Nonnull)token; @end @interface OSRequestLiveActivityExit: OneSignalRequest diff --git a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m index 184c0c477..5a3c458f5 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m +++ b/iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OSRequests.m @@ -497,7 +497,7 @@ @implementation OSRequestLiveActivityEnter + (instancetype)withUserId:(NSString * _Nonnull)userId appId:(NSString * _Nonnull)appId activityId:(NSString * _Nonnull)activityId - token:(NSString * _Nullable)token { + token:(NSString * _Nonnull)token { let request = [OSRequestLiveActivityEnter new]; let params = [NSMutableDictionary new]; params[@"push_token"] = token; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 9f305b7ea..de6574e22 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -712,14 +712,14 @@ + (void)addPendingLiveActivityUpdate:(NSString * _Nonnull)activityId withFailure:(OSFailureBlock _Nullable)failureBlock { OSPendingLiveActivityUpdate *pendingLiveActivityUpdate = [[OSPendingLiveActivityUpdate alloc] initWith:activityId withToken:token isEnter:isEnter withSuccess:successBlock withFailure:failureBlock]; - if (!pendingLiveActivityUpdates){ + if (!pendingLiveActivityUpdates) { pendingLiveActivityUpdates = [NSMutableArray new]; } [pendingLiveActivityUpdates addObject:pendingLiveActivityUpdate]; } -+ (void)executePendingLiveActivityUpdates{ - if(pendingLiveActivityUpdates.count <= 0){ ++ (void)executePendingLiveActivityUpdates { + if(pendingLiveActivityUpdates.count <= 0) { return; }