From b8147a77d726f6c75e0ef7efcf0b26f9d1c7b4b5 Mon Sep 17 00:00:00 2001 From: Louis Bur Date: Tue, 27 Sep 2022 16:09:14 -0400 Subject: [PATCH] Version 5.5.0 --- BrazeKit.podspec | 6 +- BrazeLocation.podspec | 8 +- BrazeNotificationService.podspec | 6 +- BrazePushStory.podspec | 6 +- BrazeUI.podspec | 6 +- CHANGELOG.md | 25 +- .../project.pbxproj | 1652 ++++++++++++++ .../contents.xcworkspacedata | 0 .../project.pbxproj | 1928 +++++++++++++++++ .../contents.xcworkspacedata | 0 Examples/{ => ObjC}/Package.swift | 0 Examples/{ => ObjC}/Podfile | 0 Examples/ObjC/Sources/Analytics/AppDelegate.h | 11 + Examples/ObjC/Sources/Analytics/AppDelegate.m | 35 + .../Sources/Analytics/AuthenticationManager.h | 23 + .../Sources/Analytics/AuthenticationManager.m | 22 + .../Analytics/CheckoutViewController.h | 17 + .../Analytics/CheckoutViewController.m | 34 + .../{ => ObjC}/Sources/Analytics/Info.plist | 0 Examples/ObjC/Sources/Analytics/Readme.m | 102 + .../AccentColor.colorset/Contents.json | 0 .../AppIcon.appiconset/Contents.json | 0 .../Common/Assets.xcassets/Contents.json | 0 Examples/ObjC/Sources/Common/Credentials.m | 7 + Examples/ObjC/Sources/Common/ReadmeAction.h | 9 + .../Sources/Common/ReadmeViewController.h | 9 + .../Sources/Common/ReadmeViewController.m | 142 ++ .../iOS/Base.lproj/LaunchScreen.storyboard | 0 Examples/ObjC/Sources/Common/main.m | 11 + .../tvOS/Base.lproj/LaunchScreen.storyboard | 0 .../ContentCards-Custom-UI/AppDelegate.h | 17 + .../ContentCards-Custom-UI/AppDelegate.m | 110 + .../CardsInfoViewController.h | 9 + .../CardsInfoViewController.m | 200 ++ .../Sources/ContentCards-Custom-UI/Info.plist | 0 .../Sources/ContentCards-Custom-UI/Readme.m | 75 + .../ObjC/Sources/ContentCards/AppDelegate.h | 15 + .../ObjC/Sources/ContentCards/AppDelegate.m | 101 + .../BRZGIFViewProvider+SDWebImage.h | 11 + .../BRZGIFViewProvider+SDWebImage.m | 40 + .../Sources/ContentCards/Info.plist | 0 Examples/ObjC/Sources/ContentCards/Readme.m | 55 + .../InAppMessages-Custom-UI/AppDelegate.h | 11 + .../InAppMessages-Custom-UI/AppDelegate.m | 43 + .../CustomInAppMessagePresenter.h | 6 + .../CustomInAppMessagePresenter.m | 46 + .../InAppMessageInfoViewController.h | 9 + .../InAppMessageInfoViewController.m | 282 +++ .../InAppMessages-Custom-UI/Info.plist | 0 .../Sources/InAppMessages-Custom-UI/Readme.m | 61 + .../ObjC/Sources/InAppMessages/AppDelegate.h | 11 + .../ObjC/Sources/InAppMessages/AppDelegate.m | 67 + .../BRZGIFViewProvider+SDWebImage.h | 11 + .../BRZGIFViewProvider+SDWebImage.m | 40 + .../Sources/InAppMessages/Info.plist | 0 Examples/ObjC/Sources/InAppMessages/Readme.m | 52 + Examples/ObjC/Sources/Location/AppDelegate.h | 11 + Examples/ObjC/Sources/Location/AppDelegate.m | 40 + .../{ => ObjC}/Sources/Location/Info.plist | 0 Examples/ObjC/Sources/Location/Readme.m | 69 + .../Sources/PushNotifications/AppDelegate.h | 13 + .../Sources/PushNotifications/AppDelegate.m | 114 + .../Sources/PushNotifications/Info.plist | 0 .../PushNotifications.entitlements | 0 .../ObjC/Sources/PushNotifications/Readme.m | 23 + .../Info.plist | 0 .../NotificationViewController.swift | 0 ...NotificationsContentExtension.entitlements | 0 .../Info.plist | 0 .../NotificationService.swift | 0 Examples/README.md | 13 +- .../project.pbxproj | 8 +- .../contents.xcworkspacedata | 7 + .../project.pbxproj | 10 +- .../contents.xcworkspacedata | 7 + Examples/Swift/Package.swift | 3 + Examples/Swift/Podfile | 78 + .../Sources/Analytics/AppDelegate.swift | 2 +- .../Analytics/AuthenticationManager.swift | 0 .../Analytics/CheckoutViewController.swift | 0 .../Sources/Analytics}/Info.plist | 2 +- .../Sources/Analytics/Readme.swift | 0 .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 98 + .../Common/Assets.xcassets/Contents.json | 6 + .../Sources/Common/Credentials.swift | 0 .../Sources/Common/ReadmeViewController.swift | 2 +- .../iOS/Base.lproj/LaunchScreen.storyboard | 25 + .../tvOS/Base.lproj/LaunchScreen.storyboard | 24 + .../ContentCards-Custom-UI/AppDelegate.swift | 66 +- .../CardsInfoViewController.swift | 17 +- .../ContentCards-Custom-UI}/Info.plist | 2 +- .../ContentCards-Custom-UI/Readme.swift | 12 +- .../Sources/ContentCards/AppDelegate.swift | 4 +- .../Swift/Sources/ContentCards/Info.plist | 26 + .../Sources/ContentCards/Readme.swift | 0 .../SDWebImageGIFViewProvider.swift | 0 .../InAppMessages-Custom-UI/AppDelegate.swift | 4 +- .../CustomInAppMessagePresenter.swift | 20 +- .../InAppMessages-Custom-UI/Extensions.swift | 8 +- .../InAppMessageInfoViewController.swift | 76 +- .../InAppMessages-Custom-UI/Info.plist | 26 + .../InAppMessages-Custom-UI/Readme.swift | 6 +- .../Sources/InAppMessages/AppDelegate.swift | 4 +- .../Swift/Sources/InAppMessages/Info.plist | 26 + .../Sources/InAppMessages/Readme.swift | 0 .../SDWebImageGIFViewProvider.swift | 0 .../Sources/Location/AppDelegate.swift | 2 +- Examples/Swift/Sources/Location/Info.plist | 30 + .../{ => Swift}/Sources/Location/Readme.swift | 0 .../PushNotifications/AppDelegate.swift | 2 +- .../Sources/PushNotifications/Info.plist | 30 + .../PushNotifications.entitlements | 12 + .../Sources/PushNotifications/Readme.swift | 0 .../Info.plist | 47 + .../NotificationViewController.swift | 3 + ...NotificationsContentExtension.entitlements | 10 + .../Info.plist | 31 + .../NotificationService.swift | 3 + Package.swift | 16 +- README.md | 30 +- Sources/BrazeUI/BrazeUIMocks.swift | 8 +- ...ontentCardUIModalViewController+ObjC.swift | 123 ++ .../ContentCardUIModalViewController.swift | 16 +- .../ContentCardUIViewController+ObjC.swift | 77 + .../ContentCardUIViewController.swift | 10 + ...entCardUIViewControllerDelegate+ObjC.swift | 66 + .../BrazeUI/Dependencies/AsyncImageView.swift | 6 +- .../Dependencies/GIFViewProvider+ObjC.swift | 85 + .../Dependencies/GIFViewProvider.swift | 18 +- Sources/BrazeUI/Deprecations.swift | 20 + .../InAppMessageUI/InAppMessageExt.swift | 5 - .../InAppMessageUI/InAppMessageMocks.swift | 50 +- .../InAppMessageUI/InAppMessageUI+ObjC.swift | 37 + .../InAppMessageUI/InAppMessageUI.swift | 40 +- .../InAppMessageUIDelegate+ObjC.swift | 236 ++ .../InAppMessageUI/InAppMessageUIError.swift | 14 +- .../Views/InAppMessageUIFullImageView.swift | 4 +- .../Views/InAppMessageUIFullView.swift | 4 +- .../Views/InAppMessageUIHtmlView.swift | 11 +- .../Views/InAppMessageUIModalImageView.swift | 6 +- .../Views/InAppMessageUIModalView.swift | 2 +- .../Views/InAppMessageUISlideupView.swift | 23 +- .../Views/InAppMessageView.swift | 2 +- .../InAppMessageUI/Views/Misc/IconView.swift | 4 +- 145 files changed, 7072 insertions(+), 205 deletions(-) create mode 100644 Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj rename Examples/{ => ObjC}/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) create mode 100644 Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj rename Examples/{ => ObjC}/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename Examples/{ => ObjC}/Package.swift (100%) rename Examples/{ => ObjC}/Podfile (100%) create mode 100644 Examples/ObjC/Sources/Analytics/AppDelegate.h create mode 100644 Examples/ObjC/Sources/Analytics/AppDelegate.m create mode 100644 Examples/ObjC/Sources/Analytics/AuthenticationManager.h create mode 100644 Examples/ObjC/Sources/Analytics/AuthenticationManager.m create mode 100644 Examples/ObjC/Sources/Analytics/CheckoutViewController.h create mode 100644 Examples/ObjC/Sources/Analytics/CheckoutViewController.m rename Examples/{ => ObjC}/Sources/Analytics/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/Analytics/Readme.m rename Examples/{ => ObjC}/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json (100%) rename Examples/{ => ObjC}/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename Examples/{ => ObjC}/Sources/Common/Assets.xcassets/Contents.json (100%) create mode 100644 Examples/ObjC/Sources/Common/Credentials.m create mode 100644 Examples/ObjC/Sources/Common/ReadmeAction.h create mode 100644 Examples/ObjC/Sources/Common/ReadmeViewController.h create mode 100644 Examples/ObjC/Sources/Common/ReadmeViewController.m rename Examples/{ => ObjC}/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard (100%) create mode 100644 Examples/ObjC/Sources/Common/main.m rename Examples/{ => ObjC}/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard (100%) create mode 100644 Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h create mode 100644 Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m create mode 100644 Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h create mode 100644 Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m rename Examples/{ => ObjC}/Sources/ContentCards-Custom-UI/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m create mode 100644 Examples/ObjC/Sources/ContentCards/AppDelegate.h create mode 100644 Examples/ObjC/Sources/ContentCards/AppDelegate.m create mode 100644 Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h create mode 100644 Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m rename Examples/{ => ObjC}/Sources/ContentCards/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/ContentCards/Readme.m create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m rename Examples/{ => ObjC}/Sources/InAppMessages-Custom-UI/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m create mode 100644 Examples/ObjC/Sources/InAppMessages/AppDelegate.h create mode 100644 Examples/ObjC/Sources/InAppMessages/AppDelegate.m create mode 100644 Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h create mode 100644 Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m rename Examples/{ => ObjC}/Sources/InAppMessages/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/InAppMessages/Readme.m create mode 100644 Examples/ObjC/Sources/Location/AppDelegate.h create mode 100644 Examples/ObjC/Sources/Location/AppDelegate.m rename Examples/{ => ObjC}/Sources/Location/Info.plist (100%) create mode 100644 Examples/ObjC/Sources/Location/Readme.m create mode 100644 Examples/ObjC/Sources/PushNotifications/AppDelegate.h create mode 100644 Examples/ObjC/Sources/PushNotifications/AppDelegate.m rename Examples/{ => ObjC}/Sources/PushNotifications/Info.plist (100%) rename Examples/{ => ObjC}/Sources/PushNotifications/PushNotifications.entitlements (100%) create mode 100644 Examples/ObjC/Sources/PushNotifications/Readme.m rename Examples/{ => ObjC}/Sources/PushNotificationsContentExtension/Info.plist (100%) rename Examples/{ => ObjC}/Sources/PushNotificationsContentExtension/NotificationViewController.swift (100%) rename Examples/{ => ObjC}/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements (100%) rename Examples/{ => ObjC}/Sources/PushNotificationsServiceExtension/Info.plist (100%) rename Examples/{ => ObjC}/Sources/PushNotificationsServiceExtension/NotificationService.swift (100%) rename Examples/{ => Swift}/Examples-CocoaPods.xcodeproj/project.pbxproj (99%) create mode 100644 Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename Examples/{ => Swift}/Examples-SwiftPM.xcodeproj/project.pbxproj (99%) create mode 100644 Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Examples/Swift/Package.swift create mode 100644 Examples/Swift/Podfile rename Examples/{ => Swift}/Sources/Analytics/AppDelegate.swift (89%) rename Examples/{ => Swift}/Sources/Analytics/AuthenticationManager.swift (100%) rename Examples/{ => Swift}/Sources/Analytics/CheckoutViewController.swift (100%) rename Examples/{Sources/ContentCards-In-House-UI => Swift/Sources/Analytics}/Info.plist (94%) rename Examples/{ => Swift}/Sources/Analytics/Readme.swift (100%) create mode 100644 Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Examples/Swift/Sources/Common/Assets.xcassets/Contents.json rename Examples/{ => Swift}/Sources/Common/Credentials.swift (100%) rename Examples/{ => Swift}/Sources/Common/ReadmeViewController.swift (98%) create mode 100644 Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard create mode 100644 Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard rename Examples/{ => Swift}/Sources/ContentCards-Custom-UI/AppDelegate.swift (57%) rename Examples/{ => Swift}/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift (93%) rename Examples/{Sources/InAppMessages-In-House-UI => Swift/Sources/ContentCards-Custom-UI}/Info.plist (94%) rename Examples/{ => Swift}/Sources/ContentCards-Custom-UI/Readme.swift (83%) rename Examples/{ => Swift}/Sources/ContentCards/AppDelegate.swift (96%) create mode 100644 Examples/Swift/Sources/ContentCards/Info.plist rename Examples/{ => Swift}/Sources/ContentCards/Readme.swift (100%) rename Examples/{ => Swift}/Sources/ContentCards/SDWebImageGIFViewProvider.swift (100%) rename Examples/{ => Swift}/Sources/InAppMessages-Custom-UI/AppDelegate.swift (83%) rename Examples/{ => Swift}/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift (69%) rename Examples/{ => Swift}/Sources/InAppMessages-Custom-UI/Extensions.swift (89%) rename Examples/{ => Swift}/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift (80%) create mode 100644 Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist rename Examples/{ => Swift}/Sources/InAppMessages-Custom-UI/Readme.swift (86%) rename Examples/{ => Swift}/Sources/InAppMessages/AppDelegate.swift (93%) create mode 100644 Examples/Swift/Sources/InAppMessages/Info.plist rename Examples/{ => Swift}/Sources/InAppMessages/Readme.swift (100%) rename Examples/{ => Swift}/Sources/InAppMessages/SDWebImageGIFViewProvider.swift (100%) rename Examples/{ => Swift}/Sources/Location/AppDelegate.swift (92%) create mode 100644 Examples/Swift/Sources/Location/Info.plist rename Examples/{ => Swift}/Sources/Location/Readme.swift (100%) rename Examples/{ => Swift}/Sources/PushNotifications/AppDelegate.swift (97%) create mode 100644 Examples/Swift/Sources/PushNotifications/Info.plist create mode 100644 Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements rename Examples/{ => Swift}/Sources/PushNotifications/Readme.swift (100%) create mode 100644 Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist create mode 100644 Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift create mode 100644 Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements create mode 100644 Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist create mode 100644 Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift create mode 100644 Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift create mode 100644 Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift create mode 100644 Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift create mode 100644 Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift create mode 100644 Sources/BrazeUI/Deprecations.swift create mode 100644 Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift create mode 100644 Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift diff --git a/BrazeKit.podspec b/BrazeKit.podspec index 851cda5a93..71b69adc2e 100644 --- a/BrazeKit.podspec +++ b/BrazeKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeKit' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Braze Main SDK library providing support for analytics and push notifications.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeKit-CocoaPods.zip', - :sha256 => '4228d1670c639b4139d6530d41c06e0ac670f0f4f6f517e836168aae007fbe42' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeKit-CocoaPods.zip', + :sha256 => '13e15c450429fa081c0745f51e8382030781c72d8f46657aa7a7af726d7713db' } s.swift_version = '5.0' diff --git a/BrazeLocation.podspec b/BrazeLocation.podspec index 5c17d9f4f4..d245c94126 100644 --- a/BrazeLocation.podspec +++ b/BrazeLocation.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeLocation' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Braze location library providing support for location analytics and geofence monitoring.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeLocation-CocoaPods.zip', - :sha256 => '26f732381af0031999ea19bb4386cfe999db4d467786f18449f075e82c55f6d6' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeLocation-CocoaPods.zip', + :sha256 => '3c7303f70658aa07ff8cff7442e9f1f64e2e5e09cdb826012090b07c291d6073' } s.swift_version = '5.0' @@ -21,5 +21,5 @@ Pod::Spec.new do |s| # Depends on BrazeKit because BrazeKit includes the internal _BrazeLocationClient symbols required # for linking against BrazeLocation. - s.dependency 'BrazeKit', '5.4.0' + s.dependency 'BrazeKit', '5.5.0' end diff --git a/BrazeNotificationService.podspec b/BrazeNotificationService.podspec index 15803f5a05..e2b8b59118 100644 --- a/BrazeNotificationService.podspec +++ b/BrazeNotificationService.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeNotificationService' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Braze notification service extension library providing support for Rich Push notifications.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeNotificationService-CocoaPods.zip', - :sha256 => '3ad4ccb1557c338f8a5018731aa6b543f523326cc54a055127a8c66d5ff212d4' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeNotificationService-CocoaPods.zip', + :sha256 => '47333461d0e12918222d755348158c496d9f296b9b5bf2e71b15d40b725ffcfb' } s.swift_version = '5.0' diff --git a/BrazePushStory.podspec b/BrazePushStory.podspec index 228f11c529..d6bcea2d24 100644 --- a/BrazePushStory.podspec +++ b/BrazePushStory.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazePushStory' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Braze notification content extension library providing support for Push Stories.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazePushStory-CocoaPods.zip', - :sha256 => '47d56c8a5a79e72d2a87744d8f3207ee3a09943f460cf7d11d4a12ff97df1cdd' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazePushStory-CocoaPods.zip', + :sha256 => '563764ac805374f75df403fa91c13b5611d8eb8aad4fde64dc385b3c0623f68c' } s.swift_version = '5.0' diff --git a/BrazeUI.podspec b/BrazeUI.podspec index 5e6d4e3b57..8860de85bc 100644 --- a/BrazeUI.podspec +++ b/BrazeUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeUI' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Braze-provided user interface library for In-App Messages.' s.homepage = 'https://braze.com' @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.license = { :type => 'Commercial' } s.authors = 'Braze, Inc.' - s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.4.0' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.5.0' } s.swift_version = '5.0' s.ios.deployment_target = '10.0' @@ -17,5 +17,5 @@ Pod::Spec.new do |s| s.source_files = 'Sources/BrazeUI/**/*.swift' s.resource_bundles = { 'BrazeUI' => 'Sources/BrazeUI/Resources/**/*' } - s.dependency 'BrazeKit', '5.4.0' + s.dependency 'BrazeKit', '5.5.0' end diff --git a/CHANGELOG.md b/CHANGELOG.md index 7feea1aefe..40d6eba564 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 5.5.0 + +##### Added +- Adds support for host apps written in Objective-C. + - Braze Objective-C types start either with `BRZ` or `Braze`, e.g.: + - `Braze` + - `BrazeDelegate` + - `BRZContentCardRaw` + - See our Objective-C [Examples](Examples/) project. +- Adds [`BrazeDelegate.braze(_:noMatchingTriggerForEvent:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/brazedelegate/braze(_:nomatchingtriggerforevent:)-8rt7y) which is called if no Braze in-app message is triggered for a given event. + +##### Changed +- In `Braze.Configuration.Api`: + - Renamed `SdkMetadata` to `SDKMetadata`. + - Renamed `addSdkMetadata(_:)` to `addSDKMetadata(_:)`. +- In `Braze.InAppMessage`: + - Renamed `Themes.default` to `Themes.defaults`. + - Renamed `ClickAction.uri` to `ClickAction.url`. + - Renamed `ClickAction.uri(_:useWebView:)` to `ClickAction.url(_:useWebView:)`. + ## 5.4.0 ##### Fixed @@ -29,7 +49,7 @@ - Available on iOS and tvOS. - Adds [`Braze.InAppMessage.ClickAction.uri`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/inappmessage/clickaction/uri) for direct access. - Adds [`Braze.ContentCard.ClickAction.uri`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/contentcard/clickaction/uri/) for direct access. -- Adds [`Braze.deviceId(queue:completion:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/brazekit/braze/deviceid(queue:completion:)) to retrieve the device identifier used by Braze. +- Adds [`Braze.deviceId(queue:completion:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/deviceid(queue:completion:)) to retrieve the device identifier used by Braze. ## 5.3.0 @@ -80,7 +100,8 @@ The Braze Swift SDK is set to replace the [current Braze iOS SDK](https://github ### Current limitations The following features are not supported yet: -- Objective-C integration +- ~~Objective-C integration~~ + - Added in [5.5.0](#550) - ~~tvOS integration~~ - Added in [5.3.0](#530) - News Feed diff --git a/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..625730200e --- /dev/null +++ b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.pbxproj @@ -0,0 +1,1652 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 021241249E788C93F8B9B58C /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 02D39B681AC38D3E38167BC9 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 0575EAD45DC713FDFA430364 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */; }; + 0AD73B7EB7D9DC710E0CC91D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 0BE8CE4982452A0E74D7F309 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52F765C494ACFF150F0A76C4 /* Readme.m */; }; + 0DE3276319B3F7EDE9E5761D /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DA261A3969E80D4910B919 /* NotificationViewController.swift */; }; + 14ED490CA83487F672B6CA64 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 161DC1259C44AD89479BA698 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA064323F91A22F4E14CAE9D /* NotificationService.swift */; }; + 181CEE421636AF991665AF53 /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */; }; + 18DE204B580AF59319172A34 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 1EB7F46010C2EE195B7F82DA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + 2004486C1F497F0D78D3C3C7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + 210B445D7948A3019E0B61DE /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 21406C5977E35E2DB91079C1 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B0E04E20E4B1C458222BA1 /* Readme.m */; }; + 2198B5052B89F561E1408347 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; }; + 237398E27F20D11B4A8D6F32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 2599D92D219E7BB320EB918C /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */; }; + 2A65F13CBADEAEA072B1962A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + 30D7A569B1A652D533C6DFF4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + 3170955318006DA2CDC1D371 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 330538042DBA8D66FE29106B /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 34C9C566ACB7B6220C782866 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; }; + 3C8DEAC1C01DE222C1FD7715 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = C92AD7CCB90625B324C9E200 /* Readme.m */; }; + 3CCF8C060E64864FF2F0FBC5 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 406136EAB546AFD30FFF4326 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 40BBC96C23C0D03C1876EFB3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + 40C2532843ABD07521BDA072 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 381A82D8567D19A639A65555 /* Readme.m */; }; + 4668AEE87D6BFB57357E49F8 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */; }; + 4E6928C0008070173370990E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 4E9C8479947558025D64171B /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 4F93A8E59C746BA0FE66EFD6 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + 4FBBFDC7A8AD63635182DCCC /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 5443B297E55EFFA3D9531EB5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */; }; + 56E71FBF34C707A0C76D4E92 /* PushNotificationsServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 5752C25DC8C2CA0C0925C10F /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */; }; + 5EA1891740935FEB0EB49789 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */; }; + 60D9B416B69C17AD0FF5FD87 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */; }; + 639A93232862A95314463DE5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + 656FFF89336D3AA397B40D7C /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = C92AD7CCB90625B324C9E200 /* Readme.m */; }; + 6AA695612AC940383057198A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 7440800FB6329FCB28FC0FD6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */; }; + 756350E7C92625894BC8B509 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 7B7F572DEB2E96237482FFB3 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 7BA952D41DC54C1A728AB539 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 7BF8E94ED7F5FC6A1C24A470 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 7E8AD3897D9983306EE938B9 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 7FC56E25CCA1B6080699728A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + 8AA046F58DFE835A8DBDC2FB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + 8B29E2C7B7EB260EAC5AB91D /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CD0DE7DB00697D75457F7CE /* Readme.m */; }; + 8F470EAC78320B9B5E3C2093 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + 90A4F6B53E0118D3661585D4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + 9ACDCF377DDDFE68EC46E40C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 201DC51A7B4BD5035790D967 /* AppDelegate.m */; }; + A08302940AC13A1B149928CE /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + A2BE6EE947CA0EB7BB800F8C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */; }; + A59B5541D8BDA70A1818AFDB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + A841C03E3FC310874204BBBF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */; }; + AA9687A7D3DF585AC6F6D718 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 201DC51A7B4BD5035790D967 /* AppDelegate.m */; }; + AB2FE63CFBECFD1045D16ED7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + AEDDEDC6F9B5D7838BE908D6 /* PushNotificationsContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + B20E5CC4144654C1689934FE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + B23023008FC1FDB8D94A41F5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 318B57C50A12DB5F02FC6224 /* AppDelegate.m */; }; + BAA8122F4149259E86294F99 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */; }; + BC696EE76324DB0A73B65DE7 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */; }; + BCE0FBAE8B29B501C5C77992 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 318B57C50A12DB5F02FC6224 /* AppDelegate.m */; }; + C0D38B13A94DADB550966E38 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; }; + C25E42027E9FF502BA7D7269 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */; }; + C650783920A53EDD98DD19E5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + C6A06C3B17248E8369F21897 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C307795934847C752765580 /* Readme.m */; }; + C75C09FC6605F02E7646AF0F /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B0E04E20E4B1C458222BA1 /* Readme.m */; }; + CF19792AFCEF53A28612612B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + D0DECD56C8F8201D27F59B32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + D1B4FEFA476833265065E137 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */; }; + D48FBF169A83BB8BCADCB80C /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */; }; + DAA18481E36225A541BF8091 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + DB825090EC9CD3D9BEB01EFA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */; }; + E0941C6B0D49A073B0A87A0F /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + E4206A2DEA0A202587F0F715 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + E5D78AA4EE4F9494D6AA85FA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C307795934847C752765580 /* Readme.m */; }; + E63FFCC8439CC53E8F297431 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */; }; + E93521F5478A08F3837B041D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + E9B14BAEC929FC550EC4C235 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */; }; + E9E8435129B8C5C86F579395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + EAD8D9FD10FB71AB1C44F22E /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */; }; + EB71881CFACEA23DC2CF8112 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + ECF4B3DD82D61470A3EFC3E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + EE1A489AA9350D6C14CBBBCE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */; }; + EE9EDAC6D65BA1F0AC69EE89 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 75054C03D57540CE91A71920 /* AppDelegate.m */; }; + F2395EC507EC1C960CFC6118 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + F331DB6CEE9AAC6AC1252F1D /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 77273E47E0A73317EF0235A7 /* Credentials.m */; }; + F3EF4E7F2CFCC0512F4F642F /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */; }; + F49C339077170329AC8926A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */; }; + F527CC79A52C51B1D2B30FAF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0EA46B7F46275141BF76209 /* main.m */; }; + F6077FC0D214B2BA1BFBD720 /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */; }; + F81FA5EDF6E6E785AD09482B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AE76A96578D95F43B9C0849 /* AppDelegate.m */; }; + FDFE0B5AD6C85ABC76895E1F /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */; }; + FE9AA3224EFAE15896E7A1DA /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2E6E453ED2C838C4006D08F8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9F9231105531CE428ADD921 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C7435EF6816986F173CAB4E9; + remoteInfo = PushNotificationsContentExtension; + }; + 33F46D6820611AA9F861E4F9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C9F9231105531CE428ADD921 /* Project object */; + proxyType = 1; + remoteGlobalIDString = CCD5FB3CEF0797FD385EA7F3; + remoteInfo = PushNotificationsServiceExtension; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 59784E19DCC3D0A5254ECC61 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 56E71FBF34C707A0C76D4E92 /* PushNotificationsServiceExtension.appex in Embed App Extensions */, + AEDDEDC6F9B5D7838BE908D6 /* PushNotificationsContentExtension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0CD0DE7DB00697D75457F7CE /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationManager.m; sourceTree = ""; }; + 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckoutViewController.m; sourceTree = ""; }; + 14EDA84CD87233E1D5B6725B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; }; + 1CA06BB2ED58DC38DE098EEB /* CustomInAppMessagePresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomInAppMessagePresenter.h; sourceTree = ""; }; + 201DC51A7B4BD5035790D967 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 249AA3BCC2DA49BBBD853C61 /* InAppMessageInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppMessageInfoViewController.h; sourceTree = ""; }; + 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomInAppMessagePresenter.m; sourceTree = ""; }; + 2D50867A0DB9C8686F63A371 /* InAppMessages.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = InAppMessages.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 318B57C50A12DB5F02FC6224 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 34DB46A770028DFE645A3AE4 /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 381A82D8567D19A639A65555 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 42BA0F61D883E0421B3FA7CA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 4E9C1C30C3119B822A6C482D /* ReadmeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeViewController.h; sourceTree = ""; }; + 52B0E04E20E4B1C458222BA1 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 52EBE792F20E4F26BC0E7F48 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 52F765C494ACFF150F0A76C4 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 61DA261A3969E80D4910B919 /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; }; + 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; + 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; }; + 6832319B66FB76CAA84519FA /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 6AE76A96578D95F43B9C0849 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 75054C03D57540CE91A71920 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppMessageInfoViewController.m; sourceTree = ""; }; + 77273E47E0A73317EF0235A7 /* Credentials.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Credentials.m; sourceTree = ""; }; + 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsContentExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 80CF36610D640D20AB35926E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 858AE4349E1D1D1849DB97B4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C307795934847C752765580 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A2AC34AC6990B2FA6CD647CC /* ReadmeAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeAction.h; sourceTree = ""; }; + A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = PushNotifications.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A6EEBA52A1C6E13DE9B07326 /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; }; + A77BCD95413ADCF8578235CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; }; + B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + BA064323F91A22F4E14CAE9D /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + BA37FE8457A48CD8683BE79A /* CardsInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardsInfoViewController.h; sourceTree = ""; }; + C0EA46B7F46275141BF76209 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + C92AD7CCB90625B324C9E200 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + C9C1B6158983BCB0C593DAE4 /* ContentCards.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ContentCards.app; sourceTree = BUILT_PRODUCTS_DIR; }; + CAF8A0D7B315DF4FF0A9CFC8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + CD47A5A37513C58A6E380918 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CardsInfoViewController.m; sourceTree = ""; }; + D1FC7DF6067EFA59329D3B00 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + D6EF14C19329871CCA47A1AF /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; }; + DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + DE3608B9E460175A349CDB87 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReadmeViewController.m; sourceTree = ""; }; + EFB767A3E5938B98AE96F91B /* AuthenticationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticationManager.h; sourceTree = ""; }; + F6DB4DC3F7A190B73055DD78 /* CheckoutViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckoutViewController.h; sourceTree = ""; }; + FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9C12D40A1EC1FBCBD6CA4D4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5752C25DC8C2CA0C0925C10F /* UserNotifications.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E5DFE50012E3C956DEE08F20 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 60D9B416B69C17AD0FF5FD87 /* UserNotifications.framework in Frameworks */, + E63FFCC8439CC53E8F297431 /* UserNotificationsUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4F38F2ACA591DCA04EF16BB1 /* Location */ = { + isa = PBXGroup; + children = ( + CAF8A0D7B315DF4FF0A9CFC8 /* AppDelegate.h */, + 318B57C50A12DB5F02FC6224 /* AppDelegate.m */, + 8C307795934847C752765580 /* Readme.m */, + ); + name = Location; + path = Sources/Location; + sourceTree = ""; + }; + 51FBDA444B2130ED53F050CB /* Analytics */ = { + isa = PBXGroup; + children = ( + D1FC7DF6067EFA59329D3B00 /* AppDelegate.h */, + 201DC51A7B4BD5035790D967 /* AppDelegate.m */, + EFB767A3E5938B98AE96F91B /* AuthenticationManager.h */, + 11D86AE9D1DC590AC4694323 /* AuthenticationManager.m */, + F6DB4DC3F7A190B73055DD78 /* CheckoutViewController.h */, + 133CC7FED120DA4BC4F63478 /* CheckoutViewController.m */, + C92AD7CCB90625B324C9E200 /* Readme.m */, + ); + name = Analytics; + path = Sources/Analytics; + sourceTree = ""; + }; + 5F61F41FECA7453CB4C2C3CA = { + isa = PBXGroup; + children = ( + EB043806B7BB06DCA25E0177 /* Common */, + 51FBDA444B2130ED53F050CB /* Analytics */, + EE1BF73C17001D2912250407 /* ContentCards */, + 6F112DA3865BFE3961698859 /* ContentCards-Custom-UI */, + 9AA2DA5B878C1242DBDD0410 /* InAppMessages */, + E3BAE1A02E5A97AD717C4DE1 /* InAppMessages-Custom-UI */, + 4F38F2ACA591DCA04EF16BB1 /* Location */, + E956091874C7F622B207B35A /* PushNotifications */, + 79BD163F0CE766FD84A15D5A /* PushNotificationsContentExtension */, + E239AFF5E3F3085D7A50AFF6 /* PushNotificationsServiceExtension */, + DDE0D6627F8681F53997C26F /* Frameworks */, + 944D5C0BF6DC0B28ACDA2036 /* Products */, + ); + sourceTree = ""; + }; + 6F112DA3865BFE3961698859 /* ContentCards-Custom-UI */ = { + isa = PBXGroup; + children = ( + 80CF36610D640D20AB35926E /* AppDelegate.h */, + DCD5EA6DB57BDEF9D156AF3B /* AppDelegate.m */, + BA37FE8457A48CD8683BE79A /* CardsInfoViewController.h */, + CF4B96FFF47505E424237B85 /* CardsInfoViewController.m */, + 52B0E04E20E4B1C458222BA1 /* Readme.m */, + ); + name = "ContentCards-Custom-UI"; + path = "Sources/ContentCards-Custom-UI"; + sourceTree = ""; + }; + 79BD163F0CE766FD84A15D5A /* PushNotificationsContentExtension */ = { + isa = PBXGroup; + children = ( + 61DA261A3969E80D4910B919 /* NotificationViewController.swift */, + ); + name = PushNotificationsContentExtension; + path = Sources/PushNotificationsContentExtension; + sourceTree = ""; + }; + 7D73AC8BFC703A7B9ECA6177 /* tvOS */ = { + isa = PBXGroup; + children = ( + 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */, + ); + path = tvOS; + sourceTree = ""; + }; + 944D5C0BF6DC0B28ACDA2036 /* Products */ = { + isa = PBXGroup; + children = ( + 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */, + DE3608B9E460175A349CDB87 /* Analytics.app */, + 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */, + C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */, + C9C1B6158983BCB0C593DAE4 /* ContentCards.app */, + 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */, + FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */, + 2D50867A0DB9C8686F63A371 /* InAppMessages.app */, + 6832319B66FB76CAA84519FA /* Location.app */, + 34DB46A770028DFE645A3AE4 /* Location.app */, + A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */, + 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */, + 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */, + ); + name = Products; + sourceTree = ""; + }; + 9AA2DA5B878C1242DBDD0410 /* InAppMessages */ = { + isa = PBXGroup; + children = ( + 858AE4349E1D1D1849DB97B4 /* AppDelegate.h */, + 6AE76A96578D95F43B9C0849 /* AppDelegate.m */, + D6EF14C19329871CCA47A1AF /* BRZGIFViewProvider+SDWebImage.h */, + AC38A6DD46A5E7EBC7B8FB4B /* BRZGIFViewProvider+SDWebImage.m */, + 381A82D8567D19A639A65555 /* Readme.m */, + ); + name = InAppMessages; + path = Sources/InAppMessages; + sourceTree = ""; + }; + CFAFCFEE58CC8AA1F0BDA699 /* iOS */ = { + isa = PBXGroup; + children = ( + CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */, + ); + path = iOS; + sourceTree = ""; + }; + DDE0D6627F8681F53997C26F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6208C00FB5F7F0284A26EF20 /* UserNotifications.framework */, + 1874579DE7E406E73A3CB3A1 /* UserNotificationsUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E239AFF5E3F3085D7A50AFF6 /* PushNotificationsServiceExtension */ = { + isa = PBXGroup; + children = ( + BA064323F91A22F4E14CAE9D /* NotificationService.swift */, + ); + name = PushNotificationsServiceExtension; + path = Sources/PushNotificationsServiceExtension; + sourceTree = ""; + }; + E3BAE1A02E5A97AD717C4DE1 /* InAppMessages-Custom-UI */ = { + isa = PBXGroup; + children = ( + CD47A5A37513C58A6E380918 /* AppDelegate.h */, + A9AF15EF29118835FEB5D5E2 /* AppDelegate.m */, + 1CA06BB2ED58DC38DE098EEB /* CustomInAppMessagePresenter.h */, + 2697E60398EE452C7E362B83 /* CustomInAppMessagePresenter.m */, + 249AA3BCC2DA49BBBD853C61 /* InAppMessageInfoViewController.h */, + 763258DB970F0A96B2A3DF74 /* InAppMessageInfoViewController.m */, + 3EE8EFDC1CAFFB4F4CB5D00D /* Readme.m */, + ); + name = "InAppMessages-Custom-UI"; + path = "Sources/InAppMessages-Custom-UI"; + sourceTree = ""; + }; + E956091874C7F622B207B35A /* PushNotifications */ = { + isa = PBXGroup; + children = ( + 52EBE792F20E4F26BC0E7F48 /* AppDelegate.h */, + B0DC0BEFE722FE52D53AA96B /* AppDelegate.m */, + 52F765C494ACFF150F0A76C4 /* Readme.m */, + ); + name = PushNotifications; + path = Sources/PushNotifications; + sourceTree = ""; + }; + EB043806B7BB06DCA25E0177 /* Common */ = { + isa = PBXGroup; + children = ( + 0340E1FFDDBC0C9D72FCD4D4 /* Assets.xcassets */, + 77273E47E0A73317EF0235A7 /* Credentials.m */, + C0EA46B7F46275141BF76209 /* main.m */, + A2AC34AC6990B2FA6CD647CC /* ReadmeAction.h */, + 4E9C1C30C3119B822A6C482D /* ReadmeViewController.h */, + E06A48D3D2F38E11DAA4C05E /* ReadmeViewController.m */, + CFAFCFEE58CC8AA1F0BDA699 /* iOS */, + 7D73AC8BFC703A7B9ECA6177 /* tvOS */, + ); + name = Common; + path = Sources/Common; + sourceTree = ""; + }; + EE1BF73C17001D2912250407 /* ContentCards */ = { + isa = PBXGroup; + children = ( + 14EDA84CD87233E1D5B6725B /* AppDelegate.h */, + 75054C03D57540CE91A71920 /* AppDelegate.m */, + A6EEBA52A1C6E13DE9B07326 /* BRZGIFViewProvider+SDWebImage.h */, + 645D4CFE35E1C189EF76D681 /* BRZGIFViewProvider+SDWebImage.m */, + 0CD0DE7DB00697D75457F7CE /* Readme.m */, + ); + name = ContentCards; + path = Sources/ContentCards; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0FD7FC35072A5B75852D15F7 /* InAppMessages-Custom-UI-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 72920B71D538BFAF8A028D09 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */; + buildPhases = ( + 1FF8AFF6708BEE3883392041 /* Sources */, + 39044F4BABFFCBF62ACFCECB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "InAppMessages-Custom-UI-iOS"; + productName = "InAppMessages-Custom-UI-iOS"; + productReference = 05A5CB32692A4493359A70F2 /* InAppMessages-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + 177B908F6B162DDA447880C8 /* ContentCards-Custom-UI-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 38CA0A5742C4A4988D4584C2 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */; + buildPhases = ( + 070EDE6E9735E579169F2D68 /* Sources */, + 52CCB0B63165D1463D683A73 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ContentCards-Custom-UI-tvOS"; + productName = "ContentCards-Custom-UI-tvOS"; + productReference = C78E0B5A5D52F990511A4091 /* ContentCards-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + 1A7E9979FC152DE4F7D5DC2A /* InAppMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = C8DA1DB107E7EE64BBBAEBE7 /* Build configuration list for PBXNativeTarget "InAppMessages" */; + buildPhases = ( + E446E3B55477F3BA5FB625C4 /* Sources */, + 324A65B0C1348D482EBD2C51 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = InAppMessages; + productName = InAppMessages; + productReference = 2D50867A0DB9C8686F63A371 /* InAppMessages.app */; + productType = "com.apple.product-type.application"; + }; + 284840096E199840E3A733BC /* Location-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = B76990766EAEC18717669D6F /* Build configuration list for PBXNativeTarget "Location-tvOS" */; + buildPhases = ( + 5FEBF68A041A50636A7C63D7 /* Sources */, + 78CBE3D7946A65CD24DD6D8A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Location-tvOS"; + productName = "Location-tvOS"; + productReference = 34DB46A770028DFE645A3AE4 /* Location.app */; + productType = "com.apple.product-type.application"; + }; + 4A34648A0491D5D28D9A7E8A /* InAppMessages-Custom-UI-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = E26727234EAA2C9FFB557AF2 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */; + buildPhases = ( + 923462222067359F78BABE34 /* Sources */, + 3FC37E07E197AB909115976A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "InAppMessages-Custom-UI-tvOS"; + productName = "InAppMessages-Custom-UI-tvOS"; + productReference = FE50398A21EB6A33EE9874A2 /* InAppMessages-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + 726E40C6A0B9D7595B53FE5E /* PushNotifications */ = { + isa = PBXNativeTarget; + buildConfigurationList = 59402C8CB5DE66A776947595 /* Build configuration list for PBXNativeTarget "PushNotifications" */; + buildPhases = ( + D2ACF4659AEA97A06A724AF3 /* Sources */, + B62AC56D63A64203ECF45AAE /* Resources */, + 59784E19DCC3D0A5254ECC61 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 9D311561DBF39BC8DEEAF340 /* PBXTargetDependency */, + 1CEA284D6D77D29EF745D466 /* PBXTargetDependency */, + ); + name = PushNotifications; + productName = PushNotifications; + productReference = A37E3B0FA418AB843D26F7F9 /* PushNotifications.app */; + productType = "com.apple.product-type.application"; + }; + 9097C3EC847DC7AE4B1CA969 /* ContentCards */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9D35AC44AE90C1C27CBF8577 /* Build configuration list for PBXNativeTarget "ContentCards" */; + buildPhases = ( + C7726F7D79339C85CB8B1FDB /* Sources */, + 0607C6FAE74CA8A0F8E5224B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ContentCards; + productName = ContentCards; + productReference = C9C1B6158983BCB0C593DAE4 /* ContentCards.app */; + productType = "com.apple.product-type.application"; + }; + A0EF8DC5C1ED6288C32D3D23 /* Analytics-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 43414268546ED18E21E7E892 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */; + buildPhases = ( + F57A2A4DF2E99DAA2F0E38B4 /* Sources */, + 38AC76FC42776531F9D2414E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics-iOS"; + productName = "Analytics-iOS"; + productReference = 9E2B80BBE3951963FBA6BBD3 /* Analytics.app */; + productType = "com.apple.product-type.application"; + }; + BC720D0A2A3B555DF4D1268A /* Location-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4CBDCD32BF67ACE4E2977EFA /* Build configuration list for PBXNativeTarget "Location-iOS" */; + buildPhases = ( + DBA50E39A4B67698A1CA8F34 /* Sources */, + 7299DD69BA7DDA59FA7F954F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Location-iOS"; + productName = "Location-iOS"; + productReference = 6832319B66FB76CAA84519FA /* Location.app */; + productType = "com.apple.product-type.application"; + }; + C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 03D1E503F9863A03CB17E53A /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */; + buildPhases = ( + C7487814AD5323F755B1E524 /* Sources */, + E5DFE50012E3C956DEE08F20 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PushNotificationsContentExtension; + productName = PushNotificationsContentExtension; + productReference = 7EFD35FD440D538F5EB8F021 /* PushNotificationsContentExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = D767F3158D7C98C16E53CE31 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */; + buildPhases = ( + 9AD321D868E1638BA51BFDA7 /* Sources */, + 9C12D40A1EC1FBCBD6CA4D4C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PushNotificationsServiceExtension; + productName = PushNotificationsServiceExtension; + productReference = 40B660242E5E30D22F3AC51E /* PushNotificationsServiceExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + E4E9F3507C9F70F681E5417F /* ContentCards-Custom-UI-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33777E174E4CC017CCCB31A8 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */; + buildPhases = ( + 38F46412EEF2D23C9901E6A3 /* Sources */, + CD72E9C8C68A5D330D1ED959 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ContentCards-Custom-UI-iOS"; + productName = "ContentCards-Custom-UI-iOS"; + productReference = 8854CADF86F02FA64B2CC3F1 /* ContentCards-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + FDA0A7B4C40914EAF405D9FC /* Analytics-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33A0A8897465C6BD7C17C2E6 /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */; + buildPhases = ( + 51C89F4377C3E0870055A1CA /* Sources */, + 24EBDE35CCCBEFEFF53E707D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics-tvOS"; + productName = "Analytics-tvOS"; + productReference = DE3608B9E460175A349CDB87 /* Analytics.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C9F9231105531CE428ADD921 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1200; + TargetAttributes = { + }; + }; + buildConfigurationList = 1D61EB4EA4EACDE551DB7D19 /* Build configuration list for PBXProject "Examples-CocoaPods" */; + compatibilityVersion = "Xcode 11.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 5F61F41FECA7453CB4C2C3CA; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A0EF8DC5C1ED6288C32D3D23 /* Analytics-iOS */, + FDA0A7B4C40914EAF405D9FC /* Analytics-tvOS */, + 9097C3EC847DC7AE4B1CA969 /* ContentCards */, + E4E9F3507C9F70F681E5417F /* ContentCards-Custom-UI-iOS */, + 177B908F6B162DDA447880C8 /* ContentCards-Custom-UI-tvOS */, + 1A7E9979FC152DE4F7D5DC2A /* InAppMessages */, + 0FD7FC35072A5B75852D15F7 /* InAppMessages-Custom-UI-iOS */, + 4A34648A0491D5D28D9A7E8A /* InAppMessages-Custom-UI-tvOS */, + BC720D0A2A3B555DF4D1268A /* Location-iOS */, + 284840096E199840E3A733BC /* Location-tvOS */, + 726E40C6A0B9D7595B53FE5E /* PushNotifications */, + C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */, + CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0607C6FAE74CA8A0F8E5224B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F49C339077170329AC8926A3 /* Assets.xcassets in Resources */, + 30D7A569B1A652D533C6DFF4 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 24EBDE35CCCBEFEFF53E707D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1EB7F46010C2EE195B7F82DA /* Assets.xcassets in Resources */, + D1B4FEFA476833265065E137 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 324A65B0C1348D482EBD2C51 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E4206A2DEA0A202587F0F715 /* Assets.xcassets in Resources */, + 2A65F13CBADEAEA072B1962A /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 38AC76FC42776531F9D2414E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB2FE63CFBECFD1045D16ED7 /* Assets.xcassets in Resources */, + C650783920A53EDD98DD19E5 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39044F4BABFFCBF62ACFCECB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF19792AFCEF53A28612612B /* Assets.xcassets in Resources */, + EE1A489AA9350D6C14CBBBCE /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3FC37E07E197AB909115976A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB71881CFACEA23DC2CF8112 /* Assets.xcassets in Resources */, + 2198B5052B89F561E1408347 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 52CCB0B63165D1463D683A73 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 639A93232862A95314463DE5 /* Assets.xcassets in Resources */, + 34C9C566ACB7B6220C782866 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7299DD69BA7DDA59FA7F954F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9E8435129B8C5C86F579395 /* Assets.xcassets in Resources */, + 2004486C1F497F0D78D3C3C7 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 78CBE3D7946A65CD24DD6D8A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8AA046F58DFE835A8DBDC2FB /* Assets.xcassets in Resources */, + C0D38B13A94DADB550966E38 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B62AC56D63A64203ECF45AAE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7FC56E25CCA1B6080699728A /* Assets.xcassets in Resources */, + DAA18481E36225A541BF8091 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CD72E9C8C68A5D330D1ED959 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 40BBC96C23C0D03C1876EFB3 /* Assets.xcassets in Resources */, + ECF4B3DD82D61470A3EFC3E6 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 070EDE6E9735E579169F2D68 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7440800FB6329FCB28FC0FD6 /* AppDelegate.m in Sources */, + C25E42027E9FF502BA7D7269 /* CardsInfoViewController.m in Sources */, + F2395EC507EC1C960CFC6118 /* Credentials.m in Sources */, + 21406C5977E35E2DB91079C1 /* Readme.m in Sources */, + E93521F5478A08F3837B041D /* ReadmeViewController.m in Sources */, + 4E6928C0008070173370990E /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1FF8AFF6708BEE3883392041 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5443B297E55EFFA3D9531EB5 /* AppDelegate.m in Sources */, + E0941C6B0D49A073B0A87A0F /* Credentials.m in Sources */, + BAA8122F4149259E86294F99 /* CustomInAppMessagePresenter.m in Sources */, + 4668AEE87D6BFB57357E49F8 /* InAppMessageInfoViewController.m in Sources */, + DB825090EC9CD3D9BEB01EFA /* Readme.m in Sources */, + 02D39B681AC38D3E38167BC9 /* ReadmeViewController.m in Sources */, + 7BA952D41DC54C1A728AB539 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 38F46412EEF2D23C9901E6A3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A841C03E3FC310874204BBBF /* AppDelegate.m in Sources */, + 2599D92D219E7BB320EB918C /* CardsInfoViewController.m in Sources */, + 7B7F572DEB2E96237482FFB3 /* Credentials.m in Sources */, + C75C09FC6605F02E7646AF0F /* Readme.m in Sources */, + D0DECD56C8F8201D27F59B32 /* ReadmeViewController.m in Sources */, + A59B5541D8BDA70A1818AFDB /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 51C89F4377C3E0870055A1CA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9ACDCF377DDDFE68EC46E40C /* AppDelegate.m in Sources */, + 181CEE421636AF991665AF53 /* AuthenticationManager.m in Sources */, + F6077FC0D214B2BA1BFBD720 /* CheckoutViewController.m in Sources */, + 4FBBFDC7A8AD63635182DCCC /* Credentials.m in Sources */, + 656FFF89336D3AA397B40D7C /* Readme.m in Sources */, + 4F93A8E59C746BA0FE66EFD6 /* ReadmeViewController.m in Sources */, + F527CC79A52C51B1D2B30FAF /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FEBF68A041A50636A7C63D7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B23023008FC1FDB8D94A41F5 /* AppDelegate.m in Sources */, + 330538042DBA8D66FE29106B /* Credentials.m in Sources */, + C6A06C3B17248E8369F21897 /* Readme.m in Sources */, + 210B445D7948A3019E0B61DE /* ReadmeViewController.m in Sources */, + 3170955318006DA2CDC1D371 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 923462222067359F78BABE34 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9B14BAEC929FC550EC4C235 /* AppDelegate.m in Sources */, + 18DE204B580AF59319172A34 /* Credentials.m in Sources */, + 0575EAD45DC713FDFA430364 /* CustomInAppMessagePresenter.m in Sources */, + FE9AA3224EFAE15896E7A1DA /* InAppMessageInfoViewController.m in Sources */, + D48FBF169A83BB8BCADCB80C /* Readme.m in Sources */, + F3EF4E7F2CFCC0512F4F642F /* ReadmeViewController.m in Sources */, + 90A4F6B53E0118D3661585D4 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9AD321D868E1638BA51BFDA7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 161DC1259C44AD89479BA698 /* NotificationService.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C7487814AD5323F755B1E524 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0DE3276319B3F7EDE9E5761D /* NotificationViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C7726F7D79339C85CB8B1FDB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EE9EDAC6D65BA1F0AC69EE89 /* AppDelegate.m in Sources */, + 5EA1891740935FEB0EB49789 /* BRZGIFViewProvider+SDWebImage.m in Sources */, + 021241249E788C93F8B9B58C /* Credentials.m in Sources */, + 8B29E2C7B7EB260EAC5AB91D /* Readme.m in Sources */, + 0AD73B7EB7D9DC710E0CC91D /* ReadmeViewController.m in Sources */, + 406136EAB546AFD30FFF4326 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D2ACF4659AEA97A06A724AF3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A2BE6EE947CA0EB7BB800F8C /* AppDelegate.m in Sources */, + 3CCF8C060E64864FF2F0FBC5 /* Credentials.m in Sources */, + 0BE8CE4982452A0E74D7F309 /* Readme.m in Sources */, + 4E9C8479947558025D64171B /* ReadmeViewController.m in Sources */, + B20E5CC4144654C1689934FE /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBA50E39A4B67698A1CA8F34 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BCE0FBAE8B29B501C5C77992 /* AppDelegate.m in Sources */, + 8F470EAC78320B9B5E3C2093 /* Credentials.m in Sources */, + E5D78AA4EE4F9494D6AA85FA /* Readme.m in Sources */, + A08302940AC13A1B149928CE /* ReadmeViewController.m in Sources */, + 756350E7C92625894BC8B509 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E446E3B55477F3BA5FB625C4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F81FA5EDF6E6E785AD09482B /* AppDelegate.m in Sources */, + BC696EE76324DB0A73B65DE7 /* BRZGIFViewProvider+SDWebImage.m in Sources */, + F331DB6CEE9AAC6AC1252F1D /* Credentials.m in Sources */, + 40C2532843ABD07521BDA072 /* Readme.m in Sources */, + 14ED490CA83487F672B6CA64 /* ReadmeViewController.m in Sources */, + 7BF8E94ED7F5FC6A1C24A470 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F57A2A4DF2E99DAA2F0E38B4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AA9687A7D3DF585AC6F6D718 /* AppDelegate.m in Sources */, + EAD8D9FD10FB71AB1C44F22E /* AuthenticationManager.m in Sources */, + FDFE0B5AD6C85ABC76895E1F /* CheckoutViewController.m in Sources */, + 7E8AD3897D9983306EE938B9 /* Credentials.m in Sources */, + 3C8DEAC1C01DE222C1FD7715 /* Readme.m in Sources */, + 237398E27F20D11B4A8D6F32 /* ReadmeViewController.m in Sources */, + 6AA695612AC940383057198A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 1CEA284D6D77D29EF745D466 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C7435EF6816986F173CAB4E9 /* PushNotificationsContentExtension */; + targetProxy = 2E6E453ED2C838C4006D08F8 /* PBXContainerItemProxy */; + }; + 9D311561DBF39BC8DEEAF340 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CCD5FB3CEF0797FD385EA7F3 /* PushNotificationsServiceExtension */; + targetProxy = 33F46D6820611AA9F861E4F9 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 5A56AB422F8DA782A8D2B6FD /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 42BA0F61D883E0421B3FA7CA /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + CABCDD10D6E23AB146F9F7BA /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A77BCD95413ADCF8578235CE /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0B6E144276BF004EFE80A784 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0B782479BDDFAA91B90B6411 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0DB286FC893227921592442C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0FF3E9103BDC67C9723BD0CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/ContentCards/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards; + PRODUCT_NAME = ContentCards; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1CE2539A10E8624E8EDD3601 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 2178EDBFBF71828E507601C1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 277ABE8F9A11018387A77412 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS"; + PRODUCT_NAME = Location; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 4BCF9BD39CEB19E634B6FD81 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/InAppMessages/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages; + PRODUCT_NAME = InAppMessages; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4EBD32EE3B16C9EBF7493F73 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS"; + PRODUCT_NAME = Analytics; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4FCE20B3E84CE39D624EFA02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/InAppMessages/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages; + PRODUCT_NAME = InAppMessages; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 508970482D723EDFFD096AB1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/ContentCards/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards; + PRODUCT_NAME = ContentCards; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 61077A56E64ADBA96CA8CE0C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS"; + PRODUCT_NAME = Location; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 67E21615E4F6D7BFAA160A31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 74B3175DE3731381F52D100D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS"; + PRODUCT_NAME = Location; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 77420AEFB5CE84A97B402C8C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 947EC0697CF1F01DDC513FD6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Debug; + }; + A653F811811645548266EC3A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS"; + PRODUCT_NAME = Analytics; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + AEB7354D56CC1297356D6010 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS"; + PRODUCT_NAME = Location; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + BA01071103F7280839CDFBF1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + C53D3849AB3D8DAE264A3A51 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + CFC0E247B97C5CEDBAF0B857 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements; + INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D34FC9390D8C12046901C916 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements; + INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + D41CC2321BB3390AFD4C3C77 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/PushNotifications/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications; + PRODUCT_NAME = PushNotifications; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + D42220F54B188367F09D51F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS"; + PRODUCT_NAME = Analytics; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + D73FE2FD92F59639E0E66547 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS"; + PRODUCT_NAME = Analytics; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + E93F9B7A3E25FB962107ED6A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Release; + }; + F97E175B39C55208E8A73860 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + FB51E977835920E25D8EB81E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/PushNotifications/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications; + PRODUCT_NAME = PushNotifications; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 03D1E503F9863A03CB17E53A /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CFC0E247B97C5CEDBAF0B857 /* Debug */, + D34FC9390D8C12046901C916 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1D61EB4EA4EACDE551DB7D19 /* Build configuration list for PBXProject "Examples-CocoaPods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 947EC0697CF1F01DDC513FD6 /* Debug */, + E93F9B7A3E25FB962107ED6A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 33777E174E4CC017CCCB31A8 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0B6E144276BF004EFE80A784 /* Debug */, + F97E175B39C55208E8A73860 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 33A0A8897465C6BD7C17C2E6 /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D73FE2FD92F59639E0E66547 /* Debug */, + A653F811811645548266EC3A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 38CA0A5742C4A4988D4584C2 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BA01071103F7280839CDFBF1 /* Debug */, + 67E21615E4F6D7BFAA160A31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 43414268546ED18E21E7E892 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4EBD32EE3B16C9EBF7493F73 /* Debug */, + D42220F54B188367F09D51F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 4CBDCD32BF67ACE4E2977EFA /* Build configuration list for PBXNativeTarget "Location-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 74B3175DE3731381F52D100D /* Debug */, + AEB7354D56CC1297356D6010 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 59402C8CB5DE66A776947595 /* Build configuration list for PBXNativeTarget "PushNotifications" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FB51E977835920E25D8EB81E /* Debug */, + D41CC2321BB3390AFD4C3C77 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 72920B71D538BFAF8A028D09 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 77420AEFB5CE84A97B402C8C /* Debug */, + 0B782479BDDFAA91B90B6411 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 9D35AC44AE90C1C27CBF8577 /* Build configuration list for PBXNativeTarget "ContentCards" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0FF3E9103BDC67C9723BD0CD /* Debug */, + 508970482D723EDFFD096AB1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + B76990766EAEC18717669D6F /* Build configuration list for PBXNativeTarget "Location-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 277ABE8F9A11018387A77412 /* Debug */, + 61077A56E64ADBA96CA8CE0C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + C8DA1DB107E7EE64BBBAEBE7 /* Build configuration list for PBXNativeTarget "InAppMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BCF9BD39CEB19E634B6FD81 /* Debug */, + 4FCE20B3E84CE39D624EFA02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + D767F3158D7C98C16E53CE31 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C53D3849AB3D8DAE264A3A51 /* Debug */, + 0DB286FC893227921592442C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E26727234EAA2C9FFB557AF2 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2178EDBFBF71828E507601C1 /* Debug */, + 1CE2539A10E8624E8EDD3601 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = C9F9231105531CE428ADD921 /* Project object */; +} diff --git a/Examples/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/ObjC/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Examples/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/ObjC/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..f0f2dc6790 --- /dev/null +++ b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj @@ -0,0 +1,1928 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 01B00D06564F5BC3CC2CDD91 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */; }; + 02C558571508A77542FBC26C /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */; }; + 06F87FDA5F0E0E87D405F0BB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */; }; + 07DD9E6B75B3C3E0B7B93FF9 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 0D0836D2DE975E4BF0F3D051 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 75CC1E79A9D6815B60835BA2 /* Readme.m */; }; + 0E4B45AF1E749BA1333419FA /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */; }; + 0EA9500525189479BEEA2579 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 0F7C946151DE727574B396A6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 140EBDD7D126C0DB7E24563C /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 14174CD7F71ACF6F4F3E3808 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 176536B39FED72ECC2028BFC /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 0BF370808D2F5C21870331A0 /* SDWebImage */; }; + 17B09479DD77FD4EEFFF95E8 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 18ED90A49FD6D7527CB90B7E /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 1A810C7DA64E86D3A828A920 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + 1A93472F1D5EF8BE86567BE6 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */; }; + 23FF6692F5A6D268DC355315 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; }; + 241F4F1F41D820C55156841D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 24400D6B97710B109BDD8A60 /* BrazePushStory in Frameworks */ = {isa = PBXBuildFile; productRef = 5133F5A2D91882A4AE649D4D /* BrazePushStory */; }; + 28C5F7A47286B0D4233CFD93 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D56D9CC866EB37EFC5EFD4 /* Readme.m */; }; + 2A160FCCE45E4690E694D46A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D912E013554F7C8A41F0ED /* AppDelegate.m */; }; + 2C47D73C2D8F2F68DF83612B /* BrazeNotificationService in Frameworks */ = {isa = PBXBuildFile; productRef = 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */; }; + 2D4560AC04CE0BEC2BB8749B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 2E68CB6DC13AC6CB1441D20B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; }; + 2EB145FE4832264DD7ACC3F3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 971900217FE69BE4658FE8B2 /* AppDelegate.m */; }; + 2F8F5E0C5161968068CC2A05 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 312590E9832D85052B8D9759 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F4168F1485105BAAD54B813C /* BrazeKit */; }; + 335CAD4EA24AFBE63B9199B9 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 35D55D4145464F3D006D4019 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B1FA52497F602A50792867 /* Readme.m */; }; + 365EF0CD30923A1254130722 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F68192C4A0D4928F78762878 /* BrazeKit */; }; + 3B3CDE3FA9E39EE3140F5421 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 3B90DD85782F3701AD557A6A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; }; + 3CF570CEA985E07B3DBFBBBE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */; }; + 432AF81580216BC7FECF3E0A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 437AA7B38193226049B72FBE /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 74D6487EFD8114F6B61637AB /* BrazeKit */; }; + 4484E207BCFD002822F2BB7D /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE00D10FF658213E5A00188D /* NotificationViewController.swift */; }; + 4B2B9B16A40D85A3093F1C41 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */; }; + 4BC9D0026B4908271DF68F19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 4D223F6F99924DC08BF93EE6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 4EFDEFD372D670CB56731D3E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 4FCC18D09440113FCC444C49 /* PushNotificationsContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 51E6A2F0C6E2C992A51F5F20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 55343C252FC045A6B70D521D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 59DE5747C69E47CB456FDA44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 5C0D56998D46869E0617E5A4 /* BrazeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 9AF0AF048F752A5C62317470 /* BrazeUI */; }; + 5C506223F8E16936EFF1ECAA /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 75CC1E79A9D6815B60835BA2 /* Readme.m */; }; + 60A6EE4C2AF712684F1045C5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 627920814F95860FB73D560F /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 6859B8749DCA922A8E670008 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 693EE86FDDA758DF36715F51 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 90388C63B5CA3065EB14C5E7 /* Readme.m */; }; + 69765CD7313717A7FF7B4C30 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D912E013554F7C8A41F0ED /* AppDelegate.m */; }; + 6CE3551AF54503A3FA2E7853 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 046845029FE9235B46B84104 /* BrazeKit */; }; + 6D91E6B536F0C7585E809607 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 17D80570112755DC2EEEF450 /* BrazeKit */; }; + 6DA15916A0F0F7ECF3968E42 /* PushNotificationsServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 6E358B236135C54CF185EEDC /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 6FAFF3BA371E41638E044127 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 89598718421C181B57346379 /* BrazeKit */; }; + 75D4A5808678A333BC37FD62 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 78D5F4892287E2A080AFD065 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 7CCE66927CDCF27343C8A19F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + 7F8916648BED7D17A1F5F6D4 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B1FA52497F602A50792867 /* Readme.m */; }; + 80D345EAA814805B7B762A4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + 85EBAD10002EFE00116C0892 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 87824C15AAA2003EC964C107 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08CE7C19F258AF40B394B358 /* UserNotifications.framework */; }; + 8992304A2D2955D1BA1A6F32 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + 89CC79B20BACB82640928264 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + 8A8EC9A9DB4F12593F3BA68F /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */; }; + 8EC99177B84C2FD480B24D33 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + 99DA0F0635AE21C1096495B9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8783B6A324D425D55615AFD9 /* AppDelegate.m */; }; + 99EF7BD971D6D5849078F00F /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + 9CE6B2D9DC0F3B277094AEB9 /* BrazeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 26C11D75220DCD8456AEAA39 /* BrazeUI */; }; + 9D70D60D63C3590056AE7BE9 /* CustomInAppMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */; }; + 9EC27A7D337A4DF0A2F94484 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + A47F4EBAA7A0D8D9694CDBED /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5A50D1AF8D80AC6C465155 /* BrazeKit */; }; + A4BD0CF594F83266F2C9DFB1 /* CardsInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */; }; + A725268792A6C2039D9C402B /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */; }; + AD0FB326BFA4C3E7A64469FA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + ADBC780DCB0B446D08B01BD7 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */; }; + AE9B5583963142DD6C7E2B7F /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63F498CAD1B487B718A6064 /* NotificationService.swift */; }; + AF2CC1B40270C6B61BCB36F3 /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */; }; + B17B4317A4822F6631A83E7B /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 7509FFDD2664F798C716F648 /* Readme.m */; }; + B1EA445BF1E43473B3F7A9EF /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B01598D5924C3065B7D516B /* Readme.m */; }; + B4AC1050912335DCAFDA50DC /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + B596113707879825CDA4F233 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 971900217FE69BE4658FE8B2 /* AppDelegate.m */; }; + B8FC11110451BE51D3352A0D /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + BA93CBED2945FD7B06611823 /* InAppMessageInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */; }; + BD418D0ABB09B10266CCEB9A /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */; }; + BD7243FA7D8B321F7E1B5BBF /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + C412D2A3E605123FE5CBFAB2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + C81EA3048E9D8CED3B3EDD97 /* BrazeLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 2C4994F9E91F986F0629979F /* BrazeLocation */; }; + C871120C2B04423F52FA3E92 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + CBE072256EDCC746C7BC2D29 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 12036F06D0B199D8445FCB1B /* AppDelegate.m */; }; + CD7221C36FFBC58EB536C550 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + CEC66A96DFFBEFAF75B10DD0 /* BrazeLocation in Frameworks */ = {isa = PBXBuildFile; productRef = A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */; }; + D02EBC8DF2A796ED2C9CEFC0 /* Readme.m in Sources */ = {isa = PBXBuildFile; fileRef = 7509FFDD2664F798C716F648 /* Readme.m */; }; + D0680AB119405ED4AD4AB35A /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + D0FB8791620F800C7485E52B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */; }; + D24015C9E60BC0AB214C4F83 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */; }; + D2A2CF406EE7D523247B45DD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + DB84622E0C40467BD20C3779 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */; }; + DBC0B617306F2A138194200C /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 80661DB9711EFD43546E249C /* BrazeKit */; }; + DD69D41758F99D463763675A /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + DE22594DD1123178B1CC7771 /* ReadmeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */; }; + DF5F3076246E4D156FA5A3F8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; + DFB6A101BCD151F5B9651D82 /* AuthenticationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */; }; + E743EAE4518F62189A4D3C8A /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = F173FCAB52D0340802119A34 /* BrazeKit */; }; + E7996808D67A3A1A043A0731 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8783B6A324D425D55615AFD9 /* AppDelegate.m */; }; + EA8ED23E897565712389CE3F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE7DAF62AE545D7087BB7032 /* AppDelegate.m */; }; + EC57F25FE46BBD05EA33C939 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08CE7C19F258AF40B394B358 /* UserNotifications.framework */; }; + ED42AFACDCE40F3510BCCB65 /* BRZGIFViewProvider+SDWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */; }; + EEDF56D9E060B1301014A6B0 /* CheckoutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */; }; + EF5ED1AD6790AA461DC0B2C6 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + EF5EF251D34064B14F500469 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 09701E67CAE64FCE46458059 /* BrazeKit */; }; + F658BE141364C2F62F7866D1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */; }; + F85EF5BC8A69B68633529B36 /* Credentials.m in Sources */ = {isa = PBXBuildFile; fileRef = A900B781B2DFE220B129E338 /* Credentials.m */; }; + F95AE350417AB5ED6CEDECCB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */; }; + FF9046579962F0EBB98DB78C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6459ADE015D6A93F4DDEF4D8 /* main.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 401588D076F789179E1A0954 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D0C505F98E2813EFE5D58816 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 842A3D91E0A246B872DA9846; + remoteInfo = PushNotificationsServiceExtension; + }; + E63F56BE4C659BB9547002CB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D0C505F98E2813EFE5D58816 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E59DB4201FEAE1A212979375; + remoteInfo = PushNotificationsContentExtension; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 75C027D366D7264EE07F1AC3 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 6DA15916A0F0F7ECF3968E42 /* PushNotificationsServiceExtension.appex in Embed App Extensions */, + 4FCC18D09440113FCC444C49 /* PushNotificationsContentExtension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 01BB19FD80E90EE93B172CF8 /* InAppMessageInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InAppMessageInfoViewController.h; sourceTree = ""; }; + 08CE7C19F258AF40B394B358 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; + 0B3605C45690205D4A58D1C3 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 12036F06D0B199D8445FCB1B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 142C43EBD6AA34841D26163C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReadmeViewController.m; sourceTree = ""; }; + 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ../..; sourceTree = SOURCE_ROOT; }; + 31F63E82703CC19F27872526 /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; }; + 324D8E917E21EC25C2E0EC7C /* AuthenticationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticationManager.h; sourceTree = ""; }; + 34BD000896FB64DC78BBF177 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 35A0BE5C8816D747CCA37863 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomInAppMessagePresenter.m; sourceTree = ""; }; + 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationManager.m; sourceTree = ""; }; + 40B1FA52497F602A50792867 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 54B2132B425902ECA87672DE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CardsInfoViewController.m; sourceTree = ""; }; + 5B01598D5924C3065B7D516B /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 5DFFFE740A88297EE59DB98F /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 631AC4EE3B6D81ACA0DBEFBE /* CardsInfoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardsInfoViewController.h; sourceTree = ""; }; + 6459ADE015D6A93F4DDEF4D8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 64B22ACFDEB977C9F3B3B67E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 65785E585247CC7A8661ED6B /* InAppMessages.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = InAppMessages.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7509FFDD2664F798C716F648 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 75CC1E79A9D6815B60835BA2 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 7D76AFE44929AD2F889183E3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 84D56D9CC866EB37EFC5EFD4 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 85EB91B2555C84CBD26F79F6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 8783B6A324D425D55615AFD9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = PushNotifications.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 90388C63B5CA3065EB14C5E7 /* Readme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Readme.m; sourceTree = ""; }; + 971900217FE69BE4658FE8B2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Analytics.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; }; + A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsContentExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + A900B781B2DFE220B129E338 /* Credentials.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Credentials.m; sourceTree = ""; }; + AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InAppMessageInfoViewController.m; sourceTree = ""; }; + B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; }; + B558422CCA055B4615F43572 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = PushNotificationsServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + B7F06535E19BAEA9F5B73F86 /* ContentCards.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = ContentCards.app; sourceTree = BUILT_PRODUCTS_DIR; }; + BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + C1B822E14D6196E0BDCC531E /* ReadmeAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeAction.h; sourceTree = ""; }; + C79CCF16B994DB3DCD63BE74 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + CE00D10FF658213E5A00188D /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; }; + CF2BBB04F875FF5FA863FC82 /* CustomInAppMessagePresenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomInAppMessagePresenter.h; sourceTree = ""; }; + CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckoutViewController.m; sourceTree = ""; }; + D63F498CAD1B487B718A6064 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; + E5F704300A66AB9522AA5F94 /* CheckoutViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckoutViewController.h; sourceTree = ""; }; + E86CD93FBF04F90F0ADCF89D /* BRZGIFViewProvider+SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BRZGIFViewProvider+SDWebImage.h"; sourceTree = ""; }; + ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + EE631F5EEEEB707468BF265A /* Location.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Location.app; sourceTree = BUILT_PRODUCTS_DIR; }; + EE718585DF8925CE6290EB8E /* ReadmeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReadmeViewController.h; sourceTree = ""; }; + EE7DAF62AE545D7087BB7032 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + F7D912E013554F7C8A41F0ED /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "BRZGIFViewProvider+SDWebImage.m"; sourceTree = ""; }; + FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "InAppMessages-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 034FEEA975C05994B9129B8E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 437AA7B38193226049B72FBE /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 183E99B0677A3CBB42A80754 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EC57F25FE46BBD05EA33C939 /* UserNotifications.framework in Frameworks */, + 2C47D73C2D8F2F68DF83612B /* BrazeNotificationService in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 324CB6E38E7D86E327812A17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DBC0B617306F2A138194200C /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3FE4CCA5EE34D160D3BA7E65 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EF5EF251D34064B14F500469 /* BrazeKit in Frameworks */, + 5C0D56998D46869E0617E5A4 /* BrazeUI in Frameworks */, + 176536B39FED72ECC2028BFC /* SDWebImage in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4049520CA36B4E21D2DCFCC1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 312590E9832D85052B8D9759 /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4E1BD2E76D5B08698C2D0853 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 87824C15AAA2003EC964C107 /* UserNotifications.framework in Frameworks */, + AF2CC1B40270C6B61BCB36F3 /* UserNotificationsUI.framework in Frameworks */, + 24400D6B97710B109BDD8A60 /* BrazePushStory in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4F5A962E7AA8DBEA0DB50C60 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A47F4EBAA7A0D8D9694CDBED /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6E70CCCD8CEE5D68B1E92800 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6FAFF3BA371E41638E044127 /* BrazeKit in Frameworks */, + 9CE6B2D9DC0F3B277094AEB9 /* BrazeUI in Frameworks */, + 02C558571508A77542FBC26C /* SDWebImage in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76AEEA4F011020D515A98A7F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BD418D0ABB09B10266CCEB9A /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8263C301708EEA6D3CF6B118 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D91E6B536F0C7585E809607 /* BrazeKit in Frameworks */, + CEC66A96DFFBEFAF75B10DD0 /* BrazeLocation in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9D55980B7C6BF6E4EEC94491 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 365EF0CD30923A1254130722 /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BC9BA8958DF88D295215D932 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6CE3551AF54503A3FA2E7853 /* BrazeKit in Frameworks */, + C81EA3048E9D8CED3B3EDD97 /* BrazeLocation in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EFAF41E4C424F1D471C539B5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E743EAE4518F62189A4D3C8A /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 051DD5EB27092FF8E610A438 /* tvOS */ = { + isa = PBXGroup; + children = ( + 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */, + ); + path = tvOS; + sourceTree = ""; + }; + 119FF3F930BD1BF66DEB0B47 /* ContentCards-Custom-UI */ = { + isa = PBXGroup; + children = ( + 54B2132B425902ECA87672DE /* AppDelegate.h */, + 8783B6A324D425D55615AFD9 /* AppDelegate.m */, + 631AC4EE3B6D81ACA0DBEFBE /* CardsInfoViewController.h */, + 5634FD53344A83FD267AB580 /* CardsInfoViewController.m */, + 7509FFDD2664F798C716F648 /* Readme.m */, + ); + name = "ContentCards-Custom-UI"; + path = "Sources/ContentCards-Custom-UI"; + sourceTree = ""; + }; + 234FC0FDE1EB1D2B1EE92CDA /* ContentCards */ = { + isa = PBXGroup; + children = ( + C79CCF16B994DB3DCD63BE74 /* AppDelegate.h */, + EE7DAF62AE545D7087BB7032 /* AppDelegate.m */, + E86CD93FBF04F90F0ADCF89D /* BRZGIFViewProvider+SDWebImage.h */, + A372FC98EA508F503CE11C30 /* BRZGIFViewProvider+SDWebImage.m */, + 90388C63B5CA3065EB14C5E7 /* Readme.m */, + ); + name = ContentCards; + path = Sources/ContentCards; + sourceTree = ""; + }; + 256C64FD5A9C547C95ED205A /* Location */ = { + isa = PBXGroup; + children = ( + B558422CCA055B4615F43572 /* AppDelegate.h */, + BC5EE8BE3BAD32DB6D66AC70 /* AppDelegate.m */, + 40B1FA52497F602A50792867 /* Readme.m */, + ); + name = Location; + path = Sources/Location; + sourceTree = ""; + }; + 258F28BC46EE3F2D3E079C37 /* Analytics */ = { + isa = PBXGroup; + children = ( + 64B22ACFDEB977C9F3B3B67E /* AppDelegate.h */, + 971900217FE69BE4658FE8B2 /* AppDelegate.m */, + 324D8E917E21EC25C2E0EC7C /* AuthenticationManager.h */, + 3BF7AC51A554A71CFA452B84 /* AuthenticationManager.m */, + E5F704300A66AB9522AA5F94 /* CheckoutViewController.h */, + CFCDF89427142AC55571D3A4 /* CheckoutViewController.m */, + 75CC1E79A9D6815B60835BA2 /* Readme.m */, + ); + name = Analytics; + path = Sources/Analytics; + sourceTree = ""; + }; + 602D317DF9E1FCBC46B4F176 /* PushNotificationsContentExtension */ = { + isa = PBXGroup; + children = ( + CE00D10FF658213E5A00188D /* NotificationViewController.swift */, + ); + name = PushNotificationsContentExtension; + path = Sources/PushNotificationsContentExtension; + sourceTree = ""; + }; + 63C766BFE288147BB97F9A4E /* iOS */ = { + isa = PBXGroup; + children = ( + 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */, + ); + path = iOS; + sourceTree = ""; + }; + 67175574AAFF46A4632B42DA /* PushNotifications */ = { + isa = PBXGroup; + children = ( + 35A0BE5C8816D747CCA37863 /* AppDelegate.h */, + 12036F06D0B199D8445FCB1B /* AppDelegate.m */, + 84D56D9CC866EB37EFC5EFD4 /* Readme.m */, + ); + name = PushNotifications; + path = Sources/PushNotifications; + sourceTree = ""; + }; + 6E715B0CD6028EAEB53373C9 /* InAppMessages-Custom-UI */ = { + isa = PBXGroup; + children = ( + 85EB91B2555C84CBD26F79F6 /* AppDelegate.h */, + F7D912E013554F7C8A41F0ED /* AppDelegate.m */, + CF2BBB04F875FF5FA863FC82 /* CustomInAppMessagePresenter.h */, + 3A8584CCE6D9BBC4C2F634BB /* CustomInAppMessagePresenter.m */, + 01BB19FD80E90EE93B172CF8 /* InAppMessageInfoViewController.h */, + AF02C869BF9AFF144C7C90DF /* InAppMessageInfoViewController.m */, + 5FFCA5A7A3B8EF9BFE4BF145 /* Readme.m */, + ); + name = "InAppMessages-Custom-UI"; + path = "Sources/InAppMessages-Custom-UI"; + sourceTree = ""; + }; + A3A2735A5DC208B24378D437 /* InAppMessages */ = { + isa = PBXGroup; + children = ( + 7D76AFE44929AD2F889183E3 /* AppDelegate.h */, + 9A5ECFB24E396F30D56AC2C5 /* AppDelegate.m */, + 31F63E82703CC19F27872526 /* BRZGIFViewProvider+SDWebImage.h */, + FBA572CA696173DD712458AD /* BRZGIFViewProvider+SDWebImage.m */, + 5B01598D5924C3065B7D516B /* Readme.m */, + ); + name = InAppMessages; + path = Sources/InAppMessages; + sourceTree = ""; + }; + AD1929AE02C13E7023AE1CA4 /* PushNotificationsServiceExtension */ = { + isa = PBXGroup; + children = ( + D63F498CAD1B487B718A6064 /* NotificationService.swift */, + ); + name = PushNotificationsServiceExtension; + path = Sources/PushNotificationsServiceExtension; + sourceTree = ""; + }; + B4F25C051708E808116165D4 /* Common */ = { + isa = PBXGroup; + children = ( + 0FCD17EEF41713F18F4CA702 /* Assets.xcassets */, + A900B781B2DFE220B129E338 /* Credentials.m */, + 6459ADE015D6A93F4DDEF4D8 /* main.m */, + C1B822E14D6196E0BDCC531E /* ReadmeAction.h */, + EE718585DF8925CE6290EB8E /* ReadmeViewController.h */, + 1EA72C16B9A189DE9D4D7A58 /* ReadmeViewController.m */, + 63C766BFE288147BB97F9A4E /* iOS */, + 051DD5EB27092FF8E610A438 /* tvOS */, + ); + name = Common; + path = Sources/Common; + sourceTree = ""; + }; + CD535985A50FFC8EDE928813 /* Products */ = { + isa = PBXGroup; + children = ( + 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */, + 0B3605C45690205D4A58D1C3 /* Analytics.app */, + 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */, + 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */, + B7F06535E19BAEA9F5B73F86 /* ContentCards.app */, + FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */, + ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */, + 65785E585247CC7A8661ED6B /* InAppMessages.app */, + EE631F5EEEEB707468BF265A /* Location.app */, + 5DFFFE740A88297EE59DB98F /* Location.app */, + 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */, + A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */, + B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */, + ); + name = Products; + sourceTree = ""; + }; + D8CC2266D736859D7DD9A8FF = { + isa = PBXGroup; + children = ( + E3AF9F206199B993ACB3E63D /* Packages */, + B4F25C051708E808116165D4 /* Common */, + 258F28BC46EE3F2D3E079C37 /* Analytics */, + 234FC0FDE1EB1D2B1EE92CDA /* ContentCards */, + 119FF3F930BD1BF66DEB0B47 /* ContentCards-Custom-UI */, + A3A2735A5DC208B24378D437 /* InAppMessages */, + 6E715B0CD6028EAEB53373C9 /* InAppMessages-Custom-UI */, + 256C64FD5A9C547C95ED205A /* Location */, + 67175574AAFF46A4632B42DA /* PushNotifications */, + 602D317DF9E1FCBC46B4F176 /* PushNotificationsContentExtension */, + AD1929AE02C13E7023AE1CA4 /* PushNotificationsServiceExtension */, + DF23D21F2F74022094519AC3 /* Frameworks */, + CD535985A50FFC8EDE928813 /* Products */, + ); + sourceTree = ""; + }; + DF23D21F2F74022094519AC3 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 08CE7C19F258AF40B394B358 /* UserNotifications.framework */, + B0D325AE1E7E717D151B9B6B /* UserNotificationsUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E3AF9F206199B993ACB3E63D /* Packages */ = { + isa = PBXGroup; + children = ( + 220432BEC0EA7628608EA5BA /* braze-swift-sdk */, + ); + name = Packages; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3AA5E6D1B97103DC27376A6D /* Analytics-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = E00B5C25BE5714D67E69A3EF /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */; + buildPhases = ( + B0576C5CB7B8374AB804BA17 /* Sources */, + 664A25CB9C7D704EEBC5573D /* Resources */, + 324CB6E38E7D86E327812A17 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics-tvOS"; + packageProductDependencies = ( + 80661DB9711EFD43546E249C /* BrazeKit */, + ); + productName = "Analytics-tvOS"; + productReference = 0B3605C45690205D4A58D1C3 /* Analytics.app */; + productType = "com.apple.product-type.application"; + }; + 4B98C28FD93E5AD15DE94535 /* Analytics-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 264E98511670D6BD7B0E64D2 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */; + buildPhases = ( + BDD30223625DA51AFB115FE3 /* Sources */, + 1B55699C3892866CC2E3380D /* Resources */, + 034FEEA975C05994B9129B8E /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Analytics-iOS"; + packageProductDependencies = ( + 74D6487EFD8114F6B61637AB /* BrazeKit */, + ); + productName = "Analytics-iOS"; + productReference = 9EDFB6B6D9E65C9BFD47EA17 /* Analytics.app */; + productType = "com.apple.product-type.application"; + }; + 5BE2DFC918DF0CC5E69FE387 /* InAppMessages */ = { + isa = PBXNativeTarget; + buildConfigurationList = F76B079D8771880EE7A2C01D /* Build configuration list for PBXNativeTarget "InAppMessages" */; + buildPhases = ( + 629101DE070207860B0FF0B5 /* Sources */, + 3D8D07DBB7AF1C865DA26D8E /* Resources */, + 3FE4CCA5EE34D160D3BA7E65 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = InAppMessages; + packageProductDependencies = ( + 09701E67CAE64FCE46458059 /* BrazeKit */, + 9AF0AF048F752A5C62317470 /* BrazeUI */, + 0BF370808D2F5C21870331A0 /* SDWebImage */, + ); + productName = InAppMessages; + productReference = 65785E585247CC7A8661ED6B /* InAppMessages.app */; + productType = "com.apple.product-type.application"; + }; + 6EC91F0D0FFF467CD90FB0D3 /* InAppMessages-Custom-UI-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5FD7F38C2E047474FF2AE862 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */; + buildPhases = ( + ED315B5B4830F964E3577CD9 /* Sources */, + 1555F7408F765567E3544A08 /* Resources */, + 76AEEA4F011020D515A98A7F /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "InAppMessages-Custom-UI-tvOS"; + packageProductDependencies = ( + 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */, + ); + productName = "InAppMessages-Custom-UI-tvOS"; + productReference = ECA5D86743A8F050AB493312 /* InAppMessages-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = FB6122990820F57E6DB4A7D6 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */; + buildPhases = ( + 0F4E3ECA66B0F7D180D317DF /* Sources */, + 183E99B0677A3CBB42A80754 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PushNotificationsServiceExtension; + packageProductDependencies = ( + 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */, + ); + productName = PushNotificationsServiceExtension; + productReference = B5666DA142189EEEDFAFB41F /* PushNotificationsServiceExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 9292D3D6E47059505F536422 /* Location-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 340804EFAD862F854E93596B /* Build configuration list for PBXNativeTarget "Location-tvOS" */; + buildPhases = ( + 2A4DDD3E0061EBB62528F184 /* Sources */, + 01F1E28DC32E6EFA39BE54C8 /* Resources */, + 8263C301708EEA6D3CF6B118 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Location-tvOS"; + packageProductDependencies = ( + 17D80570112755DC2EEEF450 /* BrazeKit */, + A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */, + ); + productName = "Location-tvOS"; + productReference = 5DFFFE740A88297EE59DB98F /* Location.app */; + productType = "com.apple.product-type.application"; + }; + 960C133F6A6AD264A11DD8D9 /* ContentCards-Custom-UI-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 52115E4788F114BD9F51C612 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */; + buildPhases = ( + E2EFE22428A2F3EEA61751F5 /* Sources */, + FDCF284FAF6DD56D949E0F0F /* Resources */, + 4F5A962E7AA8DBEA0DB50C60 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ContentCards-Custom-UI-iOS"; + packageProductDependencies = ( + 9F5A50D1AF8D80AC6C465155 /* BrazeKit */, + ); + productName = "ContentCards-Custom-UI-iOS"; + productReference = 870B27433E30991ABA197CD2 /* ContentCards-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + 9B3876462D904A1496AF569D /* Location-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9D5AEEE5B58C1044A4BA612B /* Build configuration list for PBXNativeTarget "Location-iOS" */; + buildPhases = ( + DADCD7F86B712F9D6A7C1EB7 /* Sources */, + 69FB3C575524EEDC0F2FC486 /* Resources */, + BC9BA8958DF88D295215D932 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Location-iOS"; + packageProductDependencies = ( + 046845029FE9235B46B84104 /* BrazeKit */, + 2C4994F9E91F986F0629979F /* BrazeLocation */, + ); + productName = "Location-iOS"; + productReference = EE631F5EEEEB707468BF265A /* Location.app */; + productType = "com.apple.product-type.application"; + }; + B64E1C1C2CDBA52874450596 /* PushNotifications */ = { + isa = PBXNativeTarget; + buildConfigurationList = 35795D9DBF2411B548D5563D /* Build configuration list for PBXNativeTarget "PushNotifications" */; + buildPhases = ( + 4D9E50A78216959662CAD320 /* Sources */, + 0AB603E26C615FD7EAD6D550 /* Resources */, + 4049520CA36B4E21D2DCFCC1 /* Frameworks */, + 75C027D366D7264EE07F1AC3 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 66C7DD376098B1684E2BD062 /* PBXTargetDependency */, + 385684E74F484291678D97E2 /* PBXTargetDependency */, + ); + name = PushNotifications; + packageProductDependencies = ( + F4168F1485105BAAD54B813C /* BrazeKit */, + ); + productName = PushNotifications; + productReference = 8D441B5B5424C3E129B2DA54 /* PushNotifications.app */; + productType = "com.apple.product-type.application"; + }; + BE02E0C55FAEA6294D129A38 /* ContentCards-Custom-UI-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 675C55871E9EBBD8A4279B5C /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */; + buildPhases = ( + 172685DE8A39EF99A470A7BD /* Sources */, + 2E3C6DE1806B99A424DECB0F /* Resources */, + EFAF41E4C424F1D471C539B5 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ContentCards-Custom-UI-tvOS"; + packageProductDependencies = ( + F173FCAB52D0340802119A34 /* BrazeKit */, + ); + productName = "ContentCards-Custom-UI-tvOS"; + productReference = 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; + DEE99E05C6F822DC78AEE272 /* ContentCards */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAC0A7E698E628D993F35934 /* Build configuration list for PBXNativeTarget "ContentCards" */; + buildPhases = ( + 6089EE24E3EFFEC175CB9A6A /* Sources */, + 1F3BD016FE47788CA94B7A4A /* Resources */, + 6E70CCCD8CEE5D68B1E92800 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ContentCards; + packageProductDependencies = ( + 89598718421C181B57346379 /* BrazeKit */, + 26C11D75220DCD8456AEAA39 /* BrazeUI */, + 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */, + ); + productName = ContentCards; + productReference = B7F06535E19BAEA9F5B73F86 /* ContentCards.app */; + productType = "com.apple.product-type.application"; + }; + E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 538A7D3F62B432A07C91FD40 /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */; + buildPhases = ( + ACB52B0CE581070F5BA1A8E7 /* Sources */, + 4E1BD2E76D5B08698C2D0853 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PushNotificationsContentExtension; + packageProductDependencies = ( + 5133F5A2D91882A4AE649D4D /* BrazePushStory */, + ); + productName = PushNotificationsContentExtension; + productReference = A7B092ACAEC915379923328F /* PushNotificationsContentExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + FD2447C0C6527F1CB2BEC9A6 /* InAppMessages-Custom-UI-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = EBB530AA4E1F5AF1FD5D5B58 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */; + buildPhases = ( + 1A26619C466A145AC378E755 /* Sources */, + 2524C2C4AECF5FA40FF674F8 /* Resources */, + 9D55980B7C6BF6E4EEC94491 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "InAppMessages-Custom-UI-iOS"; + packageProductDependencies = ( + F68192C4A0D4928F78762878 /* BrazeKit */, + ); + productName = "InAppMessages-Custom-UI-iOS"; + productReference = FF31C634A18224DB9ED02834 /* InAppMessages-Custom-UI.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D0C505F98E2813EFE5D58816 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1200; + TargetAttributes = { + }; + }; + buildConfigurationList = 121E4DAF0EB7FA3A0B03C3C0 /* Build configuration list for PBXProject "Examples-SwiftPM" */; + compatibilityVersion = "Xcode 11.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = D8CC2266D736859D7DD9A8FF; + packageReferences = ( + 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */, + ); + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4B98C28FD93E5AD15DE94535 /* Analytics-iOS */, + 3AA5E6D1B97103DC27376A6D /* Analytics-tvOS */, + DEE99E05C6F822DC78AEE272 /* ContentCards */, + 960C133F6A6AD264A11DD8D9 /* ContentCards-Custom-UI-iOS */, + BE02E0C55FAEA6294D129A38 /* ContentCards-Custom-UI-tvOS */, + 5BE2DFC918DF0CC5E69FE387 /* InAppMessages */, + FD2447C0C6527F1CB2BEC9A6 /* InAppMessages-Custom-UI-iOS */, + 6EC91F0D0FFF467CD90FB0D3 /* InAppMessages-Custom-UI-tvOS */, + 9B3876462D904A1496AF569D /* Location-iOS */, + 9292D3D6E47059505F536422 /* Location-tvOS */, + B64E1C1C2CDBA52874450596 /* PushNotifications */, + E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */, + 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 01F1E28DC32E6EFA39BE54C8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 51E6A2F0C6E2C992A51F5F20 /* Assets.xcassets in Resources */, + D0FB8791620F800C7485E52B /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AB603E26C615FD7EAD6D550 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CD7221C36FFBC58EB536C550 /* Assets.xcassets in Resources */, + C871120C2B04423F52FA3E92 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1555F7408F765567E3544A08 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2D4560AC04CE0BEC2BB8749B /* Assets.xcassets in Resources */, + 23FF6692F5A6D268DC355315 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1B55699C3892866CC2E3380D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4BC9D0026B4908271DF68F19 /* Assets.xcassets in Resources */, + C412D2A3E605123FE5CBFAB2 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F3BD016FE47788CA94B7A4A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 241F4F1F41D820C55156841D /* Assets.xcassets in Resources */, + AD0FB326BFA4C3E7A64469FA /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2524C2C4AECF5FA40FF674F8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9EC27A7D337A4DF0A2F94484 /* Assets.xcassets in Resources */, + F658BE141364C2F62F7866D1 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2E3C6DE1806B99A424DECB0F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 14174CD7F71ACF6F4F3E3808 /* Assets.xcassets in Resources */, + 3B90DD85782F3701AD557A6A /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3D8D07DBB7AF1C865DA26D8E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8EC99177B84C2FD480B24D33 /* Assets.xcassets in Resources */, + 80D345EAA814805B7B762A4E /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 664A25CB9C7D704EEBC5573D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 59DE5747C69E47CB456FDA44 /* Assets.xcassets in Resources */, + 2E68CB6DC13AC6CB1441D20B /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 69FB3C575524EEDC0F2FC486 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3B3CDE3FA9E39EE3140F5421 /* Assets.xcassets in Resources */, + 1A810C7DA64E86D3A828A920 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDCF284FAF6DD56D949E0F0F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F95AE350417AB5ED6CEDECCB /* Assets.xcassets in Resources */, + 89CC79B20BACB82640928264 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0F4E3ECA66B0F7D180D317DF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AE9B5583963142DD6C7E2B7F /* NotificationService.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 172685DE8A39EF99A470A7BD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 99DA0F0635AE21C1096495B9 /* AppDelegate.m in Sources */, + 01B00D06564F5BC3CC2CDD91 /* CardsInfoViewController.m in Sources */, + DD69D41758F99D463763675A /* Credentials.m in Sources */, + B17B4317A4822F6631A83E7B /* Readme.m in Sources */, + 17B09479DD77FD4EEFFF95E8 /* ReadmeViewController.m in Sources */, + 60A6EE4C2AF712684F1045C5 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1A26619C466A145AC378E755 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 69765CD7313717A7FF7B4C30 /* AppDelegate.m in Sources */, + F85EF5BC8A69B68633529B36 /* Credentials.m in Sources */, + 9D70D60D63C3590056AE7BE9 /* CustomInAppMessagePresenter.m in Sources */, + BA93CBED2945FD7B06611823 /* InAppMessageInfoViewController.m in Sources */, + 8A8EC9A9DB4F12593F3BA68F /* Readme.m in Sources */, + 6E358B236135C54CF185EEDC /* ReadmeViewController.m in Sources */, + 2F8F5E0C5161968068CC2A05 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2A4DDD3E0061EBB62528F184 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06F87FDA5F0E0E87D405F0BB /* AppDelegate.m in Sources */, + 18ED90A49FD6D7527CB90B7E /* Credentials.m in Sources */, + 7F8916648BED7D17A1F5F6D4 /* Readme.m in Sources */, + 8992304A2D2955D1BA1A6F32 /* ReadmeViewController.m in Sources */, + 7CCE66927CDCF27343C8A19F /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4D9E50A78216959662CAD320 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CBE072256EDCC746C7BC2D29 /* AppDelegate.m in Sources */, + EF5ED1AD6790AA461DC0B2C6 /* Credentials.m in Sources */, + 28C5F7A47286B0D4233CFD93 /* Readme.m in Sources */, + D0680AB119405ED4AD4AB35A /* ReadmeViewController.m in Sources */, + DF5F3076246E4D156FA5A3F8 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6089EE24E3EFFEC175CB9A6A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EA8ED23E897565712389CE3F /* AppDelegate.m in Sources */, + ED42AFACDCE40F3510BCCB65 /* BRZGIFViewProvider+SDWebImage.m in Sources */, + 75D4A5808678A333BC37FD62 /* Credentials.m in Sources */, + 693EE86FDDA758DF36715F51 /* Readme.m in Sources */, + 0EA9500525189479BEEA2579 /* ReadmeViewController.m in Sources */, + FF9046579962F0EBB98DB78C /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 629101DE070207860B0FF0B5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3CF570CEA985E07B3DBFBBBE /* AppDelegate.m in Sources */, + DB84622E0C40467BD20C3779 /* BRZGIFViewProvider+SDWebImage.m in Sources */, + 78D5F4892287E2A080AFD065 /* Credentials.m in Sources */, + B1EA445BF1E43473B3F7A9EF /* Readme.m in Sources */, + DE22594DD1123178B1CC7771 /* ReadmeViewController.m in Sources */, + 0F7C946151DE727574B396A6 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ACB52B0CE581070F5BA1A8E7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4484E207BCFD002822F2BB7D /* NotificationViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B0576C5CB7B8374AB804BA17 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2EB145FE4832264DD7ACC3F3 /* AppDelegate.m in Sources */, + 0E4B45AF1E749BA1333419FA /* AuthenticationManager.m in Sources */, + A725268792A6C2039D9C402B /* CheckoutViewController.m in Sources */, + 140EBDD7D126C0DB7E24563C /* Credentials.m in Sources */, + 0D0836D2DE975E4BF0F3D051 /* Readme.m in Sources */, + 335CAD4EA24AFBE63B9199B9 /* ReadmeViewController.m in Sources */, + 4EFDEFD372D670CB56731D3E /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BDD30223625DA51AFB115FE3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B596113707879825CDA4F233 /* AppDelegate.m in Sources */, + DFB6A101BCD151F5B9651D82 /* AuthenticationManager.m in Sources */, + EEDF56D9E060B1301014A6B0 /* CheckoutViewController.m in Sources */, + BD7243FA7D8B321F7E1B5BBF /* Credentials.m in Sources */, + 5C506223F8E16936EFF1ECAA /* Readme.m in Sources */, + 85EBAD10002EFE00116C0892 /* ReadmeViewController.m in Sources */, + D2A2CF406EE7D523247B45DD /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DADCD7F86B712F9D6A7C1EB7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D24015C9E60BC0AB214C4F83 /* AppDelegate.m in Sources */, + 6859B8749DCA922A8E670008 /* Credentials.m in Sources */, + 35D55D4145464F3D006D4019 /* Readme.m in Sources */, + B4AC1050912335DCAFDA50DC /* ReadmeViewController.m in Sources */, + 4D223F6F99924DC08BF93EE6 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E2EFE22428A2F3EEA61751F5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7996808D67A3A1A043A0731 /* AppDelegate.m in Sources */, + A4BD0CF594F83266F2C9DFB1 /* CardsInfoViewController.m in Sources */, + 99EF7BD971D6D5849078F00F /* Credentials.m in Sources */, + D02EBC8DF2A796ED2C9CEFC0 /* Readme.m in Sources */, + B8FC11110451BE51D3352A0D /* ReadmeViewController.m in Sources */, + 55343C252FC045A6B70D521D /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ED315B5B4830F964E3577CD9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A160FCCE45E4690E694D46A /* AppDelegate.m in Sources */, + 07DD9E6B75B3C3E0B7B93FF9 /* Credentials.m in Sources */, + 4B2B9B16A40D85A3093F1C41 /* CustomInAppMessagePresenter.m in Sources */, + ADBC780DCB0B446D08B01BD7 /* InAppMessageInfoViewController.m in Sources */, + 1A93472F1D5EF8BE86567BE6 /* Readme.m in Sources */, + 627920814F95860FB73D560F /* ReadmeViewController.m in Sources */, + 432AF81580216BC7FECF3E0A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 385684E74F484291678D97E2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E59DB4201FEAE1A212979375 /* PushNotificationsContentExtension */; + targetProxy = E63F56BE4C659BB9547002CB /* PBXContainerItemProxy */; + }; + 66C7DD376098B1684E2BD062 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 842A3D91E0A246B872DA9846 /* PushNotificationsServiceExtension */; + targetProxy = 401588D076F789179E1A0954 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 415A55D2760CB84A0CC3A13B /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 142C43EBD6AA34841D26163C /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + 5F65978FE19A988D7A5454A3 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 34BD000896FB64DC78BBF177 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0226A27891A69D569C8744B7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/PushNotifications/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications; + PRODUCT_NAME = PushNotifications; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 04F3025123A8C0FDDB374DAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS"; + PRODUCT_NAME = Location; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 2F370EA03C55814B29C4BB55 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS"; + PRODUCT_NAME = Location; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 31E178BAE5C8192F784A345A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS"; + PRODUCT_NAME = Analytics; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 338E775FC51FCA458B2B4AFB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/ContentCards/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards; + PRODUCT_NAME = ContentCards; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 35E8D78DF517B11959723F4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Debug; + }; + 4C1CEEB16B22B01668229861 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/ContentCards/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.ContentCards; + PRODUCT_NAME = ContentCards; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 56FADC974A57962ED605AB39 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/InAppMessages/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages; + PRODUCT_NAME = InAppMessages; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 582C70DAA75E87B5B1B59BCC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Release; + }; + 650A8DC9E70B7FE040122B24 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-iOS"; + PRODUCT_NAME = Analytics; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 6B390CBFB31F1AAE4B90AE70 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 6B3B491381885F5C52DC3552 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 71303405F07C56DBF2524662 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 765C7F79F40719BB865D4941 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS"; + PRODUCT_NAME = Analytics; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 8C57CF25A4A9E9D075CEAF3E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-tvOS"; + PRODUCT_NAME = Location; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 8F56A8E8C7781F27275F365C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + 95A967CAE2757BFC04407771 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-tvOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 97B315CB44E7F16916F9865E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-iOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 991EFD7B0772C9A99C44BCF4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "Sources/InAppMessages-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.InAppMessages-Custom-UI-tvOS"; + PRODUCT_NAME = "InAppMessages-Custom-UI"; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + 9E13FBC998B0A5499C68208A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + B9FD2D94FC2BF1DFA9DDA644 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements; + INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + BD14E68755890E23128DAB7A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = Sources/Analytics/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Analytics-tvOS"; + PRODUCT_NAME = Analytics; + SDKROOT = appletvos; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + BE47B129D3210EFFB3B5C0E3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements; + INFOPLIST_FILE = Sources/PushNotificationsContentExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsContentExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C13597180247AEC71E86CD9C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = "Sources/ContentCards-Custom-UI/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.ContentCards-Custom-UI-iOS"; + PRODUCT_NAME = "ContentCards-Custom-UI"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + DB1B706F4301DC478A0A4D4B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Sources/PushNotifications/PushNotifications.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/PushNotifications/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications; + PRODUCT_NAME = PushNotifications; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + F3C477DD3FBDBF3AB5B2FA92 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/InAppMessages/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.InAppMessages; + PRODUCT_NAME = InAppMessages; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + F83B82D7A7E5DB678B6196A6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + INFOPLIST_FILE = Sources/PushNotificationsServiceExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.braze.PushNotifications.PushNotificationsServiceExtension; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FF5221A5B39619377D55A14C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Sources/Location/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.braze.Location-iOS"; + PRODUCT_NAME = Location; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 121E4DAF0EB7FA3A0B03C3C0 /* Build configuration list for PBXProject "Examples-SwiftPM" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 35E8D78DF517B11959723F4D /* Debug */, + 582C70DAA75E87B5B1B59BCC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 264E98511670D6BD7B0E64D2 /* Build configuration list for PBXNativeTarget "Analytics-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 31E178BAE5C8192F784A345A /* Debug */, + 650A8DC9E70B7FE040122B24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 340804EFAD862F854E93596B /* Build configuration list for PBXNativeTarget "Location-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 04F3025123A8C0FDDB374DAA /* Debug */, + 8C57CF25A4A9E9D075CEAF3E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 35795D9DBF2411B548D5563D /* Build configuration list for PBXNativeTarget "PushNotifications" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB1B706F4301DC478A0A4D4B /* Debug */, + 0226A27891A69D569C8744B7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 52115E4788F114BD9F51C612 /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C13597180247AEC71E86CD9C /* Debug */, + 6B3B491381885F5C52DC3552 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 538A7D3F62B432A07C91FD40 /* Build configuration list for PBXNativeTarget "PushNotificationsContentExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BE47B129D3210EFFB3B5C0E3 /* Debug */, + B9FD2D94FC2BF1DFA9DDA644 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 5FD7F38C2E047474FF2AE862 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F56A8E8C7781F27275F365C /* Debug */, + 991EFD7B0772C9A99C44BCF4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 675C55871E9EBBD8A4279B5C /* Build configuration list for PBXNativeTarget "ContentCards-Custom-UI-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6B390CBFB31F1AAE4B90AE70 /* Debug */, + 95A967CAE2757BFC04407771 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 9D5AEEE5B58C1044A4BA612B /* Build configuration list for PBXNativeTarget "Location-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F370EA03C55814B29C4BB55 /* Debug */, + FF5221A5B39619377D55A14C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + DAC0A7E698E628D993F35934 /* Build configuration list for PBXNativeTarget "ContentCards" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 338E775FC51FCA458B2B4AFB /* Debug */, + 4C1CEEB16B22B01668229861 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E00B5C25BE5714D67E69A3EF /* Build configuration list for PBXNativeTarget "Analytics-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 765C7F79F40719BB865D4941 /* Debug */, + BD14E68755890E23128DAB7A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + EBB530AA4E1F5AF1FD5D5B58 /* Build configuration list for PBXNativeTarget "InAppMessages-Custom-UI-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97B315CB44E7F16916F9865E /* Debug */, + 71303405F07C56DBF2524662 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + F76B079D8771880EE7A2C01D /* Build configuration list for PBXNativeTarget "InAppMessages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 56FADC974A57962ED605AB39 /* Debug */, + F3C477DD3FBDBF3AB5B2FA92 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + FB6122990820F57E6DB4A7D6 /* Build configuration list for PBXNativeTarget "PushNotificationsServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F83B82D7A7E5DB678B6196A6 /* Debug */, + 9E13FBC998B0A5499C68208A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SDWebImage/SDWebImage"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.12.5; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 046845029FE9235B46B84104 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 09701E67CAE64FCE46458059 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 0BF370808D2F5C21870331A0 /* SDWebImage */ = { + isa = XCSwiftPackageProductDependency; + package = 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */; + productName = SDWebImage; + }; + 0D08CDAB0AE57DFC38F9B590 /* SDWebImage */ = { + isa = XCSwiftPackageProductDependency; + package = 9928D5150C45879A982BA1C6 /* XCRemoteSwiftPackageReference "SDWebImage" */; + productName = SDWebImage; + }; + 17D80570112755DC2EEEF450 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 26C11D75220DCD8456AEAA39 /* BrazeUI */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeUI; + }; + 2C4994F9E91F986F0629979F /* BrazeLocation */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeLocation; + }; + 47F3E12B1114B00B4CB70C60 /* BrazeNotificationService */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeNotificationService; + }; + 5133F5A2D91882A4AE649D4D /* BrazePushStory */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazePushStory; + }; + 74D6487EFD8114F6B61637AB /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 7793FD8C8DE601EC38DD8DD7 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 80661DB9711EFD43546E249C /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 89598718421C181B57346379 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + 9AF0AF048F752A5C62317470 /* BrazeUI */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeUI; + }; + 9F5A50D1AF8D80AC6C465155 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + A2D57BF9CEBB2DC10A5B3AE6 /* BrazeLocation */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeLocation; + }; + F173FCAB52D0340802119A34 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + F4168F1485105BAAD54B813C /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; + F68192C4A0D4928F78762878 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = BrazeKit; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = D0C505F98E2813EFE5D58816 /* Project object */; +} diff --git a/Examples/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Examples/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Examples/ObjC/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/Package.swift b/Examples/ObjC/Package.swift similarity index 100% rename from Examples/Package.swift rename to Examples/ObjC/Package.swift diff --git a/Examples/Podfile b/Examples/ObjC/Podfile similarity index 100% rename from Examples/Podfile rename to Examples/ObjC/Podfile diff --git a/Examples/ObjC/Sources/Analytics/AppDelegate.h b/Examples/ObjC/Sources/Analytics/AppDelegate.h new file mode 100644 index 0000000000..39f6d4eb6e --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/AppDelegate.h @@ -0,0 +1,11 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +@end diff --git a/Examples/ObjC/Sources/Analytics/AppDelegate.m b/Examples/ObjC/Sources/Analytics/AppDelegate.m new file mode 100644 index 0000000000..2f461c55ce --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/AppDelegate.m @@ -0,0 +1,35 @@ +#import "AppDelegate.h" + +@import BrazeKit; + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +@end diff --git a/Examples/ObjC/Sources/Analytics/AuthenticationManager.h b/Examples/ObjC/Sources/Analytics/AuthenticationManager.h new file mode 100644 index 0000000000..74db8f8851 --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/AuthenticationManager.h @@ -0,0 +1,23 @@ +@import Foundation; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - User + +@interface User : NSObject + +@property(copy, nonatomic) NSString *identifier; +@property(copy, nonatomic) NSString *email; +@property(strong, nonatomic) NSDate *birthday; + +@end + +#pragma mark - AuthenticationManager + +@interface AuthenticationManager : NSObject + +- (void)userDidLogin:(User *)user; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/ObjC/Sources/Analytics/AuthenticationManager.m b/Examples/ObjC/Sources/Analytics/AuthenticationManager.m new file mode 100644 index 0000000000..5438873804 --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/AuthenticationManager.m @@ -0,0 +1,22 @@ +#import "AuthenticationManager.h" +#import "AppDelegate.h" + +#pragma mark - User + +@implementation User +@end + +#pragma mark - AuthenticationManager + +@implementation AuthenticationManager + +- (void)userDidLogin:(User *)user { + [AppDelegate.braze changeUser:user.identifier]; + BRZUser *brazeUser = AppDelegate.braze.user; + [brazeUser setEmail:user.email]; + [brazeUser setDateOfBirth:user.birthday]; + [brazeUser setCustomAttributeWithKey:@"last_login_date" + dateValue:[NSDate date]]; +} + +@end diff --git a/Examples/ObjC/Sources/Analytics/CheckoutViewController.h b/Examples/ObjC/Sources/Analytics/CheckoutViewController.h new file mode 100644 index 0000000000..1f5cf3fb6c --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/CheckoutViewController.h @@ -0,0 +1,17 @@ +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface CheckoutViewController : UIViewController + +/// The internal checkout identifier +@property(copy, nonatomic) NSString *checkoutId; + +/// The list of identifiers for the products to checkout +@property(strong, nonatomic) NSArray *productIds; + +- (void)userDidPurchaseProduct:(NSString *)productId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/ObjC/Sources/Analytics/CheckoutViewController.m b/Examples/ObjC/Sources/Analytics/CheckoutViewController.m new file mode 100644 index 0000000000..ff7bf8fdea --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/CheckoutViewController.m @@ -0,0 +1,34 @@ +#import "CheckoutViewController.h" +#import "AppDelegate.h" + +@interface CheckoutViewController () + +- (double)priceForProduct:(NSString *)productId; + +@end + +@implementation CheckoutViewController + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [AppDelegate.braze logCustomEvent:@"open_checkout_controller" + properties:@{ + @"checkout_id" : self.checkoutId, + @"product_ids" : self.productIds, + }]; +} + +- (void)userDidPurchaseProduct:(NSString *)productId { + double price = [self priceForProduct:productId]; + [AppDelegate.braze logPurchase:productId + currency:@"USD" + price:price + properties:@{@"checkout_id" : self.checkoutId}]; +} + +- (double)priceForProduct:(NSString *)productId { + NSArray *prices = @[ @0.5, @8.0, @14.99, @0, @999.999 ]; + return prices[arc4random_uniform((uint32_t)prices.count)].doubleValue; +} + +@end diff --git a/Examples/Sources/Analytics/Info.plist b/Examples/ObjC/Sources/Analytics/Info.plist similarity index 100% rename from Examples/Sources/Analytics/Info.plist rename to Examples/ObjC/Sources/Analytics/Info.plist diff --git a/Examples/ObjC/Sources/Analytics/Readme.m b/Examples/ObjC/Sources/Analytics/Readme.m new file mode 100644 index 0000000000..26f49ec436 --- /dev/null +++ b/Examples/ObjC/Sources/Analytics/Readme.m @@ -0,0 +1,102 @@ +#import "AuthenticationManager.h" +#import "CheckoutViewController.h" +#import "ReadmeAction.h" +#import "ReadmeViewController.h" + +#pragma mark - Internal + +static AuthenticationManager *_authenticationManager; + +AuthenticationManager *authenticationManager(void) { + if (!_authenticationManager) { + _authenticationManager = [[AuthenticationManager alloc] init]; + } + return _authenticationManager; +} + +UINavigationController *createCheckoutNavigationController(void) { + NSArray *productIds = @[ + [NSUUID UUID].UUIDString, + [NSUUID UUID].UUIDString, + [NSUUID UUID].UUIDString, + ]; + + CheckoutViewController *checkoutViewController = + [[CheckoutViewController alloc] init]; + checkoutViewController.checkoutId = [NSUUID UUID].UUIDString; + checkoutViewController.productIds = productIds; + checkoutViewController.title = @"CheckoutViewController"; + checkoutViewController.view.backgroundColor = UIColor.whiteColor; + + UINavigationController *navigationController = [[UINavigationController alloc] + initWithRootViewController:checkoutViewController]; + + return navigationController; +} + +void authenticateUser(void) { + User *user = [[User alloc] init]; + user.identifier = [NSUUID UUID].UUIDString; + user.email = @"user@example.com"; + user.birthday = [NSDate dateWithTimeIntervalSince1970:0]; + [authenticationManager() userDidLogin:user]; +} + +void presentCheckout(ReadmeViewController *viewController) { + UINavigationController *navigationController = + createCheckoutNavigationController(); + [viewController presentViewController:navigationController + animated:YES + completion:nil]; +} + +void presentCheckoutAndPurchase(ReadmeViewController *viewController) { + UINavigationController *navigationController = + createCheckoutNavigationController(); + CheckoutViewController *checkoutViewController = + navigationController.viewControllers.firstObject; + [viewController + presentViewController:navigationController + animated:YES + completion:^{ + [checkoutViewController + userDidPurchaseProduct:[NSUUID UUID].UUIDString]; + }]; +} + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents how to use the analytics features of the SDK.\n" + @"\n" + @"See files:\n" + @"- AppDelegate.{h,m}\n" + @" - Configure Braze\n" + @"- AuthenticationManager.m\n" + @" - Identify the user\n" + @"- CheckoutViewController.m\n" + @" - Log custom events\n" + @" - Log purchases"; + +NSInteger const actionsCount = 3; + +ReadmeAction const actions[] = {{@"Authenticate user", + @"Identify the user on Braze", + ^(ReadmeViewController *_Nonnull _){ + authenticateUser(); +} +} +, {@"Present checkout", @"Log \"open_checkout_controller\" custom event", + ^(ReadmeViewController *_Nonnull viewController){ + presentCheckout(viewController); +} +} +, {@"Present checkout and purchase a product", + @"Log \"open_checkout_controller\" custom event and a purchase", + ^(ReadmeViewController *_Nonnull viewController){ + presentCheckoutAndPurchase(viewController); +} +} +, +} +; diff --git a/Examples/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from Examples/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json rename to Examples/ObjC/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Examples/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Examples/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Examples/ObjC/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Examples/Sources/Common/Assets.xcassets/Contents.json b/Examples/ObjC/Sources/Common/Assets.xcassets/Contents.json similarity index 100% rename from Examples/Sources/Common/Assets.xcassets/Contents.json rename to Examples/ObjC/Sources/Common/Assets.xcassets/Contents.json diff --git a/Examples/ObjC/Sources/Common/Credentials.m b/Examples/ObjC/Sources/Common/Credentials.m new file mode 100644 index 0000000000..36077aa7a3 --- /dev/null +++ b/Examples/ObjC/Sources/Common/Credentials.m @@ -0,0 +1,7 @@ +@import Foundation; + +#warning Replace with your Braze api key +NSString *const brazeApiKey = @"BRAZE_API_KEY"; + +#warning Replace with your Braze endpoint +NSString *const brazeEndpoint = @"BRAZE_ENDPOINT"; diff --git a/Examples/ObjC/Sources/Common/ReadmeAction.h b/Examples/ObjC/Sources/Common/ReadmeAction.h new file mode 100644 index 0000000000..f71f48353d --- /dev/null +++ b/Examples/ObjC/Sources/Common/ReadmeAction.h @@ -0,0 +1,9 @@ +@import Foundation; + +@class ReadmeViewController; + +typedef struct ReadmeAction { + NSString *title; + NSString *subtitle; + void (^action)(ReadmeViewController *); +} ReadmeAction; diff --git a/Examples/ObjC/Sources/Common/ReadmeViewController.h b/Examples/ObjC/Sources/Common/ReadmeViewController.h new file mode 100644 index 0000000000..66e1cfe1de --- /dev/null +++ b/Examples/ObjC/Sources/Common/ReadmeViewController.h @@ -0,0 +1,9 @@ +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface ReadmeViewController : UITableViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/ObjC/Sources/Common/ReadmeViewController.m b/Examples/ObjC/Sources/Common/ReadmeViewController.m new file mode 100644 index 0000000000..2f21ed7daa --- /dev/null +++ b/Examples/ObjC/Sources/Common/ReadmeViewController.m @@ -0,0 +1,142 @@ +#import "ReadmeViewController.h" +#import "AppDelegate.h" +#import "ReadmeAction.h" + +extern NSString *const readme; +extern ReadmeAction const actions[]; +extern NSInteger const actionsCount; + +@interface ReadmeViewController () + +@property(strong, nonatomic) UITextView *readmeTextView; + +@end + +@implementation ReadmeViewController + +- (instancetype)init { + self = [super initWithStyle:UITableViewStyleGrouped]; + if (self) { + + // Set title + self.title = [NSBundle.mainBundle + objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey]; + + // Set readme text + self.readmeTextView.text = + [NSString stringWithFormat:@"# Readme\n\n%@", readme]; + self.tableView.tableHeaderView = self.readmeTextView; + } + return self; +} + +#pragma mark - Layout + +- (void)viewWillLayoutSubviews { + [super viewWillLayoutSubviews]; + + CGSize size = [self.readmeTextView + systemLayoutSizeFittingSize:(CGSize){self.tableView.bounds.size.width, + 1000}]; + if (self.readmeTextView.frame.size.height != size.height) { + CGRect frame = self.readmeTextView.frame; + frame.size.height = size.height; + self.readmeTextView.frame = frame; + } +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)tableView:(UITableView *)tableView + numberOfRowsInSection:(NSInteger)section { + return actionsCount; +} + +- (NSString *)tableView:(UITableView *)tableView + titleForHeaderInSection:(NSInteger)section { + return @"Actions"; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath { + NSString *const identifier = @"cellIdentifier"; + UITableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:identifier]; + if (!cell) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle + reuseIdentifier:identifier]; + } + cell.textLabel.text = actions[indexPath.row].title; + cell.detailTextLabel.text = actions[indexPath.row].subtitle; + return cell; +} + +#pragma mark - UITableViewDelegate + +- (void)tableView:(UITableView *)tableView + didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + void (^action)(ReadmeViewController *) = actions[indexPath.row].action; + action(self); + [tableView deselectRowAtIndexPath:indexPath animated:true]; +} + +#pragma mark - Lazy Properties Instanciation + +- (UITextView *)readmeTextView { + if (!_readmeTextView) { + UITextView *textView = [[UITextView alloc] init]; + textView.backgroundColor = UIColor.clearColor; + [textView setScrollEnabled:NO]; + +#if TARGET_OS_IOS + [textView setEditable:NO]; + textView.textContainerInset = UIEdgeInsetsMake(16, 16, 0, 16); + if (@available(iOS 13.0, *)) { + textView.font = [UIFont monospacedSystemFontOfSize:12 + weight:UIFontWeightRegular]; + } +#elif TARGET_OS_TV + textView.textContainerInset = UIEdgeInsetsMake(0, 16 * 6, 16 * 4, 16 * 6); + if (@available(tvOS 13.0, *)) { + textView.font = [UIFont monospacedSystemFontOfSize:30 + weight:UIFontWeightRegular]; + } +#endif + + _readmeTextView = textView; + } + return _readmeTextView; +} + +@end + +#pragma mark - AutoReadme + +static NSString *const _window; + +@implementation AppDelegate (AutoWindow) + ++ (UIWindow *)_auto_window { + static dispatch_once_t once; + static UIWindow *window; + dispatch_once(&once, ^{ + ReadmeViewController *readmeViewController = + [[ReadmeViewController alloc] init]; + UINavigationController *navigationController = + [[UINavigationController alloc] + initWithRootViewController:readmeViewController]; + window = [[UIWindow alloc] init]; + window.rootViewController = navigationController; + }); + return window; +} + +- (UIWindow *)window { + return [AppDelegate _auto_window]; +} + +- (void)setWindow:(UIWindow *)window { + // noop +} + +@end diff --git a/Examples/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard b/Examples/ObjC/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Examples/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard rename to Examples/ObjC/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard diff --git a/Examples/ObjC/Sources/Common/main.m b/Examples/ObjC/Sources/Common/main.m new file mode 100644 index 0000000000..efc8505ecb --- /dev/null +++ b/Examples/ObjC/Sources/Common/main.m @@ -0,0 +1,11 @@ +#import "AppDelegate.h" + +@import UIKit; + +int main(int argc, char *argv[]) { + NSString *appDelegateClassName; + @autoreleasepool { + appDelegateClassName = NSStringFromClass([AppDelegate class]); + } + return UIApplicationMain(argc, argv, nil, appDelegateClassName); +} diff --git a/Examples/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard b/Examples/ObjC/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Examples/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard rename to Examples/ObjC/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h new file mode 100644 index 0000000000..194100359e --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.h @@ -0,0 +1,17 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +- (void)printCurrentContentCards; +- (void)refreshContentCards; +- (void)subscribeToContentCardsUpdates; +- (void)cancelContentCardsUpdatesSubscription; +- (void)presentContentCardsInfoViewController; + +@end diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m new file mode 100644 index 0000000000..9c202c982d --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/AppDelegate.m @@ -0,0 +1,110 @@ +#import "AppDelegate.h" +#import "CardsInfoViewController.h" + +@import BrazeKit; + +@interface AppDelegate () + +// The subscription needs to be retained to be active. +@property(strong, nonatomic) BRZCancellable *cardsSubscription; + +@end + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +#pragma mark - Displaying Content Cards + +- (void)printCurrentContentCards { + // Print all the cards + NSLog(@"%@", AppDelegate.braze.contentCards.cards); + + BRZContentCardRaw *cardRaw = AppDelegate.braze.contentCards.cards.firstObject; + if (cardRaw == nil) { + return; + } + + // Access the `extras` dictionary / `url`: + + NSLog(@"extras: %@", cardRaw.extras); + NSLog(@"url: %@", cardRaw.url); + + // Access the `title` / `image` + + if (cardRaw.title != nil) { + NSLog(@"title: %@", cardRaw.title); + } + + if (cardRaw.image != nil) { + NSLog(@"image: %@", cardRaw.image); + } + + // A wrapper / compatibility representation of the card is accessible via + // `-json`. + NSData *jsonData = [cardRaw json]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + if (jsonString != nil) { + NSLog(@"%@", jsonString); + } +} + +- (void)refreshContentCards { + [AppDelegate.braze.contentCards + requestRefreshWithCompletion:^( + NSArray *_Nullable cards, + NSError *_Nullable error) { + NSLog(@"cards: %@", cards); + NSLog(@"error: %@", error); + }]; +} + +- (void)subscribeToContentCardsUpdates { + self.cardsSubscription = [AppDelegate.braze.contentCards + subscribeToUpdates:^(NSArray *_Nonnull cards) { + NSLog(@"cards: %@", cards); + }]; +} + +- (void)cancelContentCardsUpdatesSubscription { + [self.cardsSubscription cancel]; +} + +- (void)presentContentCardsInfoViewController { + CardsInfoViewController *viewController = [[CardsInfoViewController alloc] + initWithCards:AppDelegate.braze.contentCards.cards]; + UINavigationController *navigationController = [[UINavigationController alloc] + initWithRootViewController:viewController]; + [self.window.rootViewController presentViewController:navigationController + animated:YES + completion:nil]; +} + +@end diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h new file mode 100644 index 0000000000..f3fdfa4f4d --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.h @@ -0,0 +1,9 @@ +@import UIKit; + +@class BRZContentCardRaw; + +@interface CardsInfoViewController : UITableViewController + +- (instancetype)initWithCards:(NSArray *)cards; + +@end diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m new file mode 100644 index 0000000000..c310086793 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/CardsInfoViewController.m @@ -0,0 +1,200 @@ +#import "CardsInfoViewController.h" + +@import UIKit; +@import BrazeKit; + +#pragma mark - Field / Section + +@interface Field : NSObject + +@property(copy, nonatomic) NSString *name; +@property(strong, nonatomic) id value; +@property(assign, nonatomic) NSInteger indentation; + ++ (instancetype)fieldWithName:(NSString *)name value:(id)value; ++ (instancetype)fieldWithName:(NSString *)name + value:(id)value + indentation:(NSInteger)indentation; + +@end + +@interface Section : NSObject + +@property(copy, nonatomic) NSString *name; +@property(strong, nonatomic) NSArray *fields; + +@end + +#pragma mark - CardsInfoViewController + +@interface CardsInfoViewController () + +@property(strong, nonatomic) NSArray
*sections; + ++ (Section *)cardSectionFromCard:(BRZContentCardRaw *)card + atIndex:(NSInteger)index; + +@end + +@implementation CardsInfoViewController + +- (instancetype)initWithCards:(NSArray *)cards { + self = [super initWithStyle:UITableViewStyleGrouped]; + if (self) { + NSMutableArray *sections = [NSMutableArray array]; + for (NSInteger i = 0; i < cards.count; ++i) { + BRZContentCardRaw *card = cards[i]; + [sections addObject:[CardsInfoViewController cardSectionFromCard:card + atIndex:i]]; + } + self.sections = [sections copy]; + + self.title = @"Content Cards Info"; + + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissModal)]; + [self.navigationItem setRightBarButtonItem:doneButton]; + + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.estimatedRowHeight = 44.0; + } + return self; +} + +- (void)dismissModal { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.sections.count; +} + +- (NSInteger)tableView:(UITableView *)tableView + numberOfRowsInSection:(NSInteger)section { + return self.sections[section].fields.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 + reuseIdentifier:@"cellIdentifier"]; + } + + Field *field = self.sections[indexPath.section].fields[indexPath.row]; + cell.textLabel.text = field.name; + cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", field.value]; + cell.indentationLevel = field.indentation; + + cell.textLabel.numberOfLines = 0; + if (@available(iOS 13.0, tvOS 13.0, *)) { + cell.textLabel.font = + [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular]; + cell.detailTextLabel.font = + [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular]; + } + + return cell; +} + +#pragma mark - UITableViewDelegate + +- (NSString *)tableView:(UITableView *)tableView + titleForHeaderInSection:(NSInteger)section { + return self.sections[section].name; +} + ++ (Section *)cardSectionFromCard:(BRZContentCardRaw *)card + atIndex:(NSInteger)index { + NSMutableArray *fields = [NSMutableArray array]; + + switch (card.type) { + case BRZContentCardRawTypeClassic: + [fields addObject:[Field fieldWithName:@"type" value:@"classic"]]; + break; + case BRZContentCardRawTypeBanner: + [fields addObject:[Field fieldWithName:@"type" value:@"banner"]]; + break; + case BRZContentCardRawTypeCaptionedImage: + [fields addObject:[Field fieldWithName:@"type" value:@"captionedImage"]]; + break; + case BRZContentCardRawTypeControl: + [fields addObject:[Field fieldWithName:@"type" value:@"control"]]; + break; + default: + break; + } + + [fields addObject:[Field fieldWithName:@"id" value:card.identifier]]; + [fields addObject:[Field fieldWithName:@"image" value:card.image]]; + [fields addObject:[Field fieldWithName:@"imageAspectRation" + value:@(card.imageAspectRatio)]]; + [fields addObject:[Field fieldWithName:@"title" value:card.title]]; + [fields addObject:[Field fieldWithName:@"description" + value:card.cardDescription]]; + [fields addObject:[Field fieldWithName:@"domain" value:card.domain]]; + [fields addObject:[Field fieldWithName:@"url" value:card.url]]; + [fields addObject:[Field fieldWithName:@"useWebView" + value:@(card.useWebView)]]; + [fields addObject:[Field fieldWithName:@"viewed" value:@(card.viewed)]]; + [fields addObject:[Field fieldWithName:@"dismissible" + value:@(card.dismissible)]]; + [fields addObject:[Field fieldWithName:@"removed" value:@(card.removed)]]; + [fields addObject:[Field fieldWithName:@"pinned" value:@(card.pinned)]]; + [fields addObject:[Field fieldWithName:@"clicked" value:@(card.clicked)]]; + [fields addObject:[Field fieldWithName:@"test" value:@(card.test)]]; + [fields addObject:[Field fieldWithName:@"createdAt" value:@(card.createdAt)]]; + [fields addObject:[Field fieldWithName:@"expiresAt" value:@(card.expiresAt)]]; + + NSData *extrasData = [NSJSONSerialization dataWithJSONObject:card.extras + options:0 + error:nil]; + NSString *extrasString = [[NSString alloc] initWithData:extrasData + encoding:NSUTF8StringEncoding]; + [fields addObject:[Field fieldWithName:@"extras" value:@""]]; + [fields addObject:[Field fieldWithName:extrasString value:@"" indentation:1]]; + + Section *section = [[Section alloc] init]; + section.name = [NSString stringWithFormat:@"Card %ld", index]; + section.fields = [fields copy]; + + return section; +} + +@end + +#pragma mark - Field / Section Implementation + +@implementation Field + +- (instancetype)initWithName:(NSString *)name value:(id)value { + self = [super init]; + if (self) { + self.name = name; + self.value = value; + } + return self; +} + ++ (instancetype)fieldWithName:(NSString *)name value:(id)value { + return [[Field alloc] initWithName:name value:value]; +} + ++ (instancetype)fieldWithName:(NSString *)name + value:(id)value + indentation:(NSInteger)indentation { + Field *field = [Field fieldWithName:name value:value]; + field.indentation = indentation; + return field; +} + +@end + +@implementation Section +@end diff --git a/Examples/Sources/ContentCards-Custom-UI/Info.plist b/Examples/ObjC/Sources/ContentCards-Custom-UI/Info.plist similarity index 100% rename from Examples/Sources/ContentCards-Custom-UI/Info.plist rename to Examples/ObjC/Sources/ContentCards-Custom-UI/Info.plist diff --git a/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m b/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m new file mode 100644 index 0000000000..00380ffdc4 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards-Custom-UI/Readme.m @@ -0,0 +1,75 @@ +#import "AppDelegate.h" +#import "ReadmeAction.h" +#import "ReadmeViewController.h" + +#pragma mark - Internal + +void printCurrentContentCards(ReadmeViewController *viewController) { + [(AppDelegate *) + UIApplication.sharedApplication.delegate printCurrentContentCards]; +} + +void refreshContentCards(ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication.delegate refreshContentCards]; +} + +void subscribeToContentCardsUpdates(ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate subscribeToContentCardsUpdates]; +} + +void cancelContentCardsUpdatesSubscription( + ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate cancelContentCardsUpdatesSubscription]; +} + +void presentContentCardsInfoViewController( + ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate presentContentCardsInfoViewController]; +} + +#pragma mark - Readme + +NSString *const readme = @"This sample demonstrates how to implement your own " + @"custom Content Cards UI:\n" + @"\n" + @"- AppDelegate.{h,m}:\n" + @" - Content cards API usage\n" + @" - Content cards custom UI presentation\n" + @"- CardsInfoViewController.{h,m}\n" + @" - UIViewController subclass presenting the " + @"content cards data in a table view"; + +NSInteger const actionsCount = 5; + +ReadmeAction const actions[] = { + {@"Print current Content Cards", @"", + ^(ReadmeViewController *_Nonnull viewController){ + printCurrentContentCards(viewController); +} +} +, {@"Refresh Content Cards", @"", + ^(ReadmeViewController *_Nonnull viewController){ + refreshContentCards(viewController); +} +} +, {@"Subscribe to Content Cards updates", @"", + ^(ReadmeViewController *_Nonnull viewController){ + subscribeToContentCardsUpdates(viewController); +} +} +, {@"Cancel Content Cards updates subscription", @"", + ^(ReadmeViewController *_Nonnull viewController){ + cancelContentCardsUpdatesSubscription(viewController); +} +} +, { + @"Present Content Cards Info view controller", @"", + ^(ReadmeViewController *_Nonnull viewController) { + presentContentCardsInfoViewController(viewController); + } +} +} +; diff --git a/Examples/ObjC/Sources/ContentCards/AppDelegate.h b/Examples/ObjC/Sources/ContentCards/AppDelegate.h new file mode 100644 index 0000000000..17572ed179 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/AppDelegate.h @@ -0,0 +1,15 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +- (void)pushContentCardsViewController; +- (void)presentModalContentCardsViewController; +- (void)presentModalContentCardsViewControllerCustomized; + +@end diff --git a/Examples/ObjC/Sources/ContentCards/AppDelegate.m b/Examples/ObjC/Sources/ContentCards/AppDelegate.m new file mode 100644 index 0000000000..7150637739 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/AppDelegate.m @@ -0,0 +1,101 @@ +#import "AppDelegate.h" +#import "BRZGIFViewProvider+SDWebImage.h" + +@import BrazeKit; +@import BrazeUI; + +@interface AppDelegate () +@end + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + // - GIF support + BRZGIFViewProvider.shared = [BRZGIFViewProvider sdWebImage]; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +#pragma mark - Displaying Content Cards + +- (void)pushContentCardsViewController { + UINavigationController *navigationController = + (UINavigationController *)self.window.rootViewController; + + // Create a content card view controller that can be pushed onto a navigation + // stack. + BRZContentCardUIViewController *viewController = + [[BRZContentCardUIViewController alloc] initWithBraze:AppDelegate.braze]; + // Set the delegate + viewController.delegate = self; + // Push it onto the navigation stack + [navigationController pushViewController:viewController animated:YES]; +} + +- (void)presentModalContentCardsViewController { + UINavigationController *navigationController = + (UINavigationController *)self.window.rootViewController; + + // Create a content card modal view controller that can be presented modally. + BRZContentCardUIModalViewController *modalViewController = + [[BRZContentCardUIModalViewController alloc] + initWithBraze:AppDelegate.braze]; + // Set the delegate + modalViewController.viewController.delegate = self; + // Present modally + [navigationController presentViewController:modalViewController + animated:YES + completion:nil]; +} + +- (void)presentModalContentCardsViewControllerCustomized { + UIAlertController *alert = [UIAlertController + alertControllerWithTitle:@"Not Supported" + message: + @"Customization via attributes is not supported " + @"using the " + @"Objective-C API. See our Swift Examples project " + @"for details about customizing the Content Cards" + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" + style:UIAlertActionStyleCancel + handler:nil]]; + [self.window.rootViewController presentViewController:alert + animated:YES + completion:nil]; +} + +#pragma mark - Content Cards delegate + +- (BOOL)contentCardController:(BRZContentCardUIViewController *)controller + shouldProcess:(NSURL *)url + card:(BRZContentCardRaw *)card { + // Intercept the content card click action here + return YES; +} + +@end diff --git a/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h new file mode 100644 index 0000000000..a0307bacf1 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.h @@ -0,0 +1,11 @@ +@import Foundation; +@import BrazeUI; + +@interface BRZGIFViewProvider (SDWebImage) + +/// A GIF view provider using +/// [SDWebImage](https://github.com/SDWebImage/SDWebImage) as a rendering +/// library. ++ (BRZGIFViewProvider *)sdWebImage; + +@end diff --git a/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m new file mode 100644 index 0000000000..35b102a1c8 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/BRZGIFViewProvider+SDWebImage.m @@ -0,0 +1,40 @@ +#import "BRZGIFViewProvider+SDWebImage.h" +#import +#import + +@interface BRZGIFViewProvider (SDWebImage) + ++ (UIImage *)imageForURL:(NSURL *)url; + +@end + +@implementation BRZGIFViewProvider (SDWebImage) + ++ (BRZGIFViewProvider *)sdWebImage { + return [BRZGIFViewProvider + providerWithView:^UIView *_Nonnull(NSURL *_Nullable url) { + UIImage *image = [BRZGIFViewProvider imageForURL:url]; + SDAnimatedImageView *view = + [[SDAnimatedImageView alloc] initWithImage:image]; + return view; + } + updateView:^(UIView *_Nonnull view, NSURL *_Nullable url) { + if ([view isKindOfClass:[SDAnimatedImageView class]]) { + ((SDAnimatedImageView *)(view)).image = + [BRZGIFViewProvider imageForURL:url]; + } + }]; +} + ++ (UIImage *)imageForURL:(NSURL *)url { + if (url == nil) { + return nil; + } + if ([url.pathExtension isEqualToString:@"gif"]) { + return [SDAnimatedImage imageWithContentsOfFile:url.path]; + } else { + return [UIImage imageWithContentsOfFile:url.path]; + } +} + +@end diff --git a/Examples/Sources/ContentCards/Info.plist b/Examples/ObjC/Sources/ContentCards/Info.plist similarity index 100% rename from Examples/Sources/ContentCards/Info.plist rename to Examples/ObjC/Sources/ContentCards/Info.plist diff --git a/Examples/ObjC/Sources/ContentCards/Readme.m b/Examples/ObjC/Sources/ContentCards/Readme.m new file mode 100644 index 0000000000..80cdb1374e --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/Readme.m @@ -0,0 +1,55 @@ +#import "AppDelegate.h" +#import "ReadmeAction.h" +#import "ReadmeViewController.h" + +#pragma mark - Internal + +void pushContentCardsViewController(ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate pushContentCardsViewController]; +} + +void presentModalContentCardsViewController( + ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate presentModalContentCardsViewController]; +} + +void presentModalContentCardsViewControllerCustomized( + ReadmeViewController *viewController) { + [(AppDelegate *)UIApplication.sharedApplication + .delegate presentModalContentCardsViewControllerCustomized]; +} + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents how to use the Braze provided content cards UI:\n" + @"\n" + @"- AppDelegate.{h,m}:\n" + @" - Content cards UI presentation\n" + @" - Content cards UI delegate\n" + @"- BRZGIFViewProvider+SDWebImage.{h,m}\n" + @" - Use SDWebImage to provide GIF support to the Braze UI components"; + +NSInteger const actionsCount = 3; + +ReadmeAction const actions[] = { + {@"Push content cards view controller", @"", + ^(ReadmeViewController *_Nonnull viewController){ + pushContentCardsViewController(viewController); +} +} +, {@"Present modal content cards view controller", @"", + ^(ReadmeViewController *_Nonnull viewController){ + presentModalContentCardsViewController(viewController); +} +} +, { + @"Present modal content cards view controller", @"(customized)", + ^(ReadmeViewController *_Nonnull viewController) { + presentModalContentCardsViewControllerCustomized(viewController); + } +} +} +; diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h new file mode 100644 index 0000000000..39f6d4eb6e --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.h @@ -0,0 +1,11 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +@end diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m new file mode 100644 index 0000000000..728d8efa13 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/AppDelegate.m @@ -0,0 +1,43 @@ +#import "AppDelegate.h" +#import "CustomInAppMessagePresenter.h" + +@import BrazeKit; + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + // Setup the custom In-App Message presenter + braze.inAppMessagePresenter = [[CustomInAppMessagePresenter alloc] init]; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +@end diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h new file mode 100644 index 0000000000..161c1f9b75 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.h @@ -0,0 +1,6 @@ +@import Foundation; +@import BrazeKit; + +@interface CustomInAppMessagePresenter : NSObject + +@end diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m new file mode 100644 index 0000000000..e275add51b --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.m @@ -0,0 +1,46 @@ +#import "CustomInAppMessagePresenter.h" +#import "AppDelegate.h" +#import "InAppMessageInfoViewController.h" + +@implementation CustomInAppMessagePresenter + +- (void)presentMessage:(BRZInAppMessageRaw *)message { + + // BRZInAppMessageRaw is a compatibility representation of the In-App Message + // type. + + // You can access the `extras` dictionary / `url`: + + NSLog(@"extras: %@", message.extras); + NSLog(@"url: %@", message.url); + + // You can access message specific values. + // - The value of `slideFrom` is irrelevant for non-slideup in-app messages. + // - The value of `header` is irrelevant for non-modal/non-full in-app + // messages. + + NSLog(@"slideFrom: %@", @(message.slideFrom)); + NSLog(@"header: %@", message.header); + + // A wrapper / compatibility representation of the in-app message is + // accessible via `-json` + NSData *jsonData = [message json]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + if (jsonString != nil) { + NSLog(@"%@", jsonString); + } + + // Here, we present a custom view controller for the message + + InAppMessageInfoViewController *viewController = + [[InAppMessageInfoViewController alloc] initWithMessage:message]; + UINavigationController *navigationController = [[UINavigationController alloc] + initWithRootViewController:viewController]; + [UIApplication.sharedApplication.delegate.window.rootViewController + presentViewController:navigationController + animated:YES + completion:nil]; +} + +@end diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h new file mode 100644 index 0000000000..1e703f716d --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.h @@ -0,0 +1,9 @@ +@import UIKit; + +@class BRZInAppMessageRaw; + +@interface InAppMessageInfoViewController : UITableViewController + +- (instancetype)initWithMessage:(BRZInAppMessageRaw *)message; + +@end diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m new file mode 100644 index 0000000000..2561eab214 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.m @@ -0,0 +1,282 @@ +#import "InAppMessageInfoViewController.h" + +@import UIKit; +@import BrazeKit; + +#pragma mark - Field / Section + +@interface Field : NSObject + +@property(copy, nonatomic) NSString *name; +@property(strong, nonatomic) id value; +@property(assign, nonatomic) NSInteger indentation; + ++ (instancetype)fieldWithName:(NSString *)name value:(id)value; ++ (instancetype)fieldWithName:(NSString *)name + value:(id)value + indentation:(NSInteger)indentation; + +@end + +@interface Section : NSObject + +@property(copy, nonatomic) NSString *name; +@property(strong, nonatomic) NSArray *fields; + +@end + +#pragma mark - InAppMessageInfoViewController + +@interface InAppMessageInfoViewController () + +@property(strong, nonatomic) NSArray
*sections; + ++ (NSArray
*)messageSectionsFromMessage: + (BRZInAppMessageRaw *)message; + +@end + +@implementation InAppMessageInfoViewController + +- (instancetype)initWithMessage:(BRZInAppMessageRaw *)message { + self = [super initWithStyle:UITableViewStyleGrouped]; + if (self) { + self.sections = + [InAppMessageInfoViewController messageSectionsFromMessage:message]; + + self.title = @"In-App Message Info"; + + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self + action:@selector(dismissModal)]; + [self.navigationItem setRightBarButtonItem:doneButton]; + + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.estimatedRowHeight = 44.0; + } + return self; +} + +- (void)dismissModal { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.sections.count; +} + +- (NSInteger)tableView:(UITableView *)tableView + numberOfRowsInSection:(NSInteger)section { + return self.sections[section].fields.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView + cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 + reuseIdentifier:@"cellIdentifier"]; + } + + Field *field = self.sections[indexPath.section].fields[indexPath.row]; + cell.textLabel.text = field.name; + cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", field.value]; + cell.indentationLevel = field.indentation; + + cell.textLabel.numberOfLines = 0; + if (@available(iOS 13.0, tvOS 13.0, *)) { + cell.textLabel.font = + [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular]; + cell.detailTextLabel.font = + [UIFont monospacedSystemFontOfSize:13 weight:UIFontWeightRegular]; + } + + return cell; +} + +#pragma mark - UITableViewDelegate + +- (NSString *)tableView:(UITableView *)tableView + titleForHeaderInSection:(NSInteger)section { + return self.sections[section].name; +} + +#pragma mark - Helpers + ++ (NSArray
*)messageSectionsFromMessage: + (BRZInAppMessageRaw *)message { + NSMutableArray *fields = [NSMutableArray array]; + + switch (message.type) { + case BRZInAppMessageRawTypeSlideup: + [fields addObject:[Field fieldWithName:@"type" value:@"slideup"]]; + break; + case BRZInAppMessageRawTypeModal: + [fields addObject:[Field fieldWithName:@"type" value:@"modal"]]; + break; + case BRZInAppMessageRawTypeFull: + [fields addObject:[Field fieldWithName:@"type" value:@"full"]]; + break; + case BRZInAppMessageRawTypeHtmlFull: + [fields addObject:[Field fieldWithName:@"type" value:@"htmlFull"]]; + break; + case BRZInAppMessageRawTypeHtml: + [fields addObject:[Field fieldWithName:@"type" value:@"html"]]; + break; + default: + break; + } + + switch (message.clickAction) { + case BRZInAppMessageRawClickActionNone: + [fields addObject:[Field fieldWithName:@"clickAction" value:@"none"]]; + break; + case BRZInAppMessageRawClickActionNewsFeed: + [fields addObject:[Field fieldWithName:@"clickAction" value:@"newsFeed"]]; + break; + case BRZInAppMessageRawClickActionURL: + [fields addObject:[Field fieldWithName:@"clickAction" value:@"uri"]]; + break; + default: + break; + } + + [fields addObject:[Field fieldWithName:@"uri" value:message.url]]; + [fields addObject:[Field fieldWithName:@"useWebView" + value:@(message.useWebView)]]; + + switch (message.messageClose) { + case BRZInAppMessageRawCloseSwipe: + [fields addObject:[Field fieldWithName:@"messageClose" value:@"swipe"]]; + break; + case BRZInAppMessageRawCloseAutoDismiss: + [fields addObject:[Field fieldWithName:@"messageClose" + value:@"autoDismiss"]]; + break; + default: + break; + } + + switch (message.orientation) { + case BRZInAppMessageRawOrientationAny: + [fields addObject:[Field fieldWithName:@"orientation" value:@"any"]]; + break; + case BRZInAppMessageRawOrientationPortrait: + [fields addObject:[Field fieldWithName:@"orientation" value:@"portrait"]]; + break; + case BRZInAppMessageRawOrientationLandscape: + [fields addObject:[Field fieldWithName:@"orientation" value:@"landscape"]]; + break; + default: + break; + } + + [fields addObject:[Field fieldWithName:@"message" value:message.message]]; + [fields addObject:[Field fieldWithName:@"header" value:message.header]]; + [fields addObject:[Field fieldWithName:@"messageTextAlignment" + value:@(message.messageTextAlignment)]]; + [fields addObject:[Field fieldWithName:@"headerTextAlignment" + value:@(message.headerTextAlignment)]]; + [fields addObject:[Field fieldWithName:@"imageUri" value:message.imageURL]]; + [fields addObject:[Field fieldWithName:@"icon" value:message.icon]]; + [fields addObject:[Field fieldWithName:@"duration" + value:@(message.duration)]]; + [fields addObject:[Field fieldWithName:@"themes" value:message.themes]]; + [fields addObject:[Field fieldWithName:@"textColor" + value:message.textColor]]; + [fields addObject:[Field fieldWithName:@"headerTextColor" + value:message.headerTextColor]]; + [fields addObject:[Field fieldWithName:@"iconColor" + value:message.iconColor]]; + [fields addObject:[Field fieldWithName:@"iconBackgroundColor" + value:message.iconBackgroundColor]]; + [fields addObject:[Field fieldWithName:@"backgroundColor" + value:message.backgroundColor]]; + [fields addObject:[Field fieldWithName:@"frameColor" + value:message.frameColor]]; + [fields addObject:[Field fieldWithName:@"closeButtonColor" + value:message.closeButtonColor]]; + [fields addObject:[Field fieldWithName:@"buttons" value:message.buttons]]; + + switch (message.imageStyle) { + case BRZInAppMessageRawImageStyleTop: + [fields addObject:[Field fieldWithName:@"imageStyle" value:@"top"]]; + break; + case BRZInAppMessageRawImageStyleGraphic: + [fields addObject:[Field fieldWithName:@"imageStyle" value:@"graphic"]]; + break; + default: + break; + } + + switch (message.slideFrom) { + case BRZInAppMessageRawSlideFromTop: + [fields addObject:[Field fieldWithName:@"slideFrom" value:@"top"]]; + break; + case BRZInAppMessageRawSlideFromBottom: + [fields addObject:[Field fieldWithName:@"slideFrom" value:@"bottom"]]; + break; + default: + break; + } + + [fields addObject:[Field fieldWithName:@"animateIn" + value:@(message.animateIn)]]; + [fields addObject:[Field fieldWithName:@"animateOut" + value:@(message.animateOut)]]; + + NSData *extrasData = [NSJSONSerialization dataWithJSONObject:message.extras + options:0 + error:nil]; + NSString *extrasString = [[NSString alloc] initWithData:extrasData + encoding:NSUTF8StringEncoding]; + [fields addObject:[Field fieldWithName:@"extras" value:@""]]; + [fields addObject:[Field fieldWithName:extrasString value:@"" indentation:1]]; + + [fields addObject:[Field fieldWithName:@"baseURL" value:message.baseURL]]; + [fields addObject:[Field fieldWithName:@"assetURLs" value:message.assetURLs]]; + [fields addObject:[Field fieldWithName:@"isControl" + value:@(message.isControl)]]; + + Section *section = [[Section alloc] init]; + section.name = @"message"; + section.fields = [fields copy]; + + return @[ section ]; +} + +@end + +#pragma mark - Field / Section Implementation + +@implementation Field + +- (instancetype)initWithName:(NSString *)name value:(id)value { + self = [super init]; + if (self) { + self.name = name; + self.value = value; + } + return self; +} + ++ (instancetype)fieldWithName:(NSString *)name value:(id)value { + return [[Field alloc] initWithName:name value:value]; +} + ++ (instancetype)fieldWithName:(NSString *)name + value:(id)value + indentation:(NSInteger)indentation { + Field *field = [Field fieldWithName:name value:value]; + field.indentation = indentation; + return field; +} + +@end + +@implementation Section +@end diff --git a/Examples/Sources/InAppMessages-Custom-UI/Info.plist b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Info.plist similarity index 100% rename from Examples/Sources/InAppMessages-Custom-UI/Info.plist rename to Examples/ObjC/Sources/InAppMessages-Custom-UI/Info.plist diff --git a/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m new file mode 100644 index 0000000000..54f719e3a8 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages-Custom-UI/Readme.m @@ -0,0 +1,61 @@ +#import "AppDelegate.h" +#import "ReadmeAction.h" +#import "ReadmeViewController.h" + +#pragma mark - Internal + +void localSlideup(ReadmeViewController *viewController) { + BRZInAppMessageRaw *slideup = [[BRZInAppMessageRaw alloc] init]; + slideup.type = BRZInAppMessageRawTypeSlideup; + slideup.clickAction = BRZInAppMessageRawClickActionURL; + slideup.url = [NSURL URLWithString:@"https://example.com"]; + slideup.useWebView = YES; + slideup.extras = @{@"key1" : @"value1", @"key2" : @"value2"}; + slideup.icon = @""; + slideup.message = @"Local slideup in-app message"; + + [AppDelegate.braze.inAppMessagePresenter presentMessage:slideup]; +} + +void localModal(ReadmeViewController *viewController) { + BRZInAppMessageRaw *modal = [[BRZInAppMessageRaw alloc] init]; + modal.type = BRZInAppMessageRawTypeModal; + modal.clickAction = BRZInAppMessageRawClickActionURL; + modal.url = [NSURL URLWithString:@"https://example.com"]; + modal.useWebView = YES; + modal.extras = @{@"key1" : @"value1", @"key2" : @"value2"}; + modal.icon = @""; + modal.header = @"Header text"; + modal.message = @"Local modal in-app message"; + + [AppDelegate.braze.inAppMessagePresenter presentMessage:modal]; +} + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents how to implement your own custom In-App Message " + @"UI:\n" + @"\n" + @"- AppDelegate.{h,m}:\n" + @" - Sets the custom in-app message presenter\n" + @"- CustomInAppMessagePresenter.{h,m}\n" + @" - Explains how to use the `BRZInAppMessageRaw` data model and present " + @"the message in a custom view controller."; + +NSInteger const actionsCount = 2; + +ReadmeAction const actions[] = { + {@"Present local slideup in-app message", @"", + ^(ReadmeViewController *_Nonnull viewController){ + localSlideup(viewController); +} +} +, { + @"Present local modal in-app message", @"", + ^(ReadmeViewController *_Nonnull viewController) { + localModal(viewController); + } +} +} +; diff --git a/Examples/ObjC/Sources/InAppMessages/AppDelegate.h b/Examples/ObjC/Sources/InAppMessages/AppDelegate.h new file mode 100644 index 0000000000..39f6d4eb6e --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/AppDelegate.h @@ -0,0 +1,11 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +@end diff --git a/Examples/ObjC/Sources/InAppMessages/AppDelegate.m b/Examples/ObjC/Sources/InAppMessages/AppDelegate.m new file mode 100644 index 0000000000..be5198de67 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/AppDelegate.m @@ -0,0 +1,67 @@ +#import "AppDelegate.h" +#import "BRZGIFViewProvider+SDWebImage.h" + +@import BrazeKit; +@import BrazeUI; + +@interface AppDelegate () + +@end + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + // - GIF support + BRZGIFViewProvider.shared = [BRZGIFViewProvider sdWebImage]; + + // - InAppMessageUI + BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init]; + inAppMessageUI.delegate = self; + braze.inAppMessagePresenter = inAppMessageUI; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +#pragma mark - BrazeInAppMessageUIDelegate + +- (BOOL)inAppMessage:(BrazeInAppMessageUI *)ui + shouldProcess:(enum BRZInAppMessageRawClickAction)clickAction + url:(NSURL *)uri + buttonId:(NSString *)buttonId + message:(BRZInAppMessageRaw *)message + view:(UIView *)view { + // Intercept the in-app message click action here + return YES; +} + +- (void)inAppMessage:(BrazeInAppMessageUI *)ui + didPresent:(BRZInAppMessageRaw *)message + view:(UIView *)view { + // Executed when `message` is presented to the user +} + +@end diff --git a/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h new file mode 100644 index 0000000000..a0307bacf1 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.h @@ -0,0 +1,11 @@ +@import Foundation; +@import BrazeUI; + +@interface BRZGIFViewProvider (SDWebImage) + +/// A GIF view provider using +/// [SDWebImage](https://github.com/SDWebImage/SDWebImage) as a rendering +/// library. ++ (BRZGIFViewProvider *)sdWebImage; + +@end diff --git a/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m new file mode 100644 index 0000000000..35b102a1c8 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/BRZGIFViewProvider+SDWebImage.m @@ -0,0 +1,40 @@ +#import "BRZGIFViewProvider+SDWebImage.h" +#import +#import + +@interface BRZGIFViewProvider (SDWebImage) + ++ (UIImage *)imageForURL:(NSURL *)url; + +@end + +@implementation BRZGIFViewProvider (SDWebImage) + ++ (BRZGIFViewProvider *)sdWebImage { + return [BRZGIFViewProvider + providerWithView:^UIView *_Nonnull(NSURL *_Nullable url) { + UIImage *image = [BRZGIFViewProvider imageForURL:url]; + SDAnimatedImageView *view = + [[SDAnimatedImageView alloc] initWithImage:image]; + return view; + } + updateView:^(UIView *_Nonnull view, NSURL *_Nullable url) { + if ([view isKindOfClass:[SDAnimatedImageView class]]) { + ((SDAnimatedImageView *)(view)).image = + [BRZGIFViewProvider imageForURL:url]; + } + }]; +} + ++ (UIImage *)imageForURL:(NSURL *)url { + if (url == nil) { + return nil; + } + if ([url.pathExtension isEqualToString:@"gif"]) { + return [SDAnimatedImage imageWithContentsOfFile:url.path]; + } else { + return [UIImage imageWithContentsOfFile:url.path]; + } +} + +@end diff --git a/Examples/Sources/InAppMessages/Info.plist b/Examples/ObjC/Sources/InAppMessages/Info.plist similarity index 100% rename from Examples/Sources/InAppMessages/Info.plist rename to Examples/ObjC/Sources/InAppMessages/Info.plist diff --git a/Examples/ObjC/Sources/InAppMessages/Readme.m b/Examples/ObjC/Sources/InAppMessages/Readme.m new file mode 100644 index 0000000000..b46bb891cd --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/Readme.m @@ -0,0 +1,52 @@ +#import "AppDelegate.h" +#import "ReadmeAction.h" +#import "ReadmeViewController.h" + +@import BrazeKit; + +#pragma mark - Internal + +void localSlideup(ReadmeViewController *viewController) { + BRZInAppMessageRaw *slideup = [[BRZInAppMessageRaw alloc] init]; + slideup.type = BRZInAppMessageRawTypeSlideup; + slideup.icon = @""; + slideup.message = @"Local slideup in-app message"; + [AppDelegate.braze.inAppMessagePresenter presentMessage:slideup]; +} + +void localModal(ReadmeViewController *viewController) { + BRZInAppMessageRaw *modal = [[BRZInAppMessageRaw alloc] init]; + modal.type = BRZInAppMessageRawTypeModal; + modal.icon = @""; + modal.header = @"Header text"; + modal.message = @"Local modal in-app message"; + [AppDelegate.braze.inAppMessagePresenter presentMessage:modal]; +} + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents how to use the Braze provided in-app message UI:\n" + @"\n" + @"- AppDelegate.{h,m}\n" + @" - In-app message UI configuration\n" + @" - In-app message UI delegate\n" + @"- BRZGIFViewProvider+SDWebImage.{h,m}\n" + @" - Use SDWebImage to provide GIF support to the Braze UI components"; + +NSInteger const actionsCount = 2; + +ReadmeAction const actions[] = { + {@"Present local slideup in-app message", @"", + ^(ReadmeViewController *_Nonnull viewController){ + localSlideup(viewController); +} +} +, {@"Present local modal in-app message", @"", + ^(ReadmeViewController *_Nonnull viewController){ + localModal(viewController); +} +} +, +} +; diff --git a/Examples/ObjC/Sources/Location/AppDelegate.h b/Examples/ObjC/Sources/Location/AppDelegate.h new file mode 100644 index 0000000000..39f6d4eb6e --- /dev/null +++ b/Examples/ObjC/Sources/Location/AppDelegate.h @@ -0,0 +1,11 @@ +@import UIKit; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +@end diff --git a/Examples/ObjC/Sources/Location/AppDelegate.m b/Examples/ObjC/Sources/Location/AppDelegate.m new file mode 100644 index 0000000000..4a120b09ab --- /dev/null +++ b/Examples/ObjC/Sources/Location/AppDelegate.m @@ -0,0 +1,40 @@ +#import "AppDelegate.h" + +@import BrazeKit; +@import BrazeLocation; + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + configuration.location.brazeLocation = [[BrazeLocation alloc] init]; + configuration.location.automaticLocationCollection = YES; + configuration.location.geofencesEnabled = YES; + configuration.location.automaticGeofenceRequests = YES; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +@end diff --git a/Examples/Sources/Location/Info.plist b/Examples/ObjC/Sources/Location/Info.plist similarity index 100% rename from Examples/Sources/Location/Info.plist rename to Examples/ObjC/Sources/Location/Info.plist diff --git a/Examples/ObjC/Sources/Location/Readme.m b/Examples/ObjC/Sources/Location/Readme.m new file mode 100644 index 0000000000..2297f4e5bf --- /dev/null +++ b/Examples/ObjC/Sources/Location/Readme.m @@ -0,0 +1,69 @@ +#import "ReadmeAction.h" + +@import CoreLocation; + +#pragma mark - Internal + +static CLLocationManager *_locationManager; + +CLLocationManager *locationManager(void) { + if (!_locationManager) { + _locationManager = [[CLLocationManager alloc] init]; + } + return _locationManager; +} + +#if TARGET_OS_IOS + +void requestAlwaysAuthorization(ReadmeViewController *viewController) { + [locationManager() requestAlwaysAuthorization]; +} + +#endif + +void requestWhenInUseAuthorization(ReadmeViewController *viewController) { + [locationManager() requestWhenInUseAuthorization]; +} + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents a complete BrazeLocation integration.\n" + @"\n" + @"- AppDelegate.{h,m}:\n" + @" - Configure the braze instance with BrazeLocation"; + +#if TARGET_OS_IOS + +NSInteger const actionsCount = 2; + +ReadmeAction const actions[] = { + {@"Request \"always\" authorization", @"", + ^(ReadmeViewController *_Nonnull viewController){ + requestAlwaysAuthorization(viewController); +} +} +, {@"Request \"when in use\" authorization", @"", + ^(ReadmeViewController *_Nonnull viewController){ + requestWhenInUseAuthorization(viewController); +} +} +, +} +; + +#elif TARGET_OS_TV + +NSInteger const actionsCount = 1; + +ReadmeAction const actions[] = { + {@"Request \"when in use\" authorization", @"", + ^(ReadmeViewController *_Nonnull viewController){ + requestWhenInUseAuthorization(viewController); +} +} +, +} +; + +#endif diff --git a/Examples/ObjC/Sources/PushNotifications/AppDelegate.h b/Examples/ObjC/Sources/PushNotifications/AppDelegate.h new file mode 100644 index 0000000000..c0ccacfda5 --- /dev/null +++ b/Examples/ObjC/Sources/PushNotifications/AppDelegate.h @@ -0,0 +1,13 @@ +@import UIKit; +@import UserNotifications; +@import BrazeKit; + +extern NSString *const brazeApiKey; +extern NSString *const brazeEndpoint; + +@interface AppDelegate + : UIResponder + +@property(class, strong, nonatomic) Braze *braze; + +@end diff --git a/Examples/ObjC/Sources/PushNotifications/AppDelegate.m b/Examples/ObjC/Sources/PushNotifications/AppDelegate.m new file mode 100644 index 0000000000..9d4c769b82 --- /dev/null +++ b/Examples/ObjC/Sources/PushNotifications/AppDelegate.m @@ -0,0 +1,114 @@ +#import "AppDelegate.h" + +@import BrazeKit; + +@implementation AppDelegate + +#pragma mark - Lifecycle + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Setup Braze + BRZConfiguration *configuration = + [[BRZConfiguration alloc] initWithApiKey:brazeApiKey + endpoint:brazeEndpoint]; + configuration.logger.level = BRZLoggerLevelInfo; + configuration.push.appGroup = + @"group.com.braze.PushNotifications.PushStories"; + Braze *braze = [[Braze alloc] initWithConfiguration:configuration]; + AppDelegate.braze = braze; + + // Push notifications support + [application registerForRemoteNotifications]; + UNUserNotificationCenter *center = + UNUserNotificationCenter.currentNotificationCenter; + [center setNotificationCategories:BRZNotifications.categories]; + center.delegate = self; + UNAuthorizationOptions options = UNAuthorizationOptionBadge | + UNAuthorizationOptionSound | + UNAuthorizationOptionAlert; + [center requestAuthorizationWithOptions:options + completionHandler:^(BOOL granted, + NSError *_Nullable error) { + NSLog(@"Notification authorization, granted: %d, " + @"error: %@)", + granted, error); + }]; + + [self.window makeKeyAndVisible]; + return YES; +} + +#pragma mark - AppDelegate.braze + +static Braze *_braze = nil; + ++ (Braze *)braze { + return _braze; +} + ++ (void)setBraze:(Braze *)braze { + _braze = braze; +} + +#pragma mark - Push Notification support + +// - Register the device token with Braze + +- (void)application:(UIApplication *)application + didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + [AppDelegate.braze.notifications registerDeviceToken:deviceToken]; +} + +// - Add support for silent notification + +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler: + (void (^)(UIBackgroundFetchResult))completionHandler { + BOOL processedByBraze = + AppDelegate.braze != nil && + [AppDelegate.braze.notifications + handleBackgroundNotificationWithUserInfo:userInfo + fetchCompletionHandler:completionHandler]; + if (processedByBraze) { + return; + } + + completionHandler(UIBackgroundFetchResultNoData); +} + +// - Add support for push notifications + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler { + BOOL processedByBraze = + AppDelegate.braze != nil && + [AppDelegate.braze.notifications + handleUserNotificationWithResponse:response + withCompletionHandler:completionHandler]; + if (processedByBraze) { + return; + } + + completionHandler(); +} + +// - Add support for displaying push notification when the app is currently +// running in the +// foreground + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + willPresentNotification:(UNNotification *)notification + withCompletionHandler: + (void (^)(UNNotificationPresentationOptions))completionHandler { + if (@available(iOS 14, *)) { + completionHandler(UNNotificationPresentationOptionList | + UNNotificationPresentationOptionBanner); + } else { + completionHandler(UNNotificationPresentationOptionAlert); + } +} + +@end diff --git a/Examples/Sources/PushNotifications/Info.plist b/Examples/ObjC/Sources/PushNotifications/Info.plist similarity index 100% rename from Examples/Sources/PushNotifications/Info.plist rename to Examples/ObjC/Sources/PushNotifications/Info.plist diff --git a/Examples/Sources/PushNotifications/PushNotifications.entitlements b/Examples/ObjC/Sources/PushNotifications/PushNotifications.entitlements similarity index 100% rename from Examples/Sources/PushNotifications/PushNotifications.entitlements rename to Examples/ObjC/Sources/PushNotifications/PushNotifications.entitlements diff --git a/Examples/ObjC/Sources/PushNotifications/Readme.m b/Examples/ObjC/Sources/PushNotifications/Readme.m new file mode 100644 index 0000000000..9add716005 --- /dev/null +++ b/Examples/ObjC/Sources/PushNotifications/Readme.m @@ -0,0 +1,23 @@ +#import "ReadmeAction.h" + +#pragma mark - Readme + +NSString *const readme = + @"This sample presents a complete push notification integration " + @"supporting:\n" + @"\n" + @"- PushNotifications/AppDelegate.{h,m}:\n" + @" - Silent push notifications\n" + @" - Foreground push notifications\n" + @" - Action buttons\n" + @" - Display push notifications when app is already open\n" + @"\n" + @"- PushNotificationsServiceExtension:\n" + @" - Rich push notification support (image, GIF, audio, video)\n" + @"\n" + @"- PushNotificationsContentExtension:\n" + @" - Braze Push Story implementation"; + +NSInteger const actionsCount = 0; + +ReadmeAction const actions[] = {}; diff --git a/Examples/Sources/PushNotificationsContentExtension/Info.plist b/Examples/ObjC/Sources/PushNotificationsContentExtension/Info.plist similarity index 100% rename from Examples/Sources/PushNotificationsContentExtension/Info.plist rename to Examples/ObjC/Sources/PushNotificationsContentExtension/Info.plist diff --git a/Examples/Sources/PushNotificationsContentExtension/NotificationViewController.swift b/Examples/ObjC/Sources/PushNotificationsContentExtension/NotificationViewController.swift similarity index 100% rename from Examples/Sources/PushNotificationsContentExtension/NotificationViewController.swift rename to Examples/ObjC/Sources/PushNotificationsContentExtension/NotificationViewController.swift diff --git a/Examples/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements b/Examples/ObjC/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements similarity index 100% rename from Examples/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements rename to Examples/ObjC/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements diff --git a/Examples/Sources/PushNotificationsServiceExtension/Info.plist b/Examples/ObjC/Sources/PushNotificationsServiceExtension/Info.plist similarity index 100% rename from Examples/Sources/PushNotificationsServiceExtension/Info.plist rename to Examples/ObjC/Sources/PushNotificationsServiceExtension/Info.plist diff --git a/Examples/Sources/PushNotificationsServiceExtension/NotificationService.swift b/Examples/ObjC/Sources/PushNotificationsServiceExtension/NotificationService.swift similarity index 100% rename from Examples/Sources/PushNotificationsServiceExtension/NotificationService.swift rename to Examples/ObjC/Sources/PushNotificationsServiceExtension/NotificationService.swift diff --git a/Examples/README.md b/Examples/README.md index cf0166a39a..b37a657fc6 100644 --- a/Examples/README.md +++ b/Examples/README.md @@ -7,10 +7,12 @@ Follow the instructions below for your preferred package manager to get started. #### Swift Package Manager +- Navigates to the `Swift` or `ObjC` directory - Open `Examples-SwiftPM.xcodeproj` #### CocoaPods +- Navigates to the `Swift` or `ObjC` directory - Run `pod install` - Open `Examples-CocoaPods.xcworkspace` @@ -19,40 +21,47 @@ Follow the instructions below for your preferred package manager to get started. #### Analytics - iOS, tvOS. +- Swift, Objective-C. - Demonstrates how to use the analytics features of the SDK. - Related tutorial: [Analytics](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/a3-analytics). #### ContentCards - iOS only. +- Swift, Objective-C. - Demonstrates how to use the Braze provided Content Cards UI. - Related tutorial: [Content Cards UI](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/c2-contentcardsui). #### ContentCards-Custom-UI - iOS, tvOS. +- Swift, Objective-C. - Demonstrates how to implement your own custom Content Cards UI. #### InAppMessages - iOS only. +- Swift, Objective-C. - Demonstrates how to use the Braze provided In-App Message UI. - Related tutorial: [In-App Messages](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/c1-inappmessageui). #### InAppMessages-Custom-UI - iOS, tvOS. +- Swift, Objective-C. - Demonstrates how to implement your own custom In-App Message UI. #### Location - iOS, tvOS. +- Swift, Objective-C. - Presents a complete BrazeLocation integration which enables location tracking and geofence monitoring. - Related tutorial: [Location and Geofences](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/d1-brazelocation). #### PushNotifications -- iOS, tvOS. +- iOS only. +- Swift, Objective-C. - Presents a complete push notification integration supporting: - Silent push notifications. - Foreground push notifications. @@ -70,11 +79,13 @@ Follow the instructions below for your preferred package manager to get started. #### PushNotificationsContentExtension - iOS only. +- Swift only. - Braze Push Story implementation. - Related tutorial: [Push Stories](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/b3-push-stories). #### PushNotificationsServiceExtension - iOS only. +- Swift only. - Rich push notification support (image, GIF, audio, video). - Related tutorial: [Rich Push Notifications](https://braze-inc.github.io/braze-swift-sdk/tutorials/braze/b2-rich-push-notifications). diff --git a/Examples/Examples-CocoaPods.xcodeproj/project.pbxproj b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj similarity index 99% rename from Examples/Examples-CocoaPods.xcodeproj/project.pbxproj rename to Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj index 3c5e524da8..a505e13a7f 100644 --- a/Examples/Examples-CocoaPods.xcodeproj/project.pbxproj +++ b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1222,7 +1222,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Debug; }; @@ -1421,14 +1421,14 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Release; }; diff --git a/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/Examples/Swift/Examples-CocoaPods.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj similarity index 99% rename from Examples/Examples-SwiftPM.xcodeproj/project.pbxproj rename to Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj index 18957ac62d..33a5d8e831 100644 --- a/Examples/Examples-SwiftPM.xcodeproj/project.pbxproj +++ b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 16F703E30F0CDB139F4DBC8E /* ContentCards-Custom-UI.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = "ContentCards-Custom-UI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 1D680CBC8E96C58FD5F8BA5D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 1F8AD06FAD6F81E92F64DD72 /* CardsInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsInfoViewController.swift; sourceTree = ""; }; - 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ..; sourceTree = SOURCE_ROOT; }; + 220432BEC0EA7628608EA5BA /* braze-swift-sdk */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "braze-swift-sdk"; path = ../..; sourceTree = SOURCE_ROOT; }; 34BD000896FB64DC78BBF177 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4AC100D3BC83C040C950594D /* SDWebImageGIFViewProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageGIFViewProvider.swift; sourceTree = ""; }; 4B0A55E8282ADE8756715B6A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -1231,7 +1231,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1239,7 +1239,7 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Debug; }; @@ -1322,14 +1322,14 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; + TVOS_DEPLOYMENT_TARGET = 11.0; }; name = Release; }; diff --git a/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Examples/Swift/Package.swift b/Examples/Swift/Package.swift new file mode 100644 index 0000000000..e92d15f7f9 --- /dev/null +++ b/Examples/Swift/Package.swift @@ -0,0 +1,3 @@ +// This Package.swift is intentionally empty. It exists for the sole purpose of preventing Xcode +// from recursively including the Examples project sources when locally referencing the Braze SDK +// SwiftPM package. diff --git a/Examples/Swift/Podfile b/Examples/Swift/Podfile new file mode 100644 index 0000000000..66dd814301 --- /dev/null +++ b/Examples/Swift/Podfile @@ -0,0 +1,78 @@ +source 'https://cdn.cocoapods.org/' + +project 'Examples-CocoaPods' + +target 'Analytics-iOS' do + platform :ios, '10.0' + pod 'BrazeKit' +end + +target 'Analytics-tvOS' do + platform :tvos, '10.0' + pod 'BrazeKit' +end + +target 'InAppMessages' do + platform :ios, '11.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end + +target 'InAppMessages-Custom-UI-iOS' do + platform :ios, '10.0' + pod 'BrazeKit' +end + +target 'InAppMessages-Custom-UI-tvOS' do + platform :tvos, '10.0' + pod 'BrazeKit' +end + +target 'ContentCards' do + platform :ios, '11.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end + +target 'ContentCards-Custom-UI-iOS' do + platform :ios, '10.0' + pod 'BrazeKit' +end + +target 'ContentCards-Custom-UI-tvOS' do + platform :tvos, '10.0' + pod 'BrazeKit' +end + +target 'Location-iOS' do + platform :ios, '10.0' + pod 'BrazeKit' + pod 'BrazeLocation' +end + +target 'Location-tvOS' do + platform :tvos, '10.0' + pod 'BrazeKit' + pod 'BrazeLocation' +end + +target 'PushNotifications' do + platform :ios, '10.0' + pod 'BrazeKit' +end + +target 'PushNotificationsServiceExtension' do + platform :ios, '10.0' + pod 'BrazeNotificationService' +end + +target 'PushNotificationsContentExtension' do + platform :ios, '10.0' + pod 'BrazePushStory' +end diff --git a/Examples/Sources/Analytics/AppDelegate.swift b/Examples/Swift/Sources/Analytics/AppDelegate.swift similarity index 89% rename from Examples/Sources/Analytics/AppDelegate.swift rename to Examples/Swift/Sources/Analytics/AppDelegate.swift index 7558036354..f3103b2412 100644 --- a/Examples/Sources/Analytics/AppDelegate.swift +++ b/Examples/Swift/Sources/Analytics/AppDelegate.swift @@ -13,7 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info let braze = Braze(configuration: configuration) AppDelegate.braze = braze diff --git a/Examples/Sources/Analytics/AuthenticationManager.swift b/Examples/Swift/Sources/Analytics/AuthenticationManager.swift similarity index 100% rename from Examples/Sources/Analytics/AuthenticationManager.swift rename to Examples/Swift/Sources/Analytics/AuthenticationManager.swift diff --git a/Examples/Sources/Analytics/CheckoutViewController.swift b/Examples/Swift/Sources/Analytics/CheckoutViewController.swift similarity index 100% rename from Examples/Sources/Analytics/CheckoutViewController.swift rename to Examples/Swift/Sources/Analytics/CheckoutViewController.swift diff --git a/Examples/Sources/ContentCards-In-House-UI/Info.plist b/Examples/Swift/Sources/Analytics/Info.plist similarity index 94% rename from Examples/Sources/ContentCards-In-House-UI/Info.plist rename to Examples/Swift/Sources/Analytics/Info.plist index e8c26c902a..6f095d6800 100644 --- a/Examples/Sources/ContentCards-In-House-UI/Info.plist +++ b/Examples/Swift/Sources/Analytics/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - ContentCards-In-House-UI + Analytics CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/Examples/Sources/Analytics/Readme.swift b/Examples/Swift/Sources/Analytics/Readme.swift similarity index 100% rename from Examples/Sources/Analytics/Readme.swift rename to Examples/Swift/Sources/Analytics/Readme.swift diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/Examples/Swift/Sources/Common/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..9221b9bb1a --- /dev/null +++ b/Examples/Swift/Sources/Common/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json b/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Examples/Swift/Sources/Common/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Examples/Sources/Common/Credentials.swift b/Examples/Swift/Sources/Common/Credentials.swift similarity index 100% rename from Examples/Sources/Common/Credentials.swift rename to Examples/Swift/Sources/Common/Credentials.swift diff --git a/Examples/Sources/Common/ReadmeViewController.swift b/Examples/Swift/Sources/Common/ReadmeViewController.swift similarity index 98% rename from Examples/Sources/Common/ReadmeViewController.swift rename to Examples/Swift/Sources/Common/ReadmeViewController.swift index 0ab4fffdaa..ed05508d53 100644 --- a/Examples/Sources/Common/ReadmeViewController.swift +++ b/Examples/Swift/Sources/Common/ReadmeViewController.swift @@ -57,7 +57,7 @@ final class ReadmeViewController: UITableViewController { super.viewWillLayoutSubviews() let size = readmeTextView.systemLayoutSizeFitting( - .init(width: tableView.bounds.width, height: 0)) + .init(width: tableView.bounds.width, height: 1000)) if readmeTextView.frame.height != size.height { readmeTextView.frame.size.height = size.height } diff --git a/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard b/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..865e9329f3 --- /dev/null +++ b/Examples/Swift/Sources/Common/iOS/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard b/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000000..660ba53de4 --- /dev/null +++ b/Examples/Swift/Sources/Common/tvOS/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift similarity index 57% rename from Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift rename to Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift index dc1852cdf7..8d48125650 100644 --- a/Examples/Sources/ContentCards-Custom-UI/AppDelegate.swift +++ b/Examples/Swift/Sources/ContentCards-Custom-UI/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info let braze = Braze(configuration: configuration) AppDelegate.braze = braze @@ -27,7 +27,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func printCurrentContentCards() { // Print all the cards - print(AppDelegate.braze?.contentCards ?? []) + print(AppDelegate.braze?.contentCards.cards ?? []) guard let card = AppDelegate.braze?.contentCards.cards.first else { return } @@ -35,16 +35,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // the Braze platform. // // All `Braze.ContentCard` have a `.data` property that contains common fields. - // For instance, you can retrieve the `extras` dictionary / `uri` on all content cards: + // For instance, you can retrieve the `extras` dictionary / `url` on all content cards: print("extras:", card.data.extras) - print("uri:", card.data.clickAction?.uri ?? "none") + print("url:", card.data.clickAction?.url ?? "none") // All `.data` properties are directly accessible on the card itself. - // For instance, you can access the `extras` dictionary / `uri` omitting the `.data` key path: + // For instance, you can access the `extras` dictionary / `url` omitting the `.data` key path: print("extras:", card.extras) - print("uri:", card.clickAction?.uri ?? "none") + print("url:", card.clickAction?.url ?? "none") // To access card specific fields, you can switch on the `card` enum: switch card { @@ -66,6 +66,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if let image = card.banner?.image { print("banner - image:", image) } + + // A wrapper / compatibility representation of the card is accessible via `.json()` + if let jsonData = card.json(), + let jsonString = String(data: jsonData, encoding: .utf8) { + print(jsonString) + } + + // A card can always be transformed into a `Braze.ContentCardRaw`, a compatibility + // representation of the Content Card type. + let cardRaw = Braze.ContentCardRaw(card) + print("extras:", cardRaw.extras) + print("url:", cardRaw.url ?? "none") + } + + func printCurrentContentCardsRaw() { + // Convert to `Braze.ContentCardRaw` + let rawCards = AppDelegate.braze?.contentCards.cards.map { + Braze.ContentCardRaw($0) + } + + // Print all the cards + print(rawCards ?? []) + + guard let cardRaw = rawCards?.first else { return } + + // Braze.ContentCardRaw is an Objective-C compatible NSObject subclass representing the + // content card object, it matches the platform representation of the Content Card. + // + // All fields are directly accessible on the raw card object. + + print("extras:", cardRaw.extras) + print("url:", cardRaw.url ?? "none") + + if let title = cardRaw.title { + print("title:", title) + } + + if let image = cardRaw.image { + print("image:", image) + } + + // A wrapper / compatibility representation of the card is accessible via `.json()` + if let jsonData = cardRaw.json(), + let jsonString = String(data: jsonData, encoding: .utf8) { + print(jsonString) + } + + // A raw card can be transformed into a `Braze.ContentCard`, the type-safe representation of the + // content card object. + guard let card = try? Braze.ContentCard(cardRaw) else { + return + } + print("extras:", card.extras) + print("url:", card.clickAction?.url ?? "none") } func refreshContentCards() { diff --git a/Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift similarity index 93% rename from Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift rename to Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift index e24752581c..64c7141933 100644 --- a/Examples/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift +++ b/Examples/Swift/Sources/ContentCards-Custom-UI/CardsInfoViewController.swift @@ -1,5 +1,5 @@ -import BrazeKit import UIKit +import BrazeKit final class CardsInfoViewController: UITableViewController { @@ -26,8 +26,7 @@ final class CardsInfoViewController: UITableViewController { sections = cards.enumerated().map { Self.cardSection(from: $1, index: $0) } super.init(style: .grouped) title = "Content Cards Info" - let doneButton = UIBarButtonItem( - barButtonSystemItem: .done, target: self, action: #selector(dismissModal)) + let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissModal)) navigationItem.setRightBarButton(doneButton, animated: false) tableView.rowHeight = UITableView.automaticDimension @@ -63,8 +62,7 @@ final class CardsInfoViewController: UITableViewController { _ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell { - let cell = - tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") + let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") ?? UITableViewCell(style: .value1, reuseIdentifier: "cellIdentifier") let field = sections[indexPath.section].fields[indexPath.row] @@ -162,11 +160,11 @@ final class CardsInfoViewController: UITableViewController { switch clickAction { case .none: header.value = "none" - case .uri(let uri, let useWebView): - header.value = "uri" + case .url(let url, let useWebView): + header.value = "url" fields = [ - Field(name: "uri", value: uri, indentation: indentation + 1), - Field(name: "useWebView", value: useWebView, indentation: indentation + 1), + Field(name: "url", value: url, indentation: indentation + 1), + Field(name: "useWebView", value: useWebView, indentation: indentation + 1) ] @unknown default: break @@ -175,4 +173,5 @@ final class CardsInfoViewController: UITableViewController { return [header] + fields } + } diff --git a/Examples/Sources/InAppMessages-In-House-UI/Info.plist b/Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist similarity index 94% rename from Examples/Sources/InAppMessages-In-House-UI/Info.plist rename to Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist index 59751b10e0..cf7a1812cd 100644 --- a/Examples/Sources/InAppMessages-In-House-UI/Info.plist +++ b/Examples/Swift/Sources/ContentCards-Custom-UI/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName - InAppMessages-In-House-UI + ContentCards-Custom-UI CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/Examples/Sources/ContentCards-Custom-UI/Readme.swift b/Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift similarity index 83% rename from Examples/Sources/ContentCards-Custom-UI/Readme.swift rename to Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift index 7f7e179471..57aa7bd0b4 100644 --- a/Examples/Sources/ContentCards-Custom-UI/Readme.swift +++ b/Examples/Swift/Sources/ContentCards-Custom-UI/Readme.swift @@ -3,7 +3,7 @@ import UIKit let readme = """ - This sample demonstrates how to implement your own custom Content Cards UI: + This sample presents how to implement your own custom Content Cards UI: - AppDelegate.swift: - Content cards API usage @@ -18,6 +18,11 @@ let actions: [(String, String, (ReadmeViewController) -> Void)] = [ "", printCurrentContentCards ), + ( + "Print current Content Cards Raw", + "", + printCurrentContentCardsRaw + ), ( "Refresh Content Cards", "", @@ -46,6 +51,10 @@ func printCurrentContentCards(_ viewController: ReadmeViewController) { (UIApplication.shared.delegate as? AppDelegate)?.printCurrentContentCards() } +func printCurrentContentCardsRaw(_ viewController: ReadmeViewController) { + (UIApplication.shared.delegate as? AppDelegate)?.printCurrentContentCardsRaw() +} + func refreshContentCards(_ viewController: ReadmeViewController) { (UIApplication.shared.delegate as? AppDelegate)?.refreshContentCards() } @@ -61,3 +70,4 @@ func cancelContentCardsUpdatesSubscription(_ viewController: ReadmeViewControlle func presentContentCardsInfoViewController(_ viewController: ReadmeViewController) { (UIApplication.shared.delegate as? AppDelegate)?.presentContentCardsInfoViewController() } + diff --git a/Examples/Sources/ContentCards/AppDelegate.swift b/Examples/Swift/Sources/ContentCards/AppDelegate.swift similarity index 96% rename from Examples/Sources/ContentCards/AppDelegate.swift rename to Examples/Swift/Sources/ContentCards/AppDelegate.swift index d087a1295d..c236943dc6 100644 --- a/Examples/Sources/ContentCards/AppDelegate.swift +++ b/Examples/Swift/Sources/ContentCards/AppDelegate.swift @@ -12,13 +12,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info let braze = Braze(configuration: configuration) AppDelegate.braze = braze // - GIF support - BrazeUI.gifViewProvider = .sdWebImage + GIFViewProvider.shared = .sdWebImage window?.makeKeyAndVisible() return true diff --git a/Examples/Swift/Sources/ContentCards/Info.plist b/Examples/Swift/Sources/ContentCards/Info.plist new file mode 100644 index 0000000000..0c015f1468 --- /dev/null +++ b/Examples/Swift/Sources/ContentCards/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ContentCards + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Sources/ContentCards/Readme.swift b/Examples/Swift/Sources/ContentCards/Readme.swift similarity index 100% rename from Examples/Sources/ContentCards/Readme.swift rename to Examples/Swift/Sources/ContentCards/Readme.swift diff --git a/Examples/Sources/ContentCards/SDWebImageGIFViewProvider.swift b/Examples/Swift/Sources/ContentCards/SDWebImageGIFViewProvider.swift similarity index 100% rename from Examples/Sources/ContentCards/SDWebImageGIFViewProvider.swift rename to Examples/Swift/Sources/ContentCards/SDWebImageGIFViewProvider.swift diff --git a/Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift similarity index 83% rename from Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift rename to Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift index abefe07cda..adca669512 100644 --- a/Examples/Sources/InAppMessages-Custom-UI/AppDelegate.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/AppDelegate.swift @@ -11,12 +11,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info let braze = Braze(configuration: configuration) AppDelegate.braze = braze - // Setup our custom In-App Message presenter. + // Setup the custom In-App Message presenter. braze.inAppMessagePresenter = CustomInAppMessagePresenter() window?.makeKeyAndVisible() diff --git a/Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift similarity index 69% rename from Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift rename to Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift index 10cf970b28..e7c05282cd 100644 --- a/Examples/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/CustomInAppMessagePresenter.swift @@ -9,16 +9,16 @@ struct CustomInAppMessagePresenter: BrazeInAppMessagePresenter { // by the Braze platform. // // All `Braze.InAppMessage` have a `.data` property that contains common fields. - // For instance, you can retrieve the `extras` dictionary / `uri` on all in-app messages: + // For instance, you can retrieve the `extras` dictionary / `url` on all in-app messages: print("extras:", message.data.extras) - print("uri:", message.data.clickAction.uri ?? "none") + print("url:", message.data.clickAction.url ?? "none") // All `.data` properties are directly accessible on the message itself. - // For instance, you can access the `extras` dictionary / `uri` omitting the `.data` key path: + // For instance, you can access the `extras` dictionary / `url` omitting the `.data` key path: print("extras:", message.extras) - print("uri:", message.clickAction.uri ?? "none") + print("url:", message.clickAction.url ?? "none") // To access message specific fields, you can switch on the `message` enum: switch message { @@ -41,6 +41,18 @@ struct CustomInAppMessagePresenter: BrazeInAppMessagePresenter { print("full - header:", header) } + // A wrapper / compatibility representation of the in-app message is accessible via `.json()` + if let jsonData = message.json(), + let jsonString = String(data: jsonData, encoding: .utf8) { + print(jsonString) + } + + // An message can always be transformed into a `Braze.InAppMessageRaw`, a compatibility + // representation of the In-App Message type. + let messageRaw = Braze.InAppMessageRaw(message) + print("extras:", messageRaw.extras) + print("url:", messageRaw.url ?? "none") + // Here, we present a custom view controller for the message let controller = InAppMessageInfoViewController(message: message) diff --git a/Examples/Sources/InAppMessages-Custom-UI/Extensions.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift similarity index 89% rename from Examples/Sources/InAppMessages-Custom-UI/Extensions.swift rename to Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift index 2d9c717aa2..38e3755223 100644 --- a/Examples/Sources/InAppMessages-Custom-UI/Extensions.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift @@ -1,5 +1,5 @@ -import BrazeKit import Foundation +import BrazeKit // MARK: - Braze @@ -27,8 +27,7 @@ extension Encodable { } guard let data = try? encoder.encode(self), - let prettyPrinted = String(data: data, encoding: .utf8) - else { + let prettyPrinted = String(data: data, encoding: .utf8) else { return "\(self)" } @@ -49,8 +48,7 @@ extension Dictionary where Key == String, Value == Any { } guard let data = try? JSONSerialization.data(withJSONObject: self, options: options), - let prettyPrinted = String(data: data, encoding: .utf8) - else { + let prettyPrinted = String(data: data, encoding: .utf8) else { return "\(self)" } diff --git a/Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift similarity index 80% rename from Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift rename to Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift index 391c7dca10..70f26c68cb 100644 --- a/Examples/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/InAppMessageInfoViewController.swift @@ -1,5 +1,5 @@ -import BrazeKit import UIKit +import BrazeKit final class InAppMessageInfoViewController: UITableViewController { @@ -26,8 +26,7 @@ final class InAppMessageInfoViewController: UITableViewController { sections = Self.messageSections(from: message) + Self.dataSections(from: message) super.init(style: .grouped) title = "In-App Message Info" - let doneButton = UIBarButtonItem( - barButtonSystemItem: .done, target: self, action: #selector(dismissModal)) + let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissModal)) navigationItem.setRightBarButton(doneButton, animated: false) tableView.rowHeight = UITableView.automaticDimension @@ -63,8 +62,7 @@ final class InAppMessageInfoViewController: UITableViewController { _ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell { - let cell = - tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") + let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") ?? UITableViewCell(style: .value1, reuseIdentifier: "cellIdentifier") let field = sections[indexPath.section].fields[indexPath.row] @@ -99,38 +97,33 @@ final class InAppMessageInfoViewController: UITableViewController { var themesSection: Section? switch message { case .slideup(let slideup): - section.fields = - [ - Field(name: "type", value: "slideup"), - Field(name: "message", value: slideup.message, indentation: 1), - Field(name: "slideFrom", value: slideup.slideFrom.rawValue, indentation: 1), - ] + fields(from: slideup.graphic, indentation: 1) + section.fields = [ + Field(name: "type", value: "slideup"), + Field(name: "message", value: slideup.message, indentation: 1), + Field(name: "slideFrom", value: slideup.slideFrom.rawValue, indentation: 1) + ] + fields(from: slideup.graphic, indentation: 1) themesSection = self.themesSection(from: slideup.themes) case .modal(let modal): - section.fields = - [ - Field(name: "type", value: "modal"), - Field(name: "header", value: modal.header, indentation: 1), - Field(name: "message", value: modal.message, indentation: 1), - Field( - name: "headerTextAlignment", value: modal.headerTextAlignment.rawValue, indentation: 1), - Field( - name: "messageTextAlignment", value: modal.messageTextAlignment.rawValue, indentation: 1 - ), - ] + fields(from: modal.graphic, indentation: 1) + section.fields = [ + Field(name: "type", value: "modal"), + Field(name: "header", value: modal.header, indentation: 1), + Field(name: "message", value: modal.message, indentation: 1), + Field(name: "headerTextAlignment", value: modal.headerTextAlignment.rawValue, indentation: 1), + Field(name: "messageTextAlignment", value: modal.messageTextAlignment.rawValue, indentation: 1), + ] + fields(from: modal.graphic, indentation: 1) buttonsSection = self.buttonsSection(from: modal.buttons) themesSection = self.themesSection(from: modal.themes) case .modalImage(let modalImage): section.fields = [ Field(name: "type", value: "modalImage"), - Field(name: "imageUri", value: modalImage.imageUri, indentation: 1), + Field(name: "imageURL", value: modalImage.imageURL, indentation: 1), ] buttonsSection = self.buttonsSection(from: modalImage.buttons) themesSection = self.themesSection(from: modalImage.themes) case .full(let full): section.fields = [ Field(name: "type", value: "full"), - Field(name: "imageUri", value: full.imageUri, indentation: 1), + Field(name: "imageURL", value: full.imageURL, indentation: 1), Field(name: "header", value: full.header, indentation: 1), Field(name: "message", value: full.message, indentation: 1), Field(name: "headerTextAlignment", value: full.headerTextAlignment, indentation: 1), @@ -141,7 +134,7 @@ final class InAppMessageInfoViewController: UITableViewController { case .fullImage(let fullImage): section.fields = [ Field(name: "type", value: "fullImage"), - Field(name: "imageUri", value: fullImage.imageUri, indentation: 1), + Field(name: "imageURL", value: fullImage.imageURL, indentation: 1), ] buttonsSection = self.buttonsSection(from: fullImage.buttons) themesSection = self.themesSection(from: fullImage.themes) @@ -150,10 +143,10 @@ final class InAppMessageInfoViewController: UITableViewController { Field(name: "type", value: "html"), Field(name: "message", value: "", indentation: 1), Field(name: html.message, value: "", indentation: 2), - Field(name: "baseUrl", value: "", indentation: 1), - Field(name: html.baseUrl?.absoluteString ?? "none", value: "", indentation: 2), - Field(name: "assetUrls", value: "", indentation: 1), - Field(name: html.assetUrls.prettyPrint(), value: "", indentation: 2), + Field(name: "baseURL", value: "", indentation: 1), + Field(name: html.baseURL?.absoluteString ?? "none", value: "", indentation: 2), + Field(name: "assetURLs", value: "", indentation: 1), + Field(name: html.assetURLs.prettyPrint(), value: "", indentation: 2), Field(name: "legacy", value: html.legacy, indentation: 1), ] case .control: @@ -177,8 +170,7 @@ final class InAppMessageInfoViewController: UITableViewController { Field(name: "headerTextColor", value: theme.headerTextColor.hexString, indentation: 1), Field(name: "closeButtonColor", value: theme.closeButtonColor.hexString, indentation: 1), Field(name: "iconColor", value: theme.iconColor.hexString, indentation: 1), - Field( - name: "iconBackgroundColor", value: theme.iconBackgroundColor.hexString, indentation: 1), + Field(name: "iconBackgroundColor", value: theme.iconBackgroundColor.hexString, indentation: 1), Field(name: "backgroundColor", value: theme.backgroundColor.hexString, indentation: 1), Field(name: "frameColor", value: theme.frameColor.hexString, indentation: 1), ] @@ -226,7 +218,7 @@ final class InAppMessageInfoViewController: UITableViewController { // Extras section.fields += [ Field(name: "extras", value: ""), - Field(name: message.extras.prettyPrint(), value: "", indentation: 1), + Field(name: message.extras.prettyPrint(), value: "", indentation: 1) ] return [section] @@ -246,11 +238,11 @@ final class InAppMessageInfoViewController: UITableViewController { header.value = "none" case .newsFeed: header.value = "newsFeed" - case .uri(let uri, let useWebView): - header.value = "uri" + case .url(let url, useWebView: let useWebView): + header.value = "url" fields = [ - Field(name: "uri", value: uri, indentation: indentation + 1), - Field(name: "useWebView", value: useWebView, indentation: indentation + 1), + Field(name: "url", value: url, indentation: indentation + 1), + Field(name: "useWebView", value: useWebView, indentation: indentation + 1) ] @unknown default: break @@ -295,9 +287,7 @@ final class InAppMessageInfoViewController: UITableViewController { case .icon(let icon): header.value = "icon" fields = [ - Field( - name: "icon (FontAwesome, may not render correctly here)", value: icon, - indentation: indentation + 1) + Field(name: "icon (FontAwesome, may not render correctly here)", value: icon, indentation: indentation + 1) ] case .image(let url): header.value = "image" @@ -319,11 +309,8 @@ final class InAppMessageInfoViewController: UITableViewController { fields += [ Field(name: "theme", value: name, indentation: indentation), Field(name: "textColor", value: theme.textColor.hexString, indentation: indentation + 1), - Field( - name: "backgroundColor", value: theme.backgroundColor.hexString, - indentation: indentation + 1), - Field( - name: "borderColor", value: theme.borderColor.hexString, indentation: indentation + 1), + Field(name: "backgroundColor", value: theme.backgroundColor.hexString, indentation: indentation + 1), + Field(name: "borderColor", value: theme.borderColor.hexString, indentation: indentation + 1), ] } @@ -331,3 +318,4 @@ final class InAppMessageInfoViewController: UITableViewController { } } + diff --git a/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist b/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist new file mode 100644 index 0000000000..486c46727c --- /dev/null +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + InAppMessages-Custom-UI + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Sources/InAppMessages-Custom-UI/Readme.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift similarity index 86% rename from Examples/Sources/InAppMessages-Custom-UI/Readme.swift rename to Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift index d7f4286bfb..072046cf11 100644 --- a/Examples/Sources/InAppMessages-Custom-UI/Readme.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Readme.swift @@ -3,7 +3,7 @@ import UIKit let readme = """ - This sample demonstrates how to implement your own custom In-App Message UI: + This sample presents how to implement your own custom In-App Message UI: - AppDelegate.swift: - Sets the custom in-app message presenter @@ -30,7 +30,7 @@ func localSlideup(_ viewController: ReadmeViewController) { let slideup: Braze.InAppMessage = .slideup( .init( data: .init( - clickAction: .uri(URL(string: "https://example.com")!, useWebView: true), + clickAction: .url(URL(string: "https://example.com")!, useWebView: true), extras: ["key1": "value1", "key2": "value2"] ), graphic: .icon(""), @@ -44,7 +44,7 @@ func localModal(_ viewController: ReadmeViewController) { let modal: Braze.InAppMessage = .modal( .init( data: .init( - clickAction: .uri(URL(string: "https://example.com")!, useWebView: true), + clickAction: .url(URL(string: "https://example.com")!, useWebView: true), extras: ["key1": "value1", "key2": "value2"] ), graphic: .icon(""), diff --git a/Examples/Sources/InAppMessages/AppDelegate.swift b/Examples/Swift/Sources/InAppMessages/AppDelegate.swift similarity index 93% rename from Examples/Sources/InAppMessages/AppDelegate.swift rename to Examples/Swift/Sources/InAppMessages/AppDelegate.swift index d9a9484866..368d66c9c7 100644 --- a/Examples/Sources/InAppMessages/AppDelegate.swift +++ b/Examples/Swift/Sources/InAppMessages/AppDelegate.swift @@ -12,13 +12,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info let braze = Braze(configuration: configuration) AppDelegate.braze = braze // - GIF support - BrazeUI.gifViewProvider = .sdWebImage + GIFViewProvider.shared = .sdWebImage // - InAppMessage UI let inAppMessageUI = BrazeInAppMessageUI() diff --git a/Examples/Swift/Sources/InAppMessages/Info.plist b/Examples/Swift/Sources/InAppMessages/Info.plist new file mode 100644 index 0000000000..4f97542122 --- /dev/null +++ b/Examples/Swift/Sources/InAppMessages/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + InAppMessages + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Sources/InAppMessages/Readme.swift b/Examples/Swift/Sources/InAppMessages/Readme.swift similarity index 100% rename from Examples/Sources/InAppMessages/Readme.swift rename to Examples/Swift/Sources/InAppMessages/Readme.swift diff --git a/Examples/Sources/InAppMessages/SDWebImageGIFViewProvider.swift b/Examples/Swift/Sources/InAppMessages/SDWebImageGIFViewProvider.swift similarity index 100% rename from Examples/Sources/InAppMessages/SDWebImageGIFViewProvider.swift rename to Examples/Swift/Sources/InAppMessages/SDWebImageGIFViewProvider.swift diff --git a/Examples/Sources/Location/AppDelegate.swift b/Examples/Swift/Sources/Location/AppDelegate.swift similarity index 92% rename from Examples/Sources/Location/AppDelegate.swift rename to Examples/Swift/Sources/Location/AppDelegate.swift index 9f8cb6e23c..a18615cc1c 100644 --- a/Examples/Sources/Location/AppDelegate.swift +++ b/Examples/Swift/Sources/Location/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info configuration.location.brazeLocation = BrazeLocation() configuration.location.automaticLocationCollection = true diff --git a/Examples/Swift/Sources/Location/Info.plist b/Examples/Swift/Sources/Location/Info.plist new file mode 100644 index 0000000000..71c36b3686 --- /dev/null +++ b/Examples/Swift/Sources/Location/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Location + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSLocationAlwaysAndWhenInUseUsageDescription + Location Authorization - Always / When in Use + NSLocationWhenInUseUsageDescription + Location Authorization - When in Use + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Sources/Location/Readme.swift b/Examples/Swift/Sources/Location/Readme.swift similarity index 100% rename from Examples/Sources/Location/Readme.swift rename to Examples/Swift/Sources/Location/Readme.swift diff --git a/Examples/Sources/PushNotifications/AppDelegate.swift b/Examples/Swift/Sources/PushNotifications/AppDelegate.swift similarity index 97% rename from Examples/Sources/PushNotifications/AppDelegate.swift rename to Examples/Swift/Sources/PushNotifications/AppDelegate.swift index 5db5f5a267..8c703d2799 100644 --- a/Examples/Sources/PushNotifications/AppDelegate.swift +++ b/Examples/Swift/Sources/PushNotifications/AppDelegate.swift @@ -12,7 +12,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Setup Braze - var configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) + let configuration = Braze.Configuration(apiKey: brazeApiKey, endpoint: brazeEndpoint) configuration.logger.level = .info configuration.push.appGroup = "group.com.braze.PushNotifications.PushStories" let braze = Braze(configuration: configuration) diff --git a/Examples/Swift/Sources/PushNotifications/Info.plist b/Examples/Swift/Sources/PushNotifications/Info.plist new file mode 100644 index 0000000000..d7f8ec8ca2 --- /dev/null +++ b/Examples/Swift/Sources/PushNotifications/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + PushNotifications + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UIBackgroundModes + + remote-notification + + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements b/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements new file mode 100644 index 0000000000..9cad402b51 --- /dev/null +++ b/Examples/Swift/Sources/PushNotifications/PushNotifications.entitlements @@ -0,0 +1,12 @@ + + + + + aps-environment + development + com.apple.security.application-groups + + group.com.braze.PushNotifications.PushStories + + + diff --git a/Examples/Sources/PushNotifications/Readme.swift b/Examples/Swift/Sources/PushNotifications/Readme.swift similarity index 100% rename from Examples/Sources/PushNotifications/Readme.swift rename to Examples/Swift/Sources/PushNotifications/Readme.swift diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist b/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist new file mode 100644 index 0000000000..0ef3fe3ffc --- /dev/null +++ b/Examples/Swift/Sources/PushNotificationsContentExtension/Info.plist @@ -0,0 +1,47 @@ + + + + + Braze + + AppGroup + group.com.braze.PushNotifications.PushStories + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + PushNotificationsContentExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionAttributes + + UNNotificationExtensionCategory + ab_cat_push_story_v2 + UNNotificationExtensionDefaultContentHidden + + UNNotificationExtensionInitialContentSizeRatio + 0.59999999999999998 + UNNotificationExtensionUserInteractionEnabled + + + NSExtensionPointIdentifier + com.apple.usernotifications.content-extension + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationViewController + + + diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift b/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift new file mode 100644 index 0000000000..e4d429b3dc --- /dev/null +++ b/Examples/Swift/Sources/PushNotificationsContentExtension/NotificationViewController.swift @@ -0,0 +1,3 @@ +import BrazePushStory + +class NotificationViewController: BrazePushStory.NotificationViewController {} diff --git a/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements b/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements new file mode 100644 index 0000000000..0f4c7da6cc --- /dev/null +++ b/Examples/Swift/Sources/PushNotificationsContentExtension/PushNotificationsContentExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.com.braze.PushNotifications.PushStories + + + diff --git a/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist b/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist new file mode 100644 index 0000000000..1387b1cc92 --- /dev/null +++ b/Examples/Swift/Sources/PushNotificationsServiceExtension/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + PushNotificationsServiceExtension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift b/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift new file mode 100644 index 0000000000..71d7005a43 --- /dev/null +++ b/Examples/Swift/Sources/PushNotificationsServiceExtension/NotificationService.swift @@ -0,0 +1,3 @@ +import BrazeNotificationService + +class NotificationService: BrazeNotificationService.NotificationService {} diff --git a/Package.swift b/Package.swift index 996e880073..630cf08fc5 100644 --- a/Package.swift +++ b/Package.swift @@ -26,8 +26,8 @@ let package = Package( targets: [ .binaryTarget( name: "BrazeKit", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeKit.zip", - checksum: "384a541e56b6c56ecdf787ab31cd217f89388e98e76c9d05e0d39a6dc85e3b5a" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeKit.zip", + checksum: "a20b8922491b014387b09f8284738585a700735b5f48ff88446ba7e3d2422544" ), .target( name: "BrazeKitResources", @@ -42,18 +42,18 @@ let package = Package( ), .binaryTarget( name: "BrazeLocation", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeLocation.zip", - checksum: "541c9164a0936c05252cb6f45969a2b46c3e7cfe403a664304a3744f5c3c5a52" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeLocation.zip", + checksum: "3c1b18a5854672007684c1f99895c45a7fc47da6f7864db7fe561d6152f566ce" ), .binaryTarget( name: "BrazeNotificationService", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazeNotificationService.zip", - checksum: "86881788339faa3729dc35f81315c60ccc138d789af831ae7b64d62ccc28cb7d" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazeNotificationService.zip", + checksum: "1bda7311e0378a43fa78a57e964c953e6b3c06ac3ae57da14b367a5be6d59482" ), .binaryTarget( name: "BrazePushStory", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.4.0/BrazePushStory.zip", - checksum: "074c61f50c662f2eb4dd81562f7ffa5f774207932008e3dfa6a7224a61005816" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.5.0/BrazePushStory.zip", + checksum: "7aae86b1aa94c3fb269717423651a2bebbb0326d9674b027d4d4047e033f89d2" ), ] ) diff --git a/README.md b/README.md index 44d652ed28..9290f7f9cf 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,22 @@ Braze Logo

+

+ + Version: 5.5.0 + + + Platforms: iOS – tvOS – Mac Catalyst + + + Package Managers: SwiftPM - CocoaPods + + + License: Commercial + +

+ # Braze Swift SDK (Early Access) - [Braze User Guide](https://www.braze.com/docs/user_guide/introduction/ "Braze User Guide") @@ -31,13 +47,13 @@ The following features are planned for development. To request new Swift SDK fea -| | iOS | macCatatyst | tvOS | -| ---------------------------------------------------------------------------------------------------------------------------- | :---: | :---------: | :-----------: | -| **BrazeKit**
_Main SDK library providing support for [analytics] and [push notifications]._ | ✅ | ✅ | ✅1 | -| **BrazeUI**
_Braze-provided user interface library for [In-App Messages] and [Content Cards]._ | ✅ | ✅ | n/a | -| **BrazeLocation**
_Location library providing support for [location analytics and geofence monitoring]._ | ✅ | ✅ | ✅2 | -| **BrazeNotificationService**
_Notification service extension library providing support for [rich push notifications]._ | ✅ | ✅ | n/a | -| **BrazePushStory**
_Notification content extension library providing support for [Push Stories]._ | ✅ | ✅ | n/a | +| | iOS | tvOS | macCatatyst | +| --------------------------------------------------------------------------------------------------------------------------- | :---: | :-----------: | :---------: | +| **BrazeKit**
_Main SDK library providing support for [analytics] and [push notifications]._ | ✅ | ✅1 | ✅ | +| **BrazeUI**
_Braze-provided user interface library for [In-App Messages] and [Content Cards]._ | ✅ | n/a | ✅ | +| **BrazeLocation**
_Location library providing support for [location analytics and geofence monitoring]._ | ✅ | ✅2 | ✅ | +| **BrazeNotificationService**
_Notification service extension library providing support for [rich push notifications]._ | ✅ | n/a | ✅ | +| **BrazePushStory**
_Notification content extension library providing support for [Push Stories]._ | ✅ | n/a | ✅ | 1 _Push notifications not supported on tvOS_
2 _Geofence monitoring not supported on tvOS_ diff --git a/Sources/BrazeUI/BrazeUIMocks.swift b/Sources/BrazeUI/BrazeUIMocks.swift index f06437f706..4f6fdc9194 100644 --- a/Sources/BrazeUI/BrazeUIMocks.swift +++ b/Sources/BrazeUI/BrazeUIMocks.swift @@ -78,16 +78,16 @@ import UIKit } // Write to temporary cache - let cacheUrl = try! FileManager.default.url( + let cacheURL = try! FileManager.default.url( for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: false ) - let imageUrl = cacheUrl.appendingPathComponent("\(text).png") - try! data.write(to: imageUrl) + let imageURL = cacheURL.appendingPathComponent("\(text).png") + try! data.write(to: imageURL) - return imageUrl + return imageURL } } diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift new file mode 100644 index 0000000000..83cbc3fab0 --- /dev/null +++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController+ObjC.swift @@ -0,0 +1,123 @@ +import BrazeKit +import Foundation + +extension BrazeContentCardUI.ModalViewController { + + /// Creates and return a table view controller displaying the latest content cards fetched by + /// the Braze SDK. + /// + /// - Parameter braze: The Braze instance. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init(braze: Braze) { + self.init(braze: braze, attributes: .defaults) + } + + /// Creates and return a table view controller displaying the latest content cards fetched by + /// the Braze SDK. + /// + /// - Parameters: + /// - braze: The Braze instance. + /// - title: The navigation bar title. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init(braze: Braze, title: String) { + self.init(braze: braze, attributes: .defaults, title: title) + } + + /// Creates and return a table view controller able to display content cards. For most use + /// cases, prefer using ``init(braze:attributes:)`` instead. + /// + /// - Parameters: + /// - initialCards: The initial Content Cards displayed. + /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to + /// refresh. + /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil` + /// disables automatic updates. + /// - lastUpdate: The last time the content cards were updated. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init( + initialCards: [Braze.ContentCardRaw], + refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)?, + subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)?, + lastUpdate: Date? + ) { + self.init( + initialCards: initialCards.compactMap { try? .init($0) }, + refresh: refresh.flatMap { refresh in + { completion in + refresh { cards, error in + switch (cards, error) { + case (.some(let cards), nil): + completion(.success(cards.compactMap { try? Braze.ContentCard($0) })) + case (_, .some(let error)): + completion(.failure(error)) + case (nil, nil): + completion(.failure(URLError(.cannotOpenFile))) + } + } + } + }, + subscribe: subscribe.flatMap { subscribe in + { update in + subscribe { cards in + update(cards.compactMap { try? Braze.ContentCard($0) }) + } + } + }, + lastUpdate: lastUpdate, + attributes: .defaults, + title: "" + ) + } + + /// Creates and return a table view controller able to display content cards. For most use + /// cases, prefer using ``init(braze:attributes:)`` instead. + /// + /// - Parameters: + /// - initialCards: The initial Content Cards displayed. + /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to + /// refresh. + /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil` + /// disables automatic updates. + /// - lastUpdate: The last time the content cards were updated. + /// - title: The navigation bar title. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init( + initialCards: [Braze.ContentCardRaw], + refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)?, + subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)?, + lastUpdate: Date?, + title: String + ) { + self.init( + initialCards: initialCards.compactMap { try? .init($0) }, + refresh: refresh.flatMap { refresh in + { completion in + refresh { cards, error in + switch (cards, error) { + case (.some(let cards), nil): + completion(.success(cards.compactMap { try? Braze.ContentCard($0) })) + case (_, .some(let error)): + completion(.failure(error)) + case (nil, nil): + completion(.failure(URLError(.cannotOpenFile))) + } + } + } + }, + subscribe: subscribe.flatMap { subscribe in + { update in + subscribe { cards in + update(cards.compactMap { try? Braze.ContentCard($0) }) + } + } + }, + lastUpdate: lastUpdate, + attributes: .defaults, + title: title + ) + } +} diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift index 4ce3ccfb59..c98f20f1f3 100644 --- a/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift +++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIModalViewController.swift @@ -5,10 +5,12 @@ extension BrazeContentCardUI { /// Wraps ``ViewController`` in a `UINavigationController` with a _Done_ button. Use this class /// for presenting the content cards modally. + @objc(BRZContentCardUIModalViewController) open class ModalViewController: UINavigationController { // MARK: - Properties + @objc public let viewController: ViewController // MARK: - Initialization @@ -20,7 +22,7 @@ extension BrazeContentCardUI { /// - braze: The Braze instance. /// - attributes: An attributes struct allowing customization of the table view controller /// and its cells. - /// - title: The navigation bar title (default: `""`) + /// - title: The navigation bar title (default: `""`). public init( braze: Braze, attributes: ViewController.Attributes = .defaults, @@ -41,6 +43,7 @@ extension BrazeContentCardUI { /// refresh. /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil` /// disables automatic updates. + /// - lastUpdate: The last time the content cards were updated. /// - attributes: An attributes struct allowing customization of the table view controller /// and its cells. /// - title: The navigation bar title (default: `""`) @@ -48,6 +51,7 @@ extension BrazeContentCardUI { initialCards: [Braze.ContentCard], refresh: ((@escaping (Result<[Braze.ContentCard], Error>) -> Void) -> Void)? = nil, subscribe: ((@escaping ([Braze.ContentCard]) -> Void) -> Braze.Cancellable)? = nil, + lastUpdate: Date? = nil, attributes: ViewController.Attributes = .defaults, title: String = "" ) { @@ -55,17 +59,27 @@ extension BrazeContentCardUI { initialCards: initialCards, refresh: refresh, subscribe: subscribe, + lastUpdate: lastUpdate, attributes: attributes ) viewController.title = title super.init(rootViewController: viewController) } + /// Does not support interface-builder / storyboards. @available(*, unavailable) required public init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + /// See ``init(braze:attributes:title:)``. + @objc + @available(*, unavailable) + public init() { + // This init exists only to override the ObjC `NSObject.init` and disable it. + fatalError("init is not available") + } + // MARK: - LifeCycle open override func viewDidLoad() { diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift new file mode 100644 index 0000000000..9e173aa7de --- /dev/null +++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController+ObjC.swift @@ -0,0 +1,77 @@ +import BrazeKit +import Foundation + +extension BrazeContentCardUI.ViewController { + + /// The content cards currently displayed. + @objc(cards) + @available(swift, obsoleted: 0.0.1) + open var _objc_cards: [Braze.ContentCardRaw] { + get { cards.map(Braze.ContentCardRaw.init) } + set { cards = newValue.compactMap { try? .init($0) } } + } + + /// The delegate notified of the content cards UI lifecycle. + @objc(delegate) + @available(swift, obsoleted: 0.0.1) + public weak var _objc_delegate: _OBJC_BrazeContentCardUIViewControllerDelegate? { + get { (delegate as? _OBJC_BrazeContentCardUIViewControllerDelegateWrapper)?.delegate } + set { delegate = newValue.flatMap(_OBJC_BrazeContentCardUIViewControllerDelegateWrapper.init) } + } + + /// Creates and return a table view controller displaying the latest content cards fetched by + /// the Braze SDK. + /// + /// - Parameter braze: The Braze instance. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init(braze: Braze) { + self.init(braze: braze, attributes: .defaults) + } + + /// Creates and return a table view controller able to display content cards. For most use + /// cases, prefer using ``init(braze:attributes:)`` instead. + /// + /// - Parameters: + /// - initialCards: The initial Content Cards displayed. + /// - refresh: An optional closure implementing the refresh logic. `nil` disables pull to + /// refresh. + /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil` + /// disables automatic updates. + /// - lastUpdate: The last time the content cards were updated. + @objc + @available(swift, obsoleted: 0.0.1) + public convenience init( + initialCards: [Braze.ContentCardRaw], + refresh: ((@escaping ([Braze.ContentCardRaw]?, Error?) -> Void) -> Void)? = nil, + subscribe: ((@escaping ([Braze.ContentCardRaw]) -> Void) -> Braze.Cancellable)? = nil, + lastUpdate: Date? = nil + ) { + self.init( + initialCards: initialCards.compactMap { try? .init($0) }, + refresh: refresh.flatMap { refresh in + { completion in + refresh { cards, error in + switch (cards, error) { + case (.some(let cards), nil): + completion(.success(cards.compactMap { try? Braze.ContentCard($0) })) + case (_, .some(let error)): + completion(.failure(error)) + case (nil, nil): + completion(.failure(URLError(.cannotOpenFile))) + } + } + } + }, + subscribe: subscribe.flatMap { subscribe in + { update in + subscribe { cards in + update(cards.compactMap { try? Braze.ContentCard($0) }) + } + } + }, + lastUpdate: lastUpdate, + attributes: .defaults + ) + } +} diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift index 06b51737bb..ab011a7564 100644 --- a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift +++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewController.swift @@ -4,6 +4,7 @@ import UIKit extension BrazeContentCardUI { /// A view controller which displays Braze Content Cards. + @objc(BRZContentCardUIViewController) open class ViewController: UITableViewController, UITableViewDataSourcePrefetching { /// The content cards currently displayed. @@ -159,6 +160,7 @@ extension BrazeContentCardUI { /// refresh. /// - subscribe: An optional closure implementing the subscription to new cards logic. `nil` /// disables automatic updates. + /// - lastUpdate: The last time the content cards were updated. /// - attributes: An attributes struct allowing customization of the table view controller /// and its cells. public init( @@ -182,6 +184,14 @@ extension BrazeContentCardUI { fatalError("init(coder:) has not been implemented") } + /// See ``init(braze:attributes:)``. + @objc + @available(*, unavailable) + public init() { + // This init exists only to override the ObjC `NSObject.init` and disable it. + fatalError("init is not available") + } + // MARK: - LifeCycle open override func viewDidLoad() { diff --git a/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift new file mode 100644 index 0000000000..bf7f8b6152 --- /dev/null +++ b/Sources/BrazeUI/ContentCardUI/ContentCardUIViewControllerDelegate+ObjC.swift @@ -0,0 +1,66 @@ +import BrazeKit +import Foundation + +@objc(BrazeContentCardUIViewControllerDelegate) +public protocol _OBJC_BrazeContentCardUIViewControllerDelegate: AnyObject { + + /// Defines whether Braze should process the Content Card click action. + /// + /// If the method returns `true` (default return value), Braze processes the click action. + /// + /// - Important: When this method returns `true` and the click action is a url, Braze will + /// **still** execute the `BrazeDelegate.braze(_:shouldOpenURL:)` delegate method + /// offering a last opportunity to modify or replace Braze url handling behavior. + /// If your implementation only needs access to the `url`, use + /// `BrazeDelegate.braze(_:shouldOpenURL:)` instead. + /// + /// - Parameters: + /// - controller: The view controller containing the Content Card. + /// - url: The url to process. + /// - card: The Content Card. + /// - Returns: `true` to let Braze process the click action, `false` otherwise + @objc(contentCardController:shouldProcess:card:) + optional func _objc_contentCard( + _ controller: BrazeContentCardUI.ViewController, + shouldProcess url: URL, + card: Braze.ContentCardRaw + ) -> Bool + +} + +// MARK: - Delegate Wrapper + +final class _OBJC_BrazeContentCardUIViewControllerDelegateWrapper: + BrazeContentCardUIViewControllerDelegate +{ + + /// Property used as a unique key for the wrapper lifecycle behavior. + private static var wrapperKey: Void? + + /// The ObjC content card UI view controller delegate. + weak var delegate: _OBJC_BrazeContentCardUIViewControllerDelegate? + + init(_ delegate: _OBJC_BrazeContentCardUIViewControllerDelegate) { + self.delegate = delegate + objc_setAssociatedObject(delegate, &Self.wrapperKey, self, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + + deinit { + if let delegate = delegate { + objc_setAssociatedObject(delegate, &Self.wrapperKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + func contentCard( + _ controller: BrazeContentCardUI.ViewController, + shouldProcess clickAction: Braze.ContentCard.ClickAction, + card: Braze.ContentCard + ) -> Bool { + switch clickAction { + case .url(let url, _): + return delegate?._objc_contentCard?(controller, shouldProcess: url, card: .init(card)) ?? true + @unknown default: + return true + } + } +} diff --git a/Sources/BrazeUI/Dependencies/AsyncImageView.swift b/Sources/BrazeUI/Dependencies/AsyncImageView.swift index 2ed98ed22f..3243cd76fa 100644 --- a/Sources/BrazeUI/Dependencies/AsyncImageView.swift +++ b/Sources/BrazeUI/Dependencies/AsyncImageView.swift @@ -77,7 +77,7 @@ open class AsyncImageView: UIView { } public let imageView: UIView = { - let view = gifViewProvider.view(nil) + let view = GIFViewProvider.shared.view(nil) view.contentMode = .scaleAspectFit return view }() @@ -96,7 +96,7 @@ open class AsyncImageView: UIView { private func updateImage() { // Reset activityIndicator.stopAnimating() - gifViewProvider.updateView(imageView, nil) + GIFViewProvider.shared.updateView(imageView, nil) retryButton.isHidden = true switch imageLoad { @@ -108,7 +108,7 @@ open class AsyncImageView: UIView { retryButton.isHidden = retry == nil case .success(let url, let size): aspectRatio = size.width / size.height - gifViewProvider.updateView(imageView, url) + GIFViewProvider.shared.updateView(imageView, url) updateImageCornerRadius() } } diff --git a/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift b/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift new file mode 100644 index 0000000000..4839438de4 --- /dev/null +++ b/Sources/BrazeUI/Dependencies/GIFViewProvider+ObjC.swift @@ -0,0 +1,85 @@ +import UIKit + +/// A type providing methods to create and update views supporting animated GIF images. +/// +/// Braze does not provide animated GIF support out of the box. Support can be added by wrapping a +/// third party or your own view in an instance of `GIFViewProvider`. +/// +/// Sample implementations for popular third party libraries are provided in +/// . +/// +/// Adding any of those libraries to your project allows you to enable animated GIF support in +/// Braze's UI components. +/// For instance, a project including SDWebImage and using the compatible sample code can do: +/// ```swift +/// GIFViewProvider.shared = .sdWebImage +/// ``` +@objc(BRZGIFViewProvider) +public final class _OBJC_BRZGIFViewProvider: NSObject { + + /// The GIF view provider used for all BrazeUI components. + /// + /// By default, Braze displays animated GIFs as static images. + /// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs. + @objc + public static var shared: _OBJC_BRZGIFViewProvider { + get { .init(GIFViewProvider.shared) } + set { GIFViewProvider.shared = newValue.gifViewProvider } + } + + /// Creates a view able to display static and animated GIF images. + /// - Parameters: + /// - url: The local file url for the image. + @objc + public var view: (_ url: URL?) -> UIView { + get { gifViewProvider.view } + set { gifViewProvider.view = newValue } + } + + /// Updates the passed view with a new image at `url`. + /// - Parameters: + /// - view: The view to update. + /// - url: The local file url for the image. + @objc + public var updateView: (_ view: UIView, _ url: URL?) -> Void { + get { gifViewProvider.updateView } + set { gifViewProvider.updateView = newValue } + } + + var gifViewProvider: GIFViewProvider + + /// Creates a GIF view provider. + /// - Parameters: + /// - view: See ``view``. + /// - updateView: See ``updateView``. + @objc + public convenience init( + view: @escaping (_ url: URL?) -> UIView, + updateView: @escaping (_ view: UIView, _ url: URL?) -> Void + ) { + self.init(.init(view: view, updateView: updateView)) + } + + init(_ gifViewProvider: GIFViewProvider) { + self.gifViewProvider = gifViewProvider + } + + /// Creates a GIF view provider. + /// - Parameters: + /// - view: See ``view``. + /// - updateView: See ``updateView``. + @objc + public static func provider( + view: @escaping (_ url: URL?) -> UIView, + updateView: @escaping (_ view: UIView, _ url: URL?) -> Void + ) -> _OBJC_BRZGIFViewProvider { + .init(view: view, updateView: updateView) + } + + /// The default, non-animating provider. + /// + /// This provider does not support animated images and display them as static images. + @objc + public static let nonAnimating = _OBJC_BRZGIFViewProvider(.nonAnimating) + +} diff --git a/Sources/BrazeUI/Dependencies/GIFViewProvider.swift b/Sources/BrazeUI/Dependencies/GIFViewProvider.swift index 49c813597c..4166b9bf4c 100644 --- a/Sources/BrazeUI/Dependencies/GIFViewProvider.swift +++ b/Sources/BrazeUI/Dependencies/GIFViewProvider.swift @@ -1,11 +1,5 @@ import UIKit -/// The GIF view provider used for all BrazeUI components. -/// -/// By default, Braze displays animated GIFs as static images. -/// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs. -public var gifViewProvider: GIFViewProvider = .default - /// A type providing methods to create and update views supporting animated GIF images. /// /// Braze does not provide animated GIF support out of the box. Support can be added by wrapping a @@ -18,10 +12,16 @@ public var gifViewProvider: GIFViewProvider = .default /// Braze's UI components. /// For instance, a project including SDWebImage and using the compatible sample code can do: /// ```swift -/// BrazeUI.gifViewProvider = .sdWebImage +/// GIFViewProvider.shared = .sdWebImage /// ``` public struct GIFViewProvider { + /// The GIF view provider used for all BrazeUI components. + /// + /// By default, Braze displays animated GIFs as static images. + /// See ``GIFViewProvider-swift.struct`` for details about how to add support for animated GIFs. + public static var shared: GIFViewProvider = .nonAnimating + /// Creates a view able to display static and animated GIF images. /// - Parameters: /// - url: The local file url for the image. @@ -45,10 +45,10 @@ public struct GIFViewProvider { self.updateView = updateView } - /// The default provider. + /// The default, non-animating provider. /// /// This provider does not support animated images and display them as static images. - public static let `default` = Self( + public static let nonAnimating = GIFViewProvider( view: { UIImageView(image: ($0?.path).flatMap(UIImage.init(contentsOfFile:))) }, updateView: { ($0 as? UIImageView)?.image = ($1?.path).flatMap(UIImage.init(contentsOfFile:)) } ) diff --git a/Sources/BrazeUI/Deprecations.swift b/Sources/BrazeUI/Deprecations.swift new file mode 100644 index 0000000000..94c098d757 --- /dev/null +++ b/Sources/BrazeUI/Deprecations.swift @@ -0,0 +1,20 @@ +// MARK: - Pre feature-parity + +// MARK: 08/25/2022 + +/// See ``GIFViewProvider-swift.struct/shared``. +@available(*, deprecated, renamed: "GIFViewProvider.shared") +public var gifViewProvider: GIFViewProvider { + get { GIFViewProvider.shared } + set { GIFViewProvider.shared = newValue } +} + +// MARK: 08/26/2022 + +extension GIFViewProvider { + + /// See ``nonAnimating``. + @available(*, deprecated, renamed: "nonAnimating") + public static let `default`: GIFViewProvider = .nonAnimating + +} diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift index 22fb771d42..4bad1b45c5 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift @@ -52,11 +52,6 @@ extension Braze.InAppMessage.Button { extension Braze.InAppMessage.Color { - /// The `UIColor` representation of the in-app message color. - public var uiColor: UIColor { - UIColor(red: r, green: g, blue: b, alpha: a) - } - /// A 1x1 pt image of the color. public var image: UIImage { let rect = CGRect(x: 0, y: 0, width: 1, height: 1) diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift index 9bddf09076..7168626b49 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift @@ -201,7 +201,7 @@ import Foundation public static let mock = Self( data: .mock, - imageUri: .mockImage(width: 600, height: 600), + imageURL: .mockImage(width: 600, height: 600), buttons: [ .mockSecondary, .mockPrimary, @@ -210,7 +210,7 @@ import Foundation public static let mockLargeImage = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 2000), + imageURL: .mockImage(width: 1200, height: 2000), buttons: [ .mockSecondary, .mockPrimary, @@ -219,7 +219,7 @@ import Foundation public static let mockExtraLargeImage = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 4000), + imageURL: .mockImage(width: 1200, height: 4000), buttons: [ .mockSecondary, .mockPrimary, @@ -228,13 +228,13 @@ import Foundation public static let mockNoButtons = Self( data: .mock, - imageUri: .mockImage(width: 600, height: 600), + imageURL: .mockImage(width: 600, height: 600), buttons: [] ) public static let mockOneButton = Self( data: .mock, - imageUri: .mockImage(width: 600, height: 600), + imageURL: .mockImage(width: 600, height: 600), buttons: [ .mockPrimary ] @@ -242,7 +242,7 @@ import Foundation public static let mockThemed = Self( data: .mock, - imageUri: .mockImage(width: 600, height: 600), + imageURL: .mockImage(width: 600, height: 600), buttons: [ .mockSecondary, .mockPrimaryThemed, @@ -263,7 +263,7 @@ import Foundation public static let mock = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon." @@ -271,7 +271,7 @@ import Foundation public static let mockOneButton = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.", @@ -282,7 +282,7 @@ import Foundation public static let mockTwoButtons = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.", @@ -294,7 +294,7 @@ import Foundation public static let mockLandscape = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 600), + imageURL: .mockImage(width: 2000, height: 600), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon." @@ -302,7 +302,7 @@ import Foundation public static let mockLandscapeOneButton = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 600), + imageURL: .mockImage(width: 2000, height: 600), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.", @@ -311,7 +311,7 @@ import Foundation public static let mockLandscapeTwoButtons = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 600), + imageURL: .mockImage(width: 2000, height: 600), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.", @@ -323,7 +323,7 @@ import Foundation public static let mockLeadingAligned = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", headerTextAlignment: .leading, message: @@ -337,7 +337,7 @@ import Foundation public static let mockLong = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", message: """ @@ -353,7 +353,7 @@ import Foundation public static let mockThemed = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 1000), + imageURL: .mockImage(width: 1200, height: 1000), header: "Hello world!", message: "Cupcake ipsum dolor sit amet topping. Cookie candy chupa chups jujubes pastry soufflé. Danish cake cheesecake liquorice wafer marshmallow macaroon.", @@ -378,18 +378,18 @@ import Foundation public static let mock = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 2000) + imageURL: .mockImage(width: 1200, height: 2000) ) public static let mockOneButton = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 2000), + imageURL: .mockImage(width: 1200, height: 2000), buttons: [.mockPrimary] ) public static let mockTwoButtons = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 2000), + imageURL: .mockImage(width: 1200, height: 2000), buttons: [ .mockSecondary, .mockPrimary, @@ -398,18 +398,18 @@ import Foundation public static let mockLandscape = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 1200) + imageURL: .mockImage(width: 2000, height: 1200) ) public static let mockLandscapeOneButton = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 1200), + imageURL: .mockImage(width: 2000, height: 1200), buttons: [.mockPrimary] ) public static let mockLandscapeTwoButtons = Self( data: .mock, - imageUri: .mockImage(width: 2000, height: 1200), + imageURL: .mockImage(width: 2000, height: 1200), buttons: [ .mockSecondary, .mockPrimary, @@ -418,7 +418,7 @@ import Foundation public static let mockMinRecommendedSize = Self( data: .mock, - imageUri: .mockImage(width: 600, height: 1000), + imageURL: .mockImage(width: 600, height: 1000), buttons: [ .mockSecondary, .mockPrimary, @@ -429,7 +429,7 @@ import Foundation public static let mockNonRecommendedSize = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 4000), + imageURL: .mockImage(width: 1200, height: 4000), buttons: [ .mockSecondary, .mockPrimary, @@ -438,7 +438,7 @@ import Foundation public static let mockThemed = Self( data: .mock, - imageUri: .mockImage(width: 1200, height: 2000), + imageURL: .mockImage(width: 1200, height: 2000), themes: [ "light": .init( backgroundColor: 0xFF2D_3436, @@ -499,7 +499,7 @@ import Foundation extension Braze.InAppMessage.ClickAction { - public static let mock = Self.uri(URL(string: "https://example.com")!, useWebView: false) + public static let mock = Self.url(URL(string: "https://example.com")!, useWebView: false) } diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift new file mode 100644 index 0000000000..5939e79a1e --- /dev/null +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI+ObjC.swift @@ -0,0 +1,37 @@ +import BrazeKit +import Foundation +import UIKit + +extension BrazeInAppMessageUI { + + /// The currently visible message view. + @objc(messageView) + @available(swift, obsoleted: 0.0.1) + public var _objc_messageView: UIView? { messageView } + + /// The stack of in-app messages awaiting display. + /// + /// When the conditions to display a message are not met at trigger time, the message is pushed + /// onto the stack. + @objc(stack) + @available(swift, obsoleted: 0.0.1) + public var _objc_stack: [Braze.InAppMessageRaw] { stack.map(Braze.InAppMessageRaw.init) } + + /// The object that act as the delegate for the in-app message UI. + /// + /// The delegate is not retained and must conform to ``BrazeInAppMessageUIDelegate``. + @objc(delegate) + @available(swift, obsoleted: 0.0.1) + public weak var _objc_delegate: _OBJC_BrazeInAppMessageUIDelegate? { + get { (delegate as? _OBJC_BrazeInAppMessageUIDelegateWrapper)?.delegate } + set { delegate = newValue.flatMap(_OBJC_BrazeInAppMessageUIDelegateWrapper.init) } + } + + /// Dismisses the current in-app message view. + @objc(dismiss) + @available(swift, obsoleted: 0.0.1) + public func _objc_dismiss() { + dismiss() + } + +} diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift index 002ac684f9..f88d67d3f8 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift @@ -9,8 +9,12 @@ import UIKit /// /// To add GIF support to the in-app message UI components, set a valid /// ``gifViewProvider-swift.var``. -@objc -open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { +@objc(BrazeInAppMessageUI) +open class BrazeInAppMessageUI: + NSObject, + BrazeInAppMessagePresenter, + _OBJC_BrazeInAppMessagePresenter +{ // MARK: - Properties @@ -71,7 +75,18 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { } + @objc + public func present(message: Braze.InAppMessageRaw) { + do { + let message = try Braze.InAppMessage(message) + present(message: message) + } catch { + logError(for: message.context, error: .rawToTypedConversion(.init(error))) + } + } + /// Presents the next in-app message in the stack if any. + @objc public func presentNext() { // We use `last` instead of `popLast()` to avoid potentially modifying `stack` from a non // main thread. The message is removed from the stack in `presentNow`. @@ -117,7 +132,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { ?? createMessageView( for: context.message, attributes: context.attributes, - gifViewProvider: gifViewProvider + gifViewProvider: GIFViewProvider.shared ) guard let messageView = optMessageView else { message.context?.discard() @@ -172,20 +187,21 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { /// Dismisses the current in-app message view. /// - Parameter completion: Executed once the in-app message view has been dismissed or directly /// when no in-app message view is currently presented. + @objc public func dismiss(completion: (() -> Void)? = nil) { messageView?.dismiss(completion: completion) ?? completion?() } // MARK: - Utils - func logError(for message: Braze.InAppMessage, error: Error) { - message.context?.logError(flattened: error.logDescription) ?? print(error.logDescription) + func logError(for context: Braze.InAppMessage.Context?, error: Error) { + context?.logError(flattened: error.logDescription) ?? print(error.logDescription) } func validateMainThread(for message: Braze.InAppMessage) -> Bool { guard Thread.isMainThread else { DispatchQueue.main.sync { - logError(for: message, error: .noMainThread) + logError(for: message.context, error: .noMainThread) } return false } @@ -200,7 +216,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { } if Braze.UIUtils.activeRootViewController == nil { - logError(for: message, error: .noAppRootViewController) + logError(for: message.context, error: .noAppRootViewController) return false } @@ -215,7 +231,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { stack.append(message) } - logError(for: message, error: .otherMessagePresented(push: push)) + logError(for: message.context, error: .otherMessagePresented(push: push)) return false } return true @@ -224,7 +240,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { // Always return true, font-awesome missing is not a breaking error func validateFontAwesome(for message: Braze.InAppMessage) -> Bool { guard IconView.registerFontAwesomeIfNeeded() else { - logError(for: message, error: .noFontAwesome) + logError(for: message.context, error: .noFontAwesome) return true } return true @@ -235,7 +251,7 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { guard message.orientation.supported(by: traits) else { stack.removeAll { $0 == message } message.context?.discard() - logError(for: message, error: .noMatchingOrientation) + logError(for: message.context, error: .noMatchingOrientation) return false } return true @@ -249,14 +265,14 @@ open class BrazeInAppMessageUI: NSObject, BrazeInAppMessagePresenter { guard context.discarded == false else { stack.removeAll { $0 == message } - logError(for: message, error: .messageContextDiscarded) + logError(for: message.context, error: .messageContextDiscarded) return false } guard context.valid else { stack.removeAll { $0 == message } context.discard() - logError(for: message, error: .messageContextInvalid) + logError(for: message.context, error: .messageContextInvalid) return false } diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift new file mode 100644 index 0000000000..d572a88e9d --- /dev/null +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIDelegate+ObjC.swift @@ -0,0 +1,236 @@ +import BrazeKit +import Foundation +import UIKit + +/// Methods for reacting to the in-app message UI lifecycle. +@objc(BrazeInAppMessageUIDelegate) +public protocol _OBJC_BrazeInAppMessageUIDelegate: AnyObject { + + /// Defines whether the in-app message will be displayed now, displayed later, or discarded. + /// + /// The default implementation returns the display choice + /// ``BrazeInAppMessageUI/DisplayChoice/now``. + /// + /// If there are situations where you would not want the in-app message to appear (such as during + /// a full screen game or on a loading screen), you can use this delegate to delay or discard + /// pending in-app message messages. + /// + /// When returning ``BrazeInAppMessageUI/DisplayChoice/later``, the message is put on the top of + /// the message ``BrazeInAppMessageUI/stack``. Use ``BrazeInAppMessageUI/presentNext()`` to + /// present the next in-app message in the stack. + /// + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - message: The message to be presented. + /// - Returns: The display choice for `message`. See ``BrazeInAppMessageUI/DisplayChoice`` for + /// possible values. + @objc(inAppMessage:displayChoiceForMessage:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + displayChoiceForMessage message: Braze.InAppMessageRaw + ) -> _OBJC_BRZInAppMessageUIDisplayChoice + + /// Called before the in-app message presentation and after + /// ``inAppMessage(_:prepareWith:)-11fog``. + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - message: The message to be presented. + /// - view: The in-app message view. + @objc(inAppMessage:willPresent:view:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + willPresent message: Braze.InAppMessageRaw, + view: UIView + ) + + /// Called once the in-app message is fully visible to the user. + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - message: The message to be presented. + /// - view: The in-app message view. + @objc(inAppMessage:didPresent:view:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + didPresent message: Braze.InAppMessageRaw, + view: UIView + ) + + /// Called before any dismissal animation occurs. + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - message: The message to be presented. + /// - view: The in-app message view. + @objc(inAppMessage:willDismiss:view:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + willDismiss message: Braze.InAppMessageRaw, + view: UIView + ) + + /// Called after any dismissal animation occurs and the in-app message is fully hidden from the + /// user. + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - message: The message to be presented. + /// - view: The in-app message view. + @objc(inAppMessage:didDismiss:view:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + didDismiss message: Braze.InAppMessageRaw, + view: UIView + ) + + /// Defines whether Braze should process the message click action. + /// + /// When returning `true` (default return value), Braze processes the click action. + /// + /// - Important: When this method returns `true` and the click action is an url, Braze will + /// **still** execute the `BrazeDelegate.braze(_:shouldOpenURL:)` delegate method + /// offering a last opportunity to modify or replace Braze url handling behavior. + /// If your implementation only needs access to the `url`, prefer using + /// `BrazeDelegate.braze(_:shouldOpenURL:)` instead. + /// + /// - Parameters: + /// - ui: The in-app message ui instance. + /// - clickAction: The click action. + /// - url: The click action url when `clickAction` is of type `url`, nil otherwise. + /// - buttonId: The optional button identifier. + /// - message: The message to be presented. + /// - view: The in-app message view. + /// - Returns: `true` to let Braze process the click action, `false` otherwise. + @objc(inAppMessage:shouldProcess:url:buttonId:message:view:) + optional func _objc_inAppMessage( + _ ui: BrazeInAppMessageUI, + shouldProcess clickAction: Braze.InAppMessageRaw._OBJC_BRZInAppMessageRawClickAction, + url: URL?, + buttonId: String?, + message: Braze.InAppMessageRaw, + view: UIView + ) -> Bool + +} + +/// The different display choices supported when receiving an in-app message from the Braze SDK. +/// +/// See ``BrazeInAppMessageUIDelegate/inAppMessage(_:displayChoiceForMessage:)-1ghly``. +@objc(BRZInAppMessageUIDisplayChoice) +public enum _OBJC_BRZInAppMessageUIDisplayChoice: Int { + + /// The in-app message is displayed immediately. + case now + + /// The in-app message is **not displayed** and placed on top of the ``BrazeInAppMessageUI/stack``. + /// + /// Use ``BrazeInAppMessageUI/presentNext()`` to display the message at the top of the stack. + case later + + /// The in-app message is discarded. + case discard + + init(_ displayChoice: BrazeInAppMessageUI.DisplayChoice) { + switch displayChoice { + case .now: self = .now + case .later: self = .later + case .discard: self = .discard + } + } + + var displayChoice: BrazeInAppMessageUI.DisplayChoice { + switch self { + case .now: return .now + case .later: return .later + case .discard: return .discard + } + } + +} + +// MARK: - Delegate Wrapper + +/// This delegate wraps the ObjC version of the `BrazeInAppMessageUIDelegate` and make it compatible +/// with the base Swift implementation. +final class _OBJC_BrazeInAppMessageUIDelegateWrapper: BrazeInAppMessageUIDelegate { + + /// Property used as a unique key for the wrapper lifecycle behavior. + private static var wrapperKey: Void? + + /// The ObjC in-app message UI delegate. + weak var delegate: _OBJC_BrazeInAppMessageUIDelegate? + + /// Creates and returns a delegate wrapper for the ObjC version of `BrazeInAppMessageUIDelegate`. + /// + /// The delegate is stored weakly by the ``BrazeUI/BrazeInAppMessageUI`` instance. In order for + /// the wrapper to behave like its underlying delegate, it is dynamically attached to the ObjC + /// delegate implementation using the ObjC runtime. As long as the underlying delegate is alive, + /// this wrapper will remain alive. + /// + /// - Parameter delegate: The delegate to wrap. + init(_ delegate: _OBJC_BrazeInAppMessageUIDelegate) { + self.delegate = delegate + objc_setAssociatedObject(delegate, &Self.wrapperKey, self, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + + deinit { + if let delegate = delegate { + objc_setAssociatedObject(delegate, &Self.wrapperKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + displayChoiceForMessage message: Braze.InAppMessage + ) -> BrazeInAppMessageUI.DisplayChoice { + delegate?._objc_inAppMessage?(ui, displayChoiceForMessage: .init(message)).displayChoice ?? .now + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + willPresent message: Braze.InAppMessage, + view: InAppMessageView + ) { + delegate?._objc_inAppMessage?(ui, willPresent: .init(message), view: view) + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + didPresent message: Braze.InAppMessage, + view: InAppMessageView + ) { + delegate?._objc_inAppMessage?(ui, didPresent: .init(message), view: view) + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + willDismiss message: Braze.InAppMessage, + view: InAppMessageView + ) { + delegate?._objc_inAppMessage?(ui, willDismiss: .init(message), view: view) + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + didDismiss message: Braze.InAppMessage, + view: InAppMessageView + ) { + delegate?._objc_inAppMessage?(ui, didDismiss: .init(message), view: view) + } + + func inAppMessage( + _ ui: BrazeInAppMessageUI, + shouldProcess clickAction: Braze.InAppMessage.ClickAction, + buttonId: String?, + message: Braze.InAppMessage, + view: InAppMessageView + ) -> Bool { + let message = Braze.InAppMessageRaw(message) + return delegate?._objc_inAppMessage?( + ui, + shouldProcess: .init(message.clickAction), + url: message.url, + buttonId: buttonId, + message: message, + view: view + ) ?? true + } + +} diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift index a8bcff00c9..57481a2e85 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIError.swift @@ -8,6 +8,8 @@ extension BrazeInAppMessageUI { case noContextProcessClickAction case invalidBrazeActions + case rawToTypedConversion(Braze.ErrorString) + case noMainThread case noMessageView case noAppRootViewController @@ -18,7 +20,7 @@ extension BrazeInAppMessageUI { case messageContextDiscarded case messageContextInvalid - case htmlNoBaseUrl + case htmlNoBaseURL case webViewNavigation(Braze.ErrorString) case webViewScript(Braze.WebViewBridge.ScriptMessageHandler.Error) case webViewScheme(Braze.WebViewBridge.SchemeHandler.Error) @@ -42,6 +44,14 @@ extension BrazeInAppMessageUI.Error { case .invalidBrazeActions: return "Invalid Braze Actions found in click action. Skipping display." + case .rawToTypedConversion(let error): + return + """ + Cannot convert raw in-app message to typed in-app message, error: + - description: \(error.localizedDescription) + - error: \(error) + """ + case .noMainThread: return "Unable to present message - BrazeInAppMessageUI apis must be called from the main thread." @@ -66,7 +76,7 @@ extension BrazeInAppMessageUI.Error { return "Unable to present message - message context is invalid. The message has been discarded and removed from the stack." - case .htmlNoBaseUrl: + case .htmlNoBaseURL: return "Unable to present html in-app message - no base url." case .webViewNavigation(let error): return "Unable to load html in web view - \(error.logDescription)" diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift index e6f111e8a5..eee5bf32b0 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullImageView.swift @@ -150,7 +150,7 @@ extension BrazeInAppMessageUI { public init( message: Braze.InAppMessage.FullImage, attributes: Attributes = .defaults, - gifViewProvider: GIFViewProvider = .default, + gifViewProvider: GIFViewProvider = .nonAnimating, presented: Bool = false ) { var modalImageAttrs = ModalImageView.Attributes() @@ -174,7 +174,7 @@ extension BrazeInAppMessageUI { super.init( message: .init( data: message.data, - imageUri: message.imageUri, + imageURL: message.imageURL, buttons: message.buttons, themes: message.themes ), diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift index cf3ea78980..1ed5711a0b 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift @@ -192,7 +192,7 @@ extension BrazeInAppMessageUI { public init( message: Braze.InAppMessage.Full, attributes: Attributes = .defaults, - gifViewProvider: GIFViewProvider = .default, + gifViewProvider: GIFViewProvider = .nonAnimating, presented: Bool = false ) { var modalViewAttrs = ModalView.Attributes() @@ -220,7 +220,7 @@ extension BrazeInAppMessageUI { super.init( message: .init( data: message.data, - graphic: .image(message.imageUri), + graphic: .image(message.imageURL), header: message.header, headerTextAlignment: message.headerTextAlignment, message: message.message, diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift index 6c9d38f7fb..e2aad7624c 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift @@ -166,6 +166,7 @@ extension BrazeInAppMessageUI { yConstraint = webView?.anchors.top.pin() webView?.anchors.top.equal(anchors.bottom).priority = .defaultHigh case .auto, .fade: + webView?.anchors.center.align() break } } @@ -266,8 +267,8 @@ extension BrazeInAppMessageUI { } open func loadMessage() { - guard let baseUrl = message.baseUrl else { - logError(.htmlNoBaseUrl) + guard let baseURL = message.baseURL else { + logError(.htmlNoBaseURL) message.animateOut = false dismiss() return @@ -275,17 +276,17 @@ extension BrazeInAppMessageUI { // Create directory if needed try? FileManager.default.createDirectory( - at: baseUrl, + at: baseURL, withIntermediateDirectories: true, attributes: nil ) // Write index.html - let index = baseUrl.appendingPathComponent("index.html") + let index = baseURL.appendingPathComponent("index.html") try? message.message.write(to: index, atomically: true, encoding: .utf8) // Load - webView?.loadFileURL(index, allowingReadAccessTo: baseUrl) + webView?.loadFileURL(index, allowingReadAccessTo: baseURL) } } diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift index 453ee045c8..77039ce3d5 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift @@ -116,7 +116,7 @@ extension BrazeInAppMessageUI { let gifViewProvider: GIFViewProvider public lazy var imageView: UIView = { - let imageView = gifViewProvider.view(message.imageUri) + let imageView = gifViewProvider.view(message.imageURL) imageView.contentMode = .scaleAspectFill return imageView }() @@ -177,7 +177,7 @@ extension BrazeInAppMessageUI { public init( message: Braze.InAppMessage.ModalImage, attributes: Attributes = .defaults, - gifViewProvider: GIFViewProvider = .default, + gifViewProvider: GIFViewProvider = .nonAnimating, presented: Bool = false ) { self.message = message @@ -246,7 +246,7 @@ extension BrazeInAppMessageUI { frame = CGRect(x: 0, y: 0, width: 500, height: 500) Constraints { // ImageView - if let imageSize = imageSize(url: message.imageUri) { + if let imageSize = imageSize(url: message.imageURL) { let aspectRatio = imageSize.width / imageSize.height imageAspectRatioConstraint = imageView.anchors.width.equal( imageView.anchors.height.multiplied(by: aspectRatio) diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift index b46c96970a..d354d7573c 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift @@ -257,7 +257,7 @@ extension BrazeInAppMessageUI { public init( message: Braze.InAppMessage.Modal, attributes: Attributes = .defaults, - gifViewProvider: GIFViewProvider = .default, + gifViewProvider: GIFViewProvider = .nonAnimating, presented: Bool = false ) { self.message = message diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift index e6e4b5a78e..3ae27d0ba7 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift @@ -41,6 +41,9 @@ extension BrazeInAppMessageUI { /// The image size. public var imageSize = CGSize(width: 50, height: 50) + /// The chevron visibility. + public var chevronVisibility: ChevronVisibility = .auto + /// The content view corner radius. public var cornerRadius = 15.0 @@ -70,6 +73,19 @@ extension BrazeInAppMessageUI { } + /// Visibility options supported for the chevron. + public enum ChevronVisibility { + + /// Visible when the message has a click action, hidden otherwise. + case auto + + /// Always hidden. + case hidden + + /// Always visible. + case visible + } + /// The view attributes. See ``Attributes-swift.struct``. public var attributes: Attributes { didSet { applyAttributes() } @@ -95,6 +111,11 @@ extension BrazeInAppMessageUI { // Fonts messageLabel.font = attributes.font + // Chevron + chevronView.isHidden = + attributes.chevronVisibility == .hidden + || (attributes.chevronVisibility == .auto && message.clickAction == .none) + // Corner radius shadowView.layer.cornerRadius = attributes.cornerRadius contentView.layer.cornerRadius = attributes.cornerRadius @@ -186,7 +207,7 @@ extension BrazeInAppMessageUI { public init( message: Braze.InAppMessage.Slideup, attributes: Attributes = .defaults, - gifViewProvider: GIFViewProvider = .default, + gifViewProvider: GIFViewProvider = .nonAnimating, presented: Bool = false ) { self.message = message diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift index d878948662..dcb0c1be03 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift @@ -158,7 +158,7 @@ extension InAppMessageView { public func logError(_ error: BrazeInAppMessageUI.Error) { controller?.message.context?.logError(flattened: error.logDescription) - ?? print(error.logDescription) + ?? print("[BrazeUI]", error.logDescription) } /// The controller currently displaying the in-app message view. diff --git a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift index 534de20922..d09617cb7f 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift @@ -3,9 +3,9 @@ import UIKit extension BrazeInAppMessageUI { - /// View displaying a [FontAwesome v4.3] icon. + /// View displaying a [FontAwesome v4.3][1] icon. /// - /// [FontAwesome v4.3]: https://fontawesome.com/v4.7/cheatsheet/ + /// [1]: https://fontawesome.com/v4.7/cheatsheet/ open class IconView: UIView { /// FontAwesome symbol to display.