Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fullbleed In App Messages #1018

Merged
merged 8 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion iOS_SDK/OneSignalSDK/Source/OSInAppMessageView.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ NS_ASSUME_NONNULL_BEGIN

- (instancetype _Nonnull)initWithMessage:(OSInAppMessageInternal *)inAppMessage withScriptMessageHandler:(id<WKScriptMessageHandler>)messageHandler;
- (void)resetWebViewToMaxBoundsAndResizeHeight:(void (^) (NSNumber *newHeight)) completion;
- (void)updateSafeAreaInsets;
- (void)setupWebViewConstraints;
- (void)loadReplacementURL:(NSURL *)url;
- (void)loadedHtmlContent:(NSString *)html withBaseURL:(NSURL *)url;
- (void)removeScriptMessageHandler;

- (void)setIsFullscreen:(BOOL)isFullscreen;
@end

NS_ASSUME_NONNULL_END
56 changes: 43 additions & 13 deletions iOS_SDK/OneSignalSDK/Source/OSInAppMessageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ @interface OSInAppMessageView () <UIScrollViewDelegate, WKUIDelegate, WKNavigati
@property (strong, nonatomic, nonnull) OSInAppMessageInternal *message;
@property (strong, nonatomic, nonnull) WKWebView *webView;
@property (nonatomic) BOOL loaded;

@property (nonatomic) BOOL isFullscreen;
@end


Expand Down Expand Up @@ -89,13 +89,10 @@ - (NSString *)addTagsToHTML:(NSString *)html {

- (void)loadedHtmlContent:(NSString *)html withBaseURL:(NSURL *)url {
// UI Update must be done on the main thread
NSLog(@"11111 [self.webView loadHTMLString:html baseURL:url];");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"222222 [self.webView loadHTMLString:html baseURL:url];");
NSString *taggedHTML = [self addTagsToHTML:html];
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"loadedHtmlContent with Tags: \n%@", taggedHTML]];
[self.webView loadHTMLString:taggedHTML baseURL:url];
});
NSString *taggedHTML = [self addTagsToHTML:html];
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"loadedHtmlContent with Tags: \n%@", taggedHTML]];
[self.webView loadHTMLString:taggedHTML baseURL:url];

}

- (void)setupWebviewWithMessageHandler:(id<WKScriptMessageHandler>)handler {
Expand All @@ -118,6 +115,20 @@ - (void)setupWebviewWithMessageHandler:(id<WKScriptMessageHandler>)handler {
[self layoutIfNeeded];
}

- (void)setIsFullscreen:(BOOL)isFullscreen {
_isFullscreen = isFullscreen;
[self setWebviewFrame];
}

- (void)setWebviewFrame {
CGRect mainBounds = UIScreen.mainScreen.bounds;
if (!self.isFullscreen) {
CGFloat marginSpacing = [OneSignalViewHelper sizeToScale:MESSAGE_MARGIN];
mainBounds.size.width -= (2.0 * marginSpacing);
}
[self.webView setFrame:mainBounds];
}

/*
Method for resetting the height of the WebView so the JS can calculate the new height
WebView will have margins accounted for on width, but height just needs to be phone height or larger
Expand All @@ -126,11 +137,8 @@ - (void)setupWebviewWithMessageHandler:(id<WKScriptMessageHandler>)handler {
- (void)resetWebViewToMaxBoundsAndResizeHeight:(void (^) (NSNumber *newHeight)) completion {
[self.webView removeConstraints:[self.webView constraints]];

CGFloat marginSpacing = [OneSignalViewHelper sizeToScale:MESSAGE_MARGIN];
CGRect mainBounds = UIScreen.mainScreen.bounds;
mainBounds.size.width -= (2.0 * marginSpacing);

[self.webView setFrame:mainBounds];

[self setWebviewFrame];
[self.webView layoutIfNeeded];

// Evaluate JS getPageMetaData() method to obtain the updated height for the messageView to contain the webView contents
Expand All @@ -151,6 +159,28 @@ - (void)resetWebViewToMaxBoundsAndResizeHeight:(void (^) (NSNumber *newHeight))
}];
}

- (void)updateSafeAreaInsets {
if (@available(iOS 11, *)) {
UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
CGFloat top = keyWindow.safeAreaInsets.top;
CGFloat bottom = keyWindow.safeAreaInsets.bottom;
CGFloat right = keyWindow.safeAreaInsets.right;
CGFloat left = keyWindow.safeAreaInsets.left;
NSString *safeAreaInsetsObjectString = [NSString stringWithFormat:OS_JS_SAFE_AREA_INSETS_OBJ,top, bottom, right, left];

NSString *setInsetsString = [NSString stringWithFormat:OS_SET_SAFE_AREA_INSETS_METHOD, safeAreaInsetsObjectString];
[self.webView evaluateJavaScript:setInsetsString completionHandler:^(NSDictionary *result, NSError * _Nullable error) {
if (error) {
NSString *errorMessage = [NSString stringWithFormat:@"Javascript Method: %@ Evaluated with Error: %@", OS_SET_SAFE_AREA_INSETS_METHOD, error];
[OneSignal onesignal_Log:ONE_S_LL_ERROR message:errorMessage];
return;
}
NSString *successMessage = [NSString stringWithFormat:@"Javascript Method: %@ Evaluated with Success: %@", OS_SET_SAFE_AREA_INSETS_METHOD, result];
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:successMessage];
}];
}
}

- (NSNumber *)extractHeightFromMetaDataPayload:(NSDictionary *)result {
return @([result[@"rect"][@"height"] intValue]);
}
Expand Down
128 changes: 100 additions & 28 deletions iOS_SDK/OneSignalSDK/Source/OSInAppMessageViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ @interface OSInAppMessageViewController ()

@property (nonatomic) BOOL useWidthMargin;

@property (nonatomic) BOOL isFullscreen;

@end

@implementation OSInAppMessageViewController
Expand Down Expand Up @@ -225,25 +227,27 @@ - (void)maxDisplayTimeTimerFinished {

- (OSResultSuccessBlock)messageContentOnSuccess {
return ^(NSDictionary *data) {
if (!data) {
[self encounteredErrorLoadingMessageContent:nil];
return;
}

let message = [NSString stringWithFormat:@"In App Messaging htmlContent.html: %@", data[@"html"]];
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:message];

if (!self.message.isPreview)
[[OneSignal sessionManager] onInAppMessageReceived:self.message.messageId];
[OneSignalHelper dispatch_async_on_main_queue:^{
if (!data) {
[self encounteredErrorLoadingMessageContent:nil];
return;
}

let message = [NSString stringWithFormat:@"In App Messaging htmlContent.html: %@", data[@"html"]];
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:message];

if (!self.message.isPreview)
[[OneSignal sessionManager] onInAppMessageReceived:self.message.messageId];

let baseUrl = [NSURL URLWithString:OS_IAM_WEBVIEW_BASE_URL];
[self parseContentData:data];
if (self.waitForTags) {
return;
}
[self.delegate messageWillDisplay:self.message];
[self.messageView loadedHtmlContent:self.pendingHTMLContent withBaseURL:baseUrl];
self.pendingHTMLContent = nil;
let baseUrl = [NSURL URLWithString:OS_IAM_WEBVIEW_BASE_URL];
[self parseContentData:data];
if (self.waitForTags) {
return;
}
[self.delegate messageWillDisplay:self.message];
[self.messageView loadedHtmlContent:self.pendingHTMLContent withBaseURL:baseUrl];
self.pendingHTMLContent = nil;
}];
};
}

Expand All @@ -261,6 +265,32 @@ - (void)parseContentData:(NSDictionary *)data {
self.useWidthMargin = ![styles[@"remove_width_margin"] boolValue];
}
}
self.isFullscreen = !self.useHeightMargin;
if (self.isFullscreen) {
self.pendingHTMLContent = [self setContentInsetsInHTML:self.pendingHTMLContent];
}
[self.messageView setIsFullscreen:self.isFullscreen];
}

- (NSString *)setContentInsetsInHTML:(NSString *)html {
NSMutableString *newHTML = [[NSMutableString alloc] initWithString:html];
if (@available(iOS 11, *)) {
UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
if (!keyWindow) {
return newHTML;
}
CGFloat top = keyWindow.safeAreaInsets.top;
CGFloat bottom = keyWindow.safeAreaInsets.bottom;
CGFloat right = keyWindow.safeAreaInsets.right;
CGFloat left = keyWindow.safeAreaInsets.left;
NSString *safeAreaInsetsObjectString = [NSString stringWithFormat:OS_JS_SAFE_AREA_INSETS_OBJ,top, bottom, right, left];
NSString *insetsString = [NSString stringWithFormat:@"\n\n\
<script> \
setSafeAreaInsets(%@);\
</script>",safeAreaInsetsObjectString];
[newHTML appendString: insetsString];
}
return newHTML;
}

- (void)setWaitForTags:(BOOL)waitForTags {
Expand Down Expand Up @@ -318,13 +348,15 @@ - (void)addConstraintsForMessage {
// as a notch or a rounded corner on newer iOS devices like iPhone X
// Note that Safe Area layout guides were only introduced in iOS 11
if (@available(iOS 11, *)) {
let safeArea = self.view.safeAreaLayoutGuide;
top = safeArea.topAnchor;
bottom = safeArea.bottomAnchor;
leading = safeArea.leadingAnchor;
trailing = safeArea.trailingAnchor;
center = safeArea.centerXAnchor;
height = safeArea.heightAnchor;
if (!self.isFullscreen) {
let safeArea = self.view.safeAreaLayoutGuide;
top = safeArea.topAnchor;
bottom = safeArea.bottomAnchor;
leading = safeArea.leadingAnchor;
trailing = safeArea.trailingAnchor;
center = safeArea.centerXAnchor;
height = safeArea.heightAnchor;
}
}

CGRect mainBounds = [OneSignalViewHelper getScreenBounds];
Expand Down Expand Up @@ -400,8 +432,10 @@ - (void)addConstraintsForMessage {
self.view.window.frame = mainBounds;
NSLayoutAnchor *centerYanchor = self.view.centerYAnchor;
if (@available(iOS 11, *)) {
let safeArea = self.view.safeAreaLayoutGuide;
centerYanchor = safeArea.centerYAnchor;
if (!self.isFullscreen) {
let safeArea = self.view.safeAreaLayoutGuide;
centerYanchor = safeArea.centerYAnchor;
}
}

self.initialYConstraint = [self.messageView.centerYAnchor constraintEqualToAnchor:centerYanchor constant:0.0f];
Expand Down Expand Up @@ -699,8 +733,12 @@ - (void)jsEventOccurredWithBody:(NSData *)body {
break;
}
case OSInAppMessageBridgeEventTypePageResize: {
// Unused resize event for IAM during actions like orientation changes and displaying an IAM
// resize event for IAM during actions like orientation changes and displaying an IAM
// Currently used for fullscreen IAMs to account for safe area changes
// self.message.height = event.resize.height;
if (self.isFullscreen) {
[self.messageView updateSafeAreaInsets];
}
break;
}
case OSInAppMessageBridgeEventTypeActionTaken: {
Expand All @@ -722,6 +760,40 @@ - (void)jsEventOccurredWithBody:(NSData *)body {
}
}

/*
Unity overrides orientation behavior and enables all orientations in supportedInterfaceOrientations, regardless of
the values set in the info.plist. It then uses its own internal logic for restricting the Application's views to
the selected orientations. This view controller inherits the behavior of all orientations being allowed so we need
to manually set the supported orientations based on the values in the plist.
If no values are selected for the orientation key in the plist then we will default to super's behavior.
*/
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
NSUInteger orientationMask = 0;
NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
if (!supportedOrientations) {
return [super supportedInterfaceOrientations];
}

if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeLeft"]) {
orientationMask += UIInterfaceOrientationMaskLandscapeLeft;
}

if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeRight"]) {
orientationMask += UIInterfaceOrientationMaskLandscapeRight;
}

if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"]) {
orientationMask += UIInterfaceOrientationMaskPortrait;
}

if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortraitUpsideDown"]) {
orientationMask += UIInterfaceOrientationMaskPortraitUpsideDown;
}

return orientationMask;

}

/*
Override method for handling orientation change within a view controller on iOS 8 or higher
This specifically handles the resizing and reanimation of a currently showing IAM
Expand Down
8 changes: 8 additions & 0 deletions iOS_SDK/OneSignalSDK/Source/OSInAppMessagingDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,16 @@ typedef NS_ENUM(NSUInteger, OSTriggerOperatorType) {
// Verify that a string is a valid dynamic trigger
#define OS_IS_TRIGGER_PROPERTY(kind) [OS_TRIGGER_PROPERTY_STRINGS containsObject:property]

// Javascript object
#define OS_JS_SAFE_AREA_INSETS_OBJ @"{\n\
top: %f,\n\
bottom: %f,\n\
right: %f,\n\
left: %f,\n\
}"
// JavaScript method names
#define OS_JS_GET_PAGE_META_DATA_METHOD @"getPageMetaData()"
#define OS_SET_SAFE_AREA_INSETS_METHOD @"setSafeAreaInsets(%@)"

#define PREFERRED_VARIANT_ORDER @[@"ios", @"app", @"all"]

Expand Down