diff --git a/Examples/SwiftExample/OneSignalDemo/AppDelegate.swift b/Examples/SwiftExample/OneSignalDemo/AppDelegate.swift index e53ca7c14..7871a42ca 100644 --- a/Examples/SwiftExample/OneSignalDemo/AppDelegate.swift +++ b/Examples/SwiftExample/OneSignalDemo/AppDelegate.swift @@ -61,15 +61,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, OSPermissionObserver, OSS if let additionalData = result!.notification.payload!.additionalData { print("additionalData = \(additionalData)") - // DEEP LINK and open url in RedViewController - // Send notification with Additional Data > example key: "OpenURL" example value: "https://google.com" - let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) - let instantiateRedViewController : RedViewController = mainStoryboard.instantiateViewController(withIdentifier: "RedViewControllerID") as! RedViewController - instantiateRedViewController.receivedURL = additionalData["OpenURL"] as! String! - self.window = UIWindow(frame: UIScreen.main.bounds) - self.window?.rootViewController = instantiateRedViewController - self.window?.makeKeyAndVisible() - if let actionSelected = payload?.actionButtons { print("actionSelected = \(actionSelected)") diff --git a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj index da952f31b..ab0916109 100644 --- a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj @@ -132,6 +132,9 @@ CA08FC801FE99B25004C445F /* Requests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA08FC7D1FE99B25004C445F /* Requests.m */; }; CA08FC811FE99B25004C445F /* Requests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA08FC7D1FE99B25004C445F /* Requests.m */; }; CA08FC871FE99BB4004C445F /* OneSignalClientOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = CA08FC831FE99BB4004C445F /* OneSignalClientOverrider.m */; }; + CA1873BD2049F7070079CA09 /* NSMutableDictionary+OneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1873BC2049F7070079CA09 /* NSMutableDictionary+OneSignal.m */; }; + CA1873BF2049FB4F0079CA09 /* NSMutableDictionary+OneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1873BC2049F7070079CA09 /* NSMutableDictionary+OneSignal.m */; }; + CA1873C02049FB540079CA09 /* NSMutableDictionary+OneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = CA1873BC2049F7070079CA09 /* NSMutableDictionary+OneSignal.m */; }; CA63AF8420211F7400E340FB /* EmailTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CA63AF8320211F7400E340FB /* EmailTests.m */; }; CA63AF8720211FF800E340FB /* UnitTestCommonMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = CA63AF8620211FF800E340FB /* UnitTestCommonMethods.m */; }; CA63AFC22022670A00E340FB /* ReattemptRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CA63AFC02022670A00E340FB /* ReattemptRequest.h */; }; @@ -144,6 +147,10 @@ CA810FD1202BA97300A60FED /* OSEmailSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = CA810FD0202BA97300A60FED /* OSEmailSubscription.m */; }; CA810FD2202BA97600A60FED /* OSEmailSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = CA810FD0202BA97300A60FED /* OSEmailSubscription.m */; }; CA810FD3202BA97600A60FED /* OSEmailSubscription.m in Sources */ = {isa = PBXBuildFile; fileRef = CA810FD0202BA97300A60FED /* OSEmailSubscription.m */; }; + CA97E14E2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h in Headers */ = {isa = PBXBuildFile; fileRef = CA97E14C2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h */; }; + CA97E14F2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; + CA97E1502051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; + CA97E1512051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; CAEA1C66202BB3C600FBFE9E /* OSEmailSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = CA810FCF202BA97300A60FED /* OSEmailSubscription.h */; }; /* End PBXBuildFile section */ @@ -267,6 +274,8 @@ CA08FC7D1FE99B25004C445F /* Requests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Requests.m; sourceTree = ""; }; CA08FC821FE99BB4004C445F /* OneSignalClientOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalClientOverrider.h; sourceTree = ""; }; CA08FC831FE99BB4004C445F /* OneSignalClientOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalClientOverrider.m; sourceTree = ""; }; + CA1873BB2049F7070079CA09 /* NSMutableDictionary+OneSignal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+OneSignal.h"; sourceTree = ""; }; + CA1873BC2049F7070079CA09 /* NSMutableDictionary+OneSignal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+OneSignal.m"; sourceTree = ""; }; CA63AF8320211F7400E340FB /* EmailTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EmailTests.m; sourceTree = ""; }; CA63AF8520211FF800E340FB /* UnitTestCommonMethods.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnitTestCommonMethods.h; sourceTree = ""; }; CA63AF8620211FF800E340FB /* UnitTestCommonMethods.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTestCommonMethods.m; sourceTree = ""; }; @@ -277,6 +286,8 @@ CA70E3382023F24500019273 /* OneSignalCommonDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalCommonDefines.h; sourceTree = ""; }; CA810FCF202BA97300A60FED /* OSEmailSubscription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSEmailSubscription.h; sourceTree = ""; }; CA810FD0202BA97300A60FED /* OSEmailSubscription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSEmailSubscription.m; sourceTree = ""; }; + CA97E14C2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalWebOpenDialog.h; sourceTree = ""; }; + CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalWebOpenDialog.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -457,6 +468,8 @@ 912411F31E73342200E41FD7 /* OneSignalAlertViewDelegate.m */, 912412061E73342200E41FD7 /* OneSignalWebView.h */, 912412071E73342200E41FD7 /* OneSignalWebView.m */, + CA97E14C2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h */, + CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */, ); name = UI; sourceTree = ""; @@ -472,6 +485,8 @@ 912412091E73342200E41FD7 /* UIApplicationDelegate+OneSignal.m */, 9124120A1E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.h */, 9124120B1E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.m */, + CA1873BB2049F7070079CA09 /* NSMutableDictionary+OneSignal.h */, + CA1873BC2049F7070079CA09 /* NSMutableDictionary+OneSignal.m */, ); name = Categories; sourceTree = ""; @@ -554,6 +569,7 @@ 912412391E73342200E41FD7 /* OneSignalWebView.h in Headers */, 91C7725E1E7CCE1000D612D0 /* OneSignalInternal.h in Headers */, 9129C6BD1E89E7AB009CB6A0 /* OSSubscription.h in Headers */, + CA97E14E2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -705,6 +721,7 @@ 9129C6B81E89E59B009CB6A0 /* OSPermission.m in Sources */, 912412121E73342200E41FD7 /* OneSignalAlertViewDelegate.m in Sources */, 912412421E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.m in Sources */, + CA97E14F2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */, 9124123A1E73342200E41FD7 /* OneSignalWebView.m in Sources */, 9124123E1E73342200E41FD7 /* UIApplicationDelegate+OneSignal.m in Sources */, 912412261E73342200E41FD7 /* OneSignalMobileProvision.m in Sources */, @@ -717,6 +734,7 @@ CA810FD1202BA97300A60FED /* OSEmailSubscription.m in Sources */, CA63AFC32022670A00E340FB /* ReattemptRequest.m in Sources */, 912412221E73342200E41FD7 /* OneSignalLocation.m in Sources */, + CA1873BD2049F7070079CA09 /* NSMutableDictionary+OneSignal.m in Sources */, 1AF75EAE1E8567FD0097B315 /* NSString+OneSignal.m in Sources */, 454F94F51FAD2E5A00D74CCF /* OSNotificationPayload.m in Sources */, 9129C6BE1E89E7AB009CB6A0 /* OSSubscription.m in Sources */, @@ -741,6 +759,7 @@ 91F58D841E7C88220017D24D /* OneSignalNotificationSettingsIOS10.m in Sources */, 9129C6B91E89E59B009CB6A0 /* OSPermission.m in Sources */, 912412131E73342200E41FD7 /* OneSignalAlertViewDelegate.m in Sources */, + CA97E1502051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */, 0338566B1FBBD2270002F7C1 /* OSNotificationPayload.m in Sources */, 912412431E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.m in Sources */, 9124123B1E73342200E41FD7 /* OneSignalWebView.m in Sources */, @@ -753,6 +772,7 @@ CA810FD2202BA97600A60FED /* OSEmailSubscription.m in Sources */, CA63AFC42022670A00E340FB /* ReattemptRequest.m in Sources */, 91F58D8A1E7C9A240017D24D /* OneSignalNotificationSettingsIOS7.m in Sources */, + CA1873BF2049FB4F0079CA09 /* NSMutableDictionary+OneSignal.m in Sources */, 912412231E73342200E41FD7 /* OneSignalLocation.m in Sources */, 1AF75EB01E8569720097B315 /* NSString+OneSignal.m in Sources */, 9129C6BF1E89E7AB009CB6A0 /* OSSubscription.m in Sources */, @@ -797,6 +817,8 @@ 1AF75EAF1E8569710097B315 /* NSString+OneSignal.m in Sources */, 4529DEE71FA82CDC00CEAB1D /* UNUserNotificationCenterOverrider.m in Sources */, 4529DEDB1FA8284E00CEAB1D /* NSDataOverrider.m in Sources */, + CA97E1512051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */, + CA1873C02049FB540079CA09 /* NSMutableDictionary+OneSignal.m in Sources */, 4529DEF31FA8440A00CEAB1D /* UIAlertViewOverrider.m in Sources */, 4529DEEA1FA8360C00CEAB1D /* UIApplicationOverrider.m in Sources */, 912412281E73342200E41FD7 /* OneSignalMobileProvision.m in Sources */, diff --git a/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.h b/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.h new file mode 100644 index 000000000..1c299374b --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.h @@ -0,0 +1,32 @@ +/** + * Modified MIT License + * + * Copyright 2018 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import + +@interface NSMutableDictionary (OneSignal) +- (void)convertDatesToISO8061Strings; +@end diff --git a/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.m b/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.m new file mode 100644 index 000000000..239771ca9 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/NSMutableDictionary+OneSignal.m @@ -0,0 +1,48 @@ +/** + * Modified MIT License + * + * Copyright 2018 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "NSMutableDictionary+OneSignal.h" + +@implementation NSMutableDictionary (OneSignal) + +//NSJSONSerialization will not handle NSDates +//this method converts any occurrences of NSDate into an ISO8061 compliant string + +- (void)convertDatesToISO8061Strings { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; + [dateFormatter setLocale:enUSPOSIXLocale]; + [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; + + for (NSString *key in self.allKeys) { + id value = self[key]; + + if ([value isKindOfClass:[NSDate class]]) + self[key] = [dateFormatter stringFromDate:(NSDate *)value]; + } +} +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.h b/iOS_SDK/OneSignalSDK/Source/OneSignal.h index b9bf7c808..0194f8469 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.h @@ -282,6 +282,7 @@ typedef NS_ENUM(NSInteger, OSNotificationPermission) { @end +typedef void (^OSWebOpenURLResultBlock)(BOOL shouldOpen); typedef void (^OSResultSuccessBlock)(NSDictionary* result); typedef void (^OSFailureBlock)(NSError* error); @@ -306,6 +307,9 @@ extern NSString * const kOSSettingsKeyInAppAlerts; /*Enable In-App display of Launch URLs*/ extern NSString * const kOSSettingsKeyInAppLaunchURL; +/*Prompt user yes/no to open URL's from push notifications*/ +extern NSString * const kOSSSettingsKeyPromptBeforeOpeningPushURL; + /* iOS10 + Set notification's in-focus display option. Value must be an OSNotificationDisplayType enum @@ -364,7 +368,7 @@ typedef NS_ENUM(NSUInteger, ONE_S_LOG_LEVEL) { + (void)deleteTagsWithJsonString:(NSString*)jsonString; // Optional method that sends us the user's email as an anonymized hash so that we can better target and personalize notifications sent to that user across their devices. // Sends as MD5 and SHA1 of the provided email -+ (void)syncHashedEmail:(NSString*)email; ++ (void)syncHashedEmail:(NSString*)email __deprecated_msg("Please refer to our new Email methods/functionality such as setEmail(). This method will be removed in a future version of the OneSignal SDK"); // - Subscription and Permissions + (void)IdsAvailable:(OSIdsAvailableBlock)idsAvailableBlock __deprecated_msg("Please use getPermissionSubscriptionState or addSubscriptionObserver and addPermissionObserver instead."); diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index b019fa5ce..92a487425 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -38,6 +38,7 @@ #import "UNUserNotificationCenter+OneSignal.h" #import "OneSignalSelectorHelpers.h" #import "UIApplicationDelegate+OneSignal.h" +#import "NSMutableDictionary+OneSignal.h" #import "NSString+OneSignal.h" #import "OneSignalTrackFirebaseAnalytics.h" #import "OneSignalNotificationServiceExtensionHandler.h" @@ -103,6 +104,8 @@ /* Omit no app_id error logging, for use with wrapper SDKs. */ NSString* const kOSSettingsKeyInOmitNoAppIdLogging = @"kOSSettingsKeyInOmitNoAppIdLogging"; +/* Determine whether to automatically open push notification URL's or prompt user for permission */ +NSString* const kOSSSettingsKeyPromptBeforeOpeningPushURL = @"kOSSSettingsKeyPromptBeforeOpeningPushURL"; @implementation OSPermissionSubscriptionState - (NSString*)description { @@ -159,6 +162,8 @@ @implementation OneSignal static BOOL downloadedParameters = false; static BOOL didCallDownloadParameters = false; +static BOOL promptBeforeOpeningPushURLs = false; + static OneSignalTrackIAP* trackIAPPurchase; static NSString* app_id; NSString* emailToSet; @@ -367,11 +372,11 @@ + (BOOL)shouldDelaySubscriptionSettingsUpdate { } + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId { - return [self initWithLaunchOptions: launchOptions appId: appId handleNotificationReceived: NULL handleNotificationAction : NULL settings: @{kOSSettingsKeyAutoPrompt : @YES, kOSSettingsKeyInAppAlerts : @YES, kOSSettingsKeyInAppLaunchURL : @YES}]; + return [self initWithLaunchOptions: launchOptions appId: appId handleNotificationReceived: NULL handleNotificationAction : NULL settings: @{kOSSettingsKeyAutoPrompt : @YES, kOSSettingsKeyInAppAlerts : @YES, kOSSettingsKeyInAppLaunchURL : @YES, kOSSSettingsKeyPromptBeforeOpeningPushURL : @NO}]; } + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId handleNotificationAction:(OSHandleNotificationActionBlock)actionCallback { - return [self initWithLaunchOptions: launchOptions appId: appId handleNotificationReceived: NULL handleNotificationAction : actionCallback settings: @{kOSSettingsKeyAutoPrompt : @YES, kOSSettingsKeyInAppAlerts : @YES, kOSSettingsKeyInAppLaunchURL : @YES}]; + return [self initWithLaunchOptions: launchOptions appId: appId handleNotificationReceived: NULL handleNotificationAction : actionCallback settings: @{kOSSettingsKeyAutoPrompt : @YES, kOSSettingsKeyInAppAlerts : @YES, kOSSettingsKeyInAppLaunchURL : @YES, kOSSSettingsKeyPromptBeforeOpeningPushURL : @NO}]; } + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId handleNotificationAction:(OSHandleNotificationActionBlock)actionCallback settings:(NSDictionary*)settings { @@ -395,6 +400,8 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId [OneSignalLocation getLocation:false]; if (self) { + [OneSignal checkIfApplicationImplementsDeprecatedMethods]; + [OneSignalHelper notificationBlocks: receivedCallback : actionCallback]; if ([OneSignalHelper isIOSVersionGreaterOrEqual:8]) @@ -410,6 +417,13 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId [self enableInAppLaunchURL:@YES]; } + if (settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] && [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] isKindOfClass:[NSNumber class]]) { + promptBeforeOpeningPushURLs = [settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] boolValue]; + [userDefaults setObject:settings[kOSSSettingsKeyPromptBeforeOpeningPushURL] forKey:PROMPT_BEFORE_OPENING_PUSH_URL]; + [userDefaults synchronize]; + } else if ([userDefaults objectForKey:PROMPT_BEFORE_OPENING_PUSH_URL]) { + promptBeforeOpeningPushURLs = [[userDefaults objectForKey:PROMPT_BEFORE_OPENING_PUSH_URL] boolValue]; + } var autoPrompt = YES; if (settings[kOSSettingsKeyAutoPrompt] && [settings[kOSSettingsKeyAutoPrompt] isKindOfClass:[NSNumber class]]) @@ -525,6 +539,14 @@ +(bool)initAppId:(NSString*)appId withUserDefaults:(NSUserDefaults*)userDefaults return true; } +// the iOS SDK used to call these selectors as a convenience but has stopped due to concerns about private API usage +// the SDK will now print warnings when a developer's app implements these selectors ++ (void)checkIfApplicationImplementsDeprecatedMethods { + for (NSString *selectorName in DEPRECATED_SELECTORS) + if ([[[UIApplication sharedApplication] delegate] respondsToSelector:NSSelectorFromString(selectorName)]) + [OneSignal onesignal_Log:ONE_S_LL_WARN message:[NSString stringWithFormat:@"OneSignal has detected that your application delegate implements a deprecated method (%@). Please note that this method has been officially deprecated and the OneSignal SDK will no longer call it. You should use UNUserNotificationCenter instead", selectorName]]; +} + +(void)downloadIOSParams { [self onesignal_Log:ONE_S_LL_DEBUG message:@"Downloading iOS parameters for this application"]; didCallDownloadParameters = true; @@ -588,7 +610,7 @@ void onesignal_Log(ONE_S_LOG_LEVEL logLevel, NSString* message) { let alertView = [[UIAlertView alloc] initWithTitle:levelString message:message delegate:nil - cancelButtonTitle:NSLocalizedString(@"Close", nil) + cancelButtonTitle:NSLocalizedString(@"Close", @"Close button") otherButtonTitles:nil, nil]; [alertView show]; }]; @@ -876,18 +898,26 @@ + (void)postNotification:(NSDictionary*)jsonData { } + (void)postNotification:(NSDictionary*)jsonData onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSFailureBlock)failureBlock { - [OneSignalClient.sharedClient executeRequest:[OSRequestPostNotification withAppId:self.app_id withJson:[jsonData mutableCopy]] onSuccess:^(NSDictionary *result) { - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:result options:0 error:nil]; - NSString* jsonResultsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - - onesignal_Log(ONE_S_LL_DEBUG, [NSString stringWithFormat: @"HTTP create notification success %@", jsonResultsString]); - if (successBlock) + NSMutableDictionary *json = [jsonData mutableCopy]; + + [json convertDatesToISO8061Strings]; //convert any dates to NSString's + + [OneSignalClient.sharedClient executeRequest:[OSRequestPostNotification withAppId:self.app_id withJson:json] onSuccess:^(NSDictionary *result) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSData* jsonData = [NSJSONSerialization dataWithJSONObject:result options:0 error:nil]; + NSString* jsonResultsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + + onesignal_Log(ONE_S_LL_DEBUG, [NSString stringWithFormat: @"HTTP create notification success %@", jsonResultsString]); + if (successBlock) successBlock(result); + }); } onFailure:^(NSError *error) { - onesignal_Log(ONE_S_LL_ERROR, @"Create notification failed"); - onesignal_Log(ONE_S_LL_INFO, [NSString stringWithFormat: @"%@", error]); - if (failureBlock) + dispatch_async(dispatch_get_main_queue(), ^{ + onesignal_Log(ONE_S_LL_ERROR, @"Create notification failed"); + onesignal_Log(ONE_S_LL_INFO, [NSString stringWithFormat: @"%@", error]); + if (failureBlock) failureBlock(error); + }); }]; } @@ -1358,14 +1388,13 @@ + (void)setLastnonActiveMessageId:(NSString*)value { _lastnonActiveMessageId = v // - 2A. iOS 9 - Notification received while app is in focus. // - 2B. iOS 10 - Notification received/displayed while app is in focus. + (void)notificationOpened:(NSDictionary*)messageDict isActive:(BOOL)isActive { + if (!app_id) return; onesignal_Log(ONE_S_LL_VERBOSE, @"notificationOpened:isActive called!"); - NSDictionary* customDict = [messageDict objectForKey:@"os_data"]; - if (!customDict) - customDict = [messageDict objectForKey:@"custom"]; + NSDictionary* customDict = [messageDict objectForKey:@"os_data"] ?: [messageDict objectForKey:@"custom"]; // Should be called first, other methods relay on this global state below. [OneSignalHelper lastMessageReceived:messageDict]; @@ -1393,8 +1422,7 @@ + (void)notificationOpened:(NSDictionary*)messageDict isActive:(BOOL)isActive { // Notify backend that user opened the notification NSString *messageId = [customDict objectForKey:@"i"]; [OneSignal submitNotificationOpened:messageId]; - } - else { + } else { // Prevent duplicate calls let newId = [self checkForProcessedDups:customDict lastMessageId:_lastnonActiveMessageId]; if ([@"dup" isEqualToString:newId]) @@ -1434,9 +1462,8 @@ + (void)handleNotificationOpened:(NSDictionary*)messageDict isActive:(BOOL)isActive actionType:(OSNotificationActionType)actionType displayType:(OSNotificationDisplayType)displayType { - NSDictionary* customDict = [messageDict objectForKey:@"os_data"]; - if (customDict == nil) - customDict = [messageDict objectForKey:@"custom"]; + + NSDictionary* customDict = [messageDict objectForKey:@"custom"] ?: [messageDict objectForKey:@"os_data"]; // Notify backend that user opened the notification NSString* messageId = [customDict objectForKey:@"i"]; @@ -1459,7 +1486,12 @@ + (void)handleNotificationOpened:(NSDictionary*)messageDict [OneSignalHelper handleNotificationAction:actionType actionID:actionID displayType:displayType]; } ++ (BOOL)shouldPromptToShowURL { + return promptBeforeOpeningPushURLs; +} + + (void)launchWebURL:(NSString*)openUrl { + NSString* toOpenUrl = [OneSignalHelper trimURLSpacing:openUrl]; if (toOpenUrl && [OneSignalHelper verifyURL:toOpenUrl]) { diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalClient.m b/iOS_SDK/OneSignalSDK/Source/OneSignalClient.m index 7d00f1d61..e6cbed2da 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalClient.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalClient.m @@ -66,7 +66,7 @@ - (void)executeSimultaneousRequests:(NSDictionary *errors = [NSMutableDictionary new]; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h index 70b611fdb..557c8979c 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h @@ -25,5 +25,7 @@ #define ACCEPTED_PERMISSION @"ONESIGNAL_PERMISSION_ACCEPTED_LAST" #define REQUIRE_EMAIL_AUTH @"GT_REQUIRE_EMAIL_AUTH" #define EMAIL_ADDRESS @"EMAIL_ADDRESS" +#define PROMPT_BEFORE_OPENING_PUSH_URL @"PROMPT_BEFORE_OPENING_PUSH_URL" +#define DEPRECATED_SELECTORS @[@"application:didReceiveLocalNotification:", @"application:handleActionWithIdentifier:forLocalNotification:completionHandler:", @"application:handleActionWithIdentifier:forLocalNotification:withResponseInfo:completionHandler:"] #endif /* OneSignalCommonDefines_h */ diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m b/iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m index 68c501869..d4b3a02af 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalHelper.m @@ -38,6 +38,8 @@ #import +#import "OneSignalWebOpenDialog.h" +#import "OneSignalInternal.h" #define NOTIFICATION_TYPE_ALL 7 #pragma clang diagnostic push @@ -328,15 +330,18 @@ + (NSMutableDictionary*)formatApsPayloadIntoStandard:(NSDictionary*)remoteUserIn NSMutableDictionary* userInfo, *customDict, *additionalData, *optionsDict; BOOL is2dot4Format = false; - if (remoteUserInfo[@"os_data"][@"buttons"]) { + if (remoteUserInfo[@"os_data"]) { userInfo = [remoteUserInfo mutableCopy]; additionalData = [NSMutableDictionary dictionary]; - is2dot4Format = [userInfo[@"os_data"][@"buttons"] isKindOfClass:[NSArray class]]; - if (is2dot4Format) - optionsDict = userInfo[@"os_data"][@"buttons"]; - else - optionsDict = userInfo[@"os_data"][@"buttons"][@"o"]; + if (remoteUserInfo[@"os_data"][@"buttons"]) { + + is2dot4Format = [userInfo[@"os_data"][@"buttons"] isKindOfClass:[NSArray class]]; + if (is2dot4Format) + optionsDict = userInfo[@"os_data"][@"buttons"]; + else + optionsDict = userInfo[@"os_data"][@"buttons"][@"o"]; + } } else if (remoteUserInfo[@"custom"]) { userInfo = [remoteUserInfo mutableCopy]; @@ -347,8 +352,9 @@ + (NSMutableDictionary*)formatApsPayloadIntoStandard:(NSDictionary*)remoteUserIn additionalData = [[NSMutableDictionary alloc] init]; optionsDict = userInfo[@"o"]; } - else + else { return nil; + } if (optionsDict) { NSMutableArray* buttonArray = [[NSMutableArray alloc] init]; @@ -364,12 +370,12 @@ + (NSMutableDictionary*)formatApsPayloadIntoStandard:(NSDictionary*)remoteUserIn if ([additionalData count] == 0) additionalData = nil; - - if (remoteUserInfo[@"os_data"]) { + else if (remoteUserInfo[@"os_data"]) { [userInfo addEntriesFromDictionary:additionalData]; if (!is2dot4Format) userInfo[@"aps"] = @{@"alert" : userInfo[@"os_data"][@"buttons"][@"m"]}; } + else { customDict[@"a"] = additionalData; userInfo[@"custom"] = customDict; @@ -785,7 +791,7 @@ + (BOOL)isWWWScheme:(NSURL*)url { + (void) displayWebView:(NSURL*)url { // Check if in-app or safari - BOOL inAppLaunch = YES; + __block BOOL inAppLaunch = YES; if( ![[NSUserDefaults standardUserDefaults] objectForKey:@"ONESIGNAL_INAPP_LAUNCH_URL"]) { [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:@"ONESIGNAL_INAPP_LAUNCH_URL"]; [[NSUserDefaults standardUserDefaults] synchronize]; @@ -795,23 +801,38 @@ + (void) displayWebView:(NSURL*)url { // If the URL contains itunes.apple.com, it's an app store link // that should be opened using sharedApplication openURL - if ([[url absoluteString] containsString:@"itunes.apple.com"]) { + if ([[url absoluteString] rangeOfString:@"itunes.apple.com"].location != NSNotFound) { inAppLaunch = NO; } - if (inAppLaunch && [self isWWWScheme:url]) { - if (!webVC) - webVC = [[OneSignalWebView alloc] init]; - webVC.url = url; - [webVC showInApp]; - } - else { - // Keep dispatch_async. Without this the url can take an extra 2 to 10 secounds to open. - [OneSignalHelper dispatch_async_on_main_queue: ^{ - [[UIApplication sharedApplication] openURL:url]; + __block let openUrlBlock = ^void(BOOL shouldOpen) { + if (!shouldOpen) + return; + + [OneSignalHelper dispatch_async_on_main_queue: ^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (inAppLaunch && [self isWWWScheme:url]) { + if (!webVC) + webVC = [[OneSignalWebView alloc] init]; + webVC.url = url; + [webVC showInApp]; + } + else { + // Keep dispatch_async. Without this the url can take an extra 2 to 10 secounds to open. + [[UIApplication sharedApplication] openURL:url]; + } + }); }]; - } + }; + if ([OneSignal shouldPromptToShowURL]) { + [OneSignalWebOpenDialog showOpenDialogwithURL:url withResponse:^(BOOL shouldOpen) { + openUrlBlock(shouldOpen); + }]; + } else { + openUrlBlock(true); + } + } + (void) runOnMainThread:(void(^)())block { diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalInternal.h b/iOS_SDK/OneSignalSDK/Source/OneSignalInternal.h index 3ae829798..2b8929af8 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalInternal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalInternal.h @@ -54,6 +54,7 @@ + (void)updateNotificationTypes:(int)notificationTypes; + (BOOL)registerForAPNsToken; + (void)setWaitingForApnsResponse:(BOOL)value; ++ (BOOL)shouldPromptToShowURL; @property (class) NSObject* osNotificationSettings; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.h b/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.h new file mode 100644 index 000000000..fb5d8947f --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.h @@ -0,0 +1,36 @@ +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import +#import "OneSignal.h" + +@interface OneSignalWebOpenDialog : NSObject + ++ (void)showOpenDialogwithURL:(NSURL *)url withResponse:(OSWebOpenURLResultBlock)shouldOpen; + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.m b/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.m new file mode 100644 index 000000000..21c3391cc --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalWebOpenDialog.m @@ -0,0 +1,101 @@ +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "OneSignalWebOpenDialog.h" +#import "OneSignalHelper.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +@interface OneSignalWebOpenDialog () +@property (strong, nonatomic) UIAlertView *alertView; +@property (nonatomic) OSWebOpenURLResultBlock resultBlock; +@end + +@implementation OneSignalWebOpenDialog + ++ (instancetype)sharedInstance +{ + static OneSignalWebOpenDialog *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[OneSignalWebOpenDialog alloc] init]; + // Do any other initialisation stuff here + }); + return sharedInstance; +} + ++ (void)showOpenDialogwithURL:(NSURL *)url withResponse:(OSWebOpenURLResultBlock)shouldOpen { + + let message = NSLocalizedString(([NSString stringWithFormat:@"Would you like to open %@://%@", url.scheme, url.host]), @"Asks whether the user wants to open the URL"); + + //for iOS 7 + if (![OneSignalHelper isIOSVersionGreaterOrEqual:8]) { + let alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Open URL?", nil) + message:message + delegate:[OneSignalWebOpenDialog sharedInstance] + cancelButtonTitle:NSLocalizedString(@"No", nil) + otherButtonTitles:NSLocalizedString(@"Yes", nil), nil]; + + [OneSignalWebOpenDialog sharedInstance].resultBlock = shouldOpen; + + [alertView show]; + + return; + } + + //for iOS 8+ + let rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController]; + + let alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Open URL?", nil) + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Yes", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [OneSignalWebOpenDialog delayResult:shouldOpen shouldOpen:true]; + }]]; + + [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"No", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + [OneSignalWebOpenDialog delayResult:shouldOpen shouldOpen:false]; + }]]; + + [rootViewController presentViewController:alertController animated:true completion:nil]; +} + +// We need to delay the result to let pending animations (ie. dismissal of UIAlertController) to complete ++ (void)delayResult:(OSWebOpenURLResultBlock)finishBlock shouldOpen:(BOOL)shouldOpen { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + finishBlock(shouldOpen); + }); +} + +-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { + let index = (int)buttonIndex; + [OneSignalWebOpenDialog delayResult:self.resultBlock shouldOpen:index == 1]; +} + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalWebView.m b/iOS_SDK/OneSignalSDK/Source/OneSignalWebView.m index 65d6d4d41..fba47d470 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalWebView.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalWebView.m @@ -100,6 +100,16 @@ -(void)pinSubviewToMarginsWithSubview:(UIView *)subview withSuperview:(UIView *) [superview layoutIfNeeded]; } +- (UIViewController*) topMostController +{ + UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController; + + while (topController.presentedViewController) { + topController = topController.presentedViewController; + } + + return topController; +} -(void)showInApp { // if already presented, no need to present again diff --git a/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m b/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m index 0c4fdb3ba..ed0cc6b32 100644 --- a/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/UNUserNotificationCenter+OneSignal.m @@ -239,52 +239,17 @@ + (void)callLegacyAppDeletegateSelector:(UNNotification *)notification UIApplication *sharedApp = [UIApplication sharedApplication]; - // trigger is nil when UIApplication.presentLocalNotificationNow: is used. - // However it will be UNLegacyNotificationTrigger when UIApplication.scheduleLocalNotification: is used - BOOL isLegacyLocalNotif = !notification.request.trigger || [notification.request.trigger isKindOfClass:NSClassFromString(@"UNLegacyNotificationTrigger")]; + /* + The iOS SDK used to call some local notification selectors (such as didReceiveLocalNotification) + as a convenience but has stopped due to concerns about private API usage + the SDK will now print warnings when a developer's app implements these selectors + */ BOOL isCustomAction = actionIdentifier && ![@"com.apple.UNNotificationDefaultActionIdentifier" isEqualToString:actionIdentifier]; BOOL isRemote = [notification.request.trigger isKindOfClass:NSClassFromString(@"UNPushNotificationTrigger")]; - if (isLegacyLocalNotif) { - UILocalNotification *localNotif = [NSClassFromString(@"UIConcreteLocalNotification") alloc]; - localNotif.alertBody = notification.request.content.body; - localNotif.alertTitle = notification.request.content.title; - localNotif.applicationIconBadgeNumber = [notification.request.content.badge integerValue]; - NSString* soundName = [notification.request.content.sound valueForKey:@"_toneFileName"]; - if (!soundName) - soundName = @"UILocalNotificationDefaultSoundName"; - localNotif.soundName = soundName; - localNotif.alertLaunchImage = notification.request.content.launchImageName; - localNotif.userInfo = notification.request.content.userInfo; - localNotif.category = notification.request.content.categoryIdentifier; - localNotif.hasAction = true; // Defaults to true, UNLocalNotification doesn't seem to have a flag for this. - localNotif.fireDate = notification.date; - localNotif.timeZone = [notification.request.trigger valueForKey:@"_timeZone"]; - localNotif.repeatInterval = (NSCalendarUnit)[notification.request.trigger valueForKey:@"_repeatInterval"]; - localNotif.repeatCalendar = [notification.request.trigger valueForKey:@"_repeatCalendar"]; - // localNotif.region = - // localNotif.regionTriggersOnce = - - if (isTextReply && - [sharedApp.delegate respondsToSelector:@selector(application:handleActionWithIdentifier:forLocalNotification:withResponseInfo:completionHandler:)]) { - NSDictionary* dict = @{UIUserNotificationActionResponseTypedTextKey: userText}; - [sharedApp.delegate application:sharedApp handleActionWithIdentifier:actionIdentifier forLocalNotification:localNotif withResponseInfo:dict completionHandler:^() { - completionHandler(); - }]; - } - else if (isCustomAction && - [sharedApp.delegate respondsToSelector:@selector(application:handleActionWithIdentifier:forLocalNotification:completionHandler:)]) - [sharedApp.delegate application:sharedApp handleActionWithIdentifier:actionIdentifier forLocalNotification:localNotif completionHandler:^() { - completionHandler(); - }]; - else if ([sharedApp.delegate respondsToSelector:@selector(application:didReceiveLocalNotification:)]) { - [sharedApp.delegate application:sharedApp didReceiveLocalNotification:localNotif]; - completionHandler(); - } - else - completionHandler(); - } - else if (isRemote) { + + + if (isRemote) { NSDictionary* remoteUserInfo = notification.request.content.userInfo; if (isTextReply && diff --git a/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m b/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m index 6522feef4..f7558a6c3 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m @@ -496,4 +496,32 @@ - (void)testRegistration { [OneSignalClientOverrider reset:self]; } +-(void)testEmailSubscriptionDescription { + [UnitTestCommonMethods runBackgroundThreads]; + + let observer = [OSEmailSubscriptionStateTestObserver new]; + [OneSignal addEmailSubscriptionObserver:observer]; + + [self setupEmailTest]; + + let expectation = [self expectationWithDescription:@"email"]; + expectation.expectedFulfillmentCount = 1; + + [OneSignal setEmail:@"test@test.com" withSuccess:^{ + [expectation fulfill]; + } withFailure:^(NSError *error) { + XCTFail(@"Failed with error: %@", error); + }]; + + [self waitForExpectations:@[expectation] timeout:0.1]; + + [UnitTestCommonMethods runBackgroundThreads]; + + XCTAssertTrue([observer->last.to.description isEqualToString: @""]); + XCTAssertTrue([observer->last.from.description isEqualToString:@""]); + XCTAssertTrue([observer->last.description isEqualToString:@",\nto: \n>"]); + + [OneSignalClientOverrider reset:self]; +} + @end