Open source FIAM headless SDK (#2312)

This commit is contained in:
christibbs authored and Paul Beusterien committed 2019-02-01 17:05:36 -08:00
1 parent a43709f18e
commit 3905bd250a
137 files changed
+15462

No files matched your search

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
#import "FIRIAMBookKeeper.h"
#import "FIRIAMMsgFetcherUsingRestful.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property(strong, nonatomic) UIWindow *window;
@property(strong, nonatomic) FIRIAMActivityLogger *activityLogger;
@property(nonatomic, nullable) FIRIAMBookKeeperViaUserDefaults *bookKeeper;
@property(nonatomic, nullable) FIRIAMMsgFetcherUsingRestful *restfulFetcher;
@property(nonatomic, copy) NSString *backendServer;
@property(nonatomic, copy) NSString *projectId;
@property(nonatomic, copy) NSString *apiKey;
@property(nonatomic) NSInteger displayIntervalInSeconds;
@property(nonatomic) NSInteger fetchIntervalInSeconds;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,118 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "AppDelegate.h"
#import "FIRIAMClearcutUploader.h"
#import "FIRIAMRuntimeManager.h"
#import "FIRInAppMessaging+Bootstrap.h"
#import "NSString+FIRInterlaceStrings.h"
#import <FirebaseCore/FirebaseCore.h>
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
@interface FIRInAppMessaging (Testing)
+ (void)disableAutoBootstrapWithFIRApp;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(@"application started");
[FIRInAppMessaging disableAutoBootstrapWithFIRApp];
[FIROptions defaultOptions].deepLinkURLScheme = @"fiam-testing";
[FIRApp configure];
FIRIAMSDKSettings *sdkSetting = [[FIRIAMSDKSettings alloc] init];
sdkSetting.apiServerHost = @"firebaseinappmessaging.googleapis.com";
NSString *serverHostNameFirstComponent = @"pa.ogepscm";
NSString *serverHostNameSecondComponent = @"lygolai.o";
sdkSetting.clearcutServerHost = [NSString fir_interlaceString:serverHostNameFirstComponent
withString:serverHostNameSecondComponent];
sdkSetting.apiHttpProtocol = @"https";
sdkSetting.fetchMinIntervalInMinutes = 0.1; // ok to refetch every 6 seconds
sdkSetting.loggerMaxCountBeforeReduce = 800;
sdkSetting.loggerSizeAfterReduce = 600;
sdkSetting.appFGRenderMinIntervalInMinutes = 0.1;
sdkSetting.loggerInVerboseMode = YES;
sdkSetting.conversionTrackingExpiresInSeconds = 180;
sdkSetting.firebaseAutoDataCollectionEnabled = NO;
sdkSetting.clearcutStrategy =
[[FIRIAMClearcutStrategy alloc] initWithMinWaitTimeInMills:5 * 1000 // 5 seconds
maxWaitTimeInMills:30 * 1000 // 30 seconds
failureBackoffTimeInMills:60 * 1000 // 60 seconds
batchSendSize:50];
[FIRInAppMessaging bootstrapIAMWithSettings:sdkSetting];
return YES;
}
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler {
NSLog(@"handle page url %@", userActivity.webpageURL);
BOOL handled = [[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) {
if (dynamicLink) {
NSLog(@"dynamic link recogized with url as %@", dynamicLink.url.absoluteString);
[self showDeepLink:dynamicLink.url.absoluteString forUrlType:@"universal link"];
} else {
NSLog(@"error happened %@", error);
}
}];
return handled;
}
- (void)showDeepLink:(NSString *)url forUrlType:(NSString *)urlType {
NSString *message = [NSString stringWithFormat:@"App wants to open a %@ : %@", urlType, url];
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:@"Deep link recognized"
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action){
}];
[alert addAction:defaultAction];
[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert
animated:YES
completion:nil];
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
return [self application:app openURL:url sourceApplication:@"source app" annotation:@{}];
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
NSLog(@"handle link with custom scheme: %@", url.absoluteString);
[self showDeepLink:url.absoluteString forUrlType:@"custom scheme url"];
return YES;
}
@end
@@ -0,0 +1,93 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
@interface AutoDisplayFlowViewController : UIViewController <UITextFieldDelegate>
@end
@@ -0,0 +1,170 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "AppDelegate.h"
#import "AutoDisplayFlowViewController.h"
#import "AutoDisplayMesagesTableVC.h"
#import "FIRIAMDisplayCheckOnAppForegroundFlow.h"
#import "FIRIAMMessageClientCache.h"
#import "FIRIAMMessageContentDataWithImageURL.h"
#import "FIRIAMMessageDefinition.h"
#import "FIRIAMActivityLogger.h"
#import "FIRIAMDisplayCheckOnAnalyticEventsFlow.h"
#import "FIRIAMFetchOnAppForegroundFlow.h"
#import "FIRIAMMessageClientCache.h"
#import "FIRIAMMsgFetcherUsingRestful.h"
#import "FIRIAMRuntimeManager.h"
#import "FIRInAppMessaging.h"
#import <FirebaseAnalytics/FIRAnalytics.h>
@interface AutoDisplayFlowViewController ()
@property(weak, nonatomic) IBOutlet UISwitch *autoDisplayFlowSwitch;
@property(nonatomic, weak) AutoDisplayMesagesTableVC *messageTableVC;
@property(weak, nonatomic) IBOutlet UITextField *autoDisplayIntervalText;
@property(weak, nonatomic) IBOutlet UITextField *autoFetchIntervalText;
@property(weak, nonatomic) IBOutlet UITextField *eventNameText;
@property(nonatomic) FIRIAMRuntimeManager *sdkRuntime;
@property(weak, nonatomic) IBOutlet UIButton *disableEnableSDKBtn;
@property(weak, nonatomic) IBOutlet UIButton *changeDataCollectionBtn;
@end
@implementation AutoDisplayFlowViewController
- (IBAction)clearClientStorage:(id)sender {
[self.sdkRuntime.fetchResultStorage
saveResponseDictionary:@{}
withCompletion:^(BOOL success) {
[self.sdkRuntime.messageCache
loadMessageDataFromServerFetchStorage:self.sdkRuntime.fetchResultStorage
withCompletion:^(BOOL success) {
NSLog(@"load from storage result is %d", success);
}];
}];
}
- (IBAction)disableEnableClicked:(id)sender {
FIRInAppMessaging *sdk = [FIRInAppMessaging inAppMessaging];
sdk.messageDisplaySuppressed = !sdk.messageDisplaySuppressed;
[self setupDisableEnableButtonLabel];
}
- (void)setupDisableEnableButtonLabel {
FIRInAppMessaging *sdk = [FIRInAppMessaging inAppMessaging];
NSString *title = sdk.messageDisplaySuppressed ? @"allow rendering" : @"disallow rendering";
[self.disableEnableSDKBtn setTitle:title forState:UIControlStateNormal];
}
- (IBAction)triggerAnalyticEventTapped:(id)sender {
NSLog(@"triggering an analytics event: %@", self.eventNameText.text);
[FIRAnalytics logEventWithName:self.eventNameText.text parameters:@{}];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (![touch.view isMemberOfClass:[UITextField class]]) {
[touch.view endEditing:YES];
}
}
- (IBAction)changeAutoDataCollection:(id)sender {
FIRInAppMessaging *sdk = [FIRInAppMessaging inAppMessaging];
sdk.automaticDataCollectionEnabled = !sdk.automaticDataCollectionEnabled;
[self setupChangeAutoDataCollectionButtonLabel];
}
- (void)setupChangeAutoDataCollectionButtonLabel {
FIRInAppMessaging *sdk = [FIRInAppMessaging inAppMessaging];
NSString *title = sdk.automaticDataCollectionEnabled ? @"disable data-col" : @"enable data-col";
[self.changeDataCollectionBtn setTitle:title forState:UIControlStateNormal];
}
- (void)viewDidLoad {
[super viewDidLoad];
double delayInSeconds = 2.0;
dispatch_time_t setupTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(setupTime, dispatch_get_main_queue(), ^(void) {
// code to be executed on the main queue after delay
self.sdkRuntime = [FIRIAMRuntimeManager getSDKRuntimeInstance];
self.messageTableVC.messageCache = self.sdkRuntime.messageCache;
[self.sdkRuntime.messageCache setDataObserver:self.messageTableVC];
[self.messageTableVC.tableView reloadData];
[self setupDisableEnableButtonLabel];
[self setupChangeAutoDataCollectionButtonLabel];
});
NSLog(@"done with set data observer");
self.autoFetchIntervalText.text = [[NSNumber
numberWithDouble:self.sdkRuntime.currentSetting.fetchMinIntervalInMinutes * 60] stringValue];
self.autoDisplayIntervalText.text =
[[NSNumber numberWithDouble:self.sdkRuntime.currentSetting.appFGRenderMinIntervalInMinutes *
60] stringValue];
}
- (IBAction)dumpImpressionsToConsole:(id)sender {
NSArray *impressions = [self.sdkRuntime.bookKeeper getImpressions];
NSLog(@"impressions are %@", [impressions componentsJoinedByString:@","]);
}
- (IBAction)clearImpressionRecord:(id)sender {
[self.sdkRuntime.bookKeeper cleanupImpressions];
}
- (IBAction)changeAutoFetchDisplaySettings:(id)sender {
FIRIAMSDKSettings *setting = self.sdkRuntime.currentSetting;
// set fetch interval
double intervalValue = self.autoFetchIntervalText.text.doubleValue / 60;
if (intervalValue < 0.0001) {
intervalValue = 1;
self.autoFetchIntervalText.text = [[NSNumber numberWithDouble:intervalValue * 60] stringValue];
}
setting.fetchMinIntervalInMinutes = intervalValue;
// set app foreground display interval
double displayIntervalValue = self.autoDisplayIntervalText.text.doubleValue / 60;
if (displayIntervalValue < 0.0001) {
displayIntervalValue = 1;
self.autoDisplayIntervalText.text =
[[NSNumber numberWithDouble:displayIntervalValue * 60] stringValue];
}
setting.appFGRenderMinIntervalInMinutes = displayIntervalValue;
[self.sdkRuntime startRuntimeWithSDKSettings:setting];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before
// navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:@"message-table-segue"]) {
self.messageTableVC = (AutoDisplayMesagesTableVC *)[segue destinationViewController];
}
}
@end
@@ -0,0 +1,23 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
#import "FIRIAMMessageClientCache.h"
@interface AutoDisplayMesagesTableVC : UITableViewController <FIRIAMCacheDataObserver>
@property(nonatomic) FIRIAMMessageClientCache *messageCache;
@end
@@ -0,0 +1,137 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "AutoDisplayMesagesTableVC.h"
#import "FIRIAMDisplayTriggerDefinition.h"
#import "FIRIAMMessageContentData.h"
@interface AutoDisplayMesagesTableVC ()
@end
@implementation AutoDisplayMesagesTableVC
- (void)dataChanged {
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view
// controller. self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray<FIRIAMMessageDefinition *> *messages = self.messageCache.allRegularMessages;
if (messages) {
return messages.count;
} else {
return 0;
}
}
static NSString *CellIdentifier = @"CellIdentifier";
- (NSString *)viewModeDisplayString:(FIRIAMRenderingMode)viewMode {
switch (viewMode) {
case FIRIAMRenderAsBannerView:
return @"Banner";
case FIRIAMRenderAsModalView:
return @"Modal";
case FIRIAMRenderAsImageOnlyView:
return @"Image";
default:
return @"Unknown";
}
}
- (NSString *)triggerDisplayString:(NSArray<FIRIAMDisplayTriggerDefinition *> *)triggers {
NSMutableString *s = [[NSMutableString alloc] init];
for (FIRIAMDisplayTriggerDefinition *trigger in triggers) {
[s appendString:[self triggerDisplayStringForOneTrigger:trigger]];
[s appendString:@","];
}
return [s copy];
}
- (NSString *)triggerDisplayStringForOneTrigger:
(FIRIAMDisplayTriggerDefinition *)triggerDefinition {
switch (triggerDefinition.triggerType) {
case FIRIAMRenderTriggerOnAppForeground:
return @"app_foreground";
case FIRIAMRenderTriggerOnFirebaseAnalyticsEvent:
return triggerDefinition.firebaseEventName;
default:
return @"Unknown";
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray<FIRIAMMessageDefinition *> *messageDefs = self.messageCache.allRegularMessages;
NSInteger rowIndex = [indexPath row];
if (messageDefs.count > rowIndex) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
UILabel *titleLabel = (UILabel *)[cell.contentView viewWithTag:10];
UILabel *modeLabel = (UILabel *)[cell.contentView viewWithTag:20];
UIImageView *imageView = (UIImageView *)[cell.contentView viewWithTag:30];
UILabel *triggerLabel = (UILabel *)[cell.contentView viewWithTag:40];
titleLabel.text = messageDefs[rowIndex].renderData.contentData.titleText;
modeLabel.text = [self
viewModeDisplayString:messageDefs[rowIndex].renderData.renderingEffectSettings.viewMode];
triggerLabel.text = [self triggerDisplayString:messageDefs[rowIndex].renderTriggers];
[messageDefs[rowIndex].renderData.contentData
loadImageDataWithBlock:^(NSData *_Nullable imageData, NSError *error) {
if (error) {
NSLog(@"error in loading image: %@", error.localizedDescription);
} else {
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
[imageView setImage:image];
});
}
}];
return cell;
} else {
return nil;
}
}
@end
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,395 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Ebq-cZ-Ywc">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Fetch & Display Flows-->
<scene sceneID="gh4-xG-6d0">
<objects>
<viewController id="pEd-Cp-eSk" customClass="AutoDisplayFlowViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="ApJ-fZ-bbG"/>
<viewControllerLayoutGuide type="bottom" id="fcu-KV-0co"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="27y-ro-ncL">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Nbf-aL-D4Q">
<rect key="frame" x="0.0" y="320.5" width="375" height="287.5"/>
<connections>
<segue destination="PsL-F0-NPD" kind="embed" identifier="message-table-segue" id="Ruf-dB-QUH"/>
</connections>
</containerView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Messages To Display" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2lf-ei-PaY">
<rect key="frame" x="0.0" y="292" width="375" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FB6-Ej-jmi">
<rect key="frame" x="0.0" y="235" width="375" height="2"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="2" id="xBA-ln-idE"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QzN-45-brV">
<rect key="frame" x="0.0" y="618" width="375" height="2"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="2" id="qn7-el-C36"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TWl-ic-ODQ">
<rect key="frame" x="14" y="247" width="138" height="30"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<state key="normal" title="Trigger analytics event"/>
<connections>
<action selector="triggerAnalyticEventTapped:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="IEI-K3-ihJ"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3kb-Du-qxH" userLabel="Top Half View">
<rect key="frame" x="0.0" y="40" width="375" height="190"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display every" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jOj-Sz-eSe">
<rect key="frame" x="8" y="8" width="81" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="60" borderStyle="roundedRect" textAlignment="right" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="tTK-0J-lFc">
<rect key="frame" x="109" y="1" width="112" height="30"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="secs when foreground" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yhR-Gb-Fis">
<rect key="frame" x="241" y="9" width="126" height="14"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Fetch every" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AYz-Nz-twr">
<rect key="frame" x="8" y="49.5" width="71" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="10" borderStyle="roundedRect" textAlignment="right" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="BDa-nI-3WI">
<rect key="frame" x="109" y="42.5" width="112" height="30"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="secs when foreground" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Cpz-Qh-H0O">
<rect key="frame" x="241" y="47" width="126" height="14.5"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZUt-bH-BSp">
<rect key="frame" x="10" y="90" width="355" height="28"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<state key="normal" title="Apply Displa/Fetch Frequency Change"/>
<connections>
<action selector="changeAutoFetchDisplaySettings:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="3BJ-aG-3AT"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="unO-PY-Ja6">
<rect key="frame" x="101" y="158" width="97" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<state key="normal" title="Clear Client Storage"/>
<connections>
<action selector="clearClientStorage:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="uVD-WV-FCT"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Erp-ss-RqT">
<rect key="frame" x="10" y="158" width="81" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<state key="normal" title="Clear Impression"/>
<connections>
<action selector="clearImpressionRecord:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="ngv-At-BDz"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nUy-hl-LzV">
<rect key="frame" x="213" y="158" width="59" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<state key="normal" title="disable SDK"/>
<connections>
<action selector="disableEnableClicked:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="zfv-0Y-GVj"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KCx-gs-cUi">
<rect key="frame" x="287" y="158" width="76" height="24"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<state key="normal" title="enable data-col"/>
<connections>
<action selector="changeAutoDataCollection:" destination="pEd-Cp-eSk" eventType="touchUpInside" id="SEG-zG-Uut"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="yhR-Gb-Fis" secondAttribute="trailing" constant="8" id="1Pc-Db-eGC"/>
<constraint firstAttribute="bottom" secondItem="Erp-ss-RqT" secondAttribute="bottom" constant="8" id="45D-eI-ubC"/>
<constraint firstItem="jOj-Sz-eSe" firstAttribute="top" secondItem="3kb-Du-qxH" secondAttribute="top" constant="8" id="5Rb-Vg-nFV"/>
<constraint firstItem="tTK-0J-lFc" firstAttribute="centerY" secondItem="jOj-Sz-eSe" secondAttribute="centerY" id="6Xt-sE-6yg"/>
<constraint firstAttribute="height" constant="190" id="9dh-YW-rHe"/>
<constraint firstItem="AYz-Nz-twr" firstAttribute="top" secondItem="jOj-Sz-eSe" secondAttribute="bottom" constant="25.333333333333336" id="ACy-rq-NPK"/>
<constraint firstItem="tTK-0J-lFc" firstAttribute="leading" secondItem="jOj-Sz-eSe" secondAttribute="trailing" constant="20" id="ASJ-KD-XHo"/>
<constraint firstItem="unO-PY-Ja6" firstAttribute="top" secondItem="Erp-ss-RqT" secondAttribute="top" id="BHu-hz-Qig"/>
<constraint firstItem="Cpz-Qh-H0O" firstAttribute="top" secondItem="yhR-Gb-Fis" secondAttribute="bottom" constant="24" id="GCe-bk-B7o"/>
<constraint firstItem="ZUt-bH-BSp" firstAttribute="leading" secondItem="3kb-Du-qxH" secondAttribute="leading" constant="10" id="I9g-Vp-i0f"/>
<constraint firstItem="unO-PY-Ja6" firstAttribute="leading" secondItem="Erp-ss-RqT" secondAttribute="trailing" constant="10" id="M8G-es-Oyi"/>
<constraint firstItem="KCx-gs-cUi" firstAttribute="bottom" secondItem="nUy-hl-LzV" secondAttribute="bottom" id="Mcg-A1-vnX"/>
<constraint firstItem="nUy-hl-LzV" firstAttribute="leading" secondItem="unO-PY-Ja6" secondAttribute="trailing" constant="15" id="NGu-z9-kRt"/>
<constraint firstItem="yhR-Gb-Fis" firstAttribute="leading" secondItem="tTK-0J-lFc" secondAttribute="trailing" constant="20" id="Omn-JV-LAt"/>
<constraint firstItem="ZUt-bH-BSp" firstAttribute="centerX" secondItem="3kb-Du-qxH" secondAttribute="centerX" id="PLW-kz-soN"/>
<constraint firstItem="BDa-nI-3WI" firstAttribute="trailing" secondItem="tTK-0J-lFc" secondAttribute="trailing" id="QJ9-2l-v5D"/>
<constraint firstItem="ZUt-bH-BSp" firstAttribute="top" secondItem="BDa-nI-3WI" secondAttribute="bottom" constant="17.333333333333329" id="U1i-HM-lr6"/>
<constraint firstItem="AYz-Nz-twr" firstAttribute="leading" secondItem="jOj-Sz-eSe" secondAttribute="leading" id="YCS-cl-bxb"/>
<constraint firstItem="BDa-nI-3WI" firstAttribute="leading" secondItem="tTK-0J-lFc" secondAttribute="leading" id="d1h-oK-ox0"/>
<constraint firstItem="nUy-hl-LzV" firstAttribute="bottom" secondItem="unO-PY-Ja6" secondAttribute="bottom" id="efd-OH-Yg9"/>
<constraint firstItem="Cpz-Qh-H0O" firstAttribute="leading" secondItem="yhR-Gb-Fis" secondAttribute="leading" id="fLI-os-Afm"/>
<constraint firstItem="yhR-Gb-Fis" firstAttribute="centerY" secondItem="jOj-Sz-eSe" secondAttribute="centerY" id="fYi-FN-QBR"/>
<constraint firstItem="KCx-gs-cUi" firstAttribute="leading" secondItem="nUy-hl-LzV" secondAttribute="trailing" constant="15" id="gCm-J5-RhN"/>
<constraint firstItem="KCx-gs-cUi" firstAttribute="top" secondItem="nUy-hl-LzV" secondAttribute="top" id="heU-7o-tI9"/>
<constraint firstItem="jOj-Sz-eSe" firstAttribute="leading" secondItem="3kb-Du-qxH" secondAttribute="leading" constant="8" id="muA-WB-8PQ"/>
<constraint firstItem="unO-PY-Ja6" firstAttribute="bottom" secondItem="Erp-ss-RqT" secondAttribute="bottom" id="ohr-CS-Xkc"/>
<constraint firstItem="BDa-nI-3WI" firstAttribute="baseline" secondItem="AYz-Nz-twr" secondAttribute="baseline" id="pwA-4B-T8t"/>
<constraint firstItem="Cpz-Qh-H0O" firstAttribute="trailing" secondItem="yhR-Gb-Fis" secondAttribute="trailing" id="tcc-gN-feq"/>
<constraint firstItem="nUy-hl-LzV" firstAttribute="top" secondItem="unO-PY-Ja6" secondAttribute="top" id="ujd-gw-I2g"/>
<constraint firstItem="Erp-ss-RqT" firstAttribute="leading" secondItem="3kb-Du-qxH" secondAttribute="leading" constant="10" id="yst-Bp-eIN"/>
</constraints>
</view>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="test_event" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="M0T-f0-qfn">
<rect key="frame" x="182" y="247" width="173" height="30"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<textInputTraits key="textInputTraits"/>
</textField>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="2lf-ei-PaY" firstAttribute="leading" secondItem="27y-ro-ncL" secondAttribute="leading" id="0g2-Zm-MAm"/>
<constraint firstItem="FB6-Ej-jmi" firstAttribute="top" secondItem="3kb-Du-qxH" secondAttribute="bottom" constant="5" id="19L-XJ-rNE"/>
<constraint firstAttribute="trailing" secondItem="2lf-ei-PaY" secondAttribute="trailing" id="2sG-IE-v1C"/>
<constraint firstAttribute="trailing" secondItem="Nbf-aL-D4Q" secondAttribute="trailing" id="3nJ-jP-296"/>
<constraint firstItem="M0T-f0-qfn" firstAttribute="bottom" secondItem="TWl-ic-ODQ" secondAttribute="bottom" id="68L-bx-rfi"/>
<constraint firstItem="QzN-45-brV" firstAttribute="leading" secondItem="Nbf-aL-D4Q" secondAttribute="leading" id="68c-cK-w0l"/>
<constraint firstItem="QzN-45-brV" firstAttribute="top" secondItem="Nbf-aL-D4Q" secondAttribute="bottom" constant="10" id="CCo-W9-Nwb"/>
<constraint firstItem="Nbf-aL-D4Q" firstAttribute="top" secondItem="2lf-ei-PaY" secondAttribute="bottom" constant="8" id="Cvc-tl-a8s"/>
<constraint firstItem="FB6-Ej-jmi" firstAttribute="leading" secondItem="27y-ro-ncL" secondAttribute="leading" id="E6W-9R-2GN"/>
<constraint firstItem="3kb-Du-qxH" firstAttribute="top" secondItem="ApJ-fZ-bbG" secondAttribute="bottom" constant="20" id="GnX-rq-jq9"/>
<constraint firstItem="Nbf-aL-D4Q" firstAttribute="height" relation="lessThanOrEqual" secondItem="27y-ro-ncL" secondAttribute="height" multiplier="1:2" id="HBN-Cy-dFb"/>
<constraint firstItem="3kb-Du-qxH" firstAttribute="leading" secondItem="27y-ro-ncL" secondAttribute="leading" id="MQn-1u-8Is"/>
<constraint firstItem="3kb-Du-qxH" firstAttribute="centerX" secondItem="27y-ro-ncL" secondAttribute="centerX" id="Um3-SX-kub"/>
<constraint firstItem="TWl-ic-ODQ" firstAttribute="top" secondItem="FB6-Ej-jmi" secondAttribute="bottom" constant="10" id="YYp-3Y-QXH"/>
<constraint firstItem="FB6-Ej-jmi" firstAttribute="width" secondItem="27y-ro-ncL" secondAttribute="width" id="aGR-qE-35f"/>
<constraint firstAttribute="trailing" secondItem="M0T-f0-qfn" secondAttribute="trailing" constant="20" id="cHW-QJ-D5z"/>
<constraint firstItem="M0T-f0-qfn" firstAttribute="top" secondItem="TWl-ic-ODQ" secondAttribute="top" id="hHq-ch-Cw9"/>
<constraint firstItem="fcu-KV-0co" firstAttribute="top" secondItem="Nbf-aL-D4Q" secondAttribute="bottom" constant="10" id="iF9-YE-7Bh"/>
<constraint firstItem="M0T-f0-qfn" firstAttribute="leading" secondItem="TWl-ic-ODQ" secondAttribute="trailing" constant="30" id="oK4-kd-ngD"/>
<constraint firstItem="QzN-45-brV" firstAttribute="trailing" secondItem="Nbf-aL-D4Q" secondAttribute="trailing" id="ore-FG-3Z5"/>
<constraint firstItem="Nbf-aL-D4Q" firstAttribute="leading" secondItem="27y-ro-ncL" secondAttribute="leading" id="rHM-kR-Ebu"/>
<constraint firstItem="2lf-ei-PaY" firstAttribute="top" secondItem="FB6-Ej-jmi" secondAttribute="bottom" constant="55" id="xhl-Hf-WDB"/>
<constraint firstItem="TWl-ic-ODQ" firstAttribute="leading" secondItem="27y-ro-ncL" secondAttribute="leading" constant="14" id="zTT-qI-tld"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Fetch &amp; Display Flows" id="Nzu-an-zJc"/>
<connections>
<outlet property="autoDisplayIntervalText" destination="BDa-nI-3WI" id="fEx-4O-aNP"/>
<outlet property="autoFetchIntervalText" destination="tTK-0J-lFc" id="TT2-Ib-Hrj"/>
<outlet property="changeDataCollectionBtn" destination="KCx-gs-cUi" id="MWc-Kk-IWX"/>
<outlet property="disableEnableSDKBtn" destination="nUy-hl-LzV" id="Sm9-9g-Uc5"/>
<outlet property="eventNameText" destination="M0T-f0-qfn" id="PJw-AR-bWa"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1YW-qT-fHJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="339.13043478260875" y="1420.108695652174"/>
</scene>
<!--Viewing Logs-->
<scene sceneID="1fw-sb-9xA">
<objects>
<viewController id="nu8-Ds-Fz1" customClass="LogDumpViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="NqW-PZ-fID"/>
<viewControllerLayoutGuide type="bottom" id="4QO-z6-XzH"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ap7-Ba-fBV">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sW6-Cb-xEh">
<rect key="frame" x="20" y="35" width="81" height="30"/>
<state key="normal" title="Activity Log"/>
<connections>
<action selector="dumActivityLogs:" destination="nu8-Ds-Fz1" eventType="touchUpInside" id="BiP-UR-aiJ"/>
</connections>
</button>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" text="Log Dump" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="DQB-Yw-yUi">
<rect key="frame" x="20" y="80" width="335" height="533"/>
<color key="backgroundColor" white="0.87141927083333337" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hv5-EM-k16">
<rect key="frame" x="231" y="35" width="128" height="30"/>
<state key="normal" title="Impression History"/>
<connections>
<action selector="dumpImpressList:" destination="nu8-Ds-Fz1" eventType="touchUpInside" id="EsS-CF-FWw"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="sW6-Cb-xEh" firstAttribute="top" secondItem="NqW-PZ-fID" secondAttribute="bottom" constant="15" id="6DA-FW-mAK"/>
<constraint firstItem="DQB-Yw-yUi" firstAttribute="leading" secondItem="Ap7-Ba-fBV" secondAttribute="leading" constant="20" id="6pK-1H-cXJ"/>
<constraint firstItem="DQB-Yw-yUi" firstAttribute="top" secondItem="sW6-Cb-xEh" secondAttribute="bottom" constant="15" id="CYj-rX-vKt"/>
<constraint firstItem="DQB-Yw-yUi" firstAttribute="centerX" secondItem="Ap7-Ba-fBV" secondAttribute="centerX" id="CrK-n8-1lJ"/>
<constraint firstItem="sW6-Cb-xEh" firstAttribute="leading" secondItem="Ap7-Ba-fBV" secondAttribute="leading" constant="20" id="MGr-yR-bM9"/>
<constraint firstAttribute="trailing" secondItem="hv5-EM-k16" secondAttribute="trailing" constant="16" id="e9u-Lp-lGv"/>
<constraint firstItem="hv5-EM-k16" firstAttribute="baseline" secondItem="sW6-Cb-xEh" secondAttribute="baseline" id="flZ-lL-e42"/>
<constraint firstItem="4QO-z6-XzH" firstAttribute="top" secondItem="DQB-Yw-yUi" secondAttribute="bottom" constant="5" id="wzo-UQ-a5y"/>
</constraints>
</view>
<tabBarItem key="tabBarItem" title="Viewing Logs" id="Nnn-zb-noK"/>
<connections>
<outlet property="logTextView" destination="DQB-Yw-yUi" id="sZI-WT-fU1"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="c3j-np-NcL" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="946" y="500"/>
</scene>
<!--Second View Controller-->
<scene sceneID="Egu-aw-S0d">
<objects>
<viewController storyboardIdentifier="DeepLinkingView" useStoryboardIdentifierAsRestorationIdentifier="YES" id="US6-BO-dB7" customClass="SecondViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="R8m-T3-Cez"/>
<viewControllerLayoutGuide type="bottom" id="H48-Lo-aod"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="tsX-ZM-a3w">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This is a deep linking view in app" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gFH-Ov-0hM">
<rect key="frame" x="26" y="154" width="323" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="gFH-Ov-0hM" firstAttribute="centerX" secondItem="tsX-ZM-a3w" secondAttribute="centerX" id="6Hp-4v-Lc3"/>
<constraint firstItem="gFH-Ov-0hM" firstAttribute="leading" secondItem="tsX-ZM-a3w" secondAttribute="leadingMargin" constant="10" id="Cbr-dN-cQW"/>
<constraint firstItem="gFH-Ov-0hM" firstAttribute="top" secondItem="R8m-T3-Cez" secondAttribute="bottom" constant="134" id="nSY-Lo-oRo"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="BpB-dL-xbj" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3412" y="105"/>
</scene>
<!--Tab Bar Controller-->
<scene sceneID="pSH-oS-ggK">
<objects>
<tabBarController automaticallyAdjustsScrollViewInsets="NO" id="Ebq-cZ-Ywc" sceneMemberID="viewController">
<toolbarItems/>
<tabBar key="tabBar" contentMode="scaleToFill" id="kvL-FD-WNk">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</tabBar>
<connections>
<segue destination="pEd-Cp-eSk" kind="relationship" relationship="viewControllers" id="Nhl-bm-Fwd"/>
<segue destination="nu8-Ds-Fz1" kind="relationship" relationship="viewControllers" id="Kp0-V8-Czg"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="euT-LS-VkP" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-562.31884057971024" y="635.86956521739137"/>
</scene>
<!--Auto Display Mesages TableVC-->
<scene sceneID="q5h-FN-tiy">
<objects>
<tableViewController id="PsL-F0-NPD" customClass="AutoDisplayMesagesTableVC" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="qfr-gm-4ZH">
<rect key="frame" x="0.0" y="0.0" width="375" height="287.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="CellIdentifier" id="Jfn-Cu-nDc">
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Jfn-Cu-nDc" id="6o7-w6-ur1">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" tag="10" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ALb-TI-LRG">
<rect key="frame" x="66" y="11" width="125" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" tag="20" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="View Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="POn-7q-Bn9">
<rect key="frame" x="201" y="11" width="54" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" tag="30" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dmd-Df-jYr">
<rect key="frame" x="18" y="11" width="40" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="yhC-Xm-Wds"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" tag="40" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Trigger" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9KB-qI-ugU">
<rect key="frame" x="274" y="11" width="34.5" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="10"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="dmd-Df-jYr" firstAttribute="top" secondItem="6o7-w6-ur1" secondAttribute="topMargin" id="BTx-fn-tUI"/>
<constraint firstItem="9KB-qI-ugU" firstAttribute="bottom" secondItem="POn-7q-Bn9" secondAttribute="bottom" id="C9X-1M-sek"/>
<constraint firstItem="POn-7q-Bn9" firstAttribute="leading" secondItem="ALb-TI-LRG" secondAttribute="trailing" constant="10" id="Gz1-LV-5dB"/>
<constraint firstItem="POn-7q-Bn9" firstAttribute="top" secondItem="ALb-TI-LRG" secondAttribute="top" id="Jpl-XU-mf0"/>
<constraint firstItem="ALb-TI-LRG" firstAttribute="bottom" secondItem="6o7-w6-ur1" secondAttribute="bottomMargin" id="Sae-8t-YEC"/>
<constraint firstItem="POn-7q-Bn9" firstAttribute="baseline" secondItem="ALb-TI-LRG" secondAttribute="baseline" id="a85-Dq-pk9"/>
<constraint firstItem="ALb-TI-LRG" firstAttribute="leading" secondItem="6o7-w6-ur1" secondAttribute="leadingMargin" constant="50" id="cq1-6S-hAq"/>
<constraint firstItem="9KB-qI-ugU" firstAttribute="top" secondItem="POn-7q-Bn9" secondAttribute="top" id="g5J-45-riG"/>
<constraint firstItem="9KB-qI-ugU" firstAttribute="leading" secondItem="POn-7q-Bn9" secondAttribute="trailing" constant="19" id="h40-zK-676"/>
<constraint firstItem="ALb-TI-LRG" firstAttribute="width" secondItem="6o7-w6-ur1" secondAttribute="width" multiplier="1:3" id="k8C-Hq-Hr8"/>
<constraint firstItem="dmd-Df-jYr" firstAttribute="leading" secondItem="6o7-w6-ur1" secondAttribute="leadingMargin" constant="2" id="tFb-dp-Hgn"/>
<constraint firstAttribute="bottomMargin" secondItem="dmd-Df-jYr" secondAttribute="bottom" id="uDf-gE-Bdv"/>
<constraint firstItem="ALb-TI-LRG" firstAttribute="top" secondItem="6o7-w6-ur1" secondAttribute="topMargin" id="uzM-1f-tdY"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="PsL-F0-NPD" id="8zu-HO-pQe"/>
<outlet property="delegate" destination="PsL-F0-NPD" id="P8Q-tt-CaF"/>
</connections>
</tableView>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="IcO-uK-bw0" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1369.5652173913045" y="1685.8695652173915"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>correct_api_key</string>
<key>TRACKING_ID</key>
<string>correct_tracking_id</string>
<key>CLIENT_ID</key>
<string>correct_client_id</string>
<key>REVERSED_CLIENT_ID</key>
<string>correct_reversed_client_id</string>
<key>GOOGLE_APP_ID</key>
<string>1:123:ios:123abc</string>
<key>GCM_SENDER_ID</key>
<string>correct_gcm_sender_id</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.google.FirebaseSDKTests</string>
<key>PROJECT_ID</key>
<string>abc-xyz-123</string>
<key>DATABASE_URL</key>
<string>https://abc-xyz-123.firebaseio.com</string>
<key>STORAGE_BUCKET</key>
<string>project-id-123.storage.firebase.com</string>
</dict>
</plist>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>FirebaseInAppMessagingAutomaticDataCollectionEnabled</key>
<true/>
<key>FirebaseAutomaticDataCollectionEnabled</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.3</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>mytesting</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fiam-testing</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.0.3-1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@@ -0,0 +1,21 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
@interface LogDumpViewController : UIViewController
@end
@@ -0,0 +1,73 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "LogDumpViewController.h"
#import "AppDelegate.h"
#import "FIRIAMRuntimeManager.h"
@interface LogDumpViewController ()
@property(weak, nonatomic) IBOutlet UITextView *logTextView;
@end
@implementation LogDumpViewController
- (IBAction)dumpImpressList:(id)sender {
NSArray *impressions = [[FIRIAMRuntimeManager getSDKRuntimeInstance].bookKeeper getImpressions];
NSString *text = [NSString stringWithFormat:@"Message Impression History are :\n%@",
[impressions componentsJoinedByString:@"\n"]];
self.logTextView.text = text;
}
- (IBAction)dumActivityLogs:(id)sender {
NSArray<FIRIAMActivityRecord *> *records =
[[FIRIAMRuntimeManager getSDKRuntimeInstance].activityLogger readRecords];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateStyle = NSDateFormatterShortStyle;
dateFormatter.timeStyle = NSDateFormatterMediumStyle;
static NSString *appBuildVersion = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
appBuildVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
});
NSMutableString *dumpContent = [[NSString
stringWithFormat:@"App Build Version -- %@\n\n"
"SDK Settings -- %@\n\n"
"Activity Logs: %lu records\n\n",
appBuildVersion, [FIRIAMRuntimeManager getSDKRuntimeInstance].currentSetting,
(unsigned long)records.count] mutableCopy];
for (FIRIAMActivityRecord *next in records) {
NSString *nextRecordLog = [NSString
stringWithFormat:@"%@, %@, %@, %@\n", [dateFormatter stringFromDate:next.timestamp],
[next displayStringForActivityType], next.success ? @"Success" : @"Failed",
next.detail];
[dumpContent appendString:nextRecordLog];
}
self.logTextView.text = dumpContent;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
@@ -0,0 +1,34 @@
use_frameworks!
target 'InAppMessaging_Example_iOS' do
platform :ios, '8.0'
pod 'FirebaseCommunity/InAppMessaging', :path => '../..'
# Lock to the 1.0.9 version of InstanceID since 1.0.10 added a dependency
# to FirebaseCore
# pod 'FirebaseInstanceID', '1.0.9'
#target 'InAppMessaging_Tests_iOS' do
# inherit! :search_paths
# pod 'FirebaseCommunity/InAppMessaging', :path => '../..'
# pod 'OCMock'
#end
end
#target 'InAppMessaging_Example_Swift_iOS' do
# platform :ios, '8.0'
# pod 'FirebaseCommunity/InAppMessaging', :path => '../'
# Lock to the 1.0.9 version of InstanceID since 1.0.10 added a dependency
# to FirebaseCore
# pod 'FirebaseInstanceID', '1.0.9'
#target 'Messaging_Tests_iOS' do
# inherit! :search_paths
# pod 'OCMock'
#end
#end
@@ -0,0 +1,24 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}