Skip to content

Commit e502609

Browse files
authored
Merge pull request #887 from OneSignal/feature/iam_liquid_templating_support
IAM liquid templating support
2 parents 4506192 + 2f3442b commit e502609

16 files changed

+329
-33
lines changed

iOS_SDK/OneSignalDevApp/OneSignalDevApp/AppDelegate.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
8181
[OneSignal setProvidesNotificationSettingsView:NO];
8282
[OneSignal setAppId:[AppDelegate getOneSignalAppId]];
8383
[OneSignal initWithLaunchOptions:launchOptions];
84-
8584
[OneSignal addPermissionObserver:self];
8685
[OneSignal addSubscriptionObserver:self];
8786
[OneSignal addEmailSubscriptionObserver:self];

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@
466466
DE9877332591656200DE07D5 /* NSDateFormatter+OneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = DE98772A2591655800DE07D5 /* NSDateFormatter+OneSignal.m */; };
467467
DE9877342591656300DE07D5 /* NSDateFormatter+OneSignal.m in Sources */ = {isa = PBXBuildFile; fileRef = DE98772A2591655800DE07D5 /* NSDateFormatter+OneSignal.m */; };
468468
DE98773C2591656A00DE07D5 /* NSDateFormatter+OneSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = DE9877292591654600DE07D5 /* NSDateFormatter+OneSignal.h */; };
469+
DE9A5DAA25D1FD6B00FCEC21 /* OSPlayerTags.h in Headers */ = {isa = PBXBuildFile; fileRef = DE9A5DA925D1FD6B00FCEC21 /* OSPlayerTags.h */; };
470+
DE9A5DB325D1FD8000FCEC21 /* OSPlayerTags.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9A5DB225D1FD8000FCEC21 /* OSPlayerTags.m */; };
471+
DE9A5DB425D1FD8000FCEC21 /* OSPlayerTags.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9A5DB225D1FD8000FCEC21 /* OSPlayerTags.m */; };
472+
DE9A5DB525D1FD8000FCEC21 /* OSPlayerTags.m in Sources */ = {isa = PBXBuildFile; fileRef = DE9A5DB225D1FD8000FCEC21 /* OSPlayerTags.m */; };
469473
DEE8198D24E21DF000868CBA /* UIApplication+OneSignal.h in Headers */ = {isa = PBXBuildFile; fileRef = DE20425C24E21C1500350E4F /* UIApplication+OneSignal.h */; };
470474
DEF5CCF52539321A0003E9CC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEF5CCF42539321A0003E9CC /* AppDelegate.m */; };
471475
DEF5CCFB2539321A0003E9CC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DEF5CCFA2539321A0003E9CC /* ViewController.m */; };
@@ -784,6 +788,8 @@
784788
DE5EFECB24D8DC0E0032632D /* OSInAppMessageViewControllerOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSInAppMessageViewControllerOverrider.h; sourceTree = "<group>"; };
785789
DE9877292591654600DE07D5 /* NSDateFormatter+OneSignal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDateFormatter+OneSignal.h"; sourceTree = "<group>"; };
786790
DE98772A2591655800DE07D5 /* NSDateFormatter+OneSignal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDateFormatter+OneSignal.m"; sourceTree = "<group>"; };
791+
DE9A5DA925D1FD6B00FCEC21 /* OSPlayerTags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSPlayerTags.h; sourceTree = "<group>"; };
792+
DE9A5DB225D1FD8000FCEC21 /* OSPlayerTags.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSPlayerTags.m; sourceTree = "<group>"; };
787793
DEF5CCF12539321A0003E9CC /* UnitTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UnitTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
788794
DEF5CCF32539321A0003E9CC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
789795
DEF5CCF42539321A0003E9CC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -1257,6 +1263,8 @@
12571263
7A93265025A8DD4300BBEC27 /* OSUserState.m */,
12581264
7A93266925AC985500BBEC27 /* OSLocationState.h */,
12591265
7A93267225AC986400BBEC27 /* OSLocationState.m */,
1266+
DE9A5DA925D1FD6B00FCEC21 /* OSPlayerTags.h */,
1267+
DE9A5DB225D1FD8000FCEC21 /* OSPlayerTags.m */,
12601268
);
12611269
name = State;
12621270
sourceTree = "<group>";
@@ -1464,6 +1472,7 @@
14641472
7A5E721B25A66E2900CB5605 /* OSUserStateEmailSynchronizer.h in Headers */,
14651473
7AF9865624452A8C00C36EAE /* OSInfluence.h in Headers */,
14661474
912412411E73342200E41FD7 /* UNUserNotificationCenter+OneSignal.h in Headers */,
1475+
DE9A5DAA25D1FD6B00FCEC21 /* OSPlayerTags.h in Headers */,
14671476
7AF98684244A32D900C36EAE /* OSOutcomeEventsV2Repository.h in Headers */,
14681477
CA8E18FC2193A1A5009DA223 /* NSTimerOverrider.h in Headers */,
14691478
91B6EA451E86555200B5CF01 /* OSObservable.h in Headers */,
@@ -1724,6 +1733,7 @@
17241733
DE98772B2591656200DE07D5 /* NSDateFormatter+OneSignal.m in Sources */,
17251734
7AD172382416D53B00A78B19 /* OSInAppMessageLocationPrompt.m in Sources */,
17261735
9124120E1E73342200E41FD7 /* OneSignal.m in Sources */,
1736+
DE9A5DB325D1FD8000FCEC21 /* OSPlayerTags.m in Sources */,
17271737
CACBAA97218A6243000ACAA5 /* OSMessagingController.m in Sources */,
17281738
CA36F35921C33A2500300C77 /* OSInAppMessageController.m in Sources */,
17291739
CA08FC731FE99AFD004C445F /* OneSignalClient.m in Sources */,
@@ -1824,6 +1834,7 @@
18241834
DE9877332591656200DE07D5 /* NSDateFormatter+OneSignal.m in Sources */,
18251835
7AD172392416D53B00A78B19 /* OSInAppMessageLocationPrompt.m in Sources */,
18261836
CACBAA98218A6243000ACAA5 /* OSMessagingController.m in Sources */,
1837+
DE9A5DB425D1FD8000FCEC21 /* OSPlayerTags.m in Sources */,
18271838
CA36F35A21C33A2500300C77 /* OSInAppMessageController.m in Sources */,
18281839
CA08FC741FE99AFF004C445F /* OneSignalClient.m in Sources */,
18291840
91F58D861E7C88250017D24D /* OneSignalNotificationSettingsIOS9.m in Sources */,
@@ -2030,6 +2041,7 @@
20302041
7AAA606A2485D0420004FADE /* OSMigrationController.m in Sources */,
20312042
CACBAA9F218A6243000ACAA5 /* OSInAppMessageView.m in Sources */,
20322043
CA4742E7218B8FF30020DC8C /* OSTriggerController.m in Sources */,
2044+
DE9A5DB525D1FD8000FCEC21 /* OSPlayerTags.m in Sources */,
20332045
4529DEEA1FA8360C00CEAB1D /* UIApplicationOverrider.m in Sources */,
20342046
912412281E73342200E41FD7 /* OneSignalMobileProvision.m in Sources */,
20352047
7A93269E25AF4F0300BBEC27 /* OSPendingCallbacks.m in Sources */,

iOS_SDK/OneSignalSDK/Source/OSInAppMessage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
4949
@property (nonatomic) BOOL dragToDismissDisabled;
5050
@property (nonatomic) NSNumber *height;
5151
@property (nonatomic, nullable) NSDate *endTime;
52+
@property (nonatomic) BOOL hasLiquid;
5253

5354
- (BOOL)isBanner;
5455
- (BOOL)takeActionAsUnique;

iOS_SDK/OneSignalSDK/Source/OSInAppMessage.m

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ + (instancetype)instanceWithJson:(NSDictionary * _Nonnull)json {
110110
NSDate *endTime = [dateFormatter dateFromString:stringEndTime];
111111
message.endTime = endTime;
112112
}
113+
114+
if (json[@"has_liquid"]) {
115+
message.hasLiquid = YES;
116+
}
113117

114118
if (json[@"triggers"] && [json[@"triggers"] isKindOfClass:[NSArray class]]) {
115119
let triggers = [NSMutableArray new];
@@ -171,11 +175,15 @@ -(NSDictionary *)jsonRepresentation {
171175

172176
json[@"end_time"] = [[NSDateFormatter iso8601DateFormatter] stringFromDate:self.endTime];
173177

178+
if (self.hasLiquid) {
179+
json[@"has_liquid"] = @true;
180+
}
181+
174182
return json;
175183
}
176184

177185
- (NSString *)description {
178-
return [NSString stringWithFormat:@"OSInAppMessage: \nmessageId: %@ \ntriggers: %@ \ndisplayed_in_session: %@ \ndisplayStats: %@ \nendTime: %@", self.messageId, self.triggers, self.isDisplayedInSession ? @"YES" : @"NO", self.displayStats, self.endTime];
186+
return [NSString stringWithFormat:@"OSInAppMessage: \nmessageId: %@ \ntriggers: %@ \ndisplayed_in_session: %@ \ndisplayStats: %@ \nendTime: %@ \nhasLiquid: %@", self.messageId, self.triggers, self.isDisplayedInSession ? @"YES" : @"NO", self.displayStats, self.endTime, self.hasLiquid ? @"YES" : @"NO"];
179187
}
180188

181189
- (BOOL)isEqual:(id)object {
@@ -204,6 +212,7 @@ - (void)encodeWithCoder:(NSCoder *)encoder {
204212
//TODO: This will need to be changed when we add core data or database to iOS, see android implementation for reference
205213
[encoder encodeBool:_isDisplayedInSession forKey:@"displayed_in_session"];
206214
[encoder encodeObject:_endTime forKey:@"endTime"];
215+
[encoder encodeBool:_hasLiquid forKey:@"hasLiquid"];
207216
}
208217

209218
- (id)initWithCoder:(NSCoder *)decoder {
@@ -215,6 +224,7 @@ - (id)initWithCoder:(NSCoder *)decoder {
215224
//TODO: This will need to be changed when we add core data or database to iOS, see android implementation for reference
216225
_isDisplayedInSession = [decoder decodeBoolForKey:@"displayed_in_session"];
217226
_endTime = [decoder decodeObjectForKey:@"endTime"];
227+
_hasLiquid = [decoder decodeObjectForKey:@"hasLiquid"];
218228
}
219229
return self;
220230
}

iOS_SDK/OneSignalSDK/Source/OSInAppMessageView.m

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#import <WebKit/WebKit.h>
3131
#import "OSInAppMessageAction.h"
3232
#import "OneSignalViewHelper.h"
33+
#import "OSPlayerTags.h"
3334

3435

3536
@interface OSInAppMessageView () <UIScrollViewDelegate, WKUIDelegate, WKNavigationDelegate>
@@ -53,12 +54,45 @@ - (instancetype _Nonnull)initWithMessage:(OSInAppMessage *)inAppMessage withScri
5354
return self;
5455
}
5556

57+
- (NSString *)getTagsString {
58+
NSError *error;
59+
OSPlayerTags *tags = [OneSignal getPlayerTags];
60+
if (!tags.allTags) {
61+
return nil;
62+
}
63+
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tags.allTags
64+
options:NSJSONWritingPrettyPrinted
65+
error:&error];
66+
NSString *jsonString;
67+
if (!jsonData) {
68+
[OneSignal onesignalLog:ONE_S_LL_ERROR message:
69+
[NSString stringWithFormat:@"Error parsing tag dictionary to json :%@",error.localizedDescription]];
70+
} else {
71+
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
72+
}
73+
return jsonString;
74+
}
75+
76+
- (NSString *)addTagsToHTML:(NSString *)html {
77+
NSString *tags = [self getTagsString];
78+
if (!tags) {
79+
return html;
80+
}
81+
//Script to set the tags for liquid tag substitution
82+
NSString *newHtml = [NSString stringWithFormat:@"%@ \n\n\
83+
<script> \
84+
setPlayerTags(%@);\
85+
</script>",html, tags];
86+
return newHtml;
87+
}
88+
5689
- (void)loadedHtmlContent:(NSString *)html withBaseURL:(NSURL *)url {
5790
// UI Update must be done on the main thread
5891
NSLog(@"11111 [self.webView loadHTMLString:html baseURL:url];");
5992
dispatch_sync(dispatch_get_main_queue(), ^{
6093
NSLog(@"222222 [self.webView loadHTMLString:html baseURL:url];");
61-
[self.webView loadHTMLString:html baseURL:url];
94+
NSString *taggedHTML = [self addTagsToHTML:html];
95+
[self.webView loadHTMLString:taggedHTML baseURL:url];
6296
});
6397
}
6498

@@ -160,7 +194,6 @@ - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigat
160194
// WebView finished loading
161195
if (self.loaded)
162196
return;
163-
164197
self.loaded = true;
165198
}
166199

iOS_SDK/OneSignalSDK/Source/OSInAppMessageViewController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ NS_ASSUME_NONNULL_BEGIN
4848

4949
@property (weak, nonatomic, nullable) id<OSInAppMessageViewControllerDelegate> delegate;
5050
@property (strong, nonatomic, nonnull) OSInAppMessage *message;
51+
@property (nonatomic) BOOL waitForTags;
5152

5253
- (instancetype _Nonnull)initWithMessage:(OSInAppMessage *)inAppMessage delegate:(id<OSInAppMessageViewControllerDelegate>)delegate;
5354
- (void)dismissCurrentInAppMessage;

iOS_SDK/OneSignalSDK/Source/OSInAppMessageViewController.m

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ @interface OSInAppMessageViewController ()
9090
// This is a fail safe for cases where global contraints are nil and we try to modify them on dismissal of an IAM
9191
@property (nonatomic) BOOL didPageRenderingComplete;
9292

93+
// BOOL to track if the message content has loaded before tags have finished loading for liquid templating
94+
@property (nonatomic, nullable) NSString *pendingHTMLContent;
95+
9396
@end
9497

9598
@implementation OSInAppMessageViewController
@@ -229,13 +232,24 @@ - (OSResultSuccessBlock)messageContentOnSuccess {
229232
[[OneSignal sessionManager] onInAppMessageReceived:self.message.messageId];
230233

231234
let baseUrl = [NSURL URLWithString:OS_IAM_WEBVIEW_BASE_URL];
232-
NSString* htmlContent = data[@"html"];
233-
[self.messageView loadedHtmlContent:htmlContent withBaseURL:baseUrl];
234-
235+
self.pendingHTMLContent = data[@"html"];
235236
self.maxDisplayTime = [data[@"display_duration"] doubleValue];
237+
if (self.waitForTags) {
238+
return;
239+
}
240+
[self.messageView loadedHtmlContent:self.pendingHTMLContent withBaseURL:baseUrl];
241+
self.pendingHTMLContent = nil;
236242
};
237243
}
238244

245+
- (void)setWaitForTags:(BOOL)waitForTags {
246+
_waitForTags = waitForTags;
247+
if (!waitForTags && self.pendingHTMLContent) {
248+
[self.messageView loadedHtmlContent:self.pendingHTMLContent withBaseURL:[NSURL URLWithString:OS_IAM_WEBVIEW_BASE_URL]];
249+
self.pendingHTMLContent = nil;
250+
}
251+
}
252+
239253
- (void)loadMessageContent {
240254
[self.message loadMessageHTMLContentWithResult:[self messageContentOnSuccess] failure:^(NSError *error) {
241255
[self encounteredErrorLoadingMessageContent:error];

iOS_SDK/OneSignalSDK/Source/OSMessagingController.m

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ @interface OSMessagingController ()
8181

8282
@property (nonatomic) BOOL isAppInactive;
8383

84+
@property (nonatomic) BOOL calledLoadTags;
85+
8486
@end
8587

8688
@implementation OSMessagingController
@@ -171,6 +173,7 @@ - (void)updateInAppMessagesFromOnSession:(NSArray<OSInAppMessage *> *)newMessage
171173
if (self.messages)
172174
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_MESSAGES_ARRAY withValue:self.messages];
173175

176+
self.calledLoadTags = NO;
174177
[self resetRedisplayMessagesBySession];
175178
[self evaluateMessages];
176179
[self deleteOldRedisplayedInAppMessages];
@@ -277,13 +280,24 @@ - (void)displayMessage:(OSInAppMessage *)message {
277280

278281
- (void)showAndImpressMessage:(OSInAppMessage *)message {
279282
self.viewController = [[OSInAppMessageViewController alloc] initWithMessage:message delegate:self];
280-
283+
if (message.hasLiquid && !self.calledLoadTags) {
284+
self.viewController.waitForTags = YES;
285+
[self loadTags];
286+
}
281287
dispatch_async(dispatch_get_main_queue(), ^{
282288
[[self.viewController view] setNeedsLayout];
283289
[self messageViewImpressionRequest:message];
284290
});
285291
}
286292

293+
- (void)loadTags {
294+
self.calledLoadTags = YES;
295+
[OneSignal getTags:^(NSDictionary *result) {
296+
if (self.viewController) {
297+
self.viewController.waitForTags = NO;
298+
}
299+
}];
300+
}
287301
- (void)messageViewPageImpressionRequest:(OSInAppMessage *)message withPageId:(NSString *)pageId {
288302
if (message.isPreview) {
289303
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"Not sending page impression for preview message. ID: %@",pageId]];
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
Modified MIT License
3+
4+
Copyright 2021 OneSignal
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
1. The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
2. All copies of substantial portions of the Software may only be used in connection
17+
with services provided by OneSignal.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
*/
27+
28+
@interface OSPlayerTags : NSObject
29+
30+
@property (nonatomic, strong, nullable, readwrite) NSMutableDictionary *tagsToSend;
31+
32+
- (NSDictionary *) allTags;
33+
34+
- (void)setTags:(NSDictionary *)tags;
35+
36+
- (void)addTags:(NSDictionary *)tags;
37+
38+
- (void)addTagValue:(NSString *)value forKey:(NSString *)key;
39+
40+
- (void)deleteTags:(NSArray *)keys;
41+
42+
- (NSString *)tagValueForKey:(NSString *)key;
43+
44+
- (void)saveTagsToUserDefaults;
45+
46+
- (NSDictionary *_Nonnull)toDictionary;
47+
48+
@end

0 commit comments

Comments
 (0)