From a473b8e04c18860eec954d7cf1e95ec4d7113d1e Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 16 Feb 2026 14:30:14 -0500 Subject: [PATCH 01/25] feat: add Braze-12 kit --- .../braze-12/AppboyTestHost/AppDelegate.swift | 23 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 + .../AppboyTestHost/Base.lproj/Main.storyboard | 24 + kits/braze/braze-12/AppboyTestHost/Info.plist | 5 + .../AppboyTestHost/ViewController.swift | 18 + kits/braze/braze-12/CHANGELOG.md | 111 ++ .../Podfile | 21 + .../project.pbxproj | 673 +++++++++ .../AppDelegate.h | 17 + .../AppDelegate.m | 57 + .../Content.imageset/Contents.json | 11 + .../Back.imagestacklayer/Contents.json | 6 + .../Contents.json | 17 + .../Content.imageset/Contents.json | 11 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 11 + .../Middle.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Back.imagestacklayer/Contents.json | 6 + .../App Icon.imagestack/Contents.json | 17 + .../Content.imageset/Contents.json | 16 + .../Front.imagestacklayer/Contents.json | 6 + .../Content.imageset/Contents.json | 16 + .../Middle.imagestacklayer/Contents.json | 6 + .../Contents.json | 32 + .../Contents.json | 16 + .../Top Shelf Image.imageset/Contents.json | 16 + .../Assets.xcassets/Contents.json | 6 + .../Launch Image.launchimage/Contents.json | 22 + .../Base.lproj/Main.storyboard | 28 + .../mParticle-Appboy-tvOS-Example/Info.plist | 32 + .../ViewController.h | 15 + .../ViewController.m | 29 + .../mParticle-Appboy-tvOS-Example/main.m | 16 + .../Info.plist | 22 + .../mParticle_Appboy_tvOS_ExampleTests.m | 39 + .../Info.plist | 22 + .../mParticle_Appboy_tvOS_ExampleUITests.m | 40 + kits/braze/braze-12/LICENSE | 191 +++ kits/braze/braze-12/Package.resolved | 25 + kits/braze/braze-12/Package.swift | 37 + kits/braze/braze-12/README.md | 33 + kits/braze/braze-12/Scripts/release.sh | 19 + kits/braze/braze-12/Sources/Info.plist | 26 + .../Sources/mParticle-Appboy/MPKitAppboy.m | 1308 +++++++++++++++++ .../mParticle-Appboy/PrivacyInfo.xcprivacy | 14 + .../mParticle-Appboy/include/MPKitAppboy.h | 30 + .../include/mParticle_Appboy.h | 17 + .../braze-12/mParticle-Appboy-tvOS/Info.plist | 24 + .../mParticle_Appboy_tvOS.h | 12 + kits/braze/braze-12/mParticle-Appboy.podspec | 34 + .../project.pbxproj | 981 +++++++++++++ .../xcschemes/mParticle-Appboy-tvOS.xcscheme | 76 + .../xcschemes/mParticle-Appboy.xcscheme | 76 + .../xcschemes/mParticle_AppboyTests.xcscheme | 53 + kits/braze/braze-12/mParticle_Appboy.json | 13 + .../braze-12/mParticle_AppboyTests/Info.plist | 22 + .../mParticle_AppboyTests.m | 1065 ++++++++++++++ kits/braze/braze-12/release.config.js | 37 + 62 files changed, 5583 insertions(+) create mode 100644 kits/braze/braze-12/AppboyTestHost/AppDelegate.swift create mode 100644 kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 kits/braze/braze-12/AppboyTestHost/Assets.xcassets/Contents.json create mode 100644 kits/braze/braze-12/AppboyTestHost/Base.lproj/LaunchScreen.storyboard create mode 100644 kits/braze/braze-12/AppboyTestHost/Base.lproj/Main.storyboard create mode 100644 kits/braze/braze-12/AppboyTestHost/Info.plist create mode 100644 kits/braze/braze-12/AppboyTestHost/ViewController.swift create mode 100644 kits/braze/braze-12/CHANGELOG.md create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/Podfile create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example.xcodeproj/project.pbxproj create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.h create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.m create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Launch Image.launchimage/Contents.json create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Base.lproj/Main.storyboard create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Info.plist create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.h create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.m create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/main.m create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/Info.plist create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/mParticle_Appboy_tvOS_ExampleTests.m create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/Info.plist create mode 100644 kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/mParticle_Appboy_tvOS_ExampleUITests.m create mode 100644 kits/braze/braze-12/LICENSE create mode 100644 kits/braze/braze-12/Package.resolved create mode 100644 kits/braze/braze-12/Package.swift create mode 100644 kits/braze/braze-12/README.md create mode 100755 kits/braze/braze-12/Scripts/release.sh create mode 100644 kits/braze/braze-12/Sources/Info.plist create mode 100644 kits/braze/braze-12/Sources/mParticle-Appboy/MPKitAppboy.m create mode 100644 kits/braze/braze-12/Sources/mParticle-Appboy/PrivacyInfo.xcprivacy create mode 100644 kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h create mode 100644 kits/braze/braze-12/Sources/mParticle-Appboy/include/mParticle_Appboy.h create mode 100644 kits/braze/braze-12/mParticle-Appboy-tvOS/Info.plist create mode 100644 kits/braze/braze-12/mParticle-Appboy-tvOS/mParticle_Appboy_tvOS.h create mode 100755 kits/braze/braze-12/mParticle-Appboy.podspec create mode 100644 kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj create mode 100644 kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy-tvOS.xcscheme create mode 100644 kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy.xcscheme create mode 100644 kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle_AppboyTests.xcscheme create mode 100644 kits/braze/braze-12/mParticle_Appboy.json create mode 100644 kits/braze/braze-12/mParticle_AppboyTests/Info.plist create mode 100644 kits/braze/braze-12/mParticle_AppboyTests/mParticle_AppboyTests.m create mode 100644 kits/braze/braze-12/release.config.js diff --git a/kits/braze/braze-12/AppboyTestHost/AppDelegate.swift b/kits/braze/braze-12/AppboyTestHost/AppDelegate.swift new file mode 100644 index 000000000..7a5212c6f --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/AppDelegate.swift @@ -0,0 +1,23 @@ +// +// AppDelegate.swift +// AppboyTestHost +// +// Created by Ben Baron on 5/16/23. +// Copyright ยฉ 2023 mParticle. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + // Override point for customization after application launch. + return true + } +} diff --git a/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AccentColor.colorset/Contents.json b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 000000000..0afb3cf0e --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors": [ + { + "idiom": "universal" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AppIcon.appiconset/Contents.json b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..b121e3bce --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images": [ + { + "idiom": "universal", + "platform": "ios", + "size": "1024x1024" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/Contents.json b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/Contents.json new file mode 100644 index 000000000..74d6a722c --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/kits/braze/braze-12/AppboyTestHost/Base.lproj/LaunchScreen.storyboard b/kits/braze/braze-12/AppboyTestHost/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..865e9329f --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/AppboyTestHost/Base.lproj/Main.storyboard b/kits/braze/braze-12/AppboyTestHost/Base.lproj/Main.storyboard new file mode 100644 index 000000000..25a763858 --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/AppboyTestHost/Info.plist b/kits/braze/braze-12/AppboyTestHost/Info.plist new file mode 100644 index 000000000..0c67376eb --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/Info.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/kits/braze/braze-12/AppboyTestHost/ViewController.swift b/kits/braze/braze-12/AppboyTestHost/ViewController.swift new file mode 100644 index 000000000..6fe4a0e22 --- /dev/null +++ b/kits/braze/braze-12/AppboyTestHost/ViewController.swift @@ -0,0 +1,18 @@ +// +// ViewController.swift +// AppboyTestHost +// +// Created by Ben Baron on 5/16/23. +// Copyright ยฉ 2023 mParticle. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + +} diff --git a/kits/braze/braze-12/CHANGELOG.md b/kits/braze/braze-12/CHANGELOG.md new file mode 100644 index 000000000..6ee59f592 --- /dev/null +++ b/kits/braze/braze-12/CHANGELOG.md @@ -0,0 +1,111 @@ +# [8.11.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.10.2...v8.11.0) (2024-11-19) + +### Bug Fixes + +- Bump min Braze SDK to 11.2 ([#102](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/102)) ([03c3ab2](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/03c3ab265131364e7caf00f7b67e017698916bb7)) + +### Features + +- Add sendProductName Option to Braze ([#100](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/100)) ([f8deb1e](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/f8deb1ea38ed016939e1ea9f25cfeacbaf8d7834)) + +## [8.10.2](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.10.1...v8.10.2) (2024-11-06) + +### Bug Fixes + +- prevent mpid with value 0 to forward to Braze ([#99](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/99)) ([69255c2](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/69255c28df2376fdf47b5fff25c3d67a6383069d)) + +## [8.10.1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.10.0...v8.10.1) (2024-10-18) + +### Bug Fixes + +- Update consent attributes after kit is initialized ([#98](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/98)) ([0d74b3c](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/0d74b3c925e7c014c8d236a30bcf335d4dc4a4d5)) + +# [8.10.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.9.0...v8.10.0) (2024-10-16) + +### Features + +- Update Braze Kit to V11 ([#97](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/97)) ([d93e071](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/d93e0718f420c5a175c9e78d9387d021684cd351)) + +# [8.9.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.8.1...v8.9.0) (2024-10-02) + +### Features + +- Support workspace switching ([#95](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/95)) ([a80ce1d](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/a80ce1d35ee3b42e971849bf09e68c922901876c)) + +## [8.8.1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.8.0...v8.8.1) (2024-09-30) + +### Bug Fixes + +- Update Package.swift to match Podspec ([#96](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/96)) ([eddc5e5](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/eddc5e57dfa24841fc2228109931994ff039bff0)) + +# [8.8.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.7.2...v8.8.0) (2024-09-09) + +### Features + +- Implement Google EU Consent ([#94](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/94)) ([2f97151](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/2f971517f1b6c7f25d0f489539c765510e1931d9)) + +## [8.7.2](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.7.1...v8.7.2) (2024-06-24) + +### Bug Fixes + +- Kit fails to start due to missing kitApi property ([#93](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/93)) ([10bf509](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/10bf5091b2e29b7e60a0b214b1b205fa8b360c05)) + +## [8.7.1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.7.0...v8.7.1) (2024-06-18) + +### Bug Fixes + +- Forward screen events and collect IDFA configs when using an external Braze instance ([#92](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/92)) ([a8c4706](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/a8c4706518c804b977831b33d071f8fbbce61d54)) + +# [8.7.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.6.1...v8.7.0) (2024-06-12) + +### Features + +- Update External iD on Initialization ([#91](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/91)) ([5e1d301](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/5e1d301aacb2efa1a5c4dcd1686012da5bc24654)) + +## [8.6.1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.6.0...v8.6.1) (2024-05-28) + +### Bug Fixes + +- Setting urlDelegate on Braze instance ([#90](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/90)) ([596c250](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/596c250ba2b6543cfbb534af4bc74781eed2b12d)) + +# [8.6.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.5.0...v8.6.0) (2024-05-01) + +### Features + +- Update to Braze 9.x.x SDK, improve privacy manifest support ([#89](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/89)) ([979b259](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/979b259de22c31fe4b1a8686756bcf5093b9642f)) + +# [8.5.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.4.0...v8.5.0) (2024-03-07) + +### Features + +- Update Braze with Privacy Manifest ([#88](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/88)) ([8eb56d3](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/8eb56d3a039ae3d7dd6ad33071743c084c5f585a)) + +# [8.4.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.3.1...v8.4.0) (2024-02-21) + +### Features + +- Allow setting Braze instance and override notification handling ([#87](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/87)) ([c3c76c1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/c3c76c1724ce3c822b9c62cb40582871c7e032fe)) + +## [8.3.1](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.3.0...v8.3.1) (2024-02-07) + +### Bug Fixes + +- Deleting property stripping from product when sent unbundled ([#86](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/86)) ([d0b477b](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/d0b477b78b6e3364de9b5f0eaeabdf64c9ec45a0)) + +# [8.3.0](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.2.5...v8.3.0) (2023-12-13) + +### Features + +- Update Braze to Latest Version ([#85](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/85)) ([559937b](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/559937be481b2018d0a549efc6d077178e2e4aaf)) + +## [8.2.5](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.2.4...v8.2.5) (2023-12-08) + +### Bug Fixes + +- Use Umbrella Imports ([#84](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/84)) ([2782055](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/278205520c7bcfbadd9d08b40555cb422a316490)) + +## [8.2.4](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/compare/v8.2.3...v8.2.4) (2023-11-02) + +### Bug Fixes + +- Bundle commerce event setting ([#83](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/issues/83)) ([1fc5f40](https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/commit/1fc5f401b4eed836c47d9e0705a5b66d38c9df1f)) diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/Podfile b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/Podfile new file mode 100644 index 000000000..b96a87f8c --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/Podfile @@ -0,0 +1,21 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'mParticle-Appboy-tvOS-Example' do + # Uncomment the next line if you're using Swift or would like to use dynamic frameworks + # use_frameworks! + + # Pods for mParticle-Appboy-tvOS-Example + pod 'mParticle-Appboy', :path => '../..' + + target 'mParticle-Appboy-tvOS-ExampleTests' do + inherit! :search_paths + # Pods for testing + end + + target 'mParticle-Appboy-tvOS-ExampleUITests' do + inherit! :search_paths + # Pods for testing + end + +end diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example.xcodeproj/project.pbxproj b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example.xcodeproj/project.pbxproj new file mode 100644 index 000000000..5e5d7a460 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example.xcodeproj/project.pbxproj @@ -0,0 +1,673 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 17535475A2413657C2C1E785 /* libPods-mParticle-Appboy-tvOS-ExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82FBA52E1027516742AD /* libPods-mParticle-Appboy-tvOS-ExampleTests.a */; }; + B577EC88F9901EAC4D5558DE /* libPods-mParticle-Appboy-tvOS-ExampleUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B7870024D5801479AF064BAA /* libPods-mParticle-Appboy-tvOS-ExampleUITests.a */; }; + DBDEDDB6209BAAC000DD3B9B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDEDDB5209BAAC000DD3B9B /* AppDelegate.m */; }; + DBDEDDB9209BAAC000DD3B9B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDEDDB8209BAAC000DD3B9B /* ViewController.m */; }; + DBDEDDBC209BAAC000DD3B9B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DBDEDDBA209BAAC000DD3B9B /* Main.storyboard */; }; + DBDEDDBE209BAAC200DD3B9B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DBDEDDBD209BAAC200DD3B9B /* Assets.xcassets */; }; + DBDEDDC1209BAAC200DD3B9B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDEDDC0209BAAC200DD3B9B /* main.m */; }; + DBDEDDCB209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDEDDCA209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleTests.m */; }; + DBDEDDD6209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = DBDEDDD5209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleUITests.m */; }; + E16C876314712579B07EFBDE /* libPods-mParticle-Appboy-tvOS-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 10B9F0B06F3654507683F9D3 /* libPods-mParticle-Appboy-tvOS-Example.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + DBDEDDC7209BAAC200DD3B9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DBDEDDA9209BAAC000DD3B9B /* Project object */; + proxyType = 1; + remoteGlobalIDString = DBDEDDB0209BAAC000DD3B9B; + remoteInfo = "mParticle-Appboy-tvOS-Example"; + }; + DBDEDDD2209BAAC200DD3B9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DBDEDDA9209BAAC000DD3B9B /* Project object */; + proxyType = 1; + remoteGlobalIDString = DBDEDDB0209BAAC000DD3B9B; + remoteInfo = "mParticle-Appboy-tvOS-Example"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0A5A1A7877715F30E127818E /* Pods-mParticle-Appboy-tvOS-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-ExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-ExampleTests/Pods-mParticle-Appboy-tvOS-ExampleTests.release.xcconfig"; sourceTree = ""; }; + 10B9F0B06F3654507683F9D3 /* libPods-mParticle-Appboy-tvOS-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-mParticle-Appboy-tvOS-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 23DACD9BFFDB7DB5EB8C3840 /* Pods-mParticle-Appboy-tvOS-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-ExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-ExampleTests/Pods-mParticle-Appboy-tvOS-ExampleTests.debug.xcconfig"; sourceTree = ""; }; + 38243F334A614C276053E3E9 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-ExampleUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-ExampleUITests/Pods-mParticle-Appboy-tvOS-ExampleUITests.release.xcconfig"; sourceTree = ""; }; + 4550D0252B2DED98A6F071B5 /* Pods-mParticle-Appboy-tvOS-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-Example/Pods-mParticle-Appboy-tvOS-Example.debug.xcconfig"; sourceTree = ""; }; + 9A0C82FBA52E1027516742AD /* libPods-mParticle-Appboy-tvOS-ExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-mParticle-Appboy-tvOS-ExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + A09B15360B87FF411E2ACE43 /* Pods-mParticle-Appboy-tvOS-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-Example/Pods-mParticle-Appboy-tvOS-Example.release.xcconfig"; sourceTree = ""; }; + A2C8A5663E5E53DDF96C3294 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-mParticle-Appboy-tvOS-ExampleUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-ExampleUITests/Pods-mParticle-Appboy-tvOS-ExampleUITests.debug.xcconfig"; sourceTree = ""; }; + B7870024D5801479AF064BAA /* libPods-mParticle-Appboy-tvOS-ExampleUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-mParticle-Appboy-tvOS-ExampleUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDDB1209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "mParticle-Appboy-tvOS-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDDB4209BAAC000DD3B9B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + DBDEDDB5209BAAC000DD3B9B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + DBDEDDB7209BAAC000DD3B9B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + DBDEDDB8209BAAC000DD3B9B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + DBDEDDBB209BAAC000DD3B9B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + DBDEDDBD209BAAC200DD3B9B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DBDEDDBF209BAAC200DD3B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DBDEDDC0209BAAC200DD3B9B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + DBDEDDC6209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mParticle-Appboy-tvOS-ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDDCA209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = mParticle_Appboy_tvOS_ExampleTests.m; sourceTree = ""; }; + DBDEDDCC209BAAC200DD3B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DBDEDDD1209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mParticle-Appboy-tvOS-ExampleUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDDD5209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = mParticle_Appboy_tvOS_ExampleUITests.m; sourceTree = ""; }; + DBDEDDD7209BAAC200DD3B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + DBDEDDAE209BAAC000DD3B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E16C876314712579B07EFBDE /* libPods-mParticle-Appboy-tvOS-Example.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDC3209BAAC200DD3B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 17535475A2413657C2C1E785 /* libPods-mParticle-Appboy-tvOS-ExampleTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDCE209BAAC200DD3B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B577EC88F9901EAC4D5558DE /* libPods-mParticle-Appboy-tvOS-ExampleUITests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1EA442DBF7A01F2FB0710150 /* Pods */ = { + isa = PBXGroup; + children = ( + 4550D0252B2DED98A6F071B5 /* Pods-mParticle-Appboy-tvOS-Example.debug.xcconfig */, + A09B15360B87FF411E2ACE43 /* Pods-mParticle-Appboy-tvOS-Example.release.xcconfig */, + 23DACD9BFFDB7DB5EB8C3840 /* Pods-mParticle-Appboy-tvOS-ExampleTests.debug.xcconfig */, + 0A5A1A7877715F30E127818E /* Pods-mParticle-Appboy-tvOS-ExampleTests.release.xcconfig */, + A2C8A5663E5E53DDF96C3294 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.debug.xcconfig */, + 38243F334A614C276053E3E9 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 4292DB86733A67864F4E47AE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 10B9F0B06F3654507683F9D3 /* libPods-mParticle-Appboy-tvOS-Example.a */, + 9A0C82FBA52E1027516742AD /* libPods-mParticle-Appboy-tvOS-ExampleTests.a */, + B7870024D5801479AF064BAA /* libPods-mParticle-Appboy-tvOS-ExampleUITests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + DBDEDDA8209BAAC000DD3B9B = { + isa = PBXGroup; + children = ( + DBDEDDB3209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */, + DBDEDDC9209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests */, + DBDEDDD4209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests */, + DBDEDDB2209BAAC000DD3B9B /* Products */, + 1EA442DBF7A01F2FB0710150 /* Pods */, + 4292DB86733A67864F4E47AE /* Frameworks */, + ); + sourceTree = ""; + }; + DBDEDDB2209BAAC000DD3B9B /* Products */ = { + isa = PBXGroup; + children = ( + DBDEDDB1209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example.app */, + DBDEDDC6209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests.xctest */, + DBDEDDD1209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + DBDEDDB3209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */ = { + isa = PBXGroup; + children = ( + DBDEDDB4209BAAC000DD3B9B /* AppDelegate.h */, + DBDEDDB5209BAAC000DD3B9B /* AppDelegate.m */, + DBDEDDB7209BAAC000DD3B9B /* ViewController.h */, + DBDEDDB8209BAAC000DD3B9B /* ViewController.m */, + DBDEDDBA209BAAC000DD3B9B /* Main.storyboard */, + DBDEDDBD209BAAC200DD3B9B /* Assets.xcassets */, + DBDEDDBF209BAAC200DD3B9B /* Info.plist */, + DBDEDDC0209BAAC200DD3B9B /* main.m */, + ); + path = "mParticle-Appboy-tvOS-Example"; + sourceTree = ""; + }; + DBDEDDC9209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests */ = { + isa = PBXGroup; + children = ( + DBDEDDCA209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleTests.m */, + DBDEDDCC209BAAC200DD3B9B /* Info.plist */, + ); + path = "mParticle-Appboy-tvOS-ExampleTests"; + sourceTree = ""; + }; + DBDEDDD4209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests */ = { + isa = PBXGroup; + children = ( + DBDEDDD5209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleUITests.m */, + DBDEDDD7209BAAC200DD3B9B /* Info.plist */, + ); + path = "mParticle-Appboy-tvOS-ExampleUITests"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + DBDEDDB0209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = DBDEDDDA209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-Example" */; + buildPhases = ( + 1716C4EADAF842D0634982C9 /* [CP] Check Pods Manifest.lock */, + DBDEDDAD209BAAC000DD3B9B /* Sources */, + DBDEDDAE209BAAC000DD3B9B /* Frameworks */, + DBDEDDAF209BAAC000DD3B9B /* Resources */, + 872CFDFE9BF7619112AADFB1 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "mParticle-Appboy-tvOS-Example"; + productName = "mParticle-Appboy-tvOS-Example"; + productReference = DBDEDDB1209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example.app */; + productType = "com.apple.product-type.application"; + }; + DBDEDDC5209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DBDEDDDD209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-ExampleTests" */; + buildPhases = ( + 29D5CFFE2FC2EB1A86219020 /* [CP] Check Pods Manifest.lock */, + DBDEDDC2209BAAC200DD3B9B /* Sources */, + DBDEDDC3209BAAC200DD3B9B /* Frameworks */, + DBDEDDC4209BAAC200DD3B9B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DBDEDDC8209BAAC200DD3B9B /* PBXTargetDependency */, + ); + name = "mParticle-Appboy-tvOS-ExampleTests"; + productName = "mParticle-Appboy-tvOS-ExampleTests"; + productReference = DBDEDDC6209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DBDEDDD0209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DBDEDDE0209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-ExampleUITests" */; + buildPhases = ( + D5DBAE90505F00E3A3FC886B /* [CP] Check Pods Manifest.lock */, + DBDEDDCD209BAAC200DD3B9B /* Sources */, + DBDEDDCE209BAAC200DD3B9B /* Frameworks */, + DBDEDDCF209BAAC200DD3B9B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DBDEDDD3209BAAC200DD3B9B /* PBXTargetDependency */, + ); + name = "mParticle-Appboy-tvOS-ExampleUITests"; + productName = "mParticle-Appboy-tvOS-ExampleUITests"; + productReference = DBDEDDD1209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DBDEDDA9209BAAC000DD3B9B /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = mParticle; + TargetAttributes = { + DBDEDDB0209BAAC000DD3B9B = { + CreatedOnToolsVersion = 9.3; + }; + DBDEDDC5209BAAC200DD3B9B = { + CreatedOnToolsVersion = 9.3; + TestTargetID = DBDEDDB0209BAAC000DD3B9B; + }; + DBDEDDD0209BAAC200DD3B9B = { + CreatedOnToolsVersion = 9.3; + TestTargetID = DBDEDDB0209BAAC000DD3B9B; + }; + }; + }; + buildConfigurationList = DBDEDDAC209BAAC000DD3B9B /* Build configuration list for PBXProject "mParticle-Appboy-tvOS-Example" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = DBDEDDA8209BAAC000DD3B9B; + productRefGroup = DBDEDDB2209BAAC000DD3B9B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DBDEDDB0209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */, + DBDEDDC5209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleTests */, + DBDEDDD0209BAAC200DD3B9B /* mParticle-Appboy-tvOS-ExampleUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + DBDEDDAF209BAAC000DD3B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBDEDDBE209BAAC200DD3B9B /* Assets.xcassets in Resources */, + DBDEDDBC209BAAC000DD3B9B /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDC4209BAAC200DD3B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDCF209BAAC200DD3B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 1716C4EADAF842D0634982C9 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-mParticle-Appboy-tvOS-Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 29D5CFFE2FC2EB1A86219020 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-mParticle-Appboy-tvOS-ExampleTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 872CFDFE9BF7619112AADFB1 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-Example/Pods-mParticle-Appboy-tvOS-Example-frameworks.sh", + "${PODS_ROOT}/Appboy-tvOS-SDK/Appboy-tvOS-SDK/AppboyTVOSKit.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppboyTVOSKit.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-mParticle-Appboy-tvOS-Example/Pods-mParticle-Appboy-tvOS-Example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D5DBAE90505F00E3A3FC886B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-mParticle-Appboy-tvOS-ExampleUITests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + DBDEDDAD209BAAC000DD3B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBDEDDB9209BAAC000DD3B9B /* ViewController.m in Sources */, + DBDEDDC1209BAAC200DD3B9B /* main.m in Sources */, + DBDEDDB6209BAAC000DD3B9B /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDC2209BAAC200DD3B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBDEDDCB209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDDCD209BAAC200DD3B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBDEDDD6209BAAC200DD3B9B /* mParticle_Appboy_tvOS_ExampleUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + DBDEDDC8209BAAC200DD3B9B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DBDEDDB0209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */; + targetProxy = DBDEDDC7209BAAC200DD3B9B /* PBXContainerItemProxy */; + }; + DBDEDDD3209BAAC200DD3B9B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DBDEDDB0209BAAC000DD3B9B /* mParticle-Appboy-tvOS-Example */; + targetProxy = DBDEDDD2209BAAC200DD3B9B /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + DBDEDDBA209BAAC000DD3B9B /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + DBDEDDBB209BAAC000DD3B9B /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + DBDEDDD8209BAAC200DD3B9B /* 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_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 = ( + "DEBUG=1", + "$(inherited)", + ); + 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; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = appletvos; + TVOS_DEPLOYMENT_TARGET = 11.3; + }; + name = Debug; + }; + DBDEDDD9209BAAC200DD3B9B /* 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_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; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = appletvos; + TVOS_DEPLOYMENT_TARGET = 11.3; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + DBDEDDDB209BAAC200DD3B9B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4550D0252B2DED98A6F071B5 /* Pods-mParticle-Appboy-tvOS-Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = Q948K5LXGZ; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Debug; + }; + DBDEDDDC209BAAC200DD3B9B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A09B15360B87FF411E2ACE43 /* Pods-mParticle-Appboy-tvOS-Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = Q948K5LXGZ; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-Example/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + }; + name = Release; + }; + DBDEDDDE209BAAC200DD3B9B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 23DACD9BFFDB7DB5EB8C3840 /* Pods-mParticle-Appboy-tvOS-ExampleTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = DLD43Y3TRP; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-ExampleTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-ExampleTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/mParticle-Appboy-tvOS-Example.app/mParticle-Appboy-tvOS-Example"; + }; + name = Debug; + }; + DBDEDDDF209BAAC200DD3B9B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0A5A1A7877715F30E127818E /* Pods-mParticle-Appboy-tvOS-ExampleTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = DLD43Y3TRP; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-ExampleTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-ExampleTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/mParticle-Appboy-tvOS-Example.app/mParticle-Appboy-tvOS-Example"; + }; + name = Release; + }; + DBDEDDE1209BAAC200DD3B9B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A2C8A5663E5E53DDF96C3294 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = DLD43Y3TRP; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-ExampleUITests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-ExampleUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + TEST_TARGET_NAME = "mParticle-Appboy-tvOS-Example"; + }; + name = Debug; + }; + DBDEDDE2209BAAC200DD3B9B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 38243F334A614C276053E3E9 /* Pods-mParticle-Appboy-tvOS-ExampleUITests.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = DLD43Y3TRP; + INFOPLIST_FILE = "mParticle-Appboy-tvOS-ExampleUITests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS-ExampleUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = 3; + TEST_TARGET_NAME = "mParticle-Appboy-tvOS-Example"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + DBDEDDAC209BAAC000DD3B9B /* Build configuration list for PBXProject "mParticle-Appboy-tvOS-Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBDEDDD8209BAAC200DD3B9B /* Debug */, + DBDEDDD9209BAAC200DD3B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DBDEDDDA209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBDEDDDB209BAAC200DD3B9B /* Debug */, + DBDEDDDC209BAAC200DD3B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DBDEDDDD209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-ExampleTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBDEDDDE209BAAC200DD3B9B /* Debug */, + DBDEDDDF209BAAC200DD3B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DBDEDDE0209BAAC200DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS-ExampleUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBDEDDE1209BAAC200DD3B9B /* Debug */, + DBDEDDE2209BAAC200DD3B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = DBDEDDA9209BAAC000DD3B9B /* Project object */; +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.h b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.h new file mode 100644 index 000000000..3ac1941db --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// mParticle-Appboy-tvOS-Example +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.m b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.m new file mode 100644 index 000000000..b06f71862 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/AppDelegate.m @@ -0,0 +1,57 @@ +// +// AppDelegate.m +// mParticle-Appboy-tvOS-Example +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import "AppDelegate.h" +#import "mParticle.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + [[MParticle sharedInstance] startWithOptions:[MParticleOptions optionsWithKey:@"REPLACE WITH YOUR MPARTICLE API KEY" secret:@"REPLACE WITH YOUR MPARTICLE API SECRET"]]; + [MParticle sharedInstance].logLevel = MPILogLevelVerbose; + + [[MParticle sharedInstance] logEvent:[[MPEvent alloc] initWithName:@"foo" type:MPEventTypeOther]]; + + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..3b1a0cb9d --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images": [ + { + "idiom": "tv" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json new file mode 100644 index 000000000..8e6e0c6ec --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers": [ + { + "filename": "Front.imagestacklayer" + }, + { + "filename": "Middle.imagestacklayer" + }, + { + "filename": "Back.imagestacklayer" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..3b1a0cb9d --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images": [ + { + "idiom": "tv" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..3b1a0cb9d --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,11 @@ +{ + "images": [ + { + "idiom": "tv" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..94575ead3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "idiom": "tv", + "scale": "1x" + }, + { + "idiom": "tv", + "scale": "2x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json new file mode 100644 index 000000000..8e6e0c6ec --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers": [ + { + "filename": "Front.imagestacklayer" + }, + { + "filename": "Middle.imagestacklayer" + }, + { + "filename": "Back.imagestacklayer" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..94575ead3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "idiom": "tv", + "scale": "1x" + }, + { + "idiom": "tv", + "scale": "2x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 000000000..94575ead3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "idiom": "tv", + "scale": "1x" + }, + { + "idiom": "tv", + "scale": "2x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 000000000..ed2bb421a --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,32 @@ +{ + "assets": [ + { + "size": "1280x768", + "idiom": "tv", + "filename": "App Icon - App Store.imagestack", + "role": "primary-app-icon" + }, + { + "size": "400x240", + "idiom": "tv", + "filename": "App Icon.imagestack", + "role": "primary-app-icon" + }, + { + "size": "2320x720", + "idiom": "tv", + "filename": "Top Shelf Image Wide.imageset", + "role": "top-shelf-image-wide" + }, + { + "size": "1920x720", + "idiom": "tv", + "filename": "Top Shelf Image.imageset", + "role": "top-shelf-image" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json new file mode 100644 index 000000000..94575ead3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "idiom": "tv", + "scale": "1x" + }, + { + "idiom": "tv", + "scale": "2x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 000000000..94575ead3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images": [ + { + "idiom": "tv", + "scale": "1x" + }, + { + "idiom": "tv", + "scale": "2x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Contents.json new file mode 100644 index 000000000..97a8662eb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Launch Image.launchimage/Contents.json b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Launch Image.launchimage/Contents.json new file mode 100644 index 000000000..6a5b772bb --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Assets.xcassets/Launch Image.launchimage/Contents.json @@ -0,0 +1,22 @@ +{ + "images": [ + { + "orientation": "landscape", + "idiom": "tv", + "extent": "full-screen", + "minimum-system-version": "11.0", + "scale": "2x" + }, + { + "orientation": "landscape", + "idiom": "tv", + "extent": "full-screen", + "minimum-system-version": "9.0", + "scale": "1x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Base.lproj/Main.storyboard b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Base.lproj/Main.storyboard new file mode 100644 index 000000000..72d5e2239 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Base.lproj/Main.storyboard @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Info.plist b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Info.plist new file mode 100644 index 000000000..02942a34f --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + UIUserInterfaceStyle + Automatic + + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.h b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.h new file mode 100644 index 000000000..c58839fc1 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// mParticle-Appboy-tvOS-Example +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.m b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.m new file mode 100644 index 000000000..83de8c737 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/ViewController.m @@ -0,0 +1,29 @@ +// +// ViewController.m +// mParticle-Appboy-tvOS-Example +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +@end diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/main.m b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/main.m new file mode 100644 index 000000000..1c7219ab3 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-Example/main.m @@ -0,0 +1,16 @@ +// +// main.m +// mParticle-Appboy-tvOS-Example +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/Info.plist b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/Info.plist new file mode 100644 index 000000000..6c40a6cd0 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/mParticle_Appboy_tvOS_ExampleTests.m b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/mParticle_Appboy_tvOS_ExampleTests.m new file mode 100644 index 000000000..c5c9eff90 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleTests/mParticle_Appboy_tvOS_ExampleTests.m @@ -0,0 +1,39 @@ +// +// mParticle_Appboy_tvOS_ExampleTests.m +// mParticle-Appboy-tvOS-ExampleTests +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import + +@interface mParticle_Appboy_tvOS_ExampleTests : XCTestCase + +@end + +@implementation mParticle_Appboy_tvOS_ExampleTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/Info.plist b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/Info.plist new file mode 100644 index 000000000..6c40a6cd0 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/mParticle_Appboy_tvOS_ExampleUITests.m b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/mParticle_Appboy_tvOS_ExampleUITests.m new file mode 100644 index 000000000..131d328f7 --- /dev/null +++ b/kits/braze/braze-12/Examples/mParticle-Appboy-tvOS-Example-CocoaPods/mParticle-Appboy-tvOS-ExampleUITests/mParticle_Appboy_tvOS_ExampleUITests.m @@ -0,0 +1,40 @@ +// +// mParticle_Appboy_tvOS_ExampleUITests.m +// mParticle-Appboy-tvOS-ExampleUITests +// +// Created by Peter Jenkins on 5/3/18. +// Copyright ยฉ 2018 mParticle. All rights reserved. +// + +#import + +@interface mParticle_Appboy_tvOS_ExampleUITests : XCTestCase + +@end + +@implementation mParticle_Appboy_tvOS_ExampleUITests + +- (void)setUp { + [super setUp]; + + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + self.continueAfterFailure = NO; + // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. + [[[XCUIApplication alloc] init] launch]; + + // In UI tests itโ€™s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +@end diff --git a/kits/braze/braze-12/LICENSE b/kits/braze/braze-12/LICENSE new file mode 100644 index 000000000..1bccc65a9 --- /dev/null +++ b/kits/braze/braze-12/LICENSE @@ -0,0 +1,191 @@ +Copyright 2019 mParticle, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/kits/braze/braze-12/Package.resolved b/kits/braze/braze-12/Package.resolved new file mode 100644 index 000000000..03960fc88 --- /dev/null +++ b/kits/braze/braze-12/Package.resolved @@ -0,0 +1,25 @@ +{ + "object": { + "pins": [ + { + "package": "braze-swift-sdk", + "repositoryURL": "https://github.com/braze-inc/braze-swift-sdk", + "state": { + "branch": null, + "revision": "c630122e490fb156be2971b1f24d790488d33ac5", + "version": "12.1.0" + } + }, + { + "package": "SDWebImage", + "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", + "state": { + "branch": null, + "revision": "b62cb63bf4ed1f04c961a56c9c6c9d5ab8524ec6",#import + "version": "5.21.1" + } + } + ] + }, + "version": 1 +} diff --git a/kits/braze/braze-12/Package.swift b/kits/braze/braze-12/Package.swift new file mode 100644 index 000000000..983ceb7ac --- /dev/null +++ b/kits/braze/braze-12/Package.swift @@ -0,0 +1,37 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "mParticle-Appboy", + platforms: [ .iOS(.v15), .tvOS(.v15) ], + products: [ + .library( + name: "mParticle-Appboy", + targets: ["mParticle-Appboy"] + ) + ], + dependencies: [ + .package( + url: "https://github.com/mParticle/mparticle-apple-sdk", + branch: "workstation/9.0-Release" + ), + .package( + url: "https://github.com/braze-inc/braze-swift-sdk", + .upToNextMajor(from: "12.0.0") + ), + ], + targets: [ + .target( + name: "mParticle-Appboy", + dependencies: [ + .product(name: "mParticle-Apple-SDK", package: "mParticle-Apple-SDK"), + .product(name: "BrazeUI", package: "braze-swift-sdk", condition: .when(platforms: [.iOS])), + .product(name: "BrazeKit", package: "braze-swift-sdk"), + .product(name: "BrazeKitCompat", package: "braze-swift-sdk"), + ], + resources: [.process("PrivacyInfo.xcprivacy")] + ) + ] +) diff --git a/kits/braze/braze-12/README.md b/kits/braze/braze-12/README.md new file mode 100644 index 000000000..0b0ef0cd0 --- /dev/null +++ b/kits/braze/braze-12/README.md @@ -0,0 +1,33 @@ +## Braze (formerly Appboy) Kit Integration + +This repository contains the [Braze](https://www.braze.com) integration for the [mParticle Apple SDK](https://github.com/mParticle/mparticle-apple-sdk) using the latest [Braze Swift SDK](https://github.com/braze-inc/braze-swift-sdk/). + +### Adding the integration + +1. Add the kit dependency using SPM or add it to your app's Podfile or Cartfile: + + ``` + pod 'mParticle-Appboy', '~> 8.0' + ``` + + OR + + ``` + github "mparticle-integrations/mparticle-apple-integration-appboy" ~> 8.0 + ``` + +2. If using SPM, make sure to add the `-ObjC` flag to the target's `Other Linker Flags` setting in Xcode, according to the [Braze documentation](https://www.braze.com/docs/developer_guide/platform_integration_guides/ios/initial_sdk_setup/installation_methods/swift_package_manager#step-2-configuring-your-project). + +3. Follow the mParticle iOS SDK [quick-start](https://github.com/mParticle/mparticle-apple-sdk), then rebuild and launch your app, and verify that you see `"Included kits: { Appboy }"` in your Xcode console + +> (This requires your mParticle log level to be at least Debug) + +4. Reference mParticle's integration docs below to enable the integration. + +### Documentation + +[Braze integration](https://docs.mparticle.com/integrations/braze/event/) + +### License + +[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/kits/braze/braze-12/Scripts/release.sh b/kits/braze/braze-12/Scripts/release.sh new file mode 100755 index 000000000..36d221b68 --- /dev/null +++ b/kits/braze/braze-12/Scripts/release.sh @@ -0,0 +1,19 @@ +VERSION="$1" +PREFIXED_VERSION="v$1" +NOTES="$2" + +# Update version number +# + +# Update CocoaPods podspec file +sed -i '' 's/\(^ s.version[^=]*= \).*/\1"'"$VERSION"'"/' mParticle-Appboy.podspec + +# Make the release commit in git +# + +git add mParticle-Appboy.podspec +git add mParticle_Appboy.json +git add CHANGELOG.md +git commit -m "chore(release): $VERSION [skip ci] + +$NOTES" diff --git a/kits/braze/braze-12/Sources/Info.plist b/kits/braze/braze-12/Sources/Info.plist new file mode 100644 index 000000000..d3de8eefb --- /dev/null +++ b/kits/braze/braze-12/Sources/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/kits/braze/braze-12/Sources/mParticle-Appboy/MPKitAppboy.m b/kits/braze/braze-12/Sources/mParticle-Appboy/MPKitAppboy.m new file mode 100644 index 000000000..27fcf20b0 --- /dev/null +++ b/kits/braze/braze-12/Sources/mParticle-Appboy/MPKitAppboy.m @@ -0,0 +1,1308 @@ +#import "MPKitAppboy.h" + +#if TARGET_OS_IOS + @import BrazeKit; + @import BrazeKitCompat; + @import BrazeUI; +#else + @import BrazeKit; + @import BrazeKitCompat; +#endif + +static NSString *const eabAPIKey = @"apiKey"; +static NSString *const eabOptions = @"options"; +static NSString *const hostConfigKey = @"host"; +static NSString *const userIdTypeKey = @"userIdentificationType"; +static NSString *const emailIdTypeKey = @"emailIdentificationType"; +static NSString *const enableTypeDetectionKey = @"enableTypeDetection"; +static NSString *const bundleCommerceEventData = @"bundleCommerceEventData"; +static NSString *const replaceSkuWithProductName = @"replaceSkuWithProductName"; +static NSString *const subscriptionGroupMapping = @"subscriptionGroupMapping"; + +// The possible values for userIdentificationType +static NSString *const userIdValueOther = @"Other"; +static NSString *const userIdValueOther2 = @"Other2"; +static NSString *const userIdValueOther3 = @"Other3"; +static NSString *const userIdValueOther4 = @"Other4"; +static NSString *const userIdValueOther5 = @"Other5"; +static NSString *const userIdValueOther6 = @"Other6"; +static NSString *const userIdValueOther7 = @"Other7"; +static NSString *const userIdValueOther8 = @"Other8"; +static NSString *const userIdValueOther9 = @"Other9"; +static NSString *const userIdValueOther10 = @"Other10"; +static NSString *const userIdValueCustomerId = @"CustomerId"; +static NSString *const userIdValueFacebook = @"Facebook"; +static NSString *const userIdValueTwitter = @"Twitter"; +static NSString *const userIdValueGoogle = @"Google"; +static NSString *const userIdValueMicrosoft = @"Microsoft"; +static NSString *const userIdValueYahoo = @"Yahoo"; +static NSString *const userIdValueEmail = @"Email"; +static NSString *const userIdValueAlias = @"Alias"; +static NSString *const userIdValueMPID = @"MPID"; + +// User Attribute key with reserved functionality for Braze kit +static NSString *const brazeUserAttributeDob = @"dob"; +static NSString *const brazeUserAttributeEmailSubscribe = @"email_subscribe"; +static NSString *const brazeUserAttributePushSubscribe = @"push_subscribe"; + +// Strings used when sending enhanced commerce events +static NSString *const attributesKey = @"Attributes"; +static NSString *const productKey = @"products"; +static NSString *const promotionKey = @"promotions"; +static NSString *const impressionKey = @"impressions"; + +// Strings used for Google Consent +static NSString *const MPMapKey = @"map"; +static NSString *const MPValueKey = @"value"; +static NSString *const MPConsentMappingSDKKey = @"consentMappingSDK"; +static NSString *const MPGoogleAdUserDataKey = @"google_ad_user_data"; +static NSString *const MPGoogleAdPersonalizationKey = @"google_ad_personalization"; +static NSString *const BGoogleAdUserDataKey = @"$google_ad_user_data"; +static NSString *const BGoogleAdPersonalizationKey = @"$google_ad_personalization"; + +#if TARGET_OS_IOS +static id inAppMessageControllerDelegate = nil; +static BOOL shouldDisableNotificationHandling = NO; +#endif +static id urlDelegate = nil; +static Braze *brazeInstance = nil; +static id brazeLocationProvider = nil; +static NSSet *brazeTrackingPropertyAllowList; + +@interface MPKitAppboy() { + Braze *appboyInstance; + BOOL collectIDFA; + BOOL forwardScreenViews; + NSMutableDictionary *subscriptionGroupDictionary; +} + +@property (nonatomic) NSString *host; +@property (nonatomic) BOOL enableTypeDetection; + +@end + + +@implementation MPKitAppboy + ++ (NSNumber *)kitCode { + return @28; +} + ++ (void)load { + MPKitRegister *kitRegister = [[MPKitRegister alloc] initWithName:@"Appboy" className:@"MPKitAppboy"]; + [MParticle registerExtension:kitRegister]; +} + +#if TARGET_OS_IOS ++ (void)setInAppMessageControllerDelegate:(id)delegate { + inAppMessageControllerDelegate = (id)delegate; +} + ++ (id)inAppMessageControllerDelegate { + return inAppMessageControllerDelegate; +} + ++ (void)setShouldDisableNotificationHandling:(BOOL)isDisabled { + shouldDisableNotificationHandling = isDisabled; +} + ++ (BOOL)shouldDisableNotificationHandling { + return shouldDisableNotificationHandling; +} + +#endif + ++ (void)setURLDelegate:(id)delegate { + urlDelegate = (id)delegate; +} + ++ (id)urlDelegate { + return urlDelegate; +} + ++ (void)setBrazeInstance:(id)instance { + if ([instance isKindOfClass:[Braze class]]) { + brazeInstance = instance; + } +} + ++ (Braze *)brazeInstance { + return brazeInstance; +} + ++ (void)setBrazeLocationProvider:(nonnull id)instance { + brazeLocationProvider = instance; +} + ++ (void)setBrazeTrackingPropertyAllowList:(nonnull NSSet *)allowList { + for (id property in allowList) { + if (![property isKindOfClass:[BRZTrackingProperty class]]) { + return; + } + } + brazeTrackingPropertyAllowList = allowList; +} + +#pragma mark Private methods +- (NSString *)stringRepresentation:(id)value { + NSString *stringRepresentation = nil; + + if ([value isKindOfClass:[NSString class]]) { + stringRepresentation = value; + } else if ([value isKindOfClass:[NSNumber class]]) { + stringRepresentation = [(NSNumber *)value stringValue]; + } else if ([value isKindOfClass:[NSDate class]]) { + stringRepresentation = [MPKitAPI stringFromDateRFC3339:value]; + } else if ([value isKindOfClass:[NSData class]]) { + stringRepresentation = [[NSString alloc] initWithData:value encoding:NSUTF8StringEncoding]; + } else { + return nil; + } + + return stringRepresentation; +} + +- (Braze *)appboyInstance { + return self->appboyInstance; +} + +- (void)setAppboyInstance:(Braze *)instance { + self->appboyInstance = instance; +} + +- (NSString *)stripCharacter:(NSString *)character fromString:(NSString *)originalString { + NSRange range = [originalString rangeOfString:character]; + + if (range.location == 0) { + NSMutableString *strippedString = [originalString mutableCopy]; + [strippedString replaceOccurrencesOfString:character withString:@"" options:NSCaseInsensitiveSearch range:range]; + return [strippedString copy]; + } else { + return originalString; + } +} + +- (NSMutableDictionary *)getSubscriptionGroupIds:(NSString *)subscriptionGroupMap { + NSMutableDictionary *subscriptionGroupDictionary = [NSMutableDictionary dictionary]; + + if (!subscriptionGroupMap.length) { + return subscriptionGroupDictionary; + } + + NSData *subsctiprionGroupData = [subscriptionGroupMap dataUsingEncoding:NSUTF8StringEncoding]; + + NSError *error = nil; + NSArray *subsctiprionGroupDataArray = [NSJSONSerialization JSONObjectWithData:subsctiprionGroupData options:0 error:&error]; + + for (NSDictionary *item in subsctiprionGroupDataArray) { + NSString *key = item[@"map"]; + NSString *value = item[@"value"]; + subscriptionGroupDictionary[key] = value; + } + + return subscriptionGroupDictionary; +} + +- (MPKitExecStatus *)logAppboyCustomEvent:(MPEvent *)event eventType:(NSUInteger)eventType { + void (^logCustomEvent)(void) = ^{ + NSDictionary *transformedEventInfo = [event.customAttributes transformValuesToString]; + + NSMutableDictionary *eventInfo = [[NSMutableDictionary alloc] initWithCapacity:event.customAttributes.count]; + [transformedEventInfo enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString *strippedKey = [self stripCharacter:@"$" fromString:key]; + eventInfo[strippedKey] = obj; + }]; + + NSDictionary *detectedEventInfo = eventInfo; + if (self->_enableTypeDetection) { + detectedEventInfo = [self simplifiedDictionary:eventInfo]; + } + + // Appboy expects that the properties are non empty when present. + if (detectedEventInfo && detectedEventInfo.count > 0) { + [self->appboyInstance logCustomEvent:event.name properties:detectedEventInfo]; + } else { + [self->appboyInstance logCustomEvent:event.name]; + } + + NSString *eventTypeString = [@(eventType) stringValue]; + + for (NSString *key in eventInfo) { + NSString *eventTypePlusNamePlusKey = [[NSString stringWithFormat:@"%@%@%@", eventTypeString, event.name, key] lowercaseString]; + NSString *hashValue = [MPKitAPI hashString:eventTypePlusNamePlusKey]; + + NSDictionary *forwardUserAttributes; + + // Delete from array + forwardUserAttributes = self.configuration[@"ear"]; + if (forwardUserAttributes[hashValue]) { + [self->appboyInstance.user removeFromCustomAttributeStringArrayWithKey:forwardUserAttributes[hashValue] value:eventInfo[key]]; + } + + // Add to array + forwardUserAttributes = self.configuration[@"eaa"]; + if (forwardUserAttributes[hashValue]) { + [self->appboyInstance.user addToCustomAttributeStringArrayWithKey:forwardUserAttributes[hashValue] value:eventInfo[key]]; + } + + // Add key/value pair + forwardUserAttributes = self.configuration[@"eas"]; + if (forwardUserAttributes[hashValue]) { + [self setUserAttribute:forwardUserAttributes[hashValue] value:eventInfo[key]]; + } + } + }; + + if ([NSThread isMainThread]) { + logCustomEvent(); + } else { + dispatch_async(dispatch_get_main_queue(), logCustomEvent); + } + + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + return execStatus; +} + +- (BOOL)isAdvertisingTrackingEnabled { + BOOL advertisingTrackingEnabled = NO; + Class MPIdentifierManager = NSClassFromString(@"ASIdentifierManager"); + + if (MPIdentifierManager) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + SEL selector = NSSelectorFromString(@"sharedManager"); + id adIdentityManager = [MPIdentifierManager performSelector:selector]; + selector = NSSelectorFromString(@"isAdvertisingTrackingEnabled"); + advertisingTrackingEnabled = (BOOL)[adIdentityManager performSelector:selector]; +#pragma clang diagnostic pop +#pragma clang diagnostic pop + } + + return advertisingTrackingEnabled && collectIDFA; +} + +- (NSString *)advertisingIdentifierString { + NSString *_advertiserId = nil; + Class MPIdentifierManager = NSClassFromString(@"ASIdentifierManager"); + + if (MPIdentifierManager) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + SEL selector = NSSelectorFromString(@"sharedManager"); + id adIdentityManager = [MPIdentifierManager performSelector:selector]; + + selector = NSSelectorFromString(@"isAdvertisingTrackingEnabled"); + BOOL advertisingTrackingEnabled = (BOOL)[adIdentityManager performSelector:selector]; + if (advertisingTrackingEnabled) { + selector = NSSelectorFromString(@"advertisingIdentifier"); + _advertiserId = [[adIdentityManager performSelector:selector] UUIDString]; + } +#pragma clang diagnostic pop +#pragma clang diagnostic pop + } + + return _advertiserId; +} + +- (BOOL)isAppTrackingEnabled { + BOOL appTrackingEnabled = NO; + Class ATTrackingManager = NSClassFromString(@"ATTrackingManager"); + + if (ATTrackingManager) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + SEL selector = NSSelectorFromString(@"trackingAuthorizationStatus"); + NSUInteger trackingAuthorizationStatus = (NSUInteger)[ATTrackingManager performSelector:selector]; + appTrackingEnabled = (trackingAuthorizationStatus == 3); // ATTrackingManagerAuthorizationStatusAuthorized +#pragma clang diagnostic pop +#pragma clang diagnostic pop + } + + return appTrackingEnabled; +} + +#pragma mark MPKitInstanceProtocol methods +- (MPKitExecStatus *)didFinishLaunchingWithConfiguration:(NSDictionary *)configuration { + + // Use the static braze instance if set + [self setAppboyInstance:brazeInstance]; + + MPKitExecStatus *execStatus = nil; + + if (!configuration[eabAPIKey]) { + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] returnCode:MPKitReturnCodeRequirementsNotMet]; + return execStatus; + } + + _configuration = configuration; + + collectIDFA = NO; + forwardScreenViews = NO; + + _host = configuration[hostConfigKey]; + _enableTypeDetection = [configuration[enableTypeDetectionKey] boolValue]; + + //If Braze is already initialized, immediately "start" the kit, this + //is here for: + // 1. Apps that initialize Braze prior to mParticle, and/or + // 2. Apps that initialize mParticle too late, causing the SDK to miss + // the launch notification which would otherwise trigger start(). + if (self->appboyInstance) { + NSLog(@"mParticle -> Warning: Braze SDK initialized outside of mParticle kit, this will mean Braze settings within the mParticle dashboard such as API key, endpoint URL, flush interval and others will not be respected."); + [self start]; + } else { + _started = NO; + } + + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] returnCode:MPKitReturnCodeSuccess]; + return execStatus; +} + +- (id const)providerKitInstance { + return [self started] ? appboyInstance : nil; +} + +- (void)start { + if (!self->appboyInstance) { + NSDictionary *optionsDict = [self optionsDictionary]; + BRZConfiguration *configuration = [[BRZConfiguration alloc] initWithApiKey:self.configuration[eabAPIKey] endpoint:optionsDict[ABKEndpointKey]]; + + [configuration.api addSDKMetadata:@[BRZSDKMetadata.mparticle]]; + configuration.api.sdkFlavor = ((NSNumber *)optionsDict[ABKSDKFlavorKey]).intValue; + configuration.api.requestPolicy = ((NSNumber *)optionsDict[ABKRequestProcessingPolicyOptionKey]).intValue; + NSNumber *flushIntervalOption = (NSNumber *)optionsDict[ABKFlushIntervalOptionKey] ?: @10; // If not set, use the default 10 seconds specified in Braze SDK header + configuration.api.flushInterval = flushIntervalOption.doubleValue < 1.0 ? 1.0 : flushIntervalOption.doubleValue; // Ensure value is above the minimum of 1.0 per run time warning from Braze SDK + configuration.api.trackingPropertyAllowList = brazeTrackingPropertyAllowList; + + configuration.sessionTimeout = ((NSNumber *)optionsDict[ABKSessionTimeoutKey]).doubleValue; + + configuration.triggerMinimumTimeInterval = ((NSNumber *)optionsDict[ABKMinimumTriggerTimeIntervalKey]).doubleValue; + + NSNumber *automaticLocationTrackingOption = (NSNumber *)optionsDict[ABKEnableAutomaticLocationCollectionKey]; + if (automaticLocationTrackingOption != nil && automaticLocationTrackingOption.boolValue && brazeLocationProvider) { + configuration.location.automaticLocationCollection = YES; + configuration.location.brazeLocationProvider = brazeLocationProvider; + } + + self->appboyInstance = [[Braze alloc] initWithConfiguration:configuration]; + } + + if (!self->appboyInstance) { + return; + } + + self->forwardScreenViews = self.configuration[@"forwardScreenViews"] && [self.configuration[@"forwardScreenViews"] caseInsensitiveCompare:@"true"] == NSOrderedSame; + + self->collectIDFA = self.configuration[@"ABKCollectIDFA"] && [self.configuration[@"ABKCollectIDFA"] caseInsensitiveCompare:@"true"] == NSOrderedSame; + + if (self->collectIDFA) { + [self->appboyInstance setIdentifierForAdvertiser:[self advertisingIdentifierString]]; + } + [self->appboyInstance setAdTrackingEnabled:[self isAppTrackingEnabled]]; + + if ([MPKitAppboy urlDelegate]) { + self->appboyInstance.delegate = [MPKitAppboy urlDelegate]; + } + + self->subscriptionGroupDictionary = [self getSubscriptionGroupIds:self.configuration[subscriptionGroupMapping]]; + +#if TARGET_OS_IOS + BrazeInAppMessageUI *inAppMessageUI = [[BrazeInAppMessageUI alloc] init]; + inAppMessageUI.delegate = [MPKitAppboy inAppMessageControllerDelegate]; + [self->appboyInstance setInAppMessagePresenter:inAppMessageUI]; +#endif + + FilteredMParticleUser *currentUser = [[self kitApi] getCurrentUserWithKit:self]; + if (currentUser.userId.integerValue != 0) { + [self updateUser:currentUser request:currentUser.userIdentities]; + } + + self->_started = YES; + + // Update Consent on start + [self updateConsent]; + + dispatch_async(dispatch_get_main_queue(), ^{ + NSDictionary *userInfo = @{mParticleKitInstanceKey:[[self class] kitCode]}; + + [[NSNotificationCenter defaultCenter] postNotificationName:mParticleKitDidBecomeActiveNotification + object:nil + userInfo:userInfo]; + }); +} + +- (void)stop { + self->appboyInstance = nil; + _started = NO; + _configuration = nil; +} + +- (NSMutableDictionary *)optionsDictionary { + NSArray *serverKeys = @[@"ABKRequestProcessingPolicyOptionKey", @"ABKFlushIntervalOptionKey", @"ABKSessionTimeoutKey", @"ABKMinimumTriggerTimeIntervalKey"]; + NSArray *appboyKeys = @[ABKRequestProcessingPolicyOptionKey, ABKFlushIntervalOptionKey, ABKSessionTimeoutKey, ABKMinimumTriggerTimeIntervalKey]; + NSMutableDictionary *optionsDictionary = [[NSMutableDictionary alloc] initWithCapacity:serverKeys.count]; + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + numberFormatter.numberStyle = NSNumberFormatterNoStyle; + + [serverKeys enumerateObjectsUsingBlock:^(NSString * _Nonnull serverKey, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *optionValue = self.configuration[serverKey]; + + if (optionValue != nil && (NSNull *)optionValue != [NSNull null]) { + NSString *appboyKey = appboyKeys[idx]; + NSNumber *numberValue = nil; + @try { + numberValue = [numberFormatter numberFromString:optionValue]; + } @catch (NSException *exception) { + numberValue = nil; + } + if (numberValue != nil) { + optionsDictionary[appboyKey] = numberValue; + } + } + }]; + + if (self.host.length) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincompatible-pointer-types" + optionsDictionary[ABKEndpointKey] = self.host; +#pragma clang diagnostic pop + } + + if (optionsDictionary.count == 0) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincompatible-pointer-types" + optionsDictionary = [[NSMutableDictionary alloc] initWithCapacity:serverKeys.count]; + } + optionsDictionary[ABKSDKFlavorKey] = @(MPARTICLE); +#pragma clang diagnostic pop + +#if TARGET_OS_IOS + optionsDictionary[ABKEnableAutomaticLocationCollectionKey] = @(YES); + if (self.configuration[@"ABKDisableAutomaticLocationCollectionKey"]) { + if ([self.configuration[@"ABKDisableAutomaticLocationCollectionKey"] caseInsensitiveCompare:@"true"] == NSOrderedSame) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincompatible-pointer-types" + optionsDictionary[ABKEnableAutomaticLocationCollectionKey] = @(NO); +#pragma clang diagnostic pop + } + } +#endif + + return optionsDictionary; +} + +- (MPKitExecStatus *)incrementUserAttribute:(NSString *)key byValue:(NSNumber *)value { + [appboyInstance.user incrementCustomUserAttribute:key by:[value integerValue]]; + + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + return execStatus; +} + +- (nonnull MPKitExecStatus *)logBaseEvent:(nonnull MPBaseEvent *)event { + if ([event isKindOfClass:[MPEvent class]]) { + return [self routeEvent:(MPEvent *)event]; + } else if ([event isKindOfClass:[MPCommerceEvent class]]) { + return [self routeCommerceEvent:(MPCommerceEvent *)event]; + } else { + return [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeUnavailable]; + } +} + +- (MPKitExecStatus *)routeCommerceEvent:(MPCommerceEvent *)commerceEvent { + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess forwardCount:0]; + + if (commerceEvent.action == MPCommerceEventActionPurchase) { + NSMutableDictionary *baseProductAttributes = [[NSMutableDictionary alloc] init]; + NSDictionary *transactionAttributes = [self simplifiedDictionary:[commerceEvent.transactionAttributes beautifiedDictionaryRepresentation]]; + + if (transactionAttributes) { + [baseProductAttributes addEntriesFromDictionary:transactionAttributes]; + } + + NSDictionary *commerceEventAttributes = [commerceEvent beautifiedAttributes]; + NSArray *keys = @[kMPExpCECheckoutOptions, kMPExpCECheckoutStep, kMPExpCEProductListName, kMPExpCEProductListSource]; + + for (NSString *key in keys) { + if (commerceEventAttributes[key]) { + baseProductAttributes[key] = commerceEventAttributes[key]; + } + } + + NSDictionary *commerceCustomAttribues = [commerceEvent.customAttributes transformValuesToString]; + for (NSString *key in commerceCustomAttribues) { + baseProductAttributes[key] = commerceCustomAttribues[key]; + } + + NSArray *products = commerceEvent.products; + NSString *currency = commerceEvent.currency ? : @"USD"; + NSMutableDictionary *properties; + + // Add relevant attributes from the commerce event + properties = [[NSMutableDictionary alloc] init]; + if (baseProductAttributes.count > 0) { + [properties addEntriesFromDictionary:baseProductAttributes]; + } + + if ([_configuration[bundleCommerceEventData] boolValue]) { + if (commerceEvent.customAttributes.count > 0) { + [properties removeObjectsForKeys:[commerceEvent.customAttributes allKeys]]; + [properties setValue:commerceEvent.customAttributes forKey:attributesKey]; + } + NSArray *productArray = [self getProductListParameters:products]; + if (productArray.count > 0) { + [properties setValue:productArray forKey:productKey]; + } + NSArray *promotionArray = [self getPromotionListParameters:commerceEvent.promotionContainer.promotions]; + if (promotionArray.count > 0) { + [properties setValue:promotionArray forKey:promotionKey]; + } + NSArray *impressionArray = [self getImpressionListParameters:commerceEvent.impressions]; + if (impressionArray.count > 0) { + [properties setValue:impressionArray forKey:impressionKey]; + } + + NSString *eventName = [NSString stringWithFormat:@"eCommerce - %@", [self eventNameForAction:commerceEvent.action]]; + + [appboyInstance logPurchase:eventName + currency:currency + price:[commerceEvent.transactionAttributes.revenue doubleValue] + properties:properties]; + + [execStatus incrementForwardCount]; + } else { + for (MPProduct *product in products) { + // Add attributes from the product itself + NSDictionary *productDictionary = [product beautifiedDictionaryRepresentation]; + if (productDictionary) { + [properties addEntriesFromDictionary:productDictionary]; + } + + NSString *sanitizedProductName = product.sku; + if ([@"True" isEqualToString:_configuration[replaceSkuWithProductName]]) { + sanitizedProductName = product.name; + } + + // Strips key/values already being passed to Appboy, plus key/values initialized to default values + keys = @[kMPExpProductSKU, kMPProductCurrency, kMPExpProductUnitPrice, kMPExpProductQuantity]; + [properties removeObjectsForKeys:keys]; + + [appboyInstance logPurchase:sanitizedProductName + currency:currency + price:[product.price doubleValue] + quantity:[product.quantity integerValue] + properties:properties]; + + [execStatus incrementForwardCount]; + } + } + } else { + if ([_configuration[bundleCommerceEventData] boolValue]) { + NSDictionary *transformedEventInfo = [commerceEvent.customAttributes transformValuesToString]; + + NSMutableDictionary *eventInfo = [[NSMutableDictionary alloc] initWithCapacity:commerceEvent.customAttributes.count]; + [transformedEventInfo enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString *strippedKey = [self stripCharacter:@"$" fromString:key]; + eventInfo[strippedKey] = obj; + }]; + + if (self->_enableTypeDetection) { + eventInfo = [[self simplifiedDictionary:eventInfo] mutableCopy]; + } + + if (commerceEvent.customAttributes.count > 0) { + [eventInfo removeObjectsForKeys:[commerceEvent.customAttributes allKeys]]; + [eventInfo setValue:commerceEvent.customAttributes forKey:attributesKey]; + } + NSArray *productArray = [self getProductListParameters:commerceEvent.products]; + if (productArray.count > 0) { + [eventInfo setValue:productArray forKey:productKey]; + } + NSArray *promotionArray = [self getPromotionListParameters:commerceEvent.promotionContainer.promotions]; + if (promotionArray.count > 0) { + [eventInfo setValue:promotionArray forKey:promotionKey]; + } + NSArray *impressionArray = [self getImpressionListParameters:commerceEvent.impressions]; + if (impressionArray.count > 0) { + [eventInfo setValue:impressionArray forKey:impressionKey]; + } + + NSString *eventName = [NSString stringWithFormat:@"eCommerce - %@", [self eventNameForAction:commerceEvent.action]]; + if ([eventName isEqualToString:@"eCommerce - unknown"]) { + if (commerceEvent.impressions) { + eventName = @"eCommerce - impression"; + } else if (commerceEvent.promotionContainer.action) { + eventName = [NSString stringWithFormat:@"eCommerce - %@", [self eventNameForPromotionAction:commerceEvent.promotionContainer.action]]; + } + } + + // Appboy expects that the properties are non empty when present. + if (eventInfo.count > 0) { + [self->appboyInstance logCustomEvent:eventName properties:eventInfo]; + } else { + [self->appboyInstance logCustomEvent:eventName]; + } + [execStatus incrementForwardCount]; + } else { + NSArray *expandedInstructions = [commerceEvent expandedInstructions]; + + for (MPCommerceEventInstruction *commerceEventInstruction in expandedInstructions) { + [self logBaseEvent:commerceEventInstruction.event]; + [execStatus incrementForwardCount]; + } + } + } + + return execStatus; +} + +- (MPKitExecStatus *)routeEvent:(MPEvent *)event { + return [self logAppboyCustomEvent:event eventType:event.type]; +} + +- (MPKitExecStatus *)logScreen:(MPEvent *)event { + MPKitExecStatus *execStatus = nil; + + if (forwardScreenViews) { + execStatus = [self logAppboyCustomEvent:event eventType:0]; + } else { + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeCannotExecute]; + } + + return execStatus; +} + +- (MPKitExecStatus *)receivedUserNotification:(NSDictionary *)userInfo { + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + +#if TARGET_OS_IOS + if (shouldDisableNotificationHandling) { + return execStatus; + } + + if (![appboyInstance.notifications handleBackgroundNotificationWithUserInfo:userInfo fetchCompletionHandler:^(UIBackgroundFetchResult fetchResult) {}]) { + NSLog(@"mParticle -> Invalid Braze remote notification: %@", userInfo); + } +#endif + + return execStatus; +} + +- (MPKitExecStatus *)removeUserAttribute:(NSString *)key { + [appboyInstance.user unsetCustomAttributeWithKey:key]; + + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + return execStatus; +} + +- (MPKitExecStatus *)setDeviceToken:(NSData *)deviceToken { + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + +#if TARGET_OS_IOS + if (shouldDisableNotificationHandling) { + return execStatus; + } + + [appboyInstance.notifications registerDeviceToken:deviceToken]; +#endif + + return execStatus; +} + +- (MPKitExecStatus *)setOptOut:(BOOL)optOut { + MPKitReturnCode returnCode; + + if (optOut) { + [appboyInstance.user setEmailSubscriptionState:BRZUserSubscriptionStateSubscribed]; + returnCode = MPKitReturnCodeSuccess; + } else { + returnCode = MPKitReturnCodeCannotExecute; + } + + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:returnCode]; + return execStatus; +} + +- (MPKitExecStatus *)setUserAttribute:(NSString *)key value:(NSString *)value { + MPKitExecStatus *execStatus; + + if (!value) { + [appboyInstance.user unsetCustomAttributeWithKey:key]; + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + return execStatus; + } + + value = [self stringRepresentation:value]; + + if (!value) { + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + + if ([key isEqualToString:mParticleUserAttributeFirstName]) { + [appboyInstance.user setFirstName:value]; + } else if ([key isEqualToString:mParticleUserAttributeLastName]) { + [appboyInstance.user setLastName:value]; + } else if ([key isEqualToString:mParticleUserAttributeAge]) { + NSDate *now = [NSDate date]; + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDateComponents *dateComponents = [calendar components:NSCalendarUnitYear fromDate:now]; + NSInteger age = 0; + + @try { + age = [value integerValue]; + } @catch (NSException *exception) { + NSLog(@"mParticle -> Invalid age: %@", value); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + + NSDateComponents *birthComponents = [[NSDateComponents alloc] init]; + birthComponents.year = dateComponents.year - age; + birthComponents.month = 01; + birthComponents.day = 01; + + [appboyInstance.user setDateOfBirth:[calendar dateFromComponents:birthComponents]]; + } else if ([key isEqualToString:brazeUserAttributeDob]) { + // Expected Date Format @"yyyy'-'MM'-'dd" + NSCalendar *calendar = [NSCalendar currentCalendar]; + + NSString *yearString = [value substringToIndex:4]; + NSRange monthRange = NSMakeRange(5, 2); + NSString *monthString = [value substringWithRange:monthRange]; + NSRange dayRange = NSMakeRange(8, 2); + NSString *dayString = [value substringWithRange:dayRange]; + + NSInteger year = 0; + NSInteger month = 0; + NSInteger day = 0; + + @try { + year = [yearString integerValue]; + } @catch (NSException *exception) { + NSLog(@"mParticle -> Invalid dob year: %@ \nPlease use this date format @\"yyyy'-'MM'-'dd\"", yearString); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + + @try { + month = [monthString integerValue]; + } @catch (NSException *exception) { + NSLog(@"mParticle -> Invalid dob month: %@ \nPlease use this date format @\"yyyy'-'MM'-'dd\"", monthString); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + + @try { + day = [dayString integerValue]; + } @catch (NSException *exception) { + NSLog(@"mParticle -> Invalid dob day: %@ \nPlease use this date format @\"yyyy'-'MM'-'dd\"", dayString); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + + NSDateComponents *birthComponents = [[NSDateComponents alloc] init]; + birthComponents.year = year; + birthComponents.month = month; + birthComponents.day = day; + + [appboyInstance.user setDateOfBirth:[calendar dateFromComponents:birthComponents]]; + } else if ([key isEqualToString:mParticleUserAttributeCountry]) { + [appboyInstance.user setCountry:value]; + } else if ([key isEqualToString:mParticleUserAttributeCity]) { + [appboyInstance.user setHomeCity:value]; + } else if ([key isEqualToString:mParticleUserAttributeGender]) { + [appboyInstance.user setGender:BRZUserGender.other]; + if ([value isEqualToString:mParticleGenderMale]) { + [appboyInstance.user setGender:BRZUserGender.male]; + } else if ([value isEqualToString:mParticleGenderFemale]) { + [appboyInstance.user setGender:BRZUserGender.female]; + } else if ([value isEqualToString:mParticleGenderNotAvailable]) { + [appboyInstance.user setGender:BRZUserGender.notApplicable]; + } + } else if ([key isEqualToString:mParticleUserAttributeMobileNumber] || [key isEqualToString:@"$MPUserMobile"]) { + [appboyInstance.user setPhoneNumber:value]; + } else if ([key isEqualToString:mParticleUserAttributeZip]){ + [appboyInstance.user setCustomAttributeWithKey:@"Zip" stringValue:value]; + } else if ([key isEqualToString:brazeUserAttributeEmailSubscribe]) { + if([value isEqualToString:@"opted_in"]) { + [appboyInstance.user setEmailSubscriptionState:BRZUserSubscriptionStateOptedIn]; + } else if ([value isEqualToString:@"unsubscribed"]) { + [appboyInstance.user setEmailSubscriptionState:BRZUserSubscriptionStateUnsubscribed]; + } else if ([value isEqualToString:@"subscribed"]) { + [appboyInstance.user setEmailSubscriptionState:BRZUserSubscriptionStateSubscribed]; + } else { + NSLog(@"mParticle -> Invalid email_subscribe value: %@", value); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + } else if ([key isEqualToString:brazeUserAttributePushSubscribe]) { + if([value isEqualToString:@"opted_in"]) { + [appboyInstance.user setPushNotificationSubscriptionState:BRZUserSubscriptionStateOptedIn]; + } else if ([value isEqualToString:@"unsubscribed"]) { + [appboyInstance.user setPushNotificationSubscriptionState:BRZUserSubscriptionStateUnsubscribed]; + } else if ([value isEqualToString:@"subscribed"]) { + [appboyInstance.user setPushNotificationSubscriptionState:BRZUserSubscriptionStateSubscribed]; + } else { + NSLog(@"mParticle -> Invalid push_subscribe value: %@", value); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + } else if (subscriptionGroupDictionary[key]){ + NSString *subscriptionGroupId = subscriptionGroupDictionary[key]; + if ([value isEqualToString:@"1"]) { + [appboyInstance.user addToSubscriptionGroupWithGroupId:subscriptionGroupId]; + } else if ([value isEqualToString:@"0"]) { + [appboyInstance.user removeFromSubscriptionGroupWithGroupId:subscriptionGroupId]; + } else { + NSLog(@"mParticle -> Invalid value type for subscriptionGroupId mapped user attribute key: %@, expected value should be of type BOOL", key); + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + return execStatus; + } + } else { + key = [self stripCharacter:@"$" fromString:key]; + + if (!_enableTypeDetection) { + [appboyInstance.user setCustomAttributeWithKey:key stringValue:value]; + } else { + NSDictionary *tempConversionDictionary = @{key: value}; + tempConversionDictionary = [self simplifiedDictionary:tempConversionDictionary]; + id obj = tempConversionDictionary[key]; + if ([obj isKindOfClass:[NSString class]]) { + [appboyInstance.user setCustomAttributeWithKey:key stringValue:obj]; + } else if ([obj isKindOfClass:[NSNumber class]]) { + if ([self isBoolNumber:obj]) { + [appboyInstance.user setCustomAttributeWithKey:key boolValue:((NSNumber *)obj).boolValue]; + } else if ([self isInteger:value]) { + [appboyInstance.user setCustomAttributeWithKey:key intValue:((NSNumber *)obj).intValue]; + } else if ([self isFloat:value]) { + [appboyInstance.user setCustomAttributeWithKey:key doubleValue:((NSNumber *)obj).doubleValue]; + } + } else if ([obj isKindOfClass:[NSDate class]]) { + [appboyInstance.user setCustomAttributeWithKey:key dateValue:obj]; + } + } + } + + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + return execStatus; +} + +- (nonnull MPKitExecStatus *)setUserAttribute:(nonnull NSString *)key values:(nonnull NSArray *)values { + MPKitExecStatus *execStatus; + + if (!values) { + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeFail]; + } else { + [appboyInstance.user setCustomAttributeArrayWithKey:key array:values]; + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + } + + return execStatus; +} + +- (nonnull MPKitExecStatus *)onIdentifyComplete:(FilteredMParticleUser *)user request:(FilteredMPIdentityApiRequest *)request { + return [self updateUser:user request:request.userIdentities]; +} + +- (nonnull MPKitExecStatus *)onLoginComplete:(FilteredMParticleUser *)user request:(FilteredMPIdentityApiRequest *)request { + return [self updateUser:user request:request.userIdentities]; +} + +- (nonnull MPKitExecStatus *)onLogoutComplete:(FilteredMParticleUser *)user request:(FilteredMPIdentityApiRequest *)request { + return [self updateUser:user request:request.userIdentities]; +} + +- (nonnull MPKitExecStatus *)onModifyComplete:(FilteredMParticleUser *)user request:(FilteredMPIdentityApiRequest *)request { + return [self updateUser:user request:request.userIdentities]; +} + +- (nonnull MPKitExecStatus *)updateUser:(FilteredMParticleUser *)user request:(NSDictionary *)userIdentities { + MPKitExecStatus *execStatus = nil; + + if (userIdentities) { + NSMutableDictionary *userIDsCopy = [userIdentities copy]; + NSString *userId; + + if (_configuration[userIdTypeKey]) { + NSString *userIdKey = _configuration[userIdTypeKey]; + if ([userIdKey isEqualToString:userIdValueOther]) { + if (userIDsCopy[@(MPUserIdentityOther)]) { + userId = userIDsCopy[@(MPUserIdentityOther)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther2]) { + if (userIDsCopy[@(MPUserIdentityOther2)]) { + userId = userIDsCopy[@(MPUserIdentityOther2)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther3]) { + if (userIDsCopy[@(MPUserIdentityOther3)]) { + userId = userIDsCopy[@(MPUserIdentityOther3)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther4]) { + if (userIDsCopy[@(MPUserIdentityOther4)]) { + userId = userIDsCopy[@(MPUserIdentityOther4)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther5]) { + if (userIDsCopy[@(MPUserIdentityOther5)]) { + userId = userIDsCopy[@(MPUserIdentityOther5)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther6]) { + if (userIDsCopy[@(MPUserIdentityOther6)]) { + userId = userIDsCopy[@(MPUserIdentityOther6)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther7]) { + if (userIDsCopy[@(MPUserIdentityOther7)]) { + userId = userIDsCopy[@(MPUserIdentityOther7)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther8]) { + if (userIDsCopy[@(MPUserIdentityOther8)]) { + userId = userIDsCopy[@(MPUserIdentityOther8)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther9]) { + if (userIDsCopy[@(MPUserIdentityOther9)]) { + userId = userIDsCopy[@(MPUserIdentityOther9)]; + } + } else if ([userIdKey isEqualToString:userIdValueOther10]) { + if (userIDsCopy[@(MPUserIdentityOther10)]) { + userId = userIDsCopy[@(MPUserIdentityOther10)]; + } + } else if ([userIdKey isEqualToString:userIdValueCustomerId]) { + if (userIDsCopy[@(MPUserIdentityCustomerId)]) { + userId = userIDsCopy[@(MPUserIdentityCustomerId)]; + } + } else if ([userIdKey isEqualToString:userIdValueFacebook]) { + if (userIDsCopy[@(MPUserIdentityFacebook)]) { + userId = userIDsCopy[@(MPUserIdentityFacebook)]; + } + } else if ([userIdKey isEqualToString:userIdValueTwitter]) { + if (userIDsCopy[@(MPUserIdentityTwitter)]) { + userId = userIDsCopy[@(MPUserIdentityTwitter)]; + } + } else if ([userIdKey isEqualToString:userIdValueGoogle]) { + if (userIDsCopy[@(MPUserIdentityGoogle)]) { + userId = userIDsCopy[@(MPUserIdentityGoogle)]; + } + } else if ([userIdKey isEqualToString:userIdValueMicrosoft]) { + if (userIDsCopy[@(MPUserIdentityMicrosoft)]) { + userId = userIDsCopy[@(MPUserIdentityMicrosoft)]; + } + } else if ([userIdKey isEqualToString:userIdValueYahoo]) { + if (userIDsCopy[@(MPUserIdentityYahoo)]) { + userId = userIDsCopy[@(MPUserIdentityYahoo)]; + } + } else if ([userIdKey isEqualToString:userIdValueEmail]) { + if (userIDsCopy[@(MPUserIdentityEmail)]) { + userId = userIDsCopy[@(MPUserIdentityEmail)]; + } + } else if ([userIdKey isEqualToString:userIdValueAlias]) { + if (userIDsCopy[@(MPUserIdentityAlias)]) { + userId = userIDsCopy[@(MPUserIdentityAlias)]; + } + } else if ([userIdKey isEqualToString:userIdValueMPID]) { + if (user != nil) { + userId = user.userId.stringValue; + } + } else { + if (userIDsCopy[@(MPUserIdentityCustomerId)]) { + userId = userIDsCopy[@(MPUserIdentityCustomerId)]; + } + } + } + + if (userId && ![userId isKindOfClass: [NSNull class]]) { + void (^changeUser)(void) = ^ { + [self->appboyInstance changeUser:userId]; + }; + + if ([NSThread isMainThread]) { + changeUser(); + } else { + dispatch_async(dispatch_get_main_queue(), changeUser); + } + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + } + + NSString *userEmail; + + if (_configuration[emailIdTypeKey]) { + NSString *emailIdKey = _configuration[emailIdTypeKey]; + if ([emailIdKey isEqualToString:userIdValueOther]) { + if (userIDsCopy[@(MPUserIdentityOther)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther2]) { + if (userIDsCopy[@(MPUserIdentityOther2)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther2)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther3]) { + if (userIDsCopy[@(MPUserIdentityOther3)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther3)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther4]) { + if (userIDsCopy[@(MPUserIdentityOther4)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther4)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther5]) { + if (userIDsCopy[@(MPUserIdentityOther5)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther5)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther6]) { + if (userIDsCopy[@(MPUserIdentityOther6)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther6)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther7]) { + if (userIDsCopy[@(MPUserIdentityOther7)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther7)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther8]) { + if (userIDsCopy[@(MPUserIdentityOther8)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther8)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther9]) { + if (userIDsCopy[@(MPUserIdentityOther9)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther9)]; + } + } else if ([emailIdKey isEqualToString:userIdValueOther10]) { + if (userIDsCopy[@(MPUserIdentityOther10)]) { + userEmail = userIDsCopy[@(MPUserIdentityOther10)]; + } + } else if ([emailIdKey isEqualToString:userIdValueEmail]) { + if (userIDsCopy[@(MPUserIdentityEmail)]) { + userEmail = userIDsCopy[@(MPUserIdentityEmail)]; + } + } else { + if (userIDsCopy[@(MPUserIdentityEmail)]) { + userEmail = userIDsCopy[@(MPUserIdentityEmail)]; + } + } + } + + if (userEmail && ![userEmail isKindOfClass: [NSNull class]]) { + [appboyInstance.user setEmail:userEmail]; + execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + } + } + + return execStatus; +} + +- (MPKitExecStatus *)setUserIdentity:(NSString *)identityString identityType:(MPUserIdentity)identityType { + return [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; +} + +#if TARGET_OS_IOS +- (nonnull MPKitExecStatus *)userNotificationCenter:(nonnull UNUserNotificationCenter *)center willPresentNotification:(nonnull UNNotification *)notification { + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + + if (shouldDisableNotificationHandling) { + return execStatus; + } + + if (![appboyInstance.notifications handleBackgroundNotificationWithUserInfo:notification.request.content.userInfo fetchCompletionHandler:^(UIBackgroundFetchResult fetchResult) {}]) { + NSLog(@"mParticle -> Invalid Braze remote notification: %@", notification.request.content.userInfo); + } + + return execStatus; +} + +- (nonnull MPKitExecStatus *)userNotificationCenter:(nonnull UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response API_AVAILABLE(ios(10.0)) { + MPKitExecStatus *execStatus = [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; + + if (shouldDisableNotificationHandling) { + return execStatus; + } + + if (![appboyInstance.notifications handleUserNotificationWithResponse:response withCompletionHandler:^{}]) { + NSLog(@"mParticle -> Notification Response rejected by Braze: %@", response); + } + + return execStatus; +} +#endif + +- (MPKitExecStatus *)setATTStatus:(MPATTAuthorizationStatus)status withATTStatusTimestampMillis:(NSNumber *)attStatusTimestampMillis { + BOOL isEnabled = status == MPATTAuthorizationStatusAuthorized; + [appboyInstance setAdTrackingEnabled:isEnabled]; + return [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; +} + +- (MPKitExecStatus *)setConsentState:(nullable MPConsentState *)state { + [self updateConsent]; + + return [[MPKitExecStatus alloc] initWithSDKCode:@(MPKitInstanceAppboy) returnCode:MPKitReturnCodeSuccess]; +} + +- (void)updateConsent { + MParticleUser *currentUser = [[[MParticle sharedInstance] identity] currentUser]; + NSDictionary *userConsentMap = currentUser.consentState.gdprConsentState; + + // Update from mParticle consent + if (self.configuration && self.configuration[MPConsentMappingSDKKey]) { + // Retrieve the array of Consent Map Dictionaries from the Config + NSData *objectData = [self.configuration[MPConsentMappingSDKKey] dataUsingEncoding:NSUTF8StringEncoding]; + NSArray *consentMappingArray = [NSJSONSerialization JSONObjectWithData:objectData + options:NSJSONReadingMutableContainers + error:nil]; + + // For each valid Consent Map check if mParticle has a corresponding consent setting and, if so, send to Braze + for (NSDictionary *consentMappingDict in consentMappingArray) { + NSString *consentPurpose = consentMappingDict[MPMapKey]; + if (consentMappingDict[MPValueKey] && userConsentMap[consentPurpose.lowercaseString]) { + NSString *brazeConsentName = consentMappingDict[MPValueKey]; + MPGDPRConsent *consent = userConsentMap[consentPurpose.lowercaseString]; + if ([brazeConsentName isEqualToString:MPGoogleAdUserDataKey]) { + [appboyInstance.user setCustomAttributeWithKey:BGoogleAdUserDataKey boolValue:consent.consented]; + } else if ([brazeConsentName isEqualToString:MPGoogleAdPersonalizationKey]) { + [appboyInstance.user setCustomAttributeWithKey:BGoogleAdPersonalizationKey boolValue:consent.consented]; + } + } + } + } +} + +#pragma mark Configuration Dictionary + +- (NSMutableDictionary *)simplifiedDictionary:(NSDictionary *)originalDictionary { + __block NSMutableDictionary *transformedDictionary = [[NSMutableDictionary alloc] init]; + + [originalDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + if ([value isKindOfClass:[NSString class]]) { + NSString *stringValue = (NSString *)value; + NSDate *dateValue = [MPKitAPI dateFromStringRFC3339:stringValue]; + if (dateValue) { + transformedDictionary[key] = dateValue; + } else if ([self isInteger:stringValue]) { + transformedDictionary[key] = [NSNumber numberWithInteger:[stringValue integerValue]]; + } else if ([self isFloat:stringValue]) { + transformedDictionary[key] = [NSNumber numberWithFloat:[stringValue floatValue]]; + } else if ([stringValue caseInsensitiveCompare:@"true"] == NSOrderedSame) { + transformedDictionary[key] = @YES; + } else if ([stringValue caseInsensitiveCompare:@"false"] == NSOrderedSame) { + transformedDictionary[key] = @NO; + } + else { + transformedDictionary[key] = stringValue; + } + } else if ([value isKindOfClass:[NSNumber class]]) { + transformedDictionary[key] = (NSNumber *)value; + } else if ([value isKindOfClass:[NSDate class]]) { + transformedDictionary[key] = (NSDate *)value; + } + }]; + + return transformedDictionary; +} + +- (BOOL) isInteger:(NSString *)string { + NSCharacterSet* nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + + if([string hasPrefix:@"-"]) { + NSString *absoluteString = [string stringByReplacingOccurrencesOfString:@"-" withString:@""]; + NSRange r = [absoluteString rangeOfCharacterFromSet: nonNumbers]; + + return r.location == NSNotFound && absoluteString.length > 0; + } else { + NSRange r = [string rangeOfCharacterFromSet: nonNumbers]; + + return r.location == NSNotFound && string.length > 0; + } +} + +- (BOOL) isFloat:(NSString *)string { + NSArray *numList = [string componentsSeparatedByString:@"."]; + + if (numList.count == 2) { + if ([self isInteger:numList[0]] && [self isInteger:numList[1]]) { + return true; + } + } + + return false; +} + +- (BOOL) isBoolNumber:(NSNumber *)num { + CFTypeID boolID = CFBooleanGetTypeID(); + CFTypeID numID = CFGetTypeID((__bridge CFTypeRef)(num)); + return numID == boolID; +} + +- (void)setEnableTypeDetection:(BOOL)enableTypeDetection { + _enableTypeDetection = enableTypeDetection; +} + +- (NSArray *)getProductListParameters:(NSArray *)products { + NSMutableArray *productArray = [[NSMutableArray alloc] init]; + for (MPProduct *product in products) { + // Add attributes from the products themselves + NSMutableDictionary *productDictionary = [[product beautifiedDictionaryRepresentation] mutableCopy]; + + if (product.userDefinedAttributes.count > 0) { + [productDictionary removeObjectsForKeys:[product.userDefinedAttributes allKeys]]; + [productDictionary setValue:product.userDefinedAttributes forKey:attributesKey]; + } + + // Adds the product dictionary to the product array being supplied to Braze + if (productDictionary) { + [productArray addObject:productDictionary]; + } + } + return productArray; +} + +- (NSArray *)getPromotionListParameters:(NSArray *)promotions { + NSMutableArray *promotionArray = [[NSMutableArray alloc] init]; + for (MPPromotion *promotion in promotions) { + // Add attributes from the promotions themselves + NSMutableDictionary *promotionDictionary = [[NSMutableDictionary alloc] init]; + promotionDictionary[@"Creative"] = promotion.creative; + promotionDictionary[@"Name"] = promotion.name; + promotionDictionary[@"Position"] = promotion.position; + promotionDictionary[@"Id"] = promotion.promotionId; + + // Adds the promotion dictionary to the promotion array being supplied to Braze + [promotionArray addObject:promotionDictionary]; + } + return promotionArray; +} + +- (NSArray *)getImpressionListParameters:(NSDictionary *> *)impressions { + NSMutableArray *impressionArray = [[NSMutableArray alloc] init]; + for (NSString *impressionName in impressions.allKeys) { + // Add attributes from the products themselves + NSMutableDictionary *impressionDictionary = [[NSMutableDictionary alloc] init]; + impressionDictionary[@"Product Impression List"] = impressionName; + NSArray *impressionProducts = [[impressions[impressionName] allObjects] copy]; + impressionDictionary[productKey] = [self getProductListParameters:impressionProducts]; + + // Adds the impression dictionary to the impression array being supplied to Braze + [impressionArray addObject:impressionDictionary]; + } + return impressionArray; +} + +- (NSString *)eventNameForAction:(MPCommerceEventAction)action { + NSArray *actionNames = @[@"add_to_cart", @"remove_from_cart", @"add_to_wishlist", @"remove_from_wishlist", @"checkout", @"checkout_option", @"click", @"view_detail", @"purchase", @"refund"]; + + if (action >= actionNames.count) { + return @"unknown"; + } + + return actionNames[(NSUInteger)action]; +} + +- (NSString *)eventNameForPromotionAction:(MPPromotionAction)action { + NSArray *actionNames = @[@"click", @"view"]; + + if (action >= actionNames.count) { + return @"unknown"; + } + + return actionNames[(NSUInteger)action]; +} + +@end diff --git a/kits/braze/braze-12/Sources/mParticle-Appboy/PrivacyInfo.xcprivacy b/kits/braze/braze-12/Sources/mParticle-Appboy/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..e08a130bc --- /dev/null +++ b/kits/braze/braze-12/Sources/mParticle-Appboy/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + diff --git a/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h b/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h new file mode 100644 index 000000000..9ba341edc --- /dev/null +++ b/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h @@ -0,0 +1,30 @@ +#import +#if defined(__has_include) && __has_include() + #import +#else + #import "mParticle.h" +#endif + +#if defined(__has_include) && __has_include() + #import +#else + #import BrazeKit-Swift.h +#endif + + +@interface MPKitAppboy : NSObject + +@property (nonatomic, strong, nonnull) NSDictionary *configuration; +@property (nonatomic, strong, nullable) NSDictionary *launchOptions; +@property (nonatomic, unsafe_unretained, readonly) BOOL started; +@property (nonatomic, strong, nullable) MPKitAPI *kitApi; + +#if TARGET_OS_IOS ++ (void)setInAppMessageControllerDelegate:(nonnull id)delegate; ++ (void)setShouldDisableNotificationHandling:(BOOL)isDisabled; +#endif ++ (void)setURLDelegate:(nonnull id)delegate; ++ (void)setBrazeInstance:(nonnull id)instance; ++ (void)setBrazeLocationProvider:(nonnull id)instance; ++ (void)setBrazeTrackingPropertyAllowList:(nonnull NSSet *)allowList; +@end diff --git a/kits/braze/braze-12/Sources/mParticle-Appboy/include/mParticle_Appboy.h b/kits/braze/braze-12/Sources/mParticle-Appboy/include/mParticle_Appboy.h new file mode 100644 index 000000000..829f2c83e --- /dev/null +++ b/kits/braze/braze-12/Sources/mParticle-Appboy/include/mParticle_Appboy.h @@ -0,0 +1,17 @@ +#import + +//! Project version number for mParticle-Appboy. +FOUNDATION_EXPORT double mParticle_AppboyVersionNumber; + +//! Project version string for mParticle-Appboy. +FOUNDATION_EXPORT const unsigned char mParticle_AppboyVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + +#if defined(__has_include) && __has_include() + #import +#elif defined(__has_include) && __has_include() + #import +#else + #import "MPKitAppboy.h" +#endif diff --git a/kits/braze/braze-12/mParticle-Appboy-tvOS/Info.plist b/kits/braze/braze-12/mParticle-Appboy-tvOS/Info.plist new file mode 100644 index 000000000..1007fd9dd --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy-tvOS/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/kits/braze/braze-12/mParticle-Appboy-tvOS/mParticle_Appboy_tvOS.h b/kits/braze/braze-12/mParticle-Appboy-tvOS/mParticle_Appboy_tvOS.h new file mode 100644 index 000000000..1674a2e7c --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy-tvOS/mParticle_Appboy_tvOS.h @@ -0,0 +1,12 @@ +#import + +//! Project version number for mParticle_Appboy_tvOS. +FOUNDATION_EXPORT double mParticle_Appboy_tvOSVersionNumber; + +//! Project version string for mParticle_Appboy_tvOS. +FOUNDATION_EXPORT const unsigned char mParticle_Appboy_tvOSVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + +#import diff --git a/kits/braze/braze-12/mParticle-Appboy.podspec b/kits/braze/braze-12/mParticle-Appboy.podspec new file mode 100755 index 000000000..42d787142 --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy.podspec @@ -0,0 +1,34 @@ +Pod::Spec.new do |s| + s.name = "mParticle-Appboy" + s.version = "8.13.2" + s.summary = "Appboy integration for mParticle" + + s.description = <<-DESC + This is the Appboy integration for mParticle. + DESC + + s.homepage = "https://www.mparticle.com" + s.license = { :type => 'Apache 2.0', :file => 'LICENSE' } + s.author = { "mParticle" => "support@mparticle.com" } + s.source = { :git => "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy.git", :tag => "v" + s.version.to_s } + s.social_media_url = "https://twitter.com/mparticle" + s.static_framework = true + s.swift_version = '5.3' + + s.ios.deployment_target = "12.0" + s.ios.source_files = 'Sources/**/*.{h,m,mm}' + s.ios.resource_bundles = { 'mParticle-Appboy-Privacy' => ['Sources/mParticle-Appboy/PrivacyInfo.xcprivacy'] } + s.ios.dependency 'mParticle-Apple-SDK', '~> 8.19' + s.ios.dependency 'BrazeKit', '~> 12.0' + s.ios.dependency 'BrazeKitCompat', '~> 12.0' + s.ios.dependency 'BrazeUI', '~> 12.0' + + s.tvos.deployment_target = "12.0" + s.tvos.source_files = 'Sources/**/*.{h,m,mm}' + s.tvos.resource_bundles = { 'mParticle-Appboy-Privacy' => ['Sources/mParticle-Appboy/PrivacyInfo.xcprivacy'] } + s.tvos.dependency 'mParticle-Apple-SDK', '~> 8.19' + s.tvos.dependency 'BrazeKit', '~> 12.0' + s.tvos.dependency 'BrazeKitCompat', '~> 12.0' + + +end diff --git a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj new file mode 100644 index 000000000..cace2b6d7 --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj @@ -0,0 +1,981 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 351557782F43A6AF006096E1 /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = 351557772F43A6AF006096E1 /* mParticle-Apple-SDK */; }; + 3515577A2F43A6CA006096E1 /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = 351557792F43A6CA006096E1 /* mParticle-Apple-SDK */; }; + 531861FF2A13E147006FFE90 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531861FE2A13E147006FFE90 /* AppDelegate.swift */; }; + 531862032A13E147006FFE90 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531862022A13E147006FFE90 /* ViewController.swift */; }; + 531862062A13E147006FFE90 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 531862042A13E147006FFE90 /* Main.storyboard */; }; + 531862082A13E14A006FFE90 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 531862072A13E14A006FFE90 /* Assets.xcassets */; }; + 5318620B2A13E14A006FFE90 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 531862092A13E14A006FFE90 /* LaunchScreen.storyboard */; }; + 5387EC002A18050500219E89 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5387EBFF2A18050500219E89 /* BrazeKit */; }; + 5387EC022A18051200219E89 /* BrazeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5387EC012A18051200219E89 /* BrazeKit */; }; + 539B2E952A13D62200C8339D /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = 539B2E942A13D62200C8339D /* OCMock */; }; + 539B2E9D2A13D69F00C8339D /* BrazeKitCompat in Frameworks */ = {isa = PBXBuildFile; productRef = 539B2E9C2A13D69F00C8339D /* BrazeKitCompat */; }; + 539B2E9F2A13D69F00C8339D /* BrazeUI in Frameworks */ = {isa = PBXBuildFile; productRef = 539B2E9E2A13D69F00C8339D /* BrazeUI */; }; + 539B2EA12A13D6AB00C8339D /* BrazeKitCompat in Frameworks */ = {isa = PBXBuildFile; productRef = 539B2EA02A13D6AB00C8339D /* BrazeKitCompat */; }; + D31A98A92153F73400358293 /* mParticle_AppboyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D31A98A82153F73400358293 /* mParticle_AppboyTests.m */; }; + D31A98AB2153F73400358293 /* mParticle_Appboy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB94016C1CB703F2007ABB18 /* mParticle_Appboy.framework */; }; + D34423302B960F44006CD046 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D344232F2B960F44006CD046 /* PrivacyInfo.xcprivacy */; }; + D34423312B960F44006CD046 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D344232F2B960F44006CD046 /* PrivacyInfo.xcprivacy */; }; + DB76F1CF25D2E71D00CAB3EB /* MPKitAppboy.h in Headers */ = {isa = PBXBuildFile; fileRef = DB76F1CB25D2E71D00CAB3EB /* MPKitAppboy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB76F1D025D2E71D00CAB3EB /* mParticle_Appboy.h in Headers */ = {isa = PBXBuildFile; fileRef = DB76F1CC25D2E71D00CAB3EB /* mParticle_Appboy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB76F1D125D2E71D00CAB3EB /* MPKitAppboy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB76F1CD25D2E71D00CAB3EB /* MPKitAppboy.m */; }; + DB76F1D225D2E71D00CAB3EB /* MPKitAppboy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB76F1CD25D2E71D00CAB3EB /* MPKitAppboy.m */; }; + DB76F1DB25D2E73700CAB3EB /* MPKitAppboy.m in Sources */ = {isa = PBXBuildFile; fileRef = DB76F1CD25D2E71D00CAB3EB /* MPKitAppboy.m */; }; + DB76F1DF25D2E74900CAB3EB /* MPKitAppboy.h in Headers */ = {isa = PBXBuildFile; fileRef = DB76F1CB25D2E71D00CAB3EB /* MPKitAppboy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DBDEDD9C209B8FD600DD3B9B /* mParticle_Appboy_tvOS.h in Headers */ = {isa = PBXBuildFile; fileRef = DBDEDD9A209B8FD600DD3B9B /* mParticle_Appboy_tvOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 531862102A13E17D006FFE90 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DB9401631CB703F2007ABB18 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 531861FB2A13E147006FFE90; + remoteInfo = AppboyTestHost; + }; + D31A98AC2153F73400358293 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DB9401631CB703F2007ABB18 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB94016B1CB703F2007ABB18; + remoteInfo = "mParticle-Appboy"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 531861FC2A13E147006FFE90 /* AppboyTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppboyTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 531861FE2A13E147006FFE90 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 531862022A13E147006FFE90 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 531862052A13E147006FFE90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 531862072A13E14A006FFE90 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 5318620A2A13E14A006FFE90 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 5318620C2A13E14A006FFE90 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D31A98A62153F73400358293 /* mParticle_AppboyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = mParticle_AppboyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D31A98A82153F73400358293 /* mParticle_AppboyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = mParticle_AppboyTests.m; sourceTree = ""; }; + D31A98AA2153F73400358293 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D344232F2B960F44006CD046 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + DB76F1CB25D2E71D00CAB3EB /* MPKitAppboy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPKitAppboy.h; sourceTree = ""; }; + DB76F1CC25D2E71D00CAB3EB /* mParticle_Appboy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mParticle_Appboy.h; sourceTree = ""; }; + DB76F1CD25D2E71D00CAB3EB /* MPKitAppboy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPKitAppboy.m; sourceTree = ""; }; + DB76F1CE25D2E71D00CAB3EB /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DB94016C1CB703F2007ABB18 /* mParticle_Appboy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = mParticle_Appboy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDD98209B8FD600DD3B9B /* mParticle_Appboy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = mParticle_Appboy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DBDEDD9A209B8FD600DD3B9B /* mParticle_Appboy_tvOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mParticle_Appboy_tvOS.h; sourceTree = ""; }; + DBDEDD9B209B8FD600DD3B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DBDEDDA5209BA36900DD3B9B /* mParticle_Apple_SDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mParticle_Apple_SDK.framework; path = Carthage/Build/tvOS/mParticle_Apple_SDK.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 531861F92A13E147006FFE90 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D31A98A32153F73400358293 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 539B2E952A13D62200C8339D /* OCMock in Frameworks */, + D31A98AB2153F73400358293 /* mParticle_Appboy.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB9401681CB703F2007ABB18 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5387EC022A18051200219E89 /* BrazeKit in Frameworks */, + 539B2E9F2A13D69F00C8339D /* BrazeUI in Frameworks */, + 351557782F43A6AF006096E1 /* mParticle-Apple-SDK in Frameworks */, + 539B2E9D2A13D69F00C8339D /* BrazeKitCompat in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDD94209B8FD600DD3B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 539B2EA12A13D6AB00C8339D /* BrazeKitCompat in Frameworks */, + 3515577A2F43A6CA006096E1 /* mParticle-Apple-SDK in Frameworks */, + 5387EC002A18050500219E89 /* BrazeKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 531861FD2A13E147006FFE90 /* AppboyTestHost */ = { + isa = PBXGroup; + children = ( + 531861FE2A13E147006FFE90 /* AppDelegate.swift */, + 531862022A13E147006FFE90 /* ViewController.swift */, + 531862042A13E147006FFE90 /* Main.storyboard */, + 531862072A13E14A006FFE90 /* Assets.xcassets */, + 531862092A13E14A006FFE90 /* LaunchScreen.storyboard */, + 5318620C2A13E14A006FFE90 /* Info.plist */, + ); + path = AppboyTestHost; + sourceTree = ""; + }; + D31A98A72153F73400358293 /* mParticle_AppboyTests */ = { + isa = PBXGroup; + children = ( + D31A98A82153F73400358293 /* mParticle_AppboyTests.m */, + D31A98AA2153F73400358293 /* Info.plist */, + ); + path = mParticle_AppboyTests; + sourceTree = ""; + }; + DB76F1C825D2E71D00CAB3EB /* Sources */ = { + isa = PBXGroup; + children = ( + DB76F1C925D2E71D00CAB3EB /* mParticle-Appboy */, + DB76F1CE25D2E71D00CAB3EB /* Info.plist */, + ); + path = Sources; + sourceTree = ""; + }; + DB76F1C925D2E71D00CAB3EB /* mParticle-Appboy */ = { + isa = PBXGroup; + children = ( + DB76F1CA25D2E71D00CAB3EB /* include */, + DB76F1CD25D2E71D00CAB3EB /* MPKitAppboy.m */, + D344232F2B960F44006CD046 /* PrivacyInfo.xcprivacy */, + ); + path = "mParticle-Appboy"; + sourceTree = ""; + }; + DB76F1CA25D2E71D00CAB3EB /* include */ = { + isa = PBXGroup; + children = ( + DB76F1CB25D2E71D00CAB3EB /* MPKitAppboy.h */, + DB76F1CC25D2E71D00CAB3EB /* mParticle_Appboy.h */, + ); + path = include; + sourceTree = ""; + }; + DB9401621CB703F2007ABB18 = { + isa = PBXGroup; + children = ( + DB76F1C825D2E71D00CAB3EB /* Sources */, + DBDEDD99209B8FD600DD3B9B /* mParticle-Appboy-tvOS */, + D31A98A72153F73400358293 /* mParticle_AppboyTests */, + 531861FD2A13E147006FFE90 /* AppboyTestHost */, + DB94016D1CB703F2007ABB18 /* Products */, + DBDEDDA3209BA34E00DD3B9B /* Frameworks */, + ); + sourceTree = ""; + }; + DB94016D1CB703F2007ABB18 /* Products */ = { + isa = PBXGroup; + children = ( + DB94016C1CB703F2007ABB18 /* mParticle_Appboy.framework */, + DBDEDD98209B8FD600DD3B9B /* mParticle_Appboy.framework */, + D31A98A62153F73400358293 /* mParticle_AppboyTests.xctest */, + 531861FC2A13E147006FFE90 /* AppboyTestHost.app */, + ); + name = Products; + sourceTree = ""; + }; + DBDEDD99209B8FD600DD3B9B /* mParticle-Appboy-tvOS */ = { + isa = PBXGroup; + children = ( + DBDEDD9A209B8FD600DD3B9B /* mParticle_Appboy_tvOS.h */, + DBDEDD9B209B8FD600DD3B9B /* Info.plist */, + ); + path = "mParticle-Appboy-tvOS"; + sourceTree = ""; + }; + DBDEDDA3209BA34E00DD3B9B /* Frameworks */ = { + isa = PBXGroup; + children = ( + DBDEDDA5209BA36900DD3B9B /* mParticle_Apple_SDK.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + DB9401691CB703F2007ABB18 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DB76F1CF25D2E71D00CAB3EB /* MPKitAppboy.h in Headers */, + DB76F1D025D2E71D00CAB3EB /* mParticle_Appboy.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDD95209B8FD600DD3B9B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DB76F1DF25D2E74900CAB3EB /* MPKitAppboy.h in Headers */, + DBDEDD9C209B8FD600DD3B9B /* mParticle_Appboy_tvOS.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 531861FB2A13E147006FFE90 /* AppboyTestHost */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5318620D2A13E14A006FFE90 /* Build configuration list for PBXNativeTarget "AppboyTestHost" */; + buildPhases = ( + 531861F82A13E147006FFE90 /* Sources */, + 531861F92A13E147006FFE90 /* Frameworks */, + 531861FA2A13E147006FFE90 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AppboyTestHost; + productName = AppboyTestHost; + productReference = 531861FC2A13E147006FFE90 /* AppboyTestHost.app */; + productType = "com.apple.product-type.application"; + }; + D31A98A52153F73400358293 /* mParticle_AppboyTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D31A98B02153F73400358293 /* Build configuration list for PBXNativeTarget "mParticle_AppboyTests" */; + buildPhases = ( + D31A98A22153F73400358293 /* Sources */, + D31A98A32153F73400358293 /* Frameworks */, + D31A98A42153F73400358293 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 539B2EA52A13D95200C8339D /* PBXTargetDependency */, + 539B2EA32A13D94E00C8339D /* PBXTargetDependency */, + D31A98AD2153F73400358293 /* PBXTargetDependency */, + 531862112A13E17D006FFE90 /* PBXTargetDependency */, + ); + name = mParticle_AppboyTests; + packageProductDependencies = ( + 539B2E942A13D62200C8339D /* OCMock */, + ); + productName = mParticle_AppboyTests; + productReference = D31A98A62153F73400358293 /* mParticle_AppboyTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DB94016B1CB703F2007ABB18 /* mParticle-Appboy */ = { + isa = PBXNativeTarget; + buildConfigurationList = DB9401741CB703F2007ABB18 /* Build configuration list for PBXNativeTarget "mParticle-Appboy" */; + buildPhases = ( + DB9401671CB703F2007ABB18 /* Sources */, + DB9401681CB703F2007ABB18 /* Frameworks */, + DB9401691CB703F2007ABB18 /* Headers */, + DB94016A1CB703F2007ABB18 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "mParticle-Appboy"; + packageProductDependencies = ( + 539B2E9C2A13D69F00C8339D /* BrazeKitCompat */, + 539B2E9E2A13D69F00C8339D /* BrazeUI */, + 5387EC012A18051200219E89 /* BrazeKit */, + 351557772F43A6AF006096E1 /* mParticle-Apple-SDK */, + ); + productName = "mParticle-Appboy"; + productReference = DB94016C1CB703F2007ABB18 /* mParticle_Appboy.framework */; + productType = "com.apple.product-type.framework"; + }; + DBDEDD97209B8FD600DD3B9B /* mParticle-Appboy-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = DBDEDD9F209B8FD600DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS" */; + buildPhases = ( + DBDEDD93209B8FD600DD3B9B /* Sources */, + DBDEDD94209B8FD600DD3B9B /* Frameworks */, + DBDEDD95209B8FD600DD3B9B /* Headers */, + DBDEDD96209B8FD600DD3B9B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "mParticle-Appboy-tvOS"; + packageProductDependencies = ( + 539B2EA02A13D6AB00C8339D /* BrazeKitCompat */, + 5387EBFF2A18050500219E89 /* BrazeKit */, + 351557792F43A6CA006096E1 /* mParticle-Apple-SDK */, + ); + productName = "mParticle-Appboy-tvOS"; + productReference = DBDEDD98209B8FD600DD3B9B /* mParticle_Appboy.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + DB9401631CB703F2007ABB18 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1430; + LastUpgradeCheck = 1200; + ORGANIZATIONNAME = mParticle; + TargetAttributes = { + 531861FB2A13E147006FFE90 = { + CreatedOnToolsVersion = 14.3; + }; + D31A98A52153F73400358293 = { + CreatedOnToolsVersion = 10.0; + ProvisioningStyle = Automatic; + TestTargetID = 531861FB2A13E147006FFE90; + }; + DB94016B1CB703F2007ABB18 = { + CreatedOnToolsVersion = 7.3; + DevelopmentTeam = Q948K5LXGZ; + }; + DBDEDD97209B8FD600DD3B9B = { + CreatedOnToolsVersion = 9.3; + DevelopmentTeam = DLD43Y3TRP; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = DB9401661CB703F2007ABB18 /* Build configuration list for PBXProject "mParticle-Appboy" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = DB9401621CB703F2007ABB18; + packageReferences = ( + 539B2E932A13D62200C8339D /* XCRemoteSwiftPackageReference "ocmock" */, + 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */, + 351557762F43A6AF006096E1 /* XCLocalSwiftPackageReference "../../../../mparticle-apple-sdk" */, + ); + productRefGroup = DB94016D1CB703F2007ABB18 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + DB94016B1CB703F2007ABB18 /* mParticle-Appboy */, + DBDEDD97209B8FD600DD3B9B /* mParticle-Appboy-tvOS */, + D31A98A52153F73400358293 /* mParticle_AppboyTests */, + 531861FB2A13E147006FFE90 /* AppboyTestHost */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 531861FA2A13E147006FFE90 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5318620B2A13E14A006FFE90 /* LaunchScreen.storyboard in Resources */, + 531862082A13E14A006FFE90 /* Assets.xcassets in Resources */, + 531862062A13E147006FFE90 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D31A98A42153F73400358293 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB94016A1CB703F2007ABB18 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D34423302B960F44006CD046 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDD96209B8FD600DD3B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D34423312B960F44006CD046 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 531861F82A13E147006FFE90 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 531862032A13E147006FFE90 /* ViewController.swift in Sources */, + 531861FF2A13E147006FFE90 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D31A98A22153F73400358293 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB76F1D225D2E71D00CAB3EB /* MPKitAppboy.m in Sources */, + D31A98A92153F73400358293 /* mParticle_AppboyTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB9401671CB703F2007ABB18 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB76F1D125D2E71D00CAB3EB /* MPKitAppboy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBDEDD93209B8FD600DD3B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB76F1DB25D2E73700CAB3EB /* MPKitAppboy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 531862112A13E17D006FFE90 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 531861FB2A13E147006FFE90 /* AppboyTestHost */; + targetProxy = 531862102A13E17D006FFE90 /* PBXContainerItemProxy */; + }; + 539B2EA32A13D94E00C8339D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = 539B2EA22A13D94E00C8339D /* BrazeKitCompat */; + }; + 539B2EA52A13D95200C8339D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = 539B2EA42A13D95200C8339D /* BrazeUI */; + }; + D31A98AD2153F73400358293 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB94016B1CB703F2007ABB18 /* mParticle-Appboy */; + targetProxy = D31A98AC2153F73400358293 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 531862042A13E147006FFE90 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 531862052A13E147006FFE90 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 531862092A13E14A006FFE90 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 5318620A2A13E14A006FFE90 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 5318620E2A13E14A006FFE90 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AppboyTestHost/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.mparticle.AppboyTestHost; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Debug; + }; + 5318620F2A13E14A006FFE90 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = AppboyTestHost/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.mparticle.AppboyTestHost; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Release; + }; + D31A98AE2153F73400358293 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = mParticle_AppboyTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-AppboyTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppboyTestHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppboyTestHost"; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Debug; + }; + D31A98AF2153F73400358293 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = mParticle_AppboyTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-AppboyTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppboyTestHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppboyTestHost"; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Release; + }; + DB9401721CB703F2007ABB18 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = 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_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 = NO; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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 = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 11.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DB9401731CB703F2007ABB18 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = 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_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 = NO; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 11.0; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DB9401751CB703F2007ABB18 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Sources/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Debug; + }; + DB9401761CB703F2007ABB18 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Sources/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 12.0; + }; + name = Release; + }; + DBDEDD9D209B8FD600DD3B9B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = DLD43Y3TRP; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "mParticle-Appboy-tvOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + OTHER_LDFLAGS = ( + "-ObjC", + "-all_load", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS"; + PRODUCT_NAME = mParticle_Appboy; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 15.6; + }; + name = Debug; + }; + DBDEDD9E209B8FD600DD3B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = DLD43Y3TRP; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "mParticle-Appboy-tvOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + OTHER_LDFLAGS = ( + "-ObjC", + "-all_load", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy-tvOS"; + PRODUCT_NAME = mParticle_Appboy; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 15.6; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5318620D2A13E14A006FFE90 /* Build configuration list for PBXNativeTarget "AppboyTestHost" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5318620E2A13E14A006FFE90 /* Debug */, + 5318620F2A13E14A006FFE90 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D31A98B02153F73400358293 /* Build configuration list for PBXNativeTarget "mParticle_AppboyTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D31A98AE2153F73400358293 /* Debug */, + D31A98AF2153F73400358293 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DB9401661CB703F2007ABB18 /* Build configuration list for PBXProject "mParticle-Appboy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB9401721CB703F2007ABB18 /* Debug */, + DB9401731CB703F2007ABB18 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DB9401741CB703F2007ABB18 /* Build configuration list for PBXNativeTarget "mParticle-Appboy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB9401751CB703F2007ABB18 /* Debug */, + DB9401761CB703F2007ABB18 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DBDEDD9F209B8FD600DD3B9B /* Build configuration list for PBXNativeTarget "mParticle-Appboy-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBDEDD9D209B8FD600DD3B9B /* Debug */, + DBDEDD9E209B8FD600DD3B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 351557762F43A6AF006096E1 /* XCLocalSwiftPackageReference "../../../../mparticle-apple-sdk" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "../../../../mparticle-apple-sdk"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 539B2E932A13D62200C8339D /* XCRemoteSwiftPackageReference "ocmock" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/erikdoe/ocmock"; + requirement = { + branch = master; + kind = branch; + }; + }; + 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/braze-inc/braze-swift-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 9.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 351557772F43A6AF006096E1 /* mParticle-Apple-SDK */ = { + isa = XCSwiftPackageProductDependency; + productName = "mParticle-Apple-SDK"; + }; + 351557792F43A6CA006096E1 /* mParticle-Apple-SDK */ = { + isa = XCSwiftPackageProductDependency; + package = 351557762F43A6AF006096E1 /* XCLocalSwiftPackageReference "../../../../mparticle-apple-sdk" */; + productName = "mParticle-Apple-SDK"; + }; + 5387EBFF2A18050500219E89 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeKit; + }; + 5387EC012A18051200219E89 /* BrazeKit */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeKit; + }; + 539B2E942A13D62200C8339D /* OCMock */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E932A13D62200C8339D /* XCRemoteSwiftPackageReference "ocmock" */; + productName = OCMock; + }; + 539B2E9C2A13D69F00C8339D /* BrazeKitCompat */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeKitCompat; + }; + 539B2E9E2A13D69F00C8339D /* BrazeUI */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeUI; + }; + 539B2EA02A13D6AB00C8339D /* BrazeKitCompat */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeKitCompat; + }; + 539B2EA22A13D94E00C8339D /* BrazeKitCompat */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeKitCompat; + }; + 539B2EA42A13D95200C8339D /* BrazeUI */ = { + isa = XCSwiftPackageProductDependency; + package = 539B2E9B2A13D69F00C8339D /* XCRemoteSwiftPackageReference "braze-swift-sdk" */; + productName = BrazeUI; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = DB9401631CB703F2007ABB18 /* Project object */; +} diff --git a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy-tvOS.xcscheme b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy-tvOS.xcscheme new file mode 100644 index 000000000..abc83a0ff --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy-tvOS.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy.xcscheme b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy.xcscheme new file mode 100644 index 000000000..8df0b6d08 --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle-Appboy.xcscheme @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle_AppboyTests.xcscheme b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle_AppboyTests.xcscheme new file mode 100644 index 000000000..431d9a6d0 --- /dev/null +++ b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/xcshareddata/xcschemes/mParticle_AppboyTests.xcscheme @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/kits/braze/braze-12/mParticle_Appboy.json b/kits/braze/braze-12/mParticle_Appboy.json new file mode 100644 index 000000000..581feef6c --- /dev/null +++ b/kits/braze/braze-12/mParticle_Appboy.json @@ -0,0 +1,13 @@ +{ + "7.7.4": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.7.4/mParticle_Appboy.framework.zip", + "7.7.5": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.7.5/mParticle_Appboy.framework.zip", + "7.8.0": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.0/mParticle_Appboy.framework.zip", + "7.8.1": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.1/mParticle_Appboy.framework.zip", + "7.8.2": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.2/mParticle_Appboy.framework.zip", + "7.8.3": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.3/mParticle_Appboy.framework.zip", + "7.8.4": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.4/mParticle_Appboy.framework.zip", + "7.8.5": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.5/mParticle_Appboy.framework.zip", + "7.8.6": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.8.6/mParticle_Appboy.framework.zip", + "7.9.0": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.9.0/mParticle_Appboy.framework.zip", + "7.9.1": "https://github.com/mparticle-integrations/mparticle-apple-integration-appboy/releases/download/7.9.1/mParticle_Appboy.framework.zip" +} diff --git a/kits/braze/braze-12/mParticle_AppboyTests/Info.plist b/kits/braze/braze-12/mParticle_AppboyTests/Info.plist new file mode 100644 index 000000000..6c40a6cd0 --- /dev/null +++ b/kits/braze/braze-12/mParticle_AppboyTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/kits/braze/braze-12/mParticle_AppboyTests/mParticle_AppboyTests.m b/kits/braze/braze-12/mParticle_AppboyTests/mParticle_AppboyTests.m new file mode 100644 index 000000000..0e1cd3429 --- /dev/null +++ b/kits/braze/braze-12/mParticle_AppboyTests/mParticle_AppboyTests.m @@ -0,0 +1,1065 @@ +@import mParticle_Apple_SDK; +@import mParticle_Appboy; +@import XCTest; +@import OCMock; +#if TARGET_OS_IOS + @import BrazeKitCompat; + @import BrazeUI; +#else + @import BrazeKitCompat; +#endif + +@interface MPKitAppboy () + +- (Braze *)appboyInstance; +- (void)setAppboyInstance:(Braze *)instance; +- (NSMutableDictionary *)optionsDictionary; ++ (id)inAppMessageControllerDelegate; +- (void)setEnableTypeDetection:(BOOL)enableTypeDetection; ++ (BOOL)shouldDisableNotificationHandling; ++ (Braze *)brazeInstance; ++ (MPKitExecStatus *)updateUser:(FilteredMParticleUser *)user request:(NSDictionary *)userIdentities; ++ (MPKitExecStatus *)setUserAttribute:(NSString *)key value:(NSString *)value; + +@end + +@interface mParticle_AppboyTests : XCTestCase + +@end + +@implementation mParticle_AppboyTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. + [MPKitAppboy setBrazeInstance:nil]; + [MPKitAppboy setURLDelegate:nil]; +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testStartwithSimpleConfig { + MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; + + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42 + }; + + [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; + + NSDictionary *testOptionsDictionary = @{ABKEnableAutomaticLocationCollectionKey:@(YES), + ABKSDKFlavorKey:@7 + }; + + NSDictionary *optionsDictionary = [appBoy optionsDictionary]; + XCTAssertEqualObjects(optionsDictionary, testOptionsDictionary); +} + +- (void)testStartwithAdvancedConfig { + MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; + + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"CustomerId" + }; + + [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; + + NSDictionary *testOptionsDictionary = @{ABKEnableAutomaticLocationCollectionKey:@(YES), + ABKSDKFlavorKey:@7, + @"ABKRquestProcessingPolicy": @(1), + @"ABKFlushInterval":@(2), + @"ABKSessionTimeout":@(3), + @"ABKMinimumTriggerTimeInterval":@(4) + }; + + NSDictionary *optionsDictionary = [appBoy optionsDictionary]; + XCTAssertEqualObjects(optionsDictionary, testOptionsDictionary); +} + +- (void)testMpidForwardingOnStartUserIdZero { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + MParticleUser *testUser = [[MParticleUser alloc] init]; + [testUser setValue:@(0) forKey:@"userId"]; + + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:testUser kitConfiguration:kitConfiguration]; + id mockKitApi = OCMClassMock([MPKitAPI class]); + OCMStub([mockKitApi getCurrentUserWithKit:kitInstance]).andReturn(filteredUser); + kitInstance.kitApi = mockKitApi; + + id mockKitInstance = OCMPartialMock(kitInstance); + [[mockKitInstance reject] updateUser:[OCMArg any] request:[OCMArg any]]; + [kitInstance start]; + [mockKitInstance verify]; +} + +- (void)testMpidForwardingOnStartUserIdPositive { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + MParticleUser *testUser = [[MParticleUser alloc] init]; + [testUser setValue:@(1) forKey:@"userId"]; + + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:testUser kitConfiguration:kitConfiguration]; + id mockKitApi = OCMClassMock([MPKitAPI class]); + OCMStub([mockKitApi getCurrentUserWithKit:kitInstance]).andReturn(filteredUser); + kitInstance.kitApi = mockKitApi; + + id mockKitInstance = OCMPartialMock(kitInstance); + [[mockKitInstance expect] updateUser:[OCMArg any] request:[OCMArg any]]; + [kitInstance start]; + [mockKitInstance verify]; +} + +- (void)testMpidForwardingOnStartUserIdNegative { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + MParticleUser *testUser = [[MParticleUser alloc] init]; + [testUser setValue:@(-1) forKey:@"userId"]; + + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:testUser kitConfiguration:kitConfiguration]; + id mockKitApi = OCMClassMock([MPKitAPI class]); + OCMStub([mockKitApi getCurrentUserWithKit:kitInstance]).andReturn(filteredUser); + kitInstance.kitApi = mockKitApi; + + id mockKitInstance = OCMPartialMock(kitInstance); + [[mockKitInstance expect] updateUser:[OCMArg any] request:[OCMArg any]]; + [kitInstance start]; + [mockKitInstance verify]; +} + +- (void)testEmailSubscribtionUserAttribute { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kitInstance setAppboyInstance:mockClient]; + XCTAssertEqualObjects(mockClient, [kitInstance appboyInstance]); + + // Should succeed since opted_in is a valid value + MPKitExecStatus *execStatus1 = [kitInstance setUserAttribute:@"email_subscribe" value:@"opted_in"]; + XCTAssertEqual(execStatus1.returnCode, MPKitReturnCodeSuccess); + // Should fail since testValue is an invalid value + MPKitExecStatus *execStatus2 = [kitInstance setUserAttribute:@"email_subscribe" value:@"testValue"]; + XCTAssertEqual(execStatus2.returnCode, MPKitReturnCodeFail); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testPushSubscribtionUserAttribute { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kitInstance setAppboyInstance:mockClient]; + XCTAssertEqualObjects(mockClient, [kitInstance appboyInstance]); + + // Should succeed since opted_in is a valid value + MPKitExecStatus *execStatus1 = [kitInstance setUserAttribute:@"push_subscribe" value:@"opted_in"]; + XCTAssertEqual(execStatus1.returnCode, MPKitReturnCodeSuccess); + // Should fail since testValue is an invalid value + MPKitExecStatus *execStatus2 = [kitInstance setUserAttribute:@"push_subscribe" value:@"testValue"]; + XCTAssertEqual(execStatus2.returnCode, MPKitReturnCodeFail); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testSubscriptionGroupIdsMappedUserAttributes { + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID", + @"subscriptionGroupMapping" : @"[{\"jsmap\":null,\"map\":\"testAttribute1\",\"maptype\":\"UserAttributeClass.Name\",\"value\":\"00000000-0000-0000-0000-00000000000\"},{\"jsmap\":null,\"map\":\"testAttribute2\",\"maptype\":\"UserAttributeClass.Name\",\"value\":\"00000000-0000-0000-0000-00000000001\"}]" + }; + + MPKitAppboy *kitInstance = [[MPKitAppboy alloc] init]; + [kitInstance didFinishLaunchingWithConfiguration:kitConfiguration]; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kitInstance setAppboyInstance:mockClient]; + XCTAssertEqualObjects(mockClient, [kitInstance appboyInstance]); + + // Should succeed since Bool false is a valid value + MPKitExecStatus *execStatus1 = [kitInstance setUserAttribute:@"testAttribute1" value:@NO]; + XCTAssertEqual(execStatus1.returnCode, MPKitReturnCodeSuccess); + // Should succeed since Bool true is a valid value + MPKitExecStatus *execStatus2 = [kitInstance setUserAttribute:@"testAttribute2" value:@YES]; + XCTAssertEqual(execStatus2.returnCode, MPKitReturnCodeSuccess); + // Should fail since testValue is not type BOOL + MPKitExecStatus *execStatus3 = [kitInstance setUserAttribute:@"testAttribute2" value:@"testValue"]; + XCTAssertEqual(execStatus3.returnCode, MPKitReturnCodeFail); + + [mockClient verify]; + + [mockClient stopMocking]; +} + + +//- (void)testEndpointOverride { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"host":@"https://foo.bar.com", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"https://foo.bar.com", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"https://moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} +// +//- (void)testEndpointOverride2 { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"host":@"http://foo.bar.com", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"http://foo.bar.com", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"http://foo.bar.com/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"http://foo.bar.com/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"https://moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} +// +//- (void)testEndpointOverride3 { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"host":@"foo.bar.com", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"https://foo.bar.com", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"https://moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} +// +//- (void)testEndpointOverride4 { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"host":@"https://foo.bar.com/baz", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"https://foo.bar.com/baz", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/baz/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/baz/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"https://moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} +// +//- (void)testEndpointOverride5 { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"host":@"https://foo.bar.com/baz/baz", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"https://foo.bar.com/baz/baz", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/baz/baz/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"https://foo.bar.com/baz/baz/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"https://moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} +// +//- (void)testEndpointOverrideNilHost { +// MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; +// +// NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", +// @"id":@42, +// @"ABKCollectIDFA":@"true", +// @"ABKRequestProcessingPolicyOptionKey": @"1", +// @"ABKFlushIntervalOptionKey":@"2", +// @"ABKSessionTimeoutKey":@"3", +// @"ABKMinimumTriggerTimeIntervalKey":@"4", +// @"ABKCollectIDFA":@"true" +// }; +// +// [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; +// +// XCTAssertEqualObjects(@"https://original.com", [appBoy getApiEndpoint:@"https://original.com"]); +// XCTAssertEqualObjects(@"https://original.com/param1", [appBoy getApiEndpoint:@"https://original.com/param1"]); +// XCTAssertEqualObjects(@"https://original.com/param1/param2", [appBoy getApiEndpoint:@"https://original.com/param1/param2"]); +// +// +// NSString *testEndpoint; +// XCTAssertNil([appBoy getApiEndpoint:testEndpoint]); +// XCTAssertEqualObjects(@"moo.far.com", [appBoy getApiEndpoint:@"moo.far.com"]); +// XCTAssertEqualObjects(@"http://moo.far.com", [appBoy getApiEndpoint:@"http://moo.far.com"]); +//} + +- (void)testSetMessageDelegate { + id delegate = (id)[NSObject new]; + + XCTAssertNil([MPKitAppboy inAppMessageControllerDelegate]); + + [MPKitAppboy setInAppMessageControllerDelegate:delegate]; + + XCTAssertEqualObjects([MPKitAppboy inAppMessageControllerDelegate], delegate); + + XCTestExpectation *expectation = [self expectationWithDescription:@"async work"]; + + dispatch_async(dispatch_get_main_queue(), ^{ + XCTAssertEqualObjects([MPKitAppboy inAppMessageControllerDelegate], delegate); + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testStrongMessageDelegate { + id delegate = (id)[NSObject new]; + + [MPKitAppboy setInAppMessageControllerDelegate:delegate]; + + delegate = nil; + + XCTestExpectation *expectation = [self expectationWithDescription:@"async work"]; + + dispatch_async(dispatch_get_main_queue(), ^{ + XCTAssertNotNil([MPKitAppboy inAppMessageControllerDelegate]); + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testSetDisableNotificationHandling { + XCTAssertEqual([MPKitAppboy shouldDisableNotificationHandling], NO); + + [MPKitAppboy setShouldDisableNotificationHandling:YES]; + + XCTAssertEqual([MPKitAppboy shouldDisableNotificationHandling], YES); + + [MPKitAppboy setShouldDisableNotificationHandling:NO]; + + XCTAssertEqual([MPKitAppboy shouldDisableNotificationHandling], NO); +} + +- (void)testSetBrazeInstance { + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + + XCTAssertEqualObjects([MPKitAppboy brazeInstance], nil); + + [MPKitAppboy setBrazeInstance:testClient]; + + MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; + + XCTAssertEqualObjects(appBoy.appboyInstance, nil); + XCTAssertEqualObjects(appBoy.providerKitInstance, nil); + XCTAssertEqualObjects([MPKitAppboy brazeInstance], testClient); + + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"CustomerId" + }; + + [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; + + XCTAssertEqualObjects(appBoy.appboyInstance, testClient); + XCTAssertEqualObjects(appBoy.providerKitInstance, testClient); + XCTAssertEqualObjects([MPKitAppboy brazeInstance], testClient); +} + +- (void)testUserIdCustomerId { + MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; + + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"CustomerId" + }; + + [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; + + XCTAssertEqual(appBoy.configuration[@"userIdentificationType"], @"CustomerId"); +} + +- (void)testUserIdMPID { + MPKitAppboy *appBoy = [[MPKitAppboy alloc] init]; + + NSDictionary *kitConfiguration = @{@"apiKey":@"BrazeID", + @"id":@42, + @"ABKCollectIDFA":@"true", + @"ABKRequestProcessingPolicyOptionKey": @"1", + @"ABKFlushIntervalOptionKey":@"2", + @"ABKSessionTimeoutKey":@"3", + @"ABKMinimumTriggerTimeIntervalKey":@"4", + @"userIdentificationType":@"MPID" + }; + + [appBoy didFinishLaunchingWithConfiguration:kitConfiguration]; + + XCTAssertEqual(appBoy.configuration[@"userIdentificationType"], @"MPID"); +} + +- (void)testlogCommerceEvent { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @0}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionClick product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @13.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + [[mockClient expect] logCustomEvent:@"eCommerce - click - Item" + properties:@{@"Id" : @"1131331343", + @"Item Price" : @"13", + @"Name" : @"product1", + @"Quantity" : @"1", + @"Total Product Amount" : @"13", + @"testKey" : @"testCustomAttValue" + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testlogCommerceEventWithBundledProducts { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @1}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionClick product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @13.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + [[mockClient expect] logCustomEvent:@"eCommerce - click" + properties:@{@"Attributes" : @{@"testKey" : @"testCustomAttValue"}, + @"products" : @[@{ + @"Id" : @"1131331343", + @"Item Price" : @"13", + @"Name" : @"product1", + @"Quantity" : @"1", + @"Total Product Amount" : @"13" + } + ] + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testlogPurchaseCommerceEvent { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @0}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + product.category = @"category1"; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionPurchase product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @13.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + [[mockClient expect] logPurchase:@"1131331343" + currency:@"USD" + price:[@"13" doubleValue] + quantity:1 + properties:@{@"Shipping Amount" : @3, + @"Total Amount" : @13.00, + @"Total Product Amount" : @"13", + @"Tax Amount" : @3, + @"Transaction Id" : @"foo-transaction-id", + @"Name" : @"product1", + @"Category" : @"category1", + @"testKey" : @"testCustomAttValue" + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testlogPurchaseCommerceEventSendingProductName { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @0, + @"replaceSkuWithProductName": @"True"}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + product.category = @"category1"; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionPurchase product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @13.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + [[mockClient expect] logPurchase:@"product1" + currency:@"USD" + price:[@"13" doubleValue] + quantity:1 + properties:@{@"Shipping Amount" : @3, + @"Total Amount" : @13.00, + @"Total Product Amount" : @"13", + @"Tax Amount" : @3, + @"Transaction Id" : @"foo-transaction-id", + @"Name" : @"product1", + @"Category" : @"category1", + @"testKey" : @"testCustomAttValue" + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testlogPurchaseCommerceEventWithBundledProducts { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @1}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionPurchase product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @13.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + NSDictionary *testResultDict = @{@"Attributes" : @{@"testKey" : @"testCustomAttValue"}, + @"Shipping Amount" : @3, + @"Total Amount" : @13.00, + @"Tax Amount" : @3, + @"Transaction Id" : @"foo-transaction-id", + @"products" : @[@{ + @"Id" : @"1131331343", + @"Item Price" : @"13", + @"Name" : @"product1", + @"Quantity" : @"1", + @"Total Product Amount" : @"13" + } + ] + }; + BOOL (^testBlock)(id value) = ^BOOL(id value) { + if ([value isKindOfClass:[NSDictionary class]]) { + for (NSString *key in [(NSDictionary *)value allKeys]) { + if ([key isEqualToString: @"products"]) { + NSArray *productArray = (NSArray *)((NSDictionary *)value[key]); + for (int i = 0; i < productArray.count; i++) { + NSDictionary *productDict = productArray[i]; + for (NSString *productDictKey in [productDict allKeys]) { + if (![productDict[productDictKey] isEqual:testResultDict[key][i][productDictKey]]) { + NSLog(@"Invalid Object in Product: %@ Key: %@", productDict, productDictKey); + return false; + } + } + } + } + if (![(NSDictionary *)value[key] isEqual:testResultDict[key]]) { + NSLog(@"Invalid Object in Key: %@", key); + return false; + } + } + return true; + } + return false; + }; + + OCMExpect(([mockClient logPurchase:@"eCommerce - purchase" + currency:@"USD" + price:[@"13" doubleValue] + properties:[OCMArg checkWithBlock:testBlock] + ])); + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + OCMVerifyAll(mockClient); + + [mockClient stopMocking]; +} + +- (void)testlogCommerceEventWithMultipleBundledProducts { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @1}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product1 = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + MPProduct *product2 = [[MPProduct alloc] initWithName:@"product2" sku:@"1131331888" quantity:@1 price:@13]; + product2.userDefinedAttributes[@"testKey"] = @"testCustomAttValue"; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionPurchase]; + [event addProducts:@[product1, product2]]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + MPTransactionAttributes *attributes = [[MPTransactionAttributes alloc] init]; + attributes.transactionId = @"foo-transaction-id"; + attributes.revenue = @26.00; + attributes.tax = @3; + attributes.shipping = @3; + + event.transactionAttributes = attributes; + + NSDictionary *testResultDict = @{@"Attributes" : @{@"testKey" : @"testCustomAttValue"}, + @"Shipping Amount" : @3, + @"Total Amount" : @26.00, + @"Tax Amount" : @3, + @"Transaction Id" : @"foo-transaction-id", + @"products" : @[@{ + @"Id" : @"1131331343", + @"Item Price" : @"13", + @"Name" : @"product1", + @"Quantity" : @"1", + @"Total Product Amount" : @"13" + }, + @{ + @"Id" : @"1131331888", + @"Item Price" : @"13", + @"Name" : @"product2", + @"Quantity" : @"1", + @"Total Product Amount" : @"13", + @"Attributes" : @{@"testKey" : @"testCustomAttValue"} + } + ] + }; + BOOL (^testBlock)(id value) = ^BOOL(id value) { + if ([value isKindOfClass:[NSDictionary class]]) { + for (NSString *key in [(NSDictionary *)value allKeys]) { + if ([key isEqualToString: @"products"]) { + NSArray *productArray = (NSArray *)((NSDictionary *)value[key]); + for (int i = 0; i < productArray.count; i++) { + NSDictionary *productDict = productArray[i]; + for (NSString *productDictKey in [productDict allKeys]) { + if (![productDict[productDictKey] isEqual:testResultDict[key][i][productDictKey]]) { + NSLog(@"Invalid Object in Product: %@ Key: %@", productDict, productDictKey); + return false; + } + } + } + } + if (![(NSDictionary *)value[key] isEqual:testResultDict[key]]) { + NSLog(@"Invalid Object in Key: %@", key); + return false; + } + } + return true; + } + return false; + }; + + OCMExpect(([mockClient logPurchase:@"eCommerce - purchase" + currency:@"USD" + price:[@"26" doubleValue] + properties:[OCMArg checkWithBlock:testBlock] + ])); + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + OCMVerifyAll(mockClient); + + [mockClient stopMocking]; +} + +- (void)testlogPromotionCommerceEventWithBundledProducts { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @1}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPPromotion *promotion = [[MPPromotion alloc] init]; + promotion.promotionId = @"my_promo_1"; + promotion.creative = @"sale_banner_1"; + promotion.name = @"App-wide 50% off sale"; + promotion.position = @"dashboard_bottom"; + + MPPromotionContainer *container = + [[MPPromotionContainer alloc] initWithAction:MPPromotionActionView + promotion:promotion]; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithPromotionContainer:container]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + [[mockClient expect] logCustomEvent:@"eCommerce - view" + properties:@{@"Attributes" : @{@"testKey" : @"testCustomAttValue"}, + @"promotions" : @[@{ + @"Creative" : @"sale_banner_1", + @"Name" : @"App-wide 50% off sale", + @"Position" : @"dashboard_bottom", + @"Id" : @"my_promo_1" + } + ] + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +- (void)testlogImpressionCommerceEventWithBundledProducts { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + kit.configuration = @{@"bundleCommerceEventData" : @1}; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + MPProduct *product = [[MPProduct alloc] initWithName:@"product1" sku:@"1131331343" quantity:@1 price:@13]; + product.userDefinedAttributes = [@{@"productTestKey" : @"productTestCustomAttValue"} mutableCopy]; + + MPCommerceEvent *event = [[MPCommerceEvent alloc] initWithImpressionName:@"Suggested Products List" product:product]; + event.customAttributes = @{@"testKey" : @"testCustomAttValue"}; + + [[mockClient expect] logCustomEvent:@"eCommerce - impression" + properties:@{@"Attributes" : @{@"testKey" : @"testCustomAttValue"}, + @"impressions" : @[@{ + @"Product Impression List" : @"Suggested Products List", + @"products" : @[@{ + @"Id" : @"1131331343", + @"Item Price" : @"13", + @"Name" : @"product1", + @"Quantity" : @"1", + @"Total Product Amount" : @"13", + @"Attributes" : @{@"productTestKey" : @"productTestCustomAttValue"} + } + ] + } + ] + }]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +//- (void)testTypeDetection { +// MPKitAppboy *kit = [[MPKitAppboy alloc] init]; +// +// BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; +// Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; +// id mockClient = OCMPartialMock(testClient); +// [kit setAppboyInstance:mockClient]; +// +// XCTAssertEqualObjects(mockClient, [kit appboyInstance]); +// +// +// MPEvent *event = [[MPEvent alloc] initWithName:@"test event" type:MPEventTypeNavigation]; +// event.customAttributes = @{@"foo":@"5.0", @"bar": @"true", @"baz": @"abc", @"qux": @"-3", @"quux": @"1970-01-01T00:00:00Z"}; +// +// [kit setEnableTypeDetection:YES]; +// [[mockClient expect] logCustomEvent:event.name withProperties:@{@"foo":@5.0, @"bar": @YES, @"baz":@"abc", @"qux": @-3, @"quux": [NSDate dateWithTimeIntervalSince1970:0]}]; +// +// MPKitExecStatus *execStatus = [kit logBaseEvent:event]; +// +// XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); +// +// [mockClient verify]; +// +// [mockClient stopMocking]; +//} +// +// +//- (void)testTypeDetectionDisable { +// MPKitAppboy *kit = [[MPKitAppboy alloc] init]; +// +// BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; +// Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; +// id mockClient = OCMPartialMock(testClient); +// [kit setAppboyInstance:mockClient]; +// +// XCTAssertEqualObjects(mockClient, [kit appboyInstance]); +// +// +// MPEvent *event = [[MPEvent alloc] initWithName:@"test event" type:MPEventTypeNavigation]; +// event.customAttributes = @{@"foo":@"5.0", @"bar": @"true", @"baz": @"abc", @"quz": @"-3", @"qux": @"1970-01-01T00:00:00Z"}; +// +// [kit setEnableTypeDetection:NO]; +// [[mockClient expect] logCustomEvent:event.name withProperties:event.customAttributes]; +// +// MPKitExecStatus *execStatus = [kit logBaseEvent:event]; +// +// XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); +// +// [mockClient verify]; +// +// [mockClient stopMocking]; +//} + +- (void)testEventWithEmptyProperties { + MPKitAppboy *kit = [[MPKitAppboy alloc] init]; + + BRZConfiguration *configuration = [[BRZConfiguration alloc] init]; + Braze *testClient = [[Braze alloc] initWithConfiguration:configuration]; + id mockClient = OCMPartialMock(testClient); + [kit setAppboyInstance:mockClient]; + + XCTAssertEqualObjects(mockClient, [kit appboyInstance]); + + + MPEvent *event = [[MPEvent alloc] initWithName:@"test event" type:MPEventTypeNavigation]; + event.customAttributes = @{}; + + [kit setEnableTypeDetection:NO]; + [[mockClient expect] logCustomEvent:event.name]; + + MPKitExecStatus *execStatus = [kit logBaseEvent:event]; + + XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); + + [mockClient verify]; + + [mockClient stopMocking]; +} + +@end diff --git a/kits/braze/braze-12/release.config.js b/kits/braze/braze-12/release.config.js new file mode 100644 index 000000000..683a77a99 --- /dev/null +++ b/kits/braze/braze-12/release.config.js @@ -0,0 +1,37 @@ +module.exports = { + branches: ["main"], + tagFormat: "v${version}", + plugins: [ + [ + "@semantic-release/commit-analyzer", + { + preset: "angular", + }, + ], + [ + "@semantic-release/release-notes-generator", + { + preset: "angular", + }, + ], + [ + "@semantic-release/changelog", + { + changelogFile: "CHANGELOG.md", + }, + ], + [ + "@semantic-release/exec", + { + prepareCmd: + 'sh ./Scripts/release.sh ${nextRelease.version} "${nextRelease.notes}"', + }, + ], + [ + "@semantic-release/github", + { + assets: [], + }, + ], + ], +}; From 195cf2f9ea686a7934aa305b1a163057836a3408 Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 16 Feb 2026 14:33:17 -0500 Subject: [PATCH 02/25] Update deployment targets --- .../mParticle-Appboy.xcodeproj/project.pbxproj | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj index cace2b6d7..bd5840805 100644 --- a/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj +++ b/kits/braze/braze-12/mParticle-Appboy.xcodeproj/project.pbxproj @@ -516,7 +516,7 @@ SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Debug; }; @@ -551,7 +551,7 @@ SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Release; }; @@ -569,7 +569,7 @@ FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = mParticle_AppboyTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-AppboyTests"; @@ -579,7 +579,7 @@ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppboyTestHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppboyTestHost"; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Debug; }; @@ -606,7 +606,7 @@ SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppboyTestHost.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppboyTestHost"; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Release; }; @@ -741,7 +741,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Debug; }; @@ -759,7 +759,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-Appboy"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; }; name = Release; }; @@ -792,7 +792,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "mParticle-Appboy-tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; OTHER_LDFLAGS = ( "-ObjC", "-all_load", @@ -835,7 +835,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "mParticle-Appboy-tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; OTHER_LDFLAGS = ( "-ObjC", "-all_load", From ada2989cd1520ec200e2e077642c82f03ac7bdd2 Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 16 Feb 2026 14:51:58 -0500 Subject: [PATCH 03/25] fix trunk checks --- .../braze-12/AppboyTestHost/ViewController.swift | 14 -------------- kits/braze/braze-12/Package.swift | 4 ++-- kits/braze/braze-12/README.md | 12 ++++++------ kits/braze/braze-12/Scripts/release.sh | 9 +++++---- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/kits/braze/braze-12/AppboyTestHost/ViewController.swift b/kits/braze/braze-12/AppboyTestHost/ViewController.swift index 6fe4a0e22..b9a63bbde 100644 --- a/kits/braze/braze-12/AppboyTestHost/ViewController.swift +++ b/kits/braze/braze-12/AppboyTestHost/ViewController.swift @@ -1,18 +1,4 @@ -// -// ViewController.swift -// AppboyTestHost -// -// Created by Ben Baron on 5/16/23. -// Copyright ยฉ 2023 mParticle. All rights reserved. -// - import UIKit class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } - } diff --git a/kits/braze/braze-12/Package.swift b/kits/braze/braze-12/Package.swift index 983ceb7ac..314b652ca 100644 --- a/kits/braze/braze-12/Package.swift +++ b/kits/braze/braze-12/Package.swift @@ -20,7 +20,7 @@ let package = Package( .package( url: "https://github.com/braze-inc/braze-swift-sdk", .upToNextMajor(from: "12.0.0") - ), + ) ], targets: [ .target( @@ -29,7 +29,7 @@ let package = Package( .product(name: "mParticle-Apple-SDK", package: "mParticle-Apple-SDK"), .product(name: "BrazeUI", package: "braze-swift-sdk", condition: .when(platforms: [.iOS])), .product(name: "BrazeKit", package: "braze-swift-sdk"), - .product(name: "BrazeKitCompat", package: "braze-swift-sdk"), + .product(name: "BrazeKitCompat", package: "braze-swift-sdk") ], resources: [.process("PrivacyInfo.xcprivacy")] ) diff --git a/kits/braze/braze-12/README.md b/kits/braze/braze-12/README.md index 0b0ef0cd0..e77a2c908 100644 --- a/kits/braze/braze-12/README.md +++ b/kits/braze/braze-12/README.md @@ -1,18 +1,18 @@ -## Braze (formerly Appboy) Kit Integration +# Braze (formerly Appboy) Kit Integration This repository contains the [Braze](https://www.braze.com) integration for the [mParticle Apple SDK](https://github.com/mParticle/mparticle-apple-sdk) using the latest [Braze Swift SDK](https://github.com/braze-inc/braze-swift-sdk/). -### Adding the integration +## Adding the integration 1. Add the kit dependency using SPM or add it to your app's Podfile or Cartfile: - ``` + ```ruby pod 'mParticle-Appboy', '~> 8.0' ``` OR - ``` + ```swift github "mparticle-integrations/mparticle-apple-integration-appboy" ~> 8.0 ``` @@ -24,10 +24,10 @@ This repository contains the [Braze](https://www.braze.com) integration for the 4. Reference mParticle's integration docs below to enable the integration. -### Documentation +## Documentation [Braze integration](https://docs.mparticle.com/integrations/braze/event/) -### License +## License [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) diff --git a/kits/braze/braze-12/Scripts/release.sh b/kits/braze/braze-12/Scripts/release.sh index 36d221b68..07a494397 100755 --- a/kits/braze/braze-12/Scripts/release.sh +++ b/kits/braze/braze-12/Scripts/release.sh @@ -1,12 +1,13 @@ +#!/bin/bash + VERSION="$1" -PREFIXED_VERSION="v$1" NOTES="$2" # Update version number # # Update CocoaPods podspec file -sed -i '' 's/\(^ s.version[^=]*= \).*/\1"'"$VERSION"'"/' mParticle-Appboy.podspec +sed -i '' 's/\(^ s.version[^=]*= \).*/\1"'"${VERSION}"'"/' mParticle-Appboy.podspec # Make the release commit in git # @@ -14,6 +15,6 @@ sed -i '' 's/\(^ s.version[^=]*= \).*/\1"'"$VERSION"'"/' mParticle-Appboy.pod git add mParticle-Appboy.podspec git add mParticle_Appboy.json git add CHANGELOG.md -git commit -m "chore(release): $VERSION [skip ci] +git commit -m "chore(release): ${VERSION} [skip ci] -$NOTES" +${NOTES}" From 842f8947c378103e5aecffb4adc737744c615fce Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 16 Feb 2026 15:00:34 -0500 Subject: [PATCH 04/25] remove empty line --- .../braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h | 1 - 1 file changed, 1 deletion(-) diff --git a/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h b/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h index 9ba341edc..26b7c78e2 100644 --- a/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h +++ b/kits/braze/braze-12/Sources/mParticle-Appboy/include/MPKitAppboy.h @@ -11,7 +11,6 @@ #import BrazeKit-Swift.h #endif - @interface MPKitAppboy : NSObject @property (nonatomic, strong, nonnull) NSDictionary *configuration; From 64b8a744132317ffcff28461744976c639be1662 Mon Sep 17 00:00:00 2001 From: Denis Chilik Date: Mon, 16 Feb 2026 15:03:45 -0500 Subject: [PATCH 05/25] ignore CHANGELOG.md --- .trunk/trunk.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 2f9171511..a7d72f3e4 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -72,6 +72,7 @@ lint: - linters: [markdownlint] paths: - CHANGELOG.md # Standard changelog format violates MD001, MD024, MD025 + - kits/braze/braze-12/CHANGELOG.md actions: enabled: From bce424ff7c2d9f5ed700cd672883dd077fe7fc7b Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 15:48:58 -0500 Subject: [PATCH 06/25] add workflow for pushing to mP integrations --- .github/workflows/mirror-kits-poc.yml | 127 ++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 .github/workflows/mirror-kits-poc.yml diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml new file mode 100644 index 000000000..0d6058555 --- /dev/null +++ b/.github/workflows/mirror-kits-poc.yml @@ -0,0 +1,127 @@ +name: Mirror Kits to mparticle-integrations (PoC) + +on: + workflow_dispatch: + +jobs: + mirror-kits: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + kit: + - name: braze-12 + local_path: kits/braze/braze-12 + dest_repo: mparticle-integrations/mparticle-apple-integration-braze-12 + # - name: braze-13 + # local_path: kits/braze/braze-13 + # dest_repo: mparticle-integrations/mparticle-apple-integration-braze-13 + # - name: braze-14 + # local_path: kits/braze/braze-14 + # dest_repo: mparticle-integrations/mparticle-apple-integration-braze-14 + + steps: + - name: Checkout monorepo + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history required for git subtree split + ref: ${{ github.ref }} + + - name: Configure Git + run: | + git config user.name "mParticle Bot" + git config user.email "developers@mparticle.com" + + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} + private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} + owner: mparticle-integrations + + - name: Verify kit directory exists + run: | + if [ ! -d "${{ matrix.kit.local_path }}" ]; then + echo "โŒ Error: Kit directory ${{ matrix.kit.local_path }} does not exist" + echo "This kit has not been imported yet. Please run git subtree add first." + exit 1 + fi + + echo "โœ… Kit directory exists: ${{ matrix.kit.local_path }}" + echo "" + echo "Directory contents:" + ls -la ${{ matrix.kit.local_path }} + + - name: Split kit directory into branch + id: split + run: | + SPLIT_BRANCH="split/${{ matrix.kit.name }}-$(date +%s)" + echo "split_branch=${SPLIT_BRANCH}" >> $GITHUB_OUTPUT + + echo "๐Ÿ“ฆ Creating split branch: ${SPLIT_BRANCH}" + echo " from: ${{ matrix.kit.local_path }}" + + git subtree split --prefix ${{ matrix.kit.local_path }} -b ${SPLIT_BRANCH} + + echo "" + echo "โœ… Split branch created successfully" + echo "" + echo "Recent commits in split branch:" + git log ${SPLIT_BRANCH} --oneline | head -10 + + - name: Push to destination repository + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + DEST_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/${{ matrix.kit.dest_repo }}.git" + + echo "๐Ÿš€ Pushing to destination repository" + echo " Repo: ${{ matrix.kit.dest_repo }}" + echo " Branch: ${{ github.ref_name }}" + echo "" + + git remote add dest-${{ matrix.kit.name }} "${DEST_URL}" + + git push dest-${{ matrix.kit.name }} \ + ${{ steps.split.outputs.split_branch }}:${{ github.ref_name }} \ + --force + + echo "" + echo "โœ… Successfully pushed to ${{ matrix.kit.dest_repo }}" + + - name: Cleanup split branch + if: always() + run: | + echo "๐Ÿงน Cleaning up split branch" + git branch -D ${{ steps.split.outputs.split_branch }} || true + echo "โœ… Cleanup complete" + + - name: Summary + if: success() + run: | + echo "## โœ… Mirror Complete: ${{ matrix.kit.name }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY + echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| **Source** | \`${{ matrix.kit.local_path }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Destination** | https://github.com/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY + echo "| **Branch** | \`${{ github.ref_name }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Kit** | ${{ matrix.kit.name }} |" >> $GITHUB_STEP_SUMMARY + + summary: + name: Mirror Summary + runs-on: ubuntu-latest + needs: mirror-kits + if: always() + steps: + - name: Check results + run: | + echo "## ๐ŸŽ‰ Kit Mirroring Complete" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "All Braze kit tracks have been mirrored to mparticle-integrations." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Next Steps" >> $GITHUB_STEP_SUMMARY + echo "1. Verify the mirrored code in each destination repo" >> $GITHUB_STEP_SUMMARY + echo "2. Test SPM package resolution" >> $GITHUB_STEP_SUMMARY + echo "3. Test CocoaPods spec lint" >> $GITHUB_STEP_SUMMARY From 16433a6176eef8129296940eec2d50b04f9400fc Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 15:53:43 -0500 Subject: [PATCH 07/25] get workflow to appear in github ui --- .github/workflows/mirror-kits-poc.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 0d6058555..7992894d9 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -2,6 +2,12 @@ name: Mirror Kits to mparticle-integrations (PoC) on: workflow_dispatch: + push: + branches: + - "**" + paths: + - "kits/**" + - ".github/workflows/mirror-kits-poc.yml" jobs: mirror-kits: From aeee403fe0645406f13b040a6ce46300e27361ad Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 16:18:03 -0500 Subject: [PATCH 08/25] Update mirror-kits-poc.yml --- .github/workflows/mirror-kits-poc.yml | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 7992894d9..6f8a995cc 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -84,13 +84,13 @@ jobs: echo "๐Ÿš€ Pushing to destination repository" echo " Repo: ${{ matrix.kit.dest_repo }}" - echo " Branch: ${{ github.ref_name }}" + echo " Branch: main" echo "" git remote add dest-${{ matrix.kit.name }} "${DEST_URL}" git push dest-${{ matrix.kit.name }} \ - ${{ steps.split.outputs.split_branch }}:${{ github.ref_name }} \ + ${{ steps.split.outputs.split_branch }}:main \ --force echo "" @@ -112,22 +112,5 @@ jobs: echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY echo "| **Source** | \`${{ matrix.kit.local_path }}\` |" >> $GITHUB_STEP_SUMMARY echo "| **Destination** | https://github.com/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY - echo "| **Branch** | \`${{ github.ref_name }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Branch** | \`main\` |" >> $GITHUB_STEP_SUMMARY echo "| **Kit** | ${{ matrix.kit.name }} |" >> $GITHUB_STEP_SUMMARY - - summary: - name: Mirror Summary - runs-on: ubuntu-latest - needs: mirror-kits - if: always() - steps: - - name: Check results - run: | - echo "## ๐ŸŽ‰ Kit Mirroring Complete" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "All Braze kit tracks have been mirrored to mparticle-integrations." >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "### Next Steps" >> $GITHUB_STEP_SUMMARY - echo "1. Verify the mirrored code in each destination repo" >> $GITHUB_STEP_SUMMARY - echo "2. Test SPM package resolution" >> $GITHUB_STEP_SUMMARY - echo "3. Test CocoaPods spec lint" >> $GITHUB_STEP_SUMMARY From 2b68ae4422860bf3f6ff0faf382035135fcca80e Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 16:36:16 -0500 Subject: [PATCH 09/25] add repo depth to token --- .github/workflows/mirror-kits-poc.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 6f8a995cc..19e28dc39 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -12,19 +12,21 @@ on: jobs: mirror-kits: runs-on: ubuntu-latest + env: + DEST_ORG: mparticle-integrations strategy: fail-fast: false matrix: kit: - name: braze-12 local_path: kits/braze/braze-12 - dest_repo: mparticle-integrations/mparticle-apple-integration-braze-12 + dest_repo: mparticle-apple-integration-braze-12 # - name: braze-13 # local_path: kits/braze/braze-13 - # dest_repo: mparticle-integrations/mparticle-apple-integration-braze-13 + # dest_repo: mparticle-apple-integration-braze-13 # - name: braze-14 # local_path: kits/braze/braze-14 - # dest_repo: mparticle-integrations/mparticle-apple-integration-braze-14 + # dest_repo: mparticle-apple-integration-braze-14 steps: - name: Checkout monorepo @@ -44,7 +46,8 @@ jobs: with: app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} - owner: mparticle-integrations + owner: ${{ env.DEST_ORG }} + repositories: ${{ matrix.kit.dest_repo }} - name: Verify kit directory exists run: | @@ -80,10 +83,10 @@ jobs: env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} run: | - DEST_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/${{ matrix.kit.dest_repo }}.git" + DEST_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}.git" echo "๐Ÿš€ Pushing to destination repository" - echo " Repo: ${{ matrix.kit.dest_repo }}" + echo " Repo: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" echo " Branch: main" echo "" @@ -94,7 +97,7 @@ jobs: --force echo "" - echo "โœ… Successfully pushed to ${{ matrix.kit.dest_repo }}" + echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" - name: Cleanup split branch if: always() @@ -111,6 +114,6 @@ jobs: echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY echo "| **Source** | \`${{ matrix.kit.local_path }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Destination** | https://github.com/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY + echo "| **Destination** | https://github.com/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY echo "| **Branch** | \`main\` |" >> $GITHUB_STEP_SUMMARY echo "| **Kit** | ${{ matrix.kit.name }} |" >> $GITHUB_STEP_SUMMARY From 0afd5aa0e4994beab94a89751736c0c2aeb5bf5b Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 16:41:31 -0500 Subject: [PATCH 10/25] add debug step --- .github/workflows/mirror-kits-poc.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 19e28dc39..1d6c4052c 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -49,6 +49,14 @@ jobs: owner: ${{ env.DEST_ORG }} repositories: ${{ matrix.kit.dest_repo }} + - name: Debug - Test API access + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + curl -s -w "\nHTTP_CODE:%{http_code}" \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + https://api.github.com/repos/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} + - name: Verify kit directory exists run: | if [ ! -d "${{ matrix.kit.local_path }}" ]; then From 6455eeb72cbc7789929e26efc53851a80949642e Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 16:59:41 -0500 Subject: [PATCH 11/25] Update mirror-kits-poc.yml --- .github/workflows/mirror-kits-poc.yml | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 1d6c4052c..3e106ab94 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout monorepo - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 # Full history required for git subtree split ref: ${{ github.ref }} @@ -39,6 +39,8 @@ jobs: run: | git config user.name "mParticle Bot" git config user.email "developers@mparticle.com" + # Required for git fetch from local path (monorepo) when pushing from dest/ + git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Generate GitHub App Token id: generate-token @@ -48,14 +50,7 @@ jobs: private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} owner: ${{ env.DEST_ORG }} repositories: ${{ matrix.kit.dest_repo }} - - - name: Debug - Test API access - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - run: | - curl -s -w "\nHTTP_CODE:%{http_code}" \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - https://api.github.com/repos/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} + permission-contents: write - name: Verify kit directory exists run: | @@ -87,22 +82,23 @@ jobs: echo "Recent commits in split branch:" git log ${SPLIT_BRANCH} --oneline | head -10 - - name: Push to destination repository - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - run: | - DEST_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}.git" + - name: Checkout destination repository + uses: actions/checkout@v5 + with: + repository: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} + token: ${{ steps.generate-token.outputs.token }} + path: dest + - name: Push split branch to destination + run: | echo "๐Ÿš€ Pushing to destination repository" echo " Repo: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" echo " Branch: main" echo "" - git remote add dest-${{ matrix.kit.name }} "${DEST_URL}" - - git push dest-${{ matrix.kit.name }} \ - ${{ steps.split.outputs.split_branch }}:main \ - --force + # Fetch split branch from monorepo into dest's main, then push + git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/main + git -C dest push origin main --force --verbose echo "" echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" From d6c3e1d4059ac00407817b664de2c4cdae202ef5 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 17:07:02 -0500 Subject: [PATCH 12/25] Update mirror-kits-poc.yml --- .github/workflows/mirror-kits-poc.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 3e106ab94..39667ed2f 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -96,8 +96,9 @@ jobs: echo " Branch: main" echo "" - # Fetch split branch from monorepo into dest's main, then push - git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/main + # Fetch into temp ref, then reset and push + git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/incoming + git -C dest reset --hard incoming git -C dest push origin main --force --verbose echo "" From 6cb653eb673233900c1a1ad79081cac8784a4865 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 17:27:29 -0500 Subject: [PATCH 13/25] simulate change in kit --- kits/braze/braze-12/Scripts/release.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/kits/braze/braze-12/Scripts/release.sh b/kits/braze/braze-12/Scripts/release.sh index 07a494397..a6ec5f40e 100755 --- a/kits/braze/braze-12/Scripts/release.sh +++ b/kits/braze/braze-12/Scripts/release.sh @@ -1,5 +1,4 @@ #!/bin/bash - VERSION="$1" NOTES="$2" From 2e70e5611f8cff2be1723b29cf49c16898a4e91d Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 17:30:11 -0500 Subject: [PATCH 14/25] use force push for first job otherwise not --- .github/workflows/mirror-kits-poc.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 39667ed2f..b23661c1e 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -96,10 +96,18 @@ jobs: echo " Branch: main" echo "" - # Fetch into temp ref, then reset and push + # Fetch into temp ref, then reset git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/incoming git -C dest reset --hard incoming - git -C dest push origin main --force --verbose + + # Use --force only on first push (no common history); otherwise normal push + if git -C dest merge-base --is-ancestor origin/main incoming 2>/dev/null; then + echo " Mode: fast-forward (subsequent push)" + git -C dest push origin main --verbose + else + echo " Mode: force (first push or unrelated history)" + git -C dest push origin main --force --verbose + fi echo "" echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" From 7093953890a08397015637d6f466cfa87cc0c6a4 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 18:00:59 -0500 Subject: [PATCH 15/25] Revert "simulate change in kit" This reverts commit 6cb653eb673233900c1a1ad79081cac8784a4865. --- kits/braze/braze-12/Scripts/release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/kits/braze/braze-12/Scripts/release.sh b/kits/braze/braze-12/Scripts/release.sh index a6ec5f40e..07a494397 100755 --- a/kits/braze/braze-12/Scripts/release.sh +++ b/kits/braze/braze-12/Scripts/release.sh @@ -1,4 +1,5 @@ #!/bin/bash + VERSION="$1" NOTES="$2" From 35228ba58a81c7ed6602a070905d8fb730bb569a Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 18:01:40 -0500 Subject: [PATCH 16/25] Revert "use force push for first job otherwise not" This reverts commit 2e70e5611f8cff2be1723b29cf49c16898a4e91d. --- .github/workflows/mirror-kits-poc.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index b23661c1e..d5bde0c8b 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -96,18 +96,10 @@ jobs: echo " Branch: main" echo "" - # Fetch into temp ref, then reset + # Fetch into temp ref, then reset and push git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/incoming git -C dest reset --hard incoming - - # Use --force only on first push (no common history); otherwise normal push - if git -C dest merge-base --is-ancestor origin/main incoming 2>/dev/null; then - echo " Mode: fast-forward (subsequent push)" - git -C dest push origin main --verbose - else - echo " Mode: force (first push or unrelated history)" - git -C dest push origin main --force --verbose - fi + git -C dest push origin main --force echo "" echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" From 4662b73c581f075bc3716cdaa60fddcdfdacb1e7 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 18:32:01 -0500 Subject: [PATCH 17/25] PoC for tagging a release --- .github/workflows/mirror-kits-poc.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index d5bde0c8b..db34b8d62 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -65,6 +65,15 @@ jobs: echo "Directory contents:" ls -la ${{ matrix.kit.local_path }} + - name: Get mP ecosystem version + id: version + run: | + # Ecosystem version from core SDK podspec (source of truth) + VERSION=$(grep 's.version' mParticle-Apple-SDK.podspec | sed 's/.*"\([^"]*\)".*/\1/') + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "tag=v${VERSION}" >> $GITHUB_OUTPUT + echo "๐Ÿ“Œ Ecosystem version: ${VERSION} (tag: v${VERSION})" + - name: Split kit directory into branch id: split run: | @@ -94,6 +103,7 @@ jobs: echo "๐Ÿš€ Pushing to destination repository" echo " Repo: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" echo " Branch: main" + echo " Tag: ${{ steps.version.outputs.tag }}" echo "" # Fetch into temp ref, then reset and push @@ -101,8 +111,13 @@ jobs: git -C dest reset --hard incoming git -C dest push origin main --force + # Tag with mP ecosystem version + git -C dest tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}" + git -C dest push origin "${{ steps.version.outputs.tag }}" + echo "" echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" + echo "โœ… Tagged: ${{ steps.version.outputs.tag }}" - name: Cleanup split branch if: always() @@ -121,4 +136,5 @@ jobs: echo "| **Source** | \`${{ matrix.kit.local_path }}\` |" >> $GITHUB_STEP_SUMMARY echo "| **Destination** | https://github.com/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY echo "| **Branch** | \`main\` |" >> $GITHUB_STEP_SUMMARY + echo "| **Tag** | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY echo "| **Kit** | ${{ matrix.kit.name }} |" >> $GITHUB_STEP_SUMMARY From 630b2a06f3fe2e78c3de125a25e076f531988103 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 18:40:08 -0500 Subject: [PATCH 18/25] adjust version number --- .github/workflows/mirror-kits-poc.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index db34b8d62..490544e0d 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -68,11 +68,19 @@ jobs: - name: Get mP ecosystem version id: version run: | - # Ecosystem version from core SDK podspec (source of truth) - VERSION=$(grep 's.version' mParticle-Apple-SDK.podspec | sed 's/.*"\([^"]*\)".*/\1/') - echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "tag=v${VERSION}" >> $GITHUB_OUTPUT - echo "๐Ÿ“Œ Ecosystem version: ${VERSION} (tag: v${VERSION})" + # TODO: Extract from core SDK podspec when ready for production + # VERSION=$(grep 's.version' mParticle-Apple-SDK.podspec | head -1 | sed 's/.*"\([^"]*\)".*/\1/' | tr -d '\r\n ') + VERSION="9.0.0" + TAG="v${VERSION}" + { + echo "version<> $GITHUB_OUTPUT + echo "๐Ÿ“Œ Ecosystem version: ${VERSION} (tag: ${TAG})" - name: Split kit directory into branch id: split From ae69fe42719663fe7f0201b4585b18b401ee5b9f Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Mon, 16 Feb 2026 18:43:15 -0500 Subject: [PATCH 19/25] git identity for tag --- .github/workflows/mirror-kits-poc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml index 490544e0d..f82449a5c 100644 --- a/.github/workflows/mirror-kits-poc.yml +++ b/.github/workflows/mirror-kits-poc.yml @@ -120,6 +120,8 @@ jobs: git -C dest push origin main --force # Tag with mP ecosystem version + git -C dest config user.name "mParticle Bot" + git -C dest config user.email "developers@mparticle.com" git -C dest tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}" git -C dest push origin "${{ steps.version.outputs.tag }}" From fce0c5d2ac0b9cd81a7bdcedbb54c44556684895 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Tue, 17 Feb 2026 11:26:43 -0500 Subject: [PATCH 20/25] clean up release ecosystem workflow --- .github/workflows/mirror-kits-poc.yml | 150 ---------------- .../workflows/release-ecosystem-from-main.yml | 164 ++++++++++++++++++ 2 files changed, 164 insertions(+), 150 deletions(-) delete mode 100644 .github/workflows/mirror-kits-poc.yml create mode 100644 .github/workflows/release-ecosystem-from-main.yml diff --git a/.github/workflows/mirror-kits-poc.yml b/.github/workflows/mirror-kits-poc.yml deleted file mode 100644 index f82449a5c..000000000 --- a/.github/workflows/mirror-kits-poc.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: Mirror Kits to mparticle-integrations (PoC) - -on: - workflow_dispatch: - push: - branches: - - "**" - paths: - - "kits/**" - - ".github/workflows/mirror-kits-poc.yml" - -jobs: - mirror-kits: - runs-on: ubuntu-latest - env: - DEST_ORG: mparticle-integrations - strategy: - fail-fast: false - matrix: - kit: - - name: braze-12 - local_path: kits/braze/braze-12 - dest_repo: mparticle-apple-integration-braze-12 - # - name: braze-13 - # local_path: kits/braze/braze-13 - # dest_repo: mparticle-apple-integration-braze-13 - # - name: braze-14 - # local_path: kits/braze/braze-14 - # dest_repo: mparticle-apple-integration-braze-14 - - steps: - - name: Checkout monorepo - uses: actions/checkout@v5 - with: - fetch-depth: 0 # Full history required for git subtree split - ref: ${{ github.ref }} - - - name: Configure Git - run: | - git config user.name "mParticle Bot" - git config user.email "developers@mparticle.com" - # Required for git fetch from local path (monorepo) when pushing from dest/ - git config --global --add safe.directory "$GITHUB_WORKSPACE" - - - name: Generate GitHub App Token - id: generate-token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} - private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} - owner: ${{ env.DEST_ORG }} - repositories: ${{ matrix.kit.dest_repo }} - permission-contents: write - - - name: Verify kit directory exists - run: | - if [ ! -d "${{ matrix.kit.local_path }}" ]; then - echo "โŒ Error: Kit directory ${{ matrix.kit.local_path }} does not exist" - echo "This kit has not been imported yet. Please run git subtree add first." - exit 1 - fi - - echo "โœ… Kit directory exists: ${{ matrix.kit.local_path }}" - echo "" - echo "Directory contents:" - ls -la ${{ matrix.kit.local_path }} - - - name: Get mP ecosystem version - id: version - run: | - # TODO: Extract from core SDK podspec when ready for production - # VERSION=$(grep 's.version' mParticle-Apple-SDK.podspec | head -1 | sed 's/.*"\([^"]*\)".*/\1/' | tr -d '\r\n ') - VERSION="9.0.0" - TAG="v${VERSION}" - { - echo "version<> $GITHUB_OUTPUT - echo "๐Ÿ“Œ Ecosystem version: ${VERSION} (tag: ${TAG})" - - - name: Split kit directory into branch - id: split - run: | - SPLIT_BRANCH="split/${{ matrix.kit.name }}-$(date +%s)" - echo "split_branch=${SPLIT_BRANCH}" >> $GITHUB_OUTPUT - - echo "๐Ÿ“ฆ Creating split branch: ${SPLIT_BRANCH}" - echo " from: ${{ matrix.kit.local_path }}" - - git subtree split --prefix ${{ matrix.kit.local_path }} -b ${SPLIT_BRANCH} - - echo "" - echo "โœ… Split branch created successfully" - echo "" - echo "Recent commits in split branch:" - git log ${SPLIT_BRANCH} --oneline | head -10 - - - name: Checkout destination repository - uses: actions/checkout@v5 - with: - repository: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} - token: ${{ steps.generate-token.outputs.token }} - path: dest - - - name: Push split branch to destination - run: | - echo "๐Ÿš€ Pushing to destination repository" - echo " Repo: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" - echo " Branch: main" - echo " Tag: ${{ steps.version.outputs.tag }}" - echo "" - - # Fetch into temp ref, then reset and push - git -C dest fetch "$GITHUB_WORKSPACE" ${{ steps.split.outputs.split_branch }}:refs/heads/incoming - git -C dest reset --hard incoming - git -C dest push origin main --force - - # Tag with mP ecosystem version - git -C dest config user.name "mParticle Bot" - git -C dest config user.email "developers@mparticle.com" - git -C dest tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}" - git -C dest push origin "${{ steps.version.outputs.tag }}" - - echo "" - echo "โœ… Successfully pushed to ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" - echo "โœ… Tagged: ${{ steps.version.outputs.tag }}" - - - name: Cleanup split branch - if: always() - run: | - echo "๐Ÿงน Cleaning up split branch" - git branch -D ${{ steps.split.outputs.split_branch }} || true - echo "โœ… Cleanup complete" - - - name: Summary - if: success() - run: | - echo "## โœ… Mirror Complete: ${{ matrix.kit.name }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY - echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| **Source** | \`${{ matrix.kit.local_path }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Destination** | https://github.com/${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} |" >> $GITHUB_STEP_SUMMARY - echo "| **Branch** | \`main\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Tag** | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| **Kit** | ${{ matrix.kit.name }} |" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release-ecosystem-from-main.yml b/.github/workflows/release-ecosystem-from-main.yml new file mode 100644 index 000000000..087ccb973 --- /dev/null +++ b/.github/workflows/release-ecosystem-from-main.yml @@ -0,0 +1,164 @@ +name: Release mParticle Ecosystem + +on: + push: + # TODO: Remove ci/** after testing + branches: + - main + - "ci/**" + paths: + - "VERSION" + - ".github/workflows/release-ecosystem-from-main.yml" + workflow_dispatch: + inputs: + dry_run: + description: "Dry run โ€” skip creating real releases/tags" + type: boolean + default: true + +permissions: + contents: write + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + tag: ${{ steps.version.outputs.tag }} + steps: + - uses: actions/checkout@v6 + + - name: Get ecosystem version + id: version + run: | + VERSION=$(head -n 1 VERSION | tr -d '\r\n ') + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "tag=v$VERSION" >> $GITHUB_OUTPUT + echo "๐Ÿ“Œ Ecosystem version: $VERSION" + + release-core: + needs: prepare + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Extract release notes + id: release-notes + uses: ffurrer2/extract-release-notes@202313ec7461b6b9e401996714484690ab1ae105 # v3.0.0 + with: + changelog_file: CHANGELOG.md + + - name: Dry run summary + if: inputs.dry_run + run: | + echo "๐Ÿœ๏ธ DRY RUN โ€” would create core release:" + echo " Tag: ${{ needs.prepare.outputs.tag }}" + echo " Release notes:" + echo "${{ steps.release-notes.outputs.release_notes }}" + + - name: Create GitHub release + if: ${{ !inputs.dry_run }} + uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 + with: + tag: ${{ needs.prepare.outputs.tag }} + makeLatest: true + body: | + ## Release notes + ${{ steps.release-notes.outputs.release_notes }} + + mirror-and-release-kits: + needs: prepare + runs-on: ubuntu-latest + env: + DEST_ORG: mparticle-integrations + strategy: + fail-fast: false + matrix: + kit: + - name: braze-12 + local_path: kits/braze/braze-12 + dest_repo: mparticle-apple-integration-braze-12 + # - name: braze-13 + # local_path: kits/braze/braze-13 + # dest_repo: mparticle-apple-integration-braze-13 + # - name: braze-14 + # local_path: kits/braze/braze-14 + # dest_repo: mparticle-apple-integration-braze-14 + + steps: + - name: Checkout monorepo + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "mParticle Bot" + git config user.email "developers@mparticle.com" + + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ secrets.SDK_RELEASE_GITHUB_APP_ID }} + private-key: ${{ secrets.SDK_RELEASE_GITHUB_APP_PRIVATE_KEY }} + owner: ${{ env.DEST_ORG }} + repositories: ${{ matrix.kit.dest_repo }} + permission-contents: write + + - name: Extract kit release notes + id: release-notes + uses: ffurrer2/extract-release-notes@202313ec7461b6b9e401996714484690ab1ae105 # v3.0.0 + with: + changelog_file: ${{ matrix.kit.local_path }}/CHANGELOG.md + + - name: Split kit and push to mirror + id: mirror + run: | + SPLIT_BRANCH="split/${{ matrix.kit.name }}" + + git subtree split --prefix ${{ matrix.kit.local_path }} -b "${SPLIT_BRANCH}" + + - name: Checkout destination repo + uses: actions/checkout@v6 + with: + repository: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }} + token: ${{ steps.generate-token.outputs.token }} + path: dest + + - name: Push split to destination + if: ${{ !inputs.dry_run }} + id: push + run: | + git -C dest fetch "$GITHUB_WORKSPACE" "split/${{ matrix.kit.name }}:refs/heads/incoming" + git -C dest reset --hard incoming + git -C dest push origin main --force + echo "sha=$(git -C dest rev-parse HEAD)" >> $GITHUB_OUTPUT + + - name: Create GitHub release on mirror + if: ${{ !inputs.dry_run }} + uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 + with: + tag: ${{ needs.prepare.outputs.tag }} + commit: ${{ steps.push.outputs.sha }} + owner: ${{ env.DEST_ORG }} + repo: ${{ matrix.kit.dest_repo }} + token: ${{ steps.generate-token.outputs.token }} + body: | + ${{ steps.release-notes.outputs.release_notes }} + + - name: Dry run summary + if: inputs.dry_run + run: | + echo "๐Ÿœ๏ธ DRY RUN โ€” would mirror and release kit:" + echo " Kit: ${{ matrix.kit.name }}" + echo " Dest: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" + echo " Tag: ${{ needs.prepare.outputs.tag }}" + echo " Split branch commits:" + git log "split/${{ matrix.kit.name }}" --oneline -5 + echo " Release notes:" + echo "${{ steps.release-notes.outputs.release_notes }}" + + - name: Cleanup split branch + if: always() + run: git branch -D "split/${{ matrix.kit.name }}" || true From dc869129dec488bce3e33c56a4fb7a64b0ccf13e Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Tue, 17 Feb 2026 11:27:21 -0500 Subject: [PATCH 21/25] add ci manual PR to trigger release --- .github/workflows/sdk-release-ecosystem.yml | 185 ++++++++++++++++++++ VERSION | 1 + 2 files changed, 186 insertions(+) create mode 100644 .github/workflows/sdk-release-ecosystem.yml create mode 100644 VERSION diff --git a/.github/workflows/sdk-release-ecosystem.yml b/.github/workflows/sdk-release-ecosystem.yml new file mode 100644 index 000000000..743ab7933 --- /dev/null +++ b/.github/workflows/sdk-release-ecosystem.yml @@ -0,0 +1,185 @@ +name: iOS SDK Ecosystem Release + +on: + workflow_dispatch: + inputs: + bump-type: + description: "Version bump type" + required: true + type: choice + options: + - patch + - minor + - major + +jobs: + confirm-main-branch: + name: Confirm release is run from main branch + uses: mParticle/mparticle-workflows/.github/workflows/sdk-release-repo-branch-check.yml@stable + + release: + name: Create release PR + runs-on: macOS-15 + needs: confirm-main-branch + env: + GITHUB_TOKEN: ${{ secrets.MP_SEMANTIC_RELEASE_BOT }} + steps: + - name: Checkout main branch + uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ secrets.MP_SEMANTIC_RELEASE_BOT }} + ref: main + + - name: Get current version from latest tag + id: current-version + run: | + CURRENT_VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "0.0.0") + echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT + + - name: Bump version + id: bump-version + uses: actions-ecosystem/action-bump-semver@v1 + with: + current_version: ${{ steps.current-version.outputs.version }} + level: ${{ github.event.inputs.bump-type }} + + - name: Set version environment variables + run: | + VERSION=$(echo "${{ steps.bump-version.outputs.new_version }}" | sed 's/^v//') + MAJOR=$(echo "$VERSION" | cut -d. -f1) + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "MAJOR=$MAJOR" >> $GITHUB_ENV + echo "๐Ÿ“Œ ${{ steps.current-version.outputs.version }} โ†’ $VERSION (${{ github.event.inputs.bump-type }})" + + - name: Setup git config + run: | + git config user.email "developers@mparticle.com" + git config user.name "mParticle Automation" + + - name: Create release branch + run: | + git push origin --delete chore/release-v${VERSION} 2>/dev/null || true + git checkout -b chore/release-v${VERSION} + + - name: Generate changelog entry + run: | + PREV_TAG="v${{ steps.current-version.outputs.version }}" + if [ "$PREV_TAG" = "v0.0.0" ]; then PREV_TAG=""; fi + DATE=$(date +%Y-%m-%d) + + echo "# [${VERSION}](https://github.com/mParticle/mparticle-apple-sdk/compare/${PREV_TAG}...v${VERSION}) (${DATE})" > /tmp/changelog_entry.md + echo "" >> /tmp/changelog_entry.md + + if [ -n "$PREV_TAG" ]; then + FIXES=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s ([%h](https://github.com/mParticle/mparticle-apple-sdk/commit/%H))" --grep="^fix" --regexp-ignore-case 2>/dev/null || true) + if [ -n "$FIXES" ]; then + echo -e "### Bug Fixes\n\n$FIXES\n" >> /tmp/changelog_entry.md + fi + + FEATURES=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s ([%h](https://github.com/mParticle/mparticle-apple-sdk/commit/%H))" --grep="^feat" --regexp-ignore-case 2>/dev/null || true) + if [ -n "$FEATURES" ]; then + echo -e "### Features\n\n$FEATURES\n" >> /tmp/changelog_entry.md + fi + + if [ -z "$FIXES" ] && [ -z "$FEATURES" ]; then + OTHER=$(git log ${PREV_TAG}..HEAD --pretty=format:"- %s ([%h](https://github.com/mParticle/mparticle-apple-sdk/commit/%H))" 2>/dev/null || true) + if [ -n "$OTHER" ]; then + echo -e "### Changes\n\n$OTHER\n" >> /tmp/changelog_entry.md + fi + fi + else + echo -e "### Initial Release\n" >> /tmp/changelog_entry.md + fi + + if [ -f CHANGELOG.md ]; then + cat /tmp/changelog_entry.md CHANGELOG.md > /tmp/new_changelog.md + mv /tmp/new_changelog.md CHANGELOG.md + else + mv /tmp/changelog_entry.md CHANGELOG.md + fi + + - name: Update VERSION file + run: echo "$VERSION" > VERSION + + - name: Update version in all podspecs + run: | + find . -name "*.podspec" -exec \ + sed -i '' 's/\(s\.version[^=]*=[[:space:]]*\)"[^"]*"/\1"'"${VERSION}"'"/' {} + + + - name: Update version in MPIConstants.m + run: sed -i '' "s/kMParticleSDKVersion = @\"[^\"]*\"/kMParticleSDKVersion = @\"${VERSION}\"/" mParticle-Apple-SDK/MPIConstants.m + + - name: Update version in MPConstants.swift + run: sed -i '' "s/let kMParticleSDKVersion = \"[^\"]*\"/let kMParticleSDKVersion = \"${VERSION}\"/" mParticle-Apple-SDK/MPConstants.swift + + - name: Update version in Info.plist + run: /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${VERSION}" Framework/Info.plist + + - name: Update SDK version in integration test mappings + run: ./Scripts/update_mapping_versions.sh "${VERSION}" + + - name: Update kit dependency on core SDK for major release + if: github.event.inputs.bump-type == 'major' + run: | + # Podspec: '~> X.Y' โ†’ '~> MAJOR.0' + find kits -name "*.podspec" -exec \ + sed -i '' "s/'mParticle-Apple-SDK', '~> [^']*'/'mParticle-Apple-SDK', '~> ${MAJOR}.0'/" {} + + + # Package.swift: .upToNextMajor(from: "X.Y.Z") โ†’ .upToNextMajor(from: "MAJOR.0.0") + find kits -name "Package.swift" -exec \ + sed -i '' "/mparticle-apple-sdk/{ + n + s/.upToNextMajor(from: \"[^\"]*\")/.upToNextMajor(from: \"${MAJOR}.0.0\")/ + s/branch: \"[^\"]*\"/.upToNextMajor(from: \"${MAJOR}.0.0\")/ + }" {} + + + # --- Commit, push, and create PR --- + + - name: Commit version changes + run: | + trunk fmt + git add \ + VERSION \ + CHANGELOG.md \ + Framework/Info.plist \ + mParticle-Apple-SDK.podspec \ + mParticle-Apple-SDK-Swift/mParticle-Apple-SDK-Swift.podspec \ + mParticle-Apple-SDK/MPConstants.swift \ + mParticle-Apple-SDK/MPIConstants.m \ + IntegrationTests/wiremock-recordings/mappings/*.json \ + kits/ + + git commit -m "chore: (release) ${VERSION} + + Updates version to ${VERSION} across the mParticle ecosystem." + + - name: Push release branch + run: git push origin chore/release-v${VERSION} + + - name: Create Pull Request + env: + GH_TOKEN: ${{ secrets.MP_SEMANTIC_RELEASE_BOT }} + run: | + gh pr create \ + --base main \ + --head chore/release-v${VERSION} \ + --title "chore: Release v${VERSION}" \ + --body "## Release v${VERSION} + + ### Bump type: \`${{ github.event.inputs.bump-type }}\` + + This PR contains the version bump and changelog updates for release ${VERSION}. + + ### Files updated + - All podspecs (core, Swift, kits) โ†’ \`${VERSION}\` + - \`mParticle-Apple-SDK/MPIConstants.m\` + - \`mParticle-Apple-SDK/MPConstants.swift\` + - \`Framework/Info.plist\` + - \`CHANGELOG.md\` + - Integration test mappings + + --- + + **On merge:** The [Release mParticle Ecosystem](https://github.com/mParticle/mparticle-apple-sdk/actions/workflows/release-ecosystem-from-main.yml) workflow will automatically create tags and GitHub releases for the core SDK and all mirrored kit repos." \ + --reviewer mParticle/sdk-team diff --git a/VERSION b/VERSION new file mode 100644 index 000000000..9d39066d3 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +8.42.2 From 00048592e659dbf44600f5f6bcd10a991116e2a9 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Tue, 17 Feb 2026 13:01:00 -0500 Subject: [PATCH 22/25] implement temp dry run and xcframework artifacts --- .../workflows/release-ecosystem-from-main.yml | 121 +++++++++++++++--- Scripts/xcframework.sh | 50 +++++--- 2 files changed, 135 insertions(+), 36 deletions(-) diff --git a/.github/workflows/release-ecosystem-from-main.yml b/.github/workflows/release-ecosystem-from-main.yml index 087ccb973..6fac4f965 100644 --- a/.github/workflows/release-ecosystem-from-main.yml +++ b/.github/workflows/release-ecosystem-from-main.yml @@ -16,6 +16,10 @@ on: type: boolean default: true +env: + # TODO: Remove after testing + DRY_RUN: true + permissions: contents: write @@ -38,10 +42,33 @@ jobs: release-core: needs: prepare - runs-on: ubuntu-latest + runs-on: macOS-15 + env: + XCODE_VERSION: "16.4" steps: - uses: actions/checkout@v6 + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app + + - name: Install signing certificate + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_P12 }} + P12_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} + KEYCHAIN_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} + run: | + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + - name: Build xcframework + run: ./Scripts/xcframework.sh mParticle-Apple-SDK.xcodeproj mParticle-Apple-SDK mParticle-Apple-SDK + - name: Extract release notes id: release-notes uses: ffurrer2/extract-release-notes@202313ec7461b6b9e401996714484690ab1ae105 # v3.0.0 @@ -49,28 +76,38 @@ jobs: changelog_file: CHANGELOG.md - name: Dry run summary - if: inputs.dry_run + if: env.DRY_RUN == 'true' run: | - echo "๐Ÿœ๏ธ DRY RUN โ€” would create core release:" - echo " Tag: ${{ needs.prepare.outputs.tag }}" - echo " Release notes:" - echo "${{ steps.release-notes.outputs.release_notes }}" + cat >> $GITHUB_STEP_SUMMARY <<'EOF' + ## ๐Ÿœ๏ธ DRY RUN โ€” Core SDK Release + + | Property | Value | + |----------|-------| + | **Tag** | `${{ needs.prepare.outputs.tag }}` | + | **Repository** | `mParticle/mparticle-apple-sdk` | + | **Artifact** | `mParticle_Apple_SDK.xcframework.zip` | + + ### Release notes + ${{ steps.release-notes.outputs.release_notes }} + EOF - name: Create GitHub release - if: ${{ !inputs.dry_run }} + if: env.DRY_RUN != 'true' uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 with: tag: ${{ needs.prepare.outputs.tag }} makeLatest: true + artifacts: mParticle_Apple_SDK.xcframework.zip body: | ## Release notes ${{ steps.release-notes.outputs.release_notes }} mirror-and-release-kits: needs: prepare - runs-on: ubuntu-latest + runs-on: macOS-15 env: DEST_ORG: mparticle-integrations + XCODE_VERSION: "16.4" strategy: fail-fast: false matrix: @@ -78,12 +115,21 @@ jobs: - name: braze-12 local_path: kits/braze/braze-12 dest_repo: mparticle-apple-integration-braze-12 + scheme: mParticle-Appboy + tvos_scheme: mParticle-Appboy-tvOS + module: mParticle_Appboy # - name: braze-13 # local_path: kits/braze/braze-13 # dest_repo: mparticle-apple-integration-braze-13 + # scheme: mParticle-Appboy + # tvos_scheme: mParticle-Appboy-tvOS + # module: mParticle_Appboy # - name: braze-14 # local_path: kits/braze/braze-14 # dest_repo: mparticle-apple-integration-braze-14 + # scheme: mParticle-Appboy + # tvos_scheme: mParticle-Appboy-tvOS + # module: mParticle_Appboy steps: - name: Checkout monorepo @@ -91,6 +137,29 @@ jobs: with: fetch-depth: 0 + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app + + - name: Install signing certificate + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_P12 }} + P12_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} + KEYCHAIN_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} + run: | + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + - name: Build kit xcframework + run: | + PROJECT="$(ls -d ${{ matrix.kit.local_path }}/*.xcodeproj | head -1)" + ./Scripts/xcframework.sh "$PROJECT" "${{ matrix.kit.scheme }}" "${{ matrix.kit.tvos_scheme }}" + - name: Configure Git run: | git config user.name "mParticle Bot" @@ -116,7 +185,6 @@ jobs: id: mirror run: | SPLIT_BRANCH="split/${{ matrix.kit.name }}" - git subtree split --prefix ${{ matrix.kit.local_path }} -b "${SPLIT_BRANCH}" - name: Checkout destination repo @@ -127,7 +195,7 @@ jobs: path: dest - name: Push split to destination - if: ${{ !inputs.dry_run }} + if: env.DRY_RUN != 'true' id: push run: | git -C dest fetch "$GITHUB_WORKSPACE" "split/${{ matrix.kit.name }}:refs/heads/incoming" @@ -136,7 +204,7 @@ jobs: echo "sha=$(git -C dest rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Create GitHub release on mirror - if: ${{ !inputs.dry_run }} + if: env.DRY_RUN != 'true' uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 with: tag: ${{ needs.prepare.outputs.tag }} @@ -144,20 +212,33 @@ jobs: owner: ${{ env.DEST_ORG }} repo: ${{ matrix.kit.dest_repo }} token: ${{ steps.generate-token.outputs.token }} + artifacts: ${{ matrix.kit.local_path }}/${{ matrix.kit.module }}.xcframework.zip body: | ${{ steps.release-notes.outputs.release_notes }} - name: Dry run summary - if: inputs.dry_run + if: env.DRY_RUN == 'true' run: | - echo "๐Ÿœ๏ธ DRY RUN โ€” would mirror and release kit:" - echo " Kit: ${{ matrix.kit.name }}" - echo " Dest: ${{ env.DEST_ORG }}/${{ matrix.kit.dest_repo }}" - echo " Tag: ${{ needs.prepare.outputs.tag }}" - echo " Split branch commits:" - git log "split/${{ matrix.kit.name }}" --oneline -5 - echo " Release notes:" - echo "${{ steps.release-notes.outputs.release_notes }}" + COMMITS=$(git log "split/${{ matrix.kit.name }}" --oneline -5) + cat >> $GITHUB_STEP_SUMMARY < Date: Tue, 17 Feb 2026 13:17:44 -0500 Subject: [PATCH 23/25] adjust for failing signing --- .../workflows/release-ecosystem-from-main.yml | 52 +++++++++++++++---- Scripts/xcframework.sh | 14 ++++- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-ecosystem-from-main.yml b/.github/workflows/release-ecosystem-from-main.yml index 6fac4f965..c76354f6d 100644 --- a/.github/workflows/release-ecosystem-from-main.yml +++ b/.github/workflows/release-ecosystem-from-main.yml @@ -115,20 +115,20 @@ jobs: - name: braze-12 local_path: kits/braze/braze-12 dest_repo: mparticle-apple-integration-braze-12 - scheme: mParticle-Appboy - tvos_scheme: mParticle-Appboy-tvOS + package_scheme: mParticle-Appboy + supports_tvos: true module: mParticle_Appboy # - name: braze-13 # local_path: kits/braze/braze-13 # dest_repo: mparticle-apple-integration-braze-13 - # scheme: mParticle-Appboy - # tvos_scheme: mParticle-Appboy-tvOS + # package_scheme: mParticle-Appboy + # supports_tvos: true # module: mParticle_Appboy # - name: braze-14 # local_path: kits/braze/braze-14 # dest_repo: mparticle-apple-integration-braze-14 - # scheme: mParticle-Appboy - # tvos_scheme: mParticle-Appboy-tvOS + # package_scheme: mParticle-Appboy + # supports_tvos: true # module: mParticle_Appboy steps: @@ -155,10 +155,44 @@ jobs: security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH - - name: Build kit xcframework + - name: Build kit xcframework from Package.swift + working-directory: ${{ matrix.kit.local_path }} run: | - PROJECT="$(ls -d ${{ matrix.kit.local_path }}/*.xcodeproj | head -1)" - ./Scripts/xcframework.sh "$PROJECT" "${{ matrix.kit.scheme }}" "${{ matrix.kit.tvos_scheme }}" + MODULE="${{ matrix.kit.module }}" + SCHEME="${{ matrix.kit.package_scheme }}" + + xcodebuild archive -scheme "$SCHEME" \ + -destination "generic/platform=iOS" -archivePath "archives/iOS" + xcodebuild archive -scheme "$SCHEME" \ + -destination "generic/platform=iOS Simulator" -archivePath "archives/iOS_Simulator" + + XCFRAMEWORK_ARGS=( + -archive archives/iOS.xcarchive -framework "${MODULE}.framework" + -archive archives/iOS_Simulator.xcarchive -framework "${MODULE}.framework" + ) + + if [ "${{ matrix.kit.supports_tvos }}" = "true" ]; then + xcodebuild archive -scheme "$SCHEME" \ + -destination "generic/platform=tvOS" -archivePath "archives/tvOS" + xcodebuild archive -scheme "$SCHEME" \ + -destination "generic/platform=tvOS Simulator" -archivePath "archives/tvOS_Simulator" + XCFRAMEWORK_ARGS+=( + -archive archives/tvOS.xcarchive -framework "${MODULE}.framework" + -archive archives/tvOS_Simulator.xcarchive -framework "${MODULE}.framework" + ) + fi + + xcodebuild -create-xcframework "${XCFRAMEWORK_ARGS[@]}" -output "${MODULE}.xcframework" + codesign --timestamp -s "Apple Distribution: mParticle, inc (DLD43Y3TRP)" "${MODULE}.xcframework" || { + if [ "${DRY_RUN}" = "true" ]; then + echo "โš ๏ธ Signing identity not found, skipping codesign in dry run" + else + echo "โŒ Signing identity not found for non-dry run" + exit 1 + fi + } + zip -r "${MODULE}.xcframework.zip" "${MODULE}.xcframework" + rm -rf archives "${MODULE}.xcframework" - name: Configure Git run: | diff --git a/Scripts/xcframework.sh b/Scripts/xcframework.sh index afc5f8757..107eb118d 100755 --- a/Scripts/xcframework.sh +++ b/Scripts/xcframework.sh @@ -38,6 +38,18 @@ fi xcodebuild -create-xcframework "${FRAMEWORK_ARGS[@]}" -output "${MODULE}.xcframework" -codesign --timestamp -s "Apple Distribution: mParticle, inc (DLD43Y3TRP)" "${MODULE}.xcframework" +# Codesign if a signing identity is available, skip otherwise +SIGNING_IDENTITY="Apple Distribution: mParticle, inc (DLD43Y3TRP)" +if security find-identity -v -p codesigning | grep -q "${SIGNING_IDENTITY}"; then + codesign --timestamp -s "${SIGNING_IDENTITY}" "${MODULE}.xcframework" +else + if [[ ${DRY_RUN:-false} == "true" ]]; then + echo "โš ๏ธ Signing identity not found, skipping codesign in dry run" + else + echo "โŒ Signing identity not found: ${SIGNING_IDENTITY}" + exit 1 + fi +fi + zip -r "${MODULE}.xcframework.zip" "${MODULE}.xcframework" rm -rf archives "$MODULE.xcframework" From 696b337b4ad4d5171beab0181de91e2063d5a92c Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Tue, 17 Feb 2026 13:47:10 -0500 Subject: [PATCH 24/25] restore xcframework script --- Scripts/xcframework.sh | 62 +++++++++++------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/Scripts/xcframework.sh b/Scripts/xcframework.sh index 107eb118d..d3219f896 100755 --- a/Scripts/xcframework.sh +++ b/Scripts/xcframework.sh @@ -2,54 +2,24 @@ # # xcframework.sh -# Parameters: ./xcframework.sh [project] [ios_scheme] [tvos_scheme (optional)] +# Paramaters: ./xcframework.sh [scheme] # Usage examples: -# ./xcframework.sh mParticle-Apple-SDK.xcodeproj mParticle-Apple-SDK mParticle-Apple-SDK -# ./xcframework.sh kits/braze/braze-12/mParticle-Appboy.xcodeproj mParticle-Appboy mParticle-Appboy-tvOS -# ./xcframework.sh kits/some-kit/SomeKit.xcodeproj SomeKit +# ./xcframework.sh mParticle-Apple-SDK +# ./xcframework.sh mParticle-Apple-SDK-NoLocation # set -euo pipefail -PROJECT=$1 -IOS_SCHEME=$2 -TVOS_SCHEME=${3-} -MODULE=${IOS_SCHEME//[-]/_} - -# iOS (required) -xcodebuild archive -project "${PROJECT}" -scheme "$IOS_SCHEME" -destination "generic/platform=iOS" -archivePath "archives/$IOS_SCHEME-iOS" -xcodebuild archive -project "${PROJECT}" -scheme "$IOS_SCHEME" -destination "generic/platform=iOS Simulator" -archivePath "archives/$IOS_SCHEME-iOS_Simulator" - -FRAMEWORK_ARGS=( - -archive "archives/${IOS_SCHEME}-iOS.xcarchive" -framework "${MODULE}.framework" - -archive "archives/${IOS_SCHEME}-iOS_Simulator.xcarchive" -framework "${MODULE}.framework" -) - -# tvOS (optional) -if [[ -n ${TVOS_SCHEME} ]]; then - xcodebuild archive -project "${PROJECT}" -scheme "$TVOS_SCHEME" -destination "generic/platform=tvOS" -archivePath "archives/$TVOS_SCHEME-tvOS" - xcodebuild archive -project "${PROJECT}" -scheme "$TVOS_SCHEME" -destination "generic/platform=tvOS Simulator" -archivePath "archives/$TVOS_SCHEME-tvOS_Simulator" - - FRAMEWORK_ARGS+=( - -archive "archives/${TVOS_SCHEME}-tvOS.xcarchive" -framework "${MODULE}.framework" - -archive "archives/${TVOS_SCHEME}-tvOS_Simulator.xcarchive" -framework "${MODULE}.framework" - ) -fi - -xcodebuild -create-xcframework "${FRAMEWORK_ARGS[@]}" -output "${MODULE}.xcframework" - -# Codesign if a signing identity is available, skip otherwise -SIGNING_IDENTITY="Apple Distribution: mParticle, inc (DLD43Y3TRP)" -if security find-identity -v -p codesigning | grep -q "${SIGNING_IDENTITY}"; then - codesign --timestamp -s "${SIGNING_IDENTITY}" "${MODULE}.xcframework" -else - if [[ ${DRY_RUN:-false} == "true" ]]; then - echo "โš ๏ธ Signing identity not found, skipping codesign in dry run" - else - echo "โŒ Signing identity not found: ${SIGNING_IDENTITY}" - exit 1 - fi -fi - -zip -r "${MODULE}.xcframework.zip" "${MODULE}.xcframework" -rm -rf archives "$MODULE.xcframework" +SCHEME=$1 +MODULE=${SCHEME//[-]/_} + +xcodebuild archive -project mParticle-Apple-SDK.xcodeproj -scheme $SCHEME -destination "generic/platform=iOS" -archivePath "archives/$SCHEME-iOS" +xcodebuild archive -project mParticle-Apple-SDK.xcodeproj -scheme $SCHEME -destination "generic/platform=iOS Simulator" -archivePath "archives/$SCHEME-iOS_Simulator" +xcodebuild archive -project mParticle-Apple-SDK.xcodeproj -scheme $SCHEME -destination "generic/platform=tvOS" -archivePath "archives/$SCHEME-tvOS" +xcodebuild archive -project mParticle-Apple-SDK.xcodeproj -scheme $SCHEME -destination "generic/platform=tvOS Simulator" -archivePath "archives/$SCHEME-tvOS_Simulator" +xcodebuild -create-xcframework \ + -archive archives/$SCHEME-iOS.xcarchive -framework $MODULE.framework \ + -archive archives/$SCHEME-iOS_Simulator.xcarchive -framework $MODULE.framework \ + -archive archives/$SCHEME-tvOS.xcarchive -framework $MODULE.framework \ + -archive archives/$SCHEME-tvOS_Simulator.xcarchive -framework $MODULE.framework \ + -output $MODULE.xcframework From 071b96536e6ee8313992f5113155499073ee80a9 Mon Sep 17 00:00:00 2001 From: Nickolas Dimitrakas Date: Tue, 17 Feb 2026 13:48:59 -0500 Subject: [PATCH 25/25] remove core release from script --- .../workflows/release-ecosystem-from-main.yml | 107 +----------------- 1 file changed, 4 insertions(+), 103 deletions(-) diff --git a/.github/workflows/release-ecosystem-from-main.yml b/.github/workflows/release-ecosystem-from-main.yml index c76354f6d..b6e67fd8a 100644 --- a/.github/workflows/release-ecosystem-from-main.yml +++ b/.github/workflows/release-ecosystem-from-main.yml @@ -40,68 +40,6 @@ jobs: echo "tag=v$VERSION" >> $GITHUB_OUTPUT echo "๐Ÿ“Œ Ecosystem version: $VERSION" - release-core: - needs: prepare - runs-on: macOS-15 - env: - XCODE_VERSION: "16.4" - steps: - - uses: actions/checkout@v6 - - - name: Select Xcode - run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app - - - name: Install signing certificate - env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_P12 }} - P12_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} - KEYCHAIN_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} - run: | - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH - - - name: Build xcframework - run: ./Scripts/xcframework.sh mParticle-Apple-SDK.xcodeproj mParticle-Apple-SDK mParticle-Apple-SDK - - - name: Extract release notes - id: release-notes - uses: ffurrer2/extract-release-notes@202313ec7461b6b9e401996714484690ab1ae105 # v3.0.0 - with: - changelog_file: CHANGELOG.md - - - name: Dry run summary - if: env.DRY_RUN == 'true' - run: | - cat >> $GITHUB_STEP_SUMMARY <<'EOF' - ## ๐Ÿœ๏ธ DRY RUN โ€” Core SDK Release - - | Property | Value | - |----------|-------| - | **Tag** | `${{ needs.prepare.outputs.tag }}` | - | **Repository** | `mParticle/mparticle-apple-sdk` | - | **Artifact** | `mParticle_Apple_SDK.xcframework.zip` | - - ### Release notes - ${{ steps.release-notes.outputs.release_notes }} - EOF - - - name: Create GitHub release - if: env.DRY_RUN != 'true' - uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 - with: - tag: ${{ needs.prepare.outputs.tag }} - makeLatest: true - artifacts: mParticle_Apple_SDK.xcframework.zip - body: | - ## Release notes - ${{ steps.release-notes.outputs.release_notes }} - mirror-and-release-kits: needs: prepare runs-on: macOS-15 @@ -115,20 +53,17 @@ jobs: - name: braze-12 local_path: kits/braze/braze-12 dest_repo: mparticle-apple-integration-braze-12 - package_scheme: mParticle-Appboy - supports_tvos: true + ios_scheme: mParticle-Appboy module: mParticle_Appboy # - name: braze-13 # local_path: kits/braze/braze-13 # dest_repo: mparticle-apple-integration-braze-13 - # package_scheme: mParticle-Appboy - # supports_tvos: true + # ios_scheme: mParticle-Appboy # module: mParticle_Appboy # - name: braze-14 # local_path: kits/braze/braze-14 # dest_repo: mparticle-apple-integration-braze-14 - # package_scheme: mParticle-Appboy - # supports_tvos: true + # ios_scheme: mParticle-Appboy # module: mParticle_Appboy steps: @@ -140,26 +75,11 @@ jobs: - name: Select Xcode run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app - - name: Install signing certificate - env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_P12 }} - P12_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} - KEYCHAIN_PASSWORD: ${{ secrets.MP_IOS_SIGNING_CERTIFICATE_PASS }} - run: | - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH - - name: Build kit xcframework from Package.swift working-directory: ${{ matrix.kit.local_path }} run: | MODULE="${{ matrix.kit.module }}" - SCHEME="${{ matrix.kit.package_scheme }}" + SCHEME="${{ matrix.kit.ios_scheme }}" xcodebuild archive -scheme "$SCHEME" \ -destination "generic/platform=iOS" -archivePath "archives/iOS" @@ -171,26 +91,7 @@ jobs: -archive archives/iOS_Simulator.xcarchive -framework "${MODULE}.framework" ) - if [ "${{ matrix.kit.supports_tvos }}" = "true" ]; then - xcodebuild archive -scheme "$SCHEME" \ - -destination "generic/platform=tvOS" -archivePath "archives/tvOS" - xcodebuild archive -scheme "$SCHEME" \ - -destination "generic/platform=tvOS Simulator" -archivePath "archives/tvOS_Simulator" - XCFRAMEWORK_ARGS+=( - -archive archives/tvOS.xcarchive -framework "${MODULE}.framework" - -archive archives/tvOS_Simulator.xcarchive -framework "${MODULE}.framework" - ) - fi - xcodebuild -create-xcframework "${XCFRAMEWORK_ARGS[@]}" -output "${MODULE}.xcframework" - codesign --timestamp -s "Apple Distribution: mParticle, inc (DLD43Y3TRP)" "${MODULE}.xcframework" || { - if [ "${DRY_RUN}" = "true" ]; then - echo "โš ๏ธ Signing identity not found, skipping codesign in dry run" - else - echo "โŒ Signing identity not found for non-dry run" - exit 1 - fi - } zip -r "${MODULE}.xcframework.zip" "${MODULE}.xcframework" rm -rf archives "${MODULE}.xcframework"