From 066955c4f16ea97036e76f552a949147178f60ba Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Thu, 16 Nov 2023 09:21:25 +0200 Subject: [PATCH 01/42] chore: remove package resolved file --- Package.resolved | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index cb3de233..00000000 --- a/Package.resolved +++ /dev/null @@ -1,16 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "Mocker", - "repositoryURL": "https://github.com/WeTransfer/Mocker.git", - "state": { - "branch": null, - "revision": "e984416c9e7d773abc476414860bae8e198d7c89", - "version": "2.0.2" - } - } - ] - }, - "version": 1 -} From b5c37af3ea621c85ae7d7760886275754bdec7e7 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Thu, 16 Nov 2023 09:45:04 +0200 Subject: [PATCH 02/42] build: disable carthage --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e293218..09a7fbcf 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/optimove-tech/Optimove-SDK-iOS?style=flat-square)](https://github.com/optimove-tech/Optimove-SDK-iOS/releases/latest) [![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml) ![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) -[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square)](https://github.com/Carthage/Carthage) + + + ![SwiftPM comppatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) ![GitHub](https://img.shields.io/github/license/optimove-tech/Optimove-SDK-iOS?style=flat-square) @@ -41,7 +43,7 @@ In this guide we will go through the following steps necessary to have the basic 4. [Deferred Deep Linking](https://github.com/optimove-tech/Optimove-SDK-iOS/wiki/deferred-deep-linking) > **NOTE**: -To unlock these capabilities, you will need to have added the relevant OptiMobile channels to your Optimove package. If you can’t see this feature in your Optimove instance, contact your CSM to find out more. +> To unlock these capabilities, you will need to have added the relevant OptiMobile channels to your Optimove package. If you can’t see this feature in your Optimove instance, contact your CSM to find out more. ## Migrations From f821a62b0c5ded85bf01fb7dacace8cb29060811 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Thu, 16 Nov 2023 10:19:19 +0200 Subject: [PATCH 03/42] build: version 5.5.0 --- CHANGELOG.md | 2 ++ OptimoveCore.podspec | 2 +- OptimoveCore/Sources/Classes/Constants/SDKVersion.swift | 2 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e666346e..6035b21a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 5.5.0 + ## 5.4.0 - Add the initial visitor identifier getter to public API. The new API is public available via the following methods: diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index 0bbc2a5e..e053a300 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index 2e26d6c4..0c5e0abe 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.4.0" +public let SDKVersion = "5.5.0" diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 32b65fa9..7dbcb490 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index 3873e0f2..6f8b27c4 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.4.0' + s.version = '5.5.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' From 00c1608b0d511f438f0ca08ccb036da9f1f80324 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Thu, 16 Nov 2023 10:31:12 +0200 Subject: [PATCH 04/42] chore: remove carthage badge --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 09a7fbcf..466c64b3 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,6 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/optimove-tech/Optimove-SDK-iOS?style=flat-square)](https://github.com/optimove-tech/Optimove-SDK-iOS/releases/latest) [![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml) ![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) - - - ![SwiftPM comppatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) ![GitHub](https://img.shields.io/github/license/optimove-tech/Optimove-SDK-iOS?style=flat-square) From fc0bb50caa06617503e30e1c07883db85f2d703c Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Thu, 16 Nov 2023 10:31:46 +0200 Subject: [PATCH 05/42] chore: point ci badge to master branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 466c64b3..f57012b3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Optimove SDK iOS [![GitHub release (latest by date)](https://img.shields.io/github/v/release/optimove-tech/Optimove-SDK-iOS?style=flat-square)](https://github.com/optimove-tech/Optimove-SDK-iOS/releases/latest) -[![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml) +[![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml?query=branch%3Amaster) ![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) ![SwiftPM comppatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) ![GitHub](https://img.shields.io/github/license/optimove-tech/Optimove-SDK-iOS?style=flat-square) From 81d59190b4cfb1e13006b789640e000f3cca6d82 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Sun, 19 Nov 2023 12:38:28 +0200 Subject: [PATCH 06/42] chore: return carthage badge --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f57012b3..c8101592 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,9 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/optimove-tech/Optimove-SDK-iOS?style=flat-square)](https://github.com/optimove-tech/Optimove-SDK-iOS/releases/latest) [![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml?query=branch%3Amaster) -![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) ![SwiftPM comppatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) +![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square)](https://github.com/Carthage/Carthage) ![GitHub](https://img.shields.io/github/license/optimove-tech/Optimove-SDK-iOS?style=flat-square) The official Optimove iOS integration frameworks are an SDK for sending analytics to an Optimove server, such as: From aa6287e143bf76de3abe9c44c8f2a1c986d95785 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Mon, 20 Nov 2023 20:53:41 +0200 Subject: [PATCH 07/42] ci: fix the unit tests runner (#80) --- .github/workflows/main.yml | 25 +- CHANGELOG.md | 2 + Cartfile.private | 1 - Optimove.xcodeproj/project.pbxproj | 1448 +++++++++-------- .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/swiftpm/Package.resolved | 14 + .../xcschemes/OptimoveCore.xcscheme | 34 +- ...imoveNotificationServiceExtension.xcscheme | 40 +- .../xcschemes/OptimoveSDK-Unit.xcscheme | 104 -- .../xcschemes/OptimoveSDK.xcscheme | 34 +- .../xcshareddata/xcschemes/UnitTests.xcscheme | 43 +- .../Info.plist | 22 + input.xcfilelist | 3 - output.xcfilelist | 3 - project.yml | 64 +- 15 files changed, 957 insertions(+), 888 deletions(-) delete mode 100644 Cartfile.private delete mode 100644 Optimove.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 Optimove.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved delete mode 100644 Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK-Unit.xcscheme create mode 100644 OptimoveNotificationServiceExtension/Info.plist delete mode 100644 input.xcfilelist delete mode 100644 output.xcfilelist diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ac613105..b37e6220 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,22 +1,13 @@ name: CI - on: [push] - jobs: - build: - + unit-tests: runs-on: macOS-latest - - env: - DEVELOPER_DIR: /Applications/Xcode_13.2.1.app/Contents/Developer - steps: - - uses: actions/checkout@v1 - - run: carthage update --use-xcframeworks --cache-builds - name: Carthage - - name: Install xcbeautify - run: brew install xcbeautify - - run: set -o pipefail && xcodebuild build-for-testing -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 11" | xcbeautify - name: Build - - run: set -o pipefail && xcodebuild test-without-building -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 11" | xcbeautify - name: Test + - uses: actions/checkout@v1 + - run: brew install xcbeautify + name: Install dependencies + - run: set -o pipefail && xcodebuild build-for-testing -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 14" | xcbeautify + name: Build + - run: set -o pipefail && xcodebuild test-without-building -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 14" | xcbeautify + name: Test diff --git a/CHANGELOG.md b/CHANGELOG.md index 6035b21a..e62cc595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 5.5.0 +- Increased the minimum supported iOS version to 12.0 for Carthage builds. + ## 5.4.0 - Add the initial visitor identifier getter to public API. The new API is public available via the following methods: diff --git a/Cartfile.private b/Cartfile.private deleted file mode 100644 index 57bd269a..00000000 --- a/Cartfile.private +++ /dev/null @@ -1 +0,0 @@ -github "WeTransfer/Mocker" ~> 1.0 \ No newline at end of file diff --git a/Optimove.xcodeproj/project.pbxproj b/Optimove.xcodeproj/project.pbxproj index 233dd515..dad3264a 100644 --- a/Optimove.xcodeproj/project.pbxproj +++ b/Optimove.xcodeproj/project.pbxproj @@ -3,150 +3,131 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 00F83D263F7049A8120B7A8A /* Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = A435A55F6D788D0ACF8085E2 /* Querying.swift */; }; 02DBEFA60A144B6092D92082 /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5F014AB9AE645C920DD038B /* NetworkRequest.swift */; }; - 03A06957E14DE9C264FD3BF4 /* EnterForegroundObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81BC45AB12DCB12A09904FB2 /* EnterForegroundObserverTests.swift */; }; - 04B351D1EFFA33FBD8A9D3CB /* GlobalConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF221484A7B1A433DB7FAD1 /* GlobalConfigTests.swift */; }; 05A2444050AEF0639DC080AC /* RemoteLoggerStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4592839140B76A8D32F05DC8 /* RemoteLoggerStream.swift */; }; 05FCC9633BD5578A77355ABF /* GlobalConfigurationDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B664ECF492F1657FC2D7036 /* GlobalConfigurationDownloader.swift */; }; - 080AE4F487F030AAC3EC2A30 /* NetworkClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6303DE7E28C8787FD8F3FA0 /* NetworkClientTests.swift */; }; 0B72803435C92BA78FD76BD0 /* MultiplexLoggerStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4713C0DA9400A929216B24D /* MultiplexLoggerStream.swift */; }; 0C81F538D5D809D568CBB16F /* ProcessInfo+OsVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB578140EEA0C61258F4C95 /* ProcessInfo+OsVersion.swift */; }; 0E86E3145ADEEE0A91734327 /* NetworkingFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2476035D945779F9130EAD /* NetworkingFactory.swift */; }; - 106BA1705BF376B6A7D81815 /* EventValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E0C85115B44FC36030D67CE /* EventValidatorTests.swift */; }; + 0F0AE34073703DC410DD4F4C /* Optimobile+DeepLinking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A02A48A58BD785A723E329 /* Optimobile+DeepLinking.swift */; }; + 1093F068DD247478DC5D67C5 /* CwlSysctl.swift in Sources */ = {isa = PBXBuildFile; fileRef = C53585DB5D3958C136A7AA42 /* CwlSysctl.swift */; }; 10D8FDCAB2DEDFDC34E715E9 /* MobileProvision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D52112BF287F638A45398EB /* MobileProvision.swift */; }; - 1277E48A2811B2AA0097AC3B /* Mocker.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4FE394EA27C78933005FABB0 /* Mocker.xcframework */; }; - 1277E48B2811B2AF0097AC3B /* Mocker.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4FE394EA27C78933005FABB0 /* Mocker.xcframework */; }; - 1277E48C2811B39C0097AC3B /* Mocker.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4FE394EA27C78933005FABB0 /* Mocker.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1277E48D2811B3A80097AC3B /* Mocker.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4FE394EA27C78933005FABB0 /* Mocker.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1277E48F2812AF650097AC3B /* AppOpenObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1277E48E2812AF650097AC3B /* AppOpenObserver.swift */; }; - 129D63E428199276005DCB7F /* OptimoveNotificationExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129D63E328199276005DCB7F /* OptimoveNotificationExtensionTests.swift */; }; - 12C3562A281194D500672B42 /* KSHttp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35621281194D500672B42 /* KSHttp.swift */; }; - 12C3562B281194D500672B42 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35622281194D500672B42 /* AnalyticsHelper.swift */; }; - 12C3562C281194D500672B42 /* KeyValPersistenceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35623281194D500672B42 /* KeyValPersistenceHelper.swift */; }; - 12C3562D281194D500672B42 /* OptimobileUserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35624281194D500672B42 /* OptimobileUserDefaultsKey.swift */; }; - 12C3562E281194D500672B42 /* AppGroupsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35625281194D500672B42 /* AppGroupsHelper.swift */; }; - 12C3562F281194D500672B42 /* OptimobileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35626281194D500672B42 /* OptimobileHelper.swift */; }; - 12C35630281194D500672B42 /* PendingNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35627281194D500672B42 /* PendingNotification.swift */; }; - 12C35631281194D500672B42 /* PendingNotificationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35628281194D500672B42 /* PendingNotificationHelper.swift */; }; - 12C35632281194D500672B42 /* MediaHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35629281194D500672B42 /* MediaHelper.swift */; }; - 12C3565A281196AB00672B42 /* OptimoveNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12C35652281196AB00672B42 /* OptimoveNotificationServiceExtension.framework */; }; - 12C35669281197A800672B42 /* OptimoveNotificationExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 12C35668281197A800672B42 /* OptimoveNotificationExtension.h */; }; - 12C356722811987C00672B42 /* OptimoveNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA8FC4F280C410B005CB88E /* OptimoveNotificationService.swift */; }; - 12C356732811987C00672B42 /* CategoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C8827FECD3E005E7BB4 /* CategoryManager.swift */; }; - 12C356742811992800672B42 /* KSHttp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35621281194D500672B42 /* KSHttp.swift */; }; - 12C356752811992B00672B42 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35622281194D500672B42 /* AnalyticsHelper.swift */; }; - 12C356762811992E00672B42 /* KeyValPersistenceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35623281194D500672B42 /* KeyValPersistenceHelper.swift */; }; - 12C356772811993100672B42 /* OptimobileUserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35624281194D500672B42 /* OptimobileUserDefaultsKey.swift */; }; - 12C356782811993400672B42 /* AppGroupsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35625281194D500672B42 /* AppGroupsHelper.swift */; }; - 12C356792811993700672B42 /* OptimobileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35626281194D500672B42 /* OptimobileHelper.swift */; }; - 12C3567A2811993A00672B42 /* PendingNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35627281194D500672B42 /* PendingNotification.swift */; }; - 12C3567B2811993C00672B42 /* PendingNotificationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35628281194D500672B42 /* PendingNotificationHelper.swift */; }; - 12C3567C2811993F00672B42 /* MediaHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C35629281194D500672B42 /* MediaHelper.swift */; }; - 12C3567E28119AD600672B42 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12C3567D28119AD600672B42 /* CoreData.framework */; }; - 12C3568028119AFC00672B42 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12C3567F28119AFC00672B42 /* UserNotifications.framework */; }; - 12C3568228119B0200672B42 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12C3568128119B0200672B42 /* UIKit.framework */; }; + 1109CC1061D9544E838C29E9 /* EnterForegroundObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58F74929F41D70EC7E3F9770 /* EnterForegroundObserverTests.swift */; }; 14F57E7FCA077C242AAE0A3C /* OptimoveSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F195D6A74F16DC039009B692 /* OptimoveSDK.framework */; }; 167EF8E42EABC80FEB2D2A1A /* AppOpenEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506941ABF70087E99952FFD6 /* AppOpenEvent.swift */; }; 16875DAAA0249966FAF85615 /* GlobalConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6C2AA83233AE32D981F3555 /* GlobalConfig.swift */; }; 16A2E2E9FFB751FC02A26BA3 /* TenantConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197CDA59D9D767513A115BDF /* TenantConfigFixture.swift */; }; - 19FAAD1B5B8F3A83CCE1681A /* MockConfigurationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E1C1A66CA07D50B6692CA7B /* MockConfigurationRepository.swift */; }; + 17E31410E98A8F445EAE07DA /* Optimobile+Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 424C0E3A1B4058EA4F789D44 /* Optimobile+Analytics.swift */; }; + 187A9CE9D150CF733D6496B7 /* OptimoveInApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11A5E8AF0D04EA97AA273293 /* OptimoveInApp.swift */; }; 1A4FD956C218500F124C94B1 /* ConfigurationFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D46EC93293B7579E9D7389 /* ConfigurationFetcher.swift */; }; + 1ABDB154E19C9B5366833376 /* Mocker in Frameworks */ = {isa = PBXBuildFile; productRef = ACA40D16D367805D921E4139 /* Mocker */; }; 1B4C918AC447976BF1DEA991 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 810A2719EF2B688A621CC8E4 /* Endpoint.swift */; }; 1B53825BF840C81BE1B3922F /* ISO+format.swift in Sources */ = {isa = PBXBuildFile; fileRef = E301AF207069DC3417330D23 /* ISO+format.swift */; }; 1CF1B6182320C994F7F4FC45 /* ProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1444FD543ED01363BB8CB274 /* ProcessInfo.swift */; }; 1D3E9806CE83FC237BAD4EB4 /* CoreEventFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0B5F1859EF1DA75FD01507 /* CoreEventFactory.swift */; }; - 1EC0331B7F3631CAFF5B4BE7 /* MockDateTimeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C1E626E9F4FECB13D350B0 /* MockDateTimeProvider.swift */; }; 1ECCB650EA8E2C46B9C74A6B /* LoggerInitializator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5217E6590AD8BD80A6985CC /* LoggerInitializator.swift */; }; - 1F0A3376596C3A8290383CD0 /* RemoteConfigurationRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C981D5B3D94C295BE60C2A /* RemoteConfigurationRequestBuilderTests.swift */; }; 1FB88D00B177B21B5D2C3BC2 /* NSManagedObjectContext+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6A19CA28B9B8E5119C61AE0 /* NSManagedObjectContext+Utilities.swift */; }; + 219417667A6FFDD03148C7ED /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC92AA41EF0FDB2098B2E829 /* Foundation.framework */; }; + 241379B33EC9E7F315FE2E8C /* MockDateTimeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519339A7CE43CB33F054E48C /* MockDateTimeProvider.swift */; }; 24AB2C2FB4F38FB0FFA4F61F /* ConfigurationFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4268499EEA7348C481371C /* ConfigurationFixture.swift */; }; 25F544315A08320ED72755A2 /* ConsoleLoggerStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8228C916C97D8339F724B907 /* ConsoleLoggerStream.swift */; }; 2831D1D6A605C2B8A6B57080 /* NewVisitorIdGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A483534D00B52DA236BB0B05 /* NewVisitorIdGenerator.swift */; }; + 28892C11EFABDB720CA7F4DE /* OptistreamNetworkingMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F2CF1316A8FD7BEFB64F3C /* OptistreamNetworkingMock.swift */; }; + 29157AAD85CBDBAC17C3A62A /* SetUserIdEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CE007CEFA3504B48265FAA /* SetUserIdEventTests.swift */; }; 2977E8E0057FF4A3E65A5E5A /* ConfigurationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111ED6383A53D5F33F54CEFF /* ConfigurationRepository.swift */; }; + 2A639EA131398E39B22B6D62 /* UserIDValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEAF62F3CA25FB3BE2AFE9D /* UserIDValidatorTests.swift */; }; + 2BBFB2D03A135BE343DCB352 /* OptimoveTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A3329FC290A675F44BEBFE /* OptimoveTestCase.swift */; }; 2C574877A3CB27755321D077 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C91AEC3B6BA8441109CBF58E /* CoreData.framework */; }; - 2D5CC37EBB1EFCC1DAB9C396 /* AppOpenEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99FBF8FEACC0C375A4C64F59 /* AppOpenEventTests.swift */; }; + 2E41CAC99770B430CCA80976 /* OptimobileBadgeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9526C15EA2A7A5548367647 /* OptimobileBadgeObserver.swift */; }; 2EA9D0284826D6D32BFA3219 /* OptiLoggerStreamsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C3181EDC81DAA89624DFD4B /* OptiLoggerStreamsContainer.swift */; }; + 2EE7C3F42D91857A85DB8A5B /* GlobalConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00AD8964C31889A296AF6ACE /* GlobalConfigTests.swift */; }; 321BFE49BBD5B3C8C0F24618 /* CoreDataMigrationVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F317F849DA6211A6DBB52A93 /* CoreDataMigrationVersion.swift */; }; - 34F891B25C0607047E535D8D /* PageVisitEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8411A92C5ADEF8363F217CD /* PageVisitEventTests.swift */; }; + 329179D5BF60BC810A939B9A /* NewUserIDHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2797AD0BB5BD176932C38C6 /* NewUserIDHandlerTests.swift */; }; + 32D946F7508437FFF4870EA8 /* core_events.json in Resources */ = {isa = PBXBuildFile; fileRef = 0FA5B03E91EC1B9C8B7A921A /* core_events.json */; }; + 36D0BE577A817ED7B5076112 /* GlobalConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558B0FF7FB691AD7EF1BC356 /* GlobalConfigFixture.swift */; }; 370BDBC6F608BEE16E9B7439 /* StubVariables.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE2A46DD2F42545E3AD9B152 /* StubVariables.swift */; }; - 39EC499624AEE7CFC0B677B5 /* CoreDataMigratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBAAF543B9FFEE56AFCA272 /* CoreDataMigratorTests.swift */; }; + 372E500B05099415082BF745 /* PendingNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F841AF4345B15514C71B49 /* PendingNotification.swift */; }; + 375F0DD93BA5A985979D5FB8 /* PendingNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499FB65BC432D40BBB409525 /* PendingNotification.swift */; }; 39F0A8EF590E06C63B8AA931 /* Operations.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2913A221183842BA07EF8F5 /* Operations.swift */; }; - 3A758813E0D3A1DFD74286FB /* OptimoveFileManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F0DCFD3F00AA505DC781F4 /* OptimoveFileManagerTests.swift */; }; + 3C4DED7A2092B00C6092CE9B /* TenantConfigurationDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D92D7E5297901568A91938B /* TenantConfigurationDownloaderTests.swift */; }; 3CA51DAAF7A58E28A27F04AE /* EventCDv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAF333FF2B62FF3501A4009A /* EventCDv2.swift */; }; + 3E1BFD924A9840F55AD60E52 /* MockSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67F3D2B3855E155D386037EE /* MockSynchronizer.swift */; }; 3F44720B367301EC17CC321B /* RuntimeCodingKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26931EEB560FA3B43177A022 /* RuntimeCodingKey.swift */; }; - 419EFD0DCB8F3A6D4017D32B /* SetUserAgentEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 799B1ECA74F09CE9EFDCC893 /* SetUserAgentEventTests.swift */; }; + 40745C5D6447231E96262ACB /* FileAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FFBD8E3E3EC13859EAA9E9 /* FileAccessible.swift */; }; + 40B1374F1803D46BB3783951 /* MediaHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A26871854B50CF09EED86457 /* MediaHelper.swift */; }; + 40F8D5713430223076ED4DA8 /* OptimobileUserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AFA2A8587C5DCA93A30108 /* OptimobileUserDefaultsKey.swift */; }; + 419C1099146E429DD1D1B87A /* StringSplitByLenghtExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA43948B8DBCBDF5A334FC9 /* StringSplitByLenghtExtensionsTests.swift */; }; 41E93887039BA10C580D3F60 /* ComponentFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 673FD2495FF2C13EFC81D1AA /* ComponentFactory.swift */; }; + 42822ABF4ACA9B04100FAF90 /* OptimoveUserNotificationCenterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC97786EB5AC1048109A3199 /* OptimoveUserNotificationCenterDelegate.swift */; }; 42E7D72B7C7AA46303506250 /* utsname+DeviceModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA021ACCF4173B1F67D03BD /* utsname+DeviceModel.swift */; }; 431DE4439C07216FF2020D9E /* StubVariables.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE2A46DD2F42545E3AD9B152 /* StubVariables.swift */; }; 432EE244D778884AEA4A9208 /* OptiLoggerOutputStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D85DCA28C5381DEE1370C6D /* OptiLoggerOutputStream.swift */; }; 44462C39B5A869E6521A9F5B /* UserDefaults+Optimove.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9FE5A14C58728AE872409BB /* UserDefaults+Optimove.swift */; }; 454AB713344799303679A602 /* Assembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 566B20B2B1E2E316902899F3 /* Assembly.swift */; }; 45AA5FDB34AD5ED3F78A8040 /* NetworkClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0CFD51DD85596306B721E0 /* NetworkClient.swift */; }; - 45AEE0276D250CF2208C644E /* OnStartEventGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1D9A9EC40981BD427CB4C /* OnStartEventGeneratorTests.swift */; }; 45E8890FB696618F19DE0E1C /* OptimoveSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F195D6A74F16DC039009B692 /* OptimoveSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4706D362A1B3BD2B148D9DDE /* NetworkResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB19792511783857E3051963 /* NetworkResponse.swift */; }; 499D5BF06BBCC8EBB94263E4 /* Optimove.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA418E3FDBEB318519B1F183 /* Optimove.swift */; }; + 49A29F260B5CF8363DFD6A72 /* MockStatisticService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 001618E0FA4F7439090C2029 /* MockStatisticService.swift */; }; 4B583BA9BF1C2FA8274AACD3 /* String+Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB8B22F680152DE4E7C00A7 /* String+Split.swift */; }; 4C7AA28A09CA23B070FFB281 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EC09BC1C5CB77E5AD50317 /* NetworkError.swift */; }; + 4D9E6D1B430F63500E3BE7C1 /* configs.json in Resources */ = {isa = PBXBuildFile; fileRef = EA680F149CF17AE295CEA268 /* configs.json */; }; 4E1437373721EFA52C894174 /* OptistreamQueueImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC4935D2FE2C45DF3CE8086 /* OptistreamQueueImpl.swift */; }; - 4F585C6827FECCFA005E7BB4 /* InAppPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5327FECCFA005E7BB4 /* InAppPresenter.swift */; }; - 4F585C6927FECCFA005E7BB4 /* InAppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5427FECCFA005E7BB4 /* InAppManager.swift */; }; - 4F585C6A27FECCFA005E7BB4 /* InAppModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5527FECCFA005E7BB4 /* InAppModels.swift */; }; - 4F585C6B27FECCFA005E7BB4 /* OptimoveConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5627FECCFA005E7BB4 /* OptimoveConfig.swift */; }; - 4F585C6C27FECCFA005E7BB4 /* Optimobile+DeepLinking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5727FECCFA005E7BB4 /* Optimobile+DeepLinking.swift */; }; - 4F585C6D27FECCFA005E7BB4 /* SessionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5827FECCFA005E7BB4 /* SessionHelper.swift */; }; - 4F585C6F27FECCFA005E7BB4 /* OptimoveInApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5A27FECCFA005E7BB4 /* OptimoveInApp.swift */; }; - 4F585C7027FECCFA005E7BB4 /* CwlSysctl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5B27FECCFA005E7BB4 /* CwlSysctl.swift */; }; - 4F585C7127FECCFA005E7BB4 /* Optimobile+Push.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5D27FECCFA005E7BB4 /* Optimobile+Push.swift */; }; - 4F585C7227FECCFA005E7BB4 /* Optimobile+Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C5E27FECCFA005E7BB4 /* Optimobile+Stats.swift */; }; - 4F585C7427FECCFA005E7BB4 /* Optimobile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C6027FECCFA005E7BB4 /* Optimobile.swift */; }; - 4F585C7527FECCFA005E7BB4 /* UrlBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C6127FECCFA005E7BB4 /* UrlBuilder.swift */; }; - 4F585C7627FECCFA005E7BB4 /* OptimoveUserNotificationCenterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C6327FECCFA005E7BB4 /* OptimoveUserNotificationCenterDelegate.swift */; }; - 4F585C7727FECCFA005E7BB4 /* Optimobile+Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C6427FECCFA005E7BB4 /* Optimobile+Analytics.swift */; }; - 4F585C7827FECCFA005E7BB4 /* DeepLinkFingerprinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F585C6527FECCFA005E7BB4 /* DeepLinkFingerprinter.swift */; }; - 4FA8F61727FEE872005CB88E /* OptimobileBadgeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FA8F61627FEE872005CB88E /* OptimobileBadgeObserver.swift */; }; + 4F8B14A78177D5D88B803A09 /* OnStartEventGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A8395C246A7545F57AD323D /* OnStartEventGeneratorTests.swift */; }; + 503930654F8FCECBDE14DA5B /* Optimobile+Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = B271013567534CB962F6D4B7 /* Optimobile+Stats.swift */; }; 50B6E591AC81B656E87934F7 /* NetworkRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66A8F39D35D2D3237AD0F678 /* NetworkRequestFactory.swift */; }; 5231F567663FDB98A45B2BB7 /* CoreDataFetchIndexDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48695180D12E3F6E69B27A64 /* CoreDataFetchIndexDescription.swift */; }; 529587C2B105ADD76A48F003 /* String+alphanumeric.swift in Sources */ = {isa = PBXBuildFile; fileRef = 877F4A8A9B50FDB1E7C91CF4 /* String+alphanumeric.swift */; }; - 54B57794ADCCA618D003408C /* SetUserEmailEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90E69482E5CEF73C23265A7 /* SetUserEmailEventTests.swift */; }; - 54F23EA51AD50E499F2D44AF /* configs.json in Resources */ = {isa = PBXBuildFile; fileRef = 38D5D03A189D6E46D85E120B /* configs.json */; }; + 52C8D4888B17B9C62D68D6E2 /* PageVisitEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B17EE5D9F063E3BBCB9A394 /* PageVisitEventTests.swift */; }; + 5324FCF377FE827FDE0A97F3 /* AppOpenObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073FA862A2FB4E726ACB520 /* AppOpenObserver.swift */; }; 5518455C199FC2B155304797 /* OptistreamEventBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DAFF319BE8F13B7DAAE338D /* OptistreamEventBuilder.swift */; }; 55754C0209B72C6239CCE64E /* OperationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECFE1A26CB2C36CBBE414871 /* OperationFactory.swift */; }; - 567FF1C790FA8B2A7FAC4F7F /* InstallationIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 809CCE6596151864378607B5 /* InstallationIdTests.swift */; }; 58C3F746E854C6C27FF1CF12 /* NewUserHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41F1FDC6F647A5DD31FCB29D /* NewUserHandler.swift */; }; + 5925077A28967E98CF5186C8 /* dev.tid.107.optipush.json in Resources */ = {isa = PBXBuildFile; fileRef = C8241EEFCB9733F06963B4E9 /* dev.tid.107.optipush.json */; }; 599FA52041C9CB1EDAD6D399 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89E7B8102C3B8854279817C1 /* Notification.swift */; }; 5A08B9EDBA80168AC667425D /* RingBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC23809D9F4BD02A13F8C661 /* RingBuffer.swift */; }; 5AF8B551D48AF8A7B37B2054 /* SDKInitializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147C9BEF1567B21AF4FB6CB4 /* SDKInitializer.swift */; }; + 5B7214C0497E11CCE22E934C /* TenantConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CCCFCA414EC7FAB65526C40 /* TenantConfigTests.swift */; }; 5C1ED211A45E17583F4499F1 /* SdkPlatform.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36EE80C309330F735D037E2 /* SdkPlatform.swift */; }; + 5C4AC13BA561A2D0EE691A7D /* KeyValPersistenceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F251A2E671B4575611FC81D5 /* KeyValPersistenceHelper.swift */; }; 5CAA99328294F84AB95EF9D2 /* ParametersDecorator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D97B467542E88DEE0300315 /* ParametersDecorator.swift */; }; + 5DF5F01D307C2628D8F1933E /* OptimoveNotificationExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = CF7096F588EBF070FC5E5A05 /* OptimoveNotificationExtension.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5E053F49077A89C08CF54B5F /* OptimoveCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2764B249D4CC9907122D2773 /* OptimoveCore.framework */; }; + 5E1A337AFFC98DDAB8BBE389 /* ConfigurationBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820E8A2D77B2A2DC2D76830 /* ConfigurationBuilderTests.swift */; }; 5EFB943F708BFECD8C7122C4 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04629380902B7E31CF43D52 /* Container.swift */; }; + 60E4C4DA168F42BD72990C1D /* PendingNotificationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 122C3D0E6C2CD0AF1A51CDFD /* PendingNotificationHelper.swift */; }; 61942EEA31C1310BA660F131 /* Pipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004C06ABAB7629E27139CBB0 /* Pipe.swift */; }; + 61D2F706F2433B8CBFD3353E /* CoreEventFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFC9209245A84DF915EF074 /* CoreEventFactoryTests.swift */; }; 626B1AF99FD89EB1053D308D /* FileAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FFBD8E3E3EC13859EAA9E9 /* FileAccessible.swift */; }; 64C373178EC3796339003DA1 /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0743DA20AB28DD7E78A80384 /* String+SHA1.swift */; }; + 64D81E877A58866CDD528539 /* InAppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2B4035AC1EEB59B3534409 /* InAppManager.swift */; }; 68FA63CCDADAD13FA979A68B /* String+random.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6D1C3E09195F4AA62DE80C /* String+random.swift */; }; 695F98AE4990411750376C41 /* UserValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C032549A1F8BD134783F0F90 /* UserValidator.swift */; }; - 69B4B6E228E5E2309F8FA445 /* KeyValueStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B51D44551B095F9BA4EDBD /* KeyValueStorageTests.swift */; }; 6AE6747FCF19E211146D3E1C /* StubEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432D5D39398212165A5C8188 /* StubEvent.swift */; }; 6B24F6C2EC13F075699916A3 /* GlobalFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1AEF7257DAA1A2E7FB12680 /* GlobalFunctions.swift */; }; - 6D08783D81F2B6D01BC5EA96 /* NewTenantInfoHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1E54304B64D97CC42E8D49 /* NewTenantInfoHandlerTests.swift */; }; 6DF6C1462D8DE0D23050BC75 /* DeviceStateObserverFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93BD2C49D756A97FA8D57EEC /* DeviceStateObserverFactory.swift */; }; 6E486EE6C7212E4017EE5F1A /* CoreDataRelationshipDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F400A7074360186390E1B18 /* CoreDataRelationshipDescription.swift */; }; 6EBAAB8917D02E887688A33D /* SetUserEmailEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F08A0D27C5C445E0BB3E46F9 /* SetUserEmailEvent.swift */; }; + 6EE18CD5F112D6AE7F1AB025 /* EventValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88CF3369980060D3BBC1DE9C /* EventValidatorTests.swift */; }; 6F2F6C1080B6763E7EE538D2 /* UserAgentGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D5405AF08AADF9DA4ED566 /* UserAgentGenerator.swift */; }; + 717BAF1D2639397092D4F216 /* Optimobile+Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3748E6F34B34958063B39F /* Optimobile+Location.swift */; }; + 718D7492799EC4068EF80F67 /* OptimobileUserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66905FCA4315A6615953B49B /* OptimobileUserDefaultsKey.swift */; }; 722BC1AC4D6531387A33F03C /* Bundle+Identifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054E84169CA88075A3A99AC4 /* Bundle+Identifiers.swift */; }; + 72AE4BC46B4A6A97E92622C3 /* OptimoveNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F686E9E2A2C29366BCDF0A37 /* OptimoveNotificationService.swift */; }; + 72D7D833022337E4C0CF9A11 /* OptimobileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F3F81B42DD7AA8AB1BEE7A /* OptimobileHelper.swift */; }; 7323B3246BBFECE6F63A3C12 /* Parameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F107FD1650EBED990862F73F /* Parameter.swift */; }; 74748751E3D0F685C3817AF3 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BB88B00B9C963F44DC8B5BD /* JSON.swift */; }; 74EB8910931416EBF66AEF33 /* Result+Successful.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37DA0C731A733771D08D4AE /* Result+Successful.swift */; }; 751E3FAF2723291C46042204 /* RealTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6424915844F66E0315561874 /* RealTime.swift */; }; + 7556ED67ED844CC556897F49 /* NewEmailHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6905325DDD3A3EAAB1BEB8DB /* NewEmailHandlerTests.swift */; }; 75DB09C4A3AD43DB5FDF2384 /* LoggerStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADF1A285E540507DACCA9630 /* LoggerStream.swift */; }; + 75F3E331C128231A1447AE8F /* GlobalConfigurationDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F791A0A07B1FC8F38A4B300 /* GlobalConfigurationDownloaderTests.swift */; }; 7699EE3297E8F95D98A71453 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F9045DB7CC19B7319FF581C /* Configuration.swift */; }; - 7718B45F3E6F2D43C6A5ED3F /* StringSplitByLenghtExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70EC39175948194604CEA34B /* StringSplitByLenghtExtensionsTests.swift */; }; 7896AC2FA8B7D13761660979 /* CoreDataModelDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7296983D1D2B5111D175002E /* CoreDataModelDescription.swift */; }; 78B7E961DD94BC6F19DF9A86 /* PersistentContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4712B5B2BEABC3056055F6 /* PersistentContainer.swift */; }; 7946547A4A94770AE03156AE /* LocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035801D597864BD02A3F3C22 /* LocationService.swift */; }; @@ -154,130 +135,158 @@ 79CD25EC4E940F6CEC7C0F03 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = F521F3899C0EF7438BF1B510 /* String.swift */; }; 7A0EA2106501AF83CA31D429 /* Bundle+HostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 902802B4E5C089844C2664BB /* Bundle+HostApp.swift */; }; 7AE7A3860389CA7E12F38A22 /* Bundle+AppVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C7E4CB736102AA3142CF32 /* Bundle+AppVersion.swift */; }; + 7AEB43BFC0E814FEBEE5BC1F /* Optimobile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EF34D1DAF7ADB95EAD9DA5 /* Optimobile.swift */; }; 7BE7BAF7F0270B023402E320 /* MergeRemoteConfigurationOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90E162F7544DA049B672F903 /* MergeRemoteConfigurationOperation.swift */; }; 7C3ABD85CE679B016ACD1C54 /* OptimoveKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36CB93F7FDDCB7374DA1CF9A /* OptimoveKeys.swift */; }; 7CAF4566492123A582434AD8 /* core_events.json in Resources */ = {isa = PBXBuildFile; fileRef = 0FA5B03E91EC1B9C8B7A921A /* core_events.json */; }; 7EE04A5EE212B2BC27F2C27F /* AsyncOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F0710E98EE949C1E5B12D69 /* AsyncOperation.swift */; }; + 82BC01FC37CB7BFFECFD693F /* AppGroupsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C03DD4D5F885584BA44C723 /* AppGroupsHelper.swift */; }; 82CC6AF0987CCEDF01CBF175 /* EventCDv1ToEventCDv2MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EE2E999B017357AC26A334F /* EventCDv1ToEventCDv2MigrationPolicy.swift */; }; - 83F8B837C82ED3DCCCF9F7FF /* UserIDValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F41B5FDAD6DB908750FDF0 /* UserIDValidatorTests.swift */; }; + 82DD6003F6614083DF6595C0 /* Optimobile+Push.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AFB035DD1E2D7DC2B47931 /* Optimobile+Push.swift */; }; + 862030422F6926A50EB96D6B /* RemoteConfigurationRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D65364A8DE8DCCC7C91AB5 /* RemoteConfigurationRequestBuilderTests.swift */; }; 866DC15E07B22C2BFE8F3EE8 /* DeviceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = F19A915CFE10EE5B80BD3AC2 /* DeviceStateObserver.swift */; }; - 86D018D4B3FDD1E5654A80B3 /* OptiTrackMockQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC14F9097C510CCDFC24ED44 /* OptiTrackMockQueueTests.swift */; }; 87034323076ABC016360E1A9 /* OptimoveCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2764B249D4CC9907122D2773 /* OptimoveCore.framework */; }; 8745A35FD66BE3126AC53223 /* FileStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0A274FE5BD042E03429284 /* FileStorage.swift */; }; + 88545DD026AD8D8E19F3F074 /* AppOpenEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86F4EE2D46B15E8B8B8EA016 /* AppOpenEventTests.swift */; }; 885DA88EB22848769955C0B7 /* OptimoveTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A3329FC290A675F44BEBFE /* OptimoveTestCase.swift */; }; + 891CCE01D5422F4D4E00B469 /* MergeRemoteConfigurationOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16A5BA2BFD07BCE1E201ADE /* MergeRemoteConfigurationOperationTests.swift */; }; + 8A548FA8E34257081564E4C3 /* DeepLinkFingerprinter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75D46D778B83D1E41AA1FADB /* DeepLinkFingerprinter.swift */; }; 8A615E8D19A27C22DC4DF552 /* NewTenantInfoHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D74FD73F62F2896D05BAFD1 /* NewTenantInfoHandler.swift */; }; 8BD11324583CA0D4625E3036 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC92AA41EF0FDB2098B2E829 /* Foundation.framework */; }; + 8C2A67FF1C272E8180249A3A /* MockLocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F4CC9BEB348E9F9D32891 /* MockLocationService.swift */; }; 8C71F306E9E7351F124BE516 /* RemoteConfigurationRequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B4DBAC7E85E0B9DB5C0E1DD /* RemoteConfigurationRequestBuilder.swift */; }; 8D229B5DC22108C54B21D53B /* EmailValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E527862BE390ACDCE2EE444 /* EmailValidator.swift */; }; 8D24DBF32623CCCAB9652019 /* OptiTrack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B5B5EC7877594E3E96DBCC /* OptiTrack.swift */; }; 8D28D0CF3F9FFB3CFCDD6B6F /* OnStartEventGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD108B5E64EF357FD2D9FEE1 /* OnStartEventGenerator.swift */; }; + 8EE975D03F10EEBA319452CD /* OptimoveFileManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8290F6F2D17FBA5D0D19383C /* OptimoveFileManagerTests.swift */; }; 9025A728FB6F87551D520BE6 /* KeyPath+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59CFEFE7F3B5B02C084AB068 /* KeyPath+Extension.swift */; }; 91EFA9B02C815F93C7725986 /* PageVisitEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669DFBB1484B628AAF9DB0DB /* PageVisitEvent.swift */; }; 92292E5A182ECEBFFDF259AE /* Pipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DCCD1C9CFAC7AA464E02A4 /* Pipeline.swift */; }; - 94CE3D9CC6C61823F42F022E /* OptitrackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C421DD075F5131CFD24CA6 /* OptitrackTests.swift */; }; - 94F0C89849632523B9598FA4 /* MockOptistreamQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD86A64C2F3772F4CCCBB335 /* MockOptistreamQueue.swift */; }; + 929E35FD131B942202950B5B /* OptimoveNotificationExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F60CE8D6E405DAC4EBCEE3C /* OptimoveNotificationExtensionTests.swift */; }; + 957510FD9374B0360E0B2495 /* NewTenantInfoHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B7CAD06AF20B0ACA56C962 /* NewTenantInfoHandlerTests.swift */; }; 95D574CDBD1AD0C0416C0CA2 /* ParametersNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA35DE83F5306D2EB306C1 /* ParametersNormalizer.swift */; }; - 9839623196598C955928FEA0 /* KVOExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2027ED43354F4EB835FA0AA0 /* KVOExpectation.swift */; }; 98C5A68EE8133BD14877F57B /* Dictionary+CompactMapKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65CA140085BC23AFEE47F451 /* Dictionary+CompactMapKeys.swift */; }; - 98F9B9E29920E18313F20771 /* MockLocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CED5C535C1EC8A385B8976A /* MockLocationService.swift */; }; 9CB2C5384B4414B52C02DBBD /* OptistreamQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E365016FD32E91448DAD12 /* OptistreamQueue.swift */; }; 9CF7237135A4CC033D355E3F /* TenantConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197CDA59D9D767513A115BDF /* TenantConfigFixture.swift */; }; + 9D326D5880402C668760EEB9 /* OptiTrackMockQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A074E950BB365437E67630D /* OptiTrackMockQueueTests.swift */; }; + 9D44CC1A12340665FCAF5A30 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B613A036D30F7735F7F325F /* AnalyticsHelper.swift */; }; 9EFAA10F84365241FB47DBF5 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E4E1BBE35E94BDE9796DE21 /* Event.swift */; }; - 9FD12FE96EA86F95AFBF7824 /* NewUserIDHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D76E087E475DC20866F2BF4 /* NewUserIDHandlerTests.swift */; }; + 9FEDC2520A6FBFF95FC6F9E2 /* Events-2590.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = B0B0B3B23068620884E438CB /* Events-2590.sqlite */; }; + A065AC8BE5A5705439533508 /* SetUserEmailEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9619B5935F5144458B85A194 /* SetUserEmailEventTests.swift */; }; A136F00619AFA98D1D61695F /* EventValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9571161A3D28F4EBCEC79233 /* EventValidator.swift */; }; + A2D0C4B960835388427190D5 /* UrlBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC4CBD77D8548EB171560ED4 /* UrlBuilder.swift */; }; A3DAFD3DEABDBCEEA6899527 /* TenantConfigurationDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B14E1CAE6DCFA63AB3C31D76 /* TenantConfigurationDownloader.swift */; }; A3DAFD9AFA1F596CF1307575 /* TimeInterval+Seconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDEDE4BE8CAAD487F2893395 /* TimeInterval+Seconds.swift */; }; A52447C34C7025C5FA5766A4 /* OptistreamNetworkingMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F2CF1316A8FD7BEFB64F3C /* OptistreamNetworkingMock.swift */; }; - A5B65BA10A3B356CAACADB8D /* TenantConfigurationDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED0FDAA1CED867DD491988C /* TenantConfigurationDownloaderTests.swift */; }; A6CC7197F19B7D0922575FC4 /* CoreDataAttributeDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9007CBB1C44B51A5BA3DF62 /* CoreDataAttributeDescription.swift */; }; A6D704D18C74065D0101020A /* MockOptimoveStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0D16D34EAA14578617D5D6 /* MockOptimoveStorage.swift */; }; A6F87FEA3C9AF4C52FC4E4DB /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 402BB9498BB39F670471DC50 /* User.swift */; }; A7120A539838969384DDA733 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC92AA41EF0FDB2098B2E829 /* Foundation.framework */; }; + A77F8D3AA2953EC27506C754 /* AnalyticsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5880EDB70E63EEF7CB2440A2 /* AnalyticsHelper.swift */; }; A7B58760AD7154C5D5616A52 /* GlobalConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558B0FF7FB691AD7EF1BC356 /* GlobalConfigFixture.swift */; }; + A7EE33E084DB5B80D844E56C /* StubVariables.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE2A46DD2F42545E3AD9B152 /* StubVariables.swift */; }; + A87DE47E621356B33E682E75 /* InstallationIdTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E72A9C1BDFDE095054F0E9F /* InstallationIdTests.swift */; }; A8F415A6B21DA9A79ACC8546 /* NewEmailHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8B6A229AC03981F9F889C5 /* NewEmailHandler.swift */; }; - A975E13C75A90B4150DCFF04 /* TenantConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 485BDCB56EA98CD3DD5AE9DE /* TenantConfigTests.swift */; }; + AA64749A1A517EC2636A22B4 /* KSHttp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99EF83EFAF52070E59C5A389 /* KSHttp.swift */; }; AAB7C3B91AA0AD65E7A6AC9B /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CF4089BCE4866C7F3FF645A /* Version.swift */; }; ABCBC196572B66EA38C77669 /* InMemoryBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383CD5703B6EE2B92C5406EC /* InMemoryBuffer.swift */; }; AC09D26D395648106E7CA59C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FC57145A54E5033A5CECAF0 /* UIKit.framework */; }; AC722DB369A32C507F882EFD /* InstallationIdGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21E3D6232CC0A82FDD03F70F /* InstallationIdGenerator.swift */; }; AD6686AAC3B244EE9A85108E /* CoreDataFetchedPropertyDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F1B59DBD7E6F9C8165F1 /* CoreDataFetchedPropertyDescription.swift */; }; AFC2BAC060B346BD49B8A68F /* EventCDv1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD3E821350C903F200ABE66 /* EventCDv1.swift */; }; - B0B632040ED242B1CFAB93E2 /* CoreEventFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB929F27ECD0720A4201056D /* CoreEventFactoryTests.swift */; }; + B12432B9CACFCBD8052F2987 /* TenantConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197CDA59D9D767513A115BDF /* TenantConfigFixture.swift */; }; B177625EF698C25631CC290E /* CoreDataMigrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0EB99EF51D86C5B64583FB /* CoreDataMigrator.swift */; }; + B188D431C30BFE47AE949B8E /* Mocker in Frameworks */ = {isa = PBXBuildFile; productRef = ADE980548010DA03B6C49B05 /* Mocker */; }; + B1E8DC1836EBD8D9924B1153 /* OptitrackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C61CE5499A164610267AD2 /* OptitrackTests.swift */; }; B3E5EED7F6260DCCE332FAFD /* OptistreamNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F723E006AF5D7BDA0DBF4DC0 /* OptistreamNetworking.swift */; }; B44B56B11935E11D4A3DFDAC /* ServiceLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ADAFC4543BF9DE8E088E61 /* ServiceLocator.swift */; }; - B6E63EA62943734C001959E5 /* Optimobile+Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E63EA52943734C001959E5 /* Optimobile+Location.swift */; }; + B494048CD01D26D8FEE2A870 /* MockConfigurationRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ACB5B8925C674D4B3D2811A /* MockConfigurationRepository.swift */; }; + B6A376B7681D9D6532B84D50 /* OptimoveCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2764B249D4CC9907122D2773 /* OptimoveCore.framework */; }; + B76405565985A5F8DA43A145 /* SetUserAgentEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89E228831AFE1D61F55AFBC0 /* SetUserAgentEventTests.swift */; }; B7CAF22D462BF215234052A2 /* SDKVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = B41BBBBB921C848D02E2BE6B /* SDKVersion.swift */; }; + B90744D2826B1CC61479CB09 /* MediaHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07BBE644C3487EC57B169E6B /* MediaHelper.swift */; }; B9D3F1723BB20889FD2817A6 /* AppOpenOnStartGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB486286AFEC603E2B5A5B71 /* AppOpenOnStartGenerator.swift */; }; - BBC3825F222CB6EDD09E8B11 /* RealtimeComponentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D1D1DEC05E2AED5EB69424 /* RealtimeComponentTests.swift */; }; BBE68E031DE089BC52731ED4 /* OptistreamEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD663863AF1C42A2374A638 /* OptistreamEvent.swift */; }; BC1825E2A93DCDAF68D16389 /* Managed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 426EC561F9EB6986A2F5AF76 /* Managed.swift */; }; + BC248EC1C9EF19594422EF11 /* KSHttp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 427D452311AC9642F4EAD787 /* KSHttp.swift */; }; + BCB5E93DE8C40BFCC84D9B95 /* AppGroupsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F31D9650475129AA4CEB54B /* AppGroupsHelper.swift */; }; BDB72CFA372352BF226C045D /* StatisticService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ED38876830A5D18E84DF284 /* StatisticService.swift */; }; - C071798869C6349DEC23D89B /* SetUserIdEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7709EE79BECC8179B83190A3 /* SetUserIdEventTests.swift */; }; + BE5803E4A1CBB7C280C8BB8E /* OptimoveStorageFacadeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB3C7B3C0173ACAD5BF630DE /* OptimoveStorageFacadeTests.swift */; }; + C26C07FBBDCCA505B88B0F82 /* CategoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 805AAE3A60691F585A7EDD39 /* CategoryManager.swift */; }; C2A001E9BC1DD27508D7B8C6 /* SetUserAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1449C522124FFE0217C05F5 /* SetUserAgent.swift */; }; - C2FD2CDE73EBFF5EE2610920 /* ConfigurationBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C5351C31727563488889DE5 /* ConfigurationBuilderTests.swift */; }; C3054B47A6ED4A4BF2277F02 /* ResignActiveObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAE898BE82A77234095B3BE0 /* ResignActiveObserver.swift */; }; C323AD127E24F3444D868D46 /* ComponentHandlers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF25EC5B91861187E65D19 /* ComponentHandlers.swift */; }; C6439A52CCEF9F1BCE79519E /* FirstRunTimestampGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FCE651A819A7B8E43FB3E38 /* FirstRunTimestampGenerator.swift */; }; C68FBC333C5593438AE404CC /* StorageFacade.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAAF6DB20C4C312785D90075 /* StorageFacade.swift */; }; + C6D90CD8E2120D32C952FFF5 /* OptimobileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED41094AA6F15AAEC368096A /* OptimobileHelper.swift */; }; C85F44214432563BCCDAFED5 /* LogBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD7C8A11E380D28029ED47E5 /* LogBody.swift */; }; C8E1C85C8DB193181D87D0C1 /* RealtimeMetaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24AF4563527F35B0569B44CE /* RealtimeMetaData.swift */; }; C9B146D3726AFD48A46265DA /* LogLevelCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43F7C2632F53C9F5CD85B4E /* LogLevelCore.swift */; }; CB4AC43D9576A580D0C217DA /* OptimoveTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A3329FC290A675F44BEBFE /* OptimoveTestCase.swift */; }; - CBA3D6BD2269778218266AD5 /* MockStatisticService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C9108020CAF36768579AA7 /* MockStatisticService.swift */; }; CC511CF1758F3B668CE207FC /* MigrationWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0C43BC7A683ABFD56EE6F3 /* MigrationWork.swift */; }; + CC79D3062081B1037A5138A0 /* CoreDataMigratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CA128410EF6CAFF5355761 /* CoreDataMigratorTests.swift */; }; CDD3242FB03DDCFDBA27E186 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38596994C26D889219B1828C /* Logger.swift */; }; - CF0221B39C0839E2FEE69AE5 /* MockSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135B5AB561246273DAD07CE1 /* MockSynchronizer.swift */; }; + CF43BED28FE6426BB06E30E8 /* OptimoveNotificationServiceExtension.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9FA39149BAE18208F17B07DB /* OptimoveNotificationServiceExtension.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CFC4BA74FBC9CD6629372AB0 /* NetworkClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D99B316C7AB5823A04CDE046 /* NetworkClientTests.swift */; }; D002E78C7BFBD4BEE5F9FECC /* FileAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FFBD8E3E3EC13859EAA9E9 /* FileAccessible.swift */; }; D0DF391C816A5EE42AC96ADF /* OptitrackMetaData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF010CD78C12263BE8ED0CDD /* OptitrackMetaData.swift */; }; + D17587E6A1F4700D55C6C9A1 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C7EC2263685823B37EC99A /* UserNotifications.framework */; }; D3126FACD3A8EED32268202F /* core_events.json in Resources */ = {isa = PBXBuildFile; fileRef = 0FA5B03E91EC1B9C8B7A921A /* core_events.json */; }; D3442290F4766F3C2835815D /* String+isBlank.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FE216E57E65CEC3F6D9F4CE /* String+isBlank.swift */; }; D3C3D981332E7956C784F156 /* RunningFlagsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC0D8804B2EC84EE6FC4B506 /* RunningFlagsContainer.swift */; }; + D40627451576BB6978A11EB0 /* StubEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432D5D39398212165A5C8188 /* StubEvent.swift */; }; + D436E32EB5FF0A1108878C06 /* SessionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB82DA87D962D6F82EFAB7F2 /* SessionHelper.swift */; }; D450B85E3B94ED96ED2F3849 /* CoreDataMigrationStep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC2D600BED2FFBD180627A1 /* CoreDataMigrationStep.swift */; }; D84FA7E0419D5AA96CE24553 /* Components.swift in Sources */ = {isa = PBXBuildFile; fileRef = B250C7CF8C880EF6A147DE7E /* Components.swift */; }; D88E575BBA436CE7BD3ED0D3 /* GlobalConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558B0FF7FB691AD7EF1BC356 /* GlobalConfigFixture.swift */; }; - D9E82D512D6810F3203A98D4 /* MergeRemoteConfigurationOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCD3B739367D0848F4CB234E /* MergeRemoteConfigurationOperationTests.swift */; }; DA7ADBC1984F1D3213CEE5E9 /* OptimoveCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2764B249D4CC9907122D2773 /* OptimoveCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; DAD792DD77AF77B7D95DD74D /* Merging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75F5659456F795700A0533BA /* Merging.swift */; }; DBD21C31B247D71522605231 /* OptistreamNetworkingMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1F2CF1316A8FD7BEFB64F3C /* OptistreamNetworkingMock.swift */; }; DDD6774A89DE3F27E8F12D0B /* TenantEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6952311F3B4BB669CE43372 /* TenantEvent.swift */; }; DF509157A7DAAF09F3FF000B /* FileManager+Optimove.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81CC3FB85E375007177F218A /* FileManager+Optimove.swift */; }; + DFBFE8B289F51A514282B44A /* ConfigurationFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4268499EEA7348C481371C /* ConfigurationFixture.swift */; }; + E0290A63EA4AF5F9CE836C50 /* InAppPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0953B68FEE43AF812A9D2D4C /* InAppPresenter.swift */; }; E04C734BCB92039C3B747495 /* ScreenVisitValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F414A61CC748EA1580342F3 /* ScreenVisitValidator.swift */; }; + E147D2E305837E0D739D1C05 /* KVOExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6E56A6CE9F936B2F897953F /* KVOExpectation.swift */; }; E1B7BB8C96DEC557EDFA7F6D /* EventCDv1ToEventCDv2MappingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6766A447E9CDA51F2CE3D91B /* EventCDv1ToEventCDv2MappingModel.swift */; }; E1E7F62209130B79A66B39EC /* MigrationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAFA8674D956078D45613FD /* MigrationObserver.swift */; }; E362BF6DD8888742811D98A0 /* StubEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432D5D39398212165A5C8188 /* StubEvent.swift */; }; E454A59BDF3B9A9F68DB6139 /* MainFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A5795C174DB5BE5833F0373 /* MainFactory.swift */; }; E55BD25E76886EA7EFA887F2 /* EventConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C95FC1B779C18A7446E2845C /* EventConfig.swift */; }; - E56294EED7434283D6BB6337 /* OptimoveStorageFacadeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8467A40C1D544CA8220AAE2 /* OptimoveStorageFacadeTests.swift */; }; E7A7D278F7020C15DA946900 /* Initialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F196F7C13C8C1950D369FA /* Initialization.swift */; }; - E7B65A20C54C58E9FE0572A1 /* NewEmailHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D0445351BA8E72B53C89A3 /* NewEmailHandlerTests.swift */; }; E92EC16E27036BFFD16F5DF2 /* CoreDataEntityDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5120297307C3C5A364386C92 /* CoreDataEntityDescription.swift */; }; + E98189436A82989CCA2EE581 /* OptimoveNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FA39149BAE18208F17B07DB /* OptimoveNotificationServiceExtension.framework */; }; EAEE293A4A4E489DB7C9E6AC /* MockOptimoveStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0D16D34EAA14578617D5D6 /* MockOptimoveStorage.swift */; }; - EC6FCE53F6000850B92B2511 /* GlobalConfigurationDownloaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF56D64273E803F0F9A6ACA /* GlobalConfigurationDownloaderTests.swift */; }; - EC8157C51B383BD1B3BD9095 /* dev.tid.107.optipush.json in Resources */ = {isa = PBXBuildFile; fileRef = 0B00D121B7D35C23D9DE8B8E /* dev.tid.107.optipush.json */; }; - ED3B6FA3936A2C173102E487 /* Events-2590.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = A50E294635F099DB396E68C2 /* Events-2590.sqlite */; }; + EC47D3A2A0C0F3589770B712 /* RealtimeComponentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF42F6E1030D68E50E8B623 /* RealtimeComponentTests.swift */; }; EEA726E93CBE99DE605ECBC4 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C7EC2263685823B37EC99A /* UserNotifications.framework */; }; + EF285892FEC9D49538D50B0C /* KeyValueStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81A4955301970EC4DFBDA13 /* KeyValueStorageTests.swift */; }; EFE8C2D3BC85DE2223893ACB /* SdkEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4FD77A1B209FBAA7B1ABAF /* SdkEnvironment.swift */; }; EFF46260ABABD75A9ED21D09 /* TenantConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ABF630842AEE0342583B677 /* TenantConfig.swift */; }; + F13364D158937A2C22431F54 /* PendingNotificationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3475E992634550F7F93076FC /* PendingNotificationHelper.swift */; }; F20E19FEEEF9B200E5321625 /* MetaDataEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CF0105BA68C767A4105F8B /* MetaDataEvent.swift */; }; F366378361753D8AC34D9449 /* ConfigurationFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4268499EEA7348C481371C /* ConfigurationFixture.swift */; }; F4463BD44A499220DDE80852 /* SetUserIdEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79935407BEFEEDD1A3D2B0A9 /* SetUserIdEvent.swift */; }; + F54F5C30E5253F81BCDE4AA3 /* InAppModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D1A7DA485740F9E353A414 /* InAppModels.swift */; }; + F670819778DAFCB8BD88988E /* MockOptistreamQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB2E66162C8123C0D0A74A8 /* MockOptistreamQueue.swift */; }; F7D485257EA33486539D87E8 /* ConfigurationBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F57DE7E2FE4814F1B86846 /* ConfigurationBuilder.swift */; }; + F80582ECAF50E9E3597299E6 /* OptimoveConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAF62F1525B39D043E850569 /* OptimoveConfig.swift */; }; F9A93090DC0B4B5ABC51C35F /* RemoteConfigurationNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD4BAAECE0E2C8D6DAD6232 /* RemoteConfigurationNetworking.swift */; }; + FBEDA772B460CEDF5A9CD453 /* KeyValPersistenceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E4B3747D4FE3D271EBADC2C /* KeyValPersistenceHelper.swift */; }; FCC20433D011E60F2C404BA8 /* LogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F5EA13B0969C648189790E /* LogLevel.swift */; }; + FD6B210141F97A6B47D3B50B /* MockOptimoveStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE0D16D34EAA14578617D5D6 /* MockOptimoveStorage.swift */; }; FE6961AE12E4BCB6A294FB85 /* OptimoveEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EECA51F0B0A4A890AD8AC1B7 /* OptimoveEvent.swift */; }; FF21D2585D696E2119159E34 /* NetworkResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 436C5AA2215F8E91D2D754E3 /* NetworkResult.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 12C3565B281196AB00672B42 /* PBXContainerItemProxy */ = { + 1CE861D9B1D38BA99AC3EAC3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F048C3E62DBD311754F63BD1 /* Project object */; proxyType = 1; - remoteGlobalIDString = 12C35651281196AB00672B42; - remoteInfo = OptimoveNotificationExtension; + remoteGlobalIDString = 7013308FB86B06E91BDD05C2; + remoteInfo = OptimoveCore; }; - 1CE861D9B1D38BA99AC3EAC3 /* PBXContainerItemProxy */ = { + 29FCBF7A2B772CC3F0B6F87B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F048C3E62DBD311754F63BD1 /* Project object */; proxyType = 1; @@ -298,16 +307,33 @@ remoteGlobalIDString = 4E6035250BAA805CC4049A9E; remoteInfo = OptimoveSDK; }; + DD314B46AF786059D0227C9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F048C3E62DBD311754F63BD1 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 43B4740CB2055B0FBF0587A0; + remoteInfo = OptimoveNotificationServiceExtension; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 03E0AABEBB3BEAB185CCF4FA /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + CF43BED28FE6426BB06E30E8 /* OptimoveNotificationServiceExtension.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 5C93863AB31B0482AE701456 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 1277E48D2811B3A80097AC3B /* Mocker.xcframework in Embed Frameworks */, DA7ADBC1984F1D3213CEE5E9 /* OptimoveCore.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -319,7 +345,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 1277E48C2811B39C0097AC3B /* Mocker.xcframework in Embed Frameworks */, 45E8890FB696618F19DE0E1C /* OptimoveSDK.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -328,144 +353,133 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 001618E0FA4F7439090C2029 /* MockStatisticService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockStatisticService.swift; sourceTree = ""; }; 004C06ABAB7629E27139CBB0 /* Pipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pipe.swift; sourceTree = ""; }; + 00AD8964C31889A296AF6ACE /* GlobalConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigTests.swift; sourceTree = ""; }; 035801D597864BD02A3F3C22 /* LocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationService.swift; sourceTree = ""; }; - 03D1D1DEC05E2AED5EB69424 /* RealtimeComponentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeComponentTests.swift; sourceTree = ""; }; 054E84169CA88075A3A99AC4 /* Bundle+Identifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Identifiers.swift"; sourceTree = ""; }; 0743DA20AB28DD7E78A80384 /* String+SHA1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+SHA1.swift"; sourceTree = ""; }; - 0B00D121B7D35C23D9DE8B8E /* dev.tid.107.optipush.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = dev.tid.107.optipush.json; sourceTree = ""; }; + 07BBE644C3487EC57B169E6B /* MediaHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaHelper.swift; sourceTree = ""; }; + 0953B68FEE43AF812A9D2D4C /* InAppPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPresenter.swift; sourceTree = ""; }; 0B664ECF492F1657FC2D7036 /* GlobalConfigurationDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigurationDownloader.swift; sourceTree = ""; }; - 0C5351C31727563488889DE5 /* ConfigurationBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationBuilderTests.swift; sourceTree = ""; }; 0CF4089BCE4866C7F3FF645A /* Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = ""; }; 0CFA35DE83F5306D2EB306C1 /* ParametersNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParametersNormalizer.swift; sourceTree = ""; }; - 0E1E54304B64D97CC42E8D49 /* NewTenantInfoHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTenantInfoHandlerTests.swift; sourceTree = ""; }; + 0F791A0A07B1FC8F38A4B300 /* GlobalConfigurationDownloaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigurationDownloaderTests.swift; sourceTree = ""; }; 0FA5B03E91EC1B9C8B7A921A /* core_events.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = core_events.json; sourceTree = ""; }; 111ED6383A53D5F33F54CEFF /* ConfigurationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationRepository.swift; sourceTree = ""; }; - 1277E48E2812AF650097AC3B /* AppOpenObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenObserver.swift; sourceTree = ""; }; - 129D63E328199276005DCB7F /* OptimoveNotificationExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimoveNotificationExtensionTests.swift; sourceTree = ""; }; - 12C1E626E9F4FECB13D350B0 /* MockDateTimeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDateTimeProvider.swift; sourceTree = ""; }; - 12C35621281194D500672B42 /* KSHttp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KSHttp.swift; sourceTree = ""; }; - 12C35622281194D500672B42 /* AnalyticsHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticsHelper.swift; sourceTree = ""; }; - 12C35623281194D500672B42 /* KeyValPersistenceHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyValPersistenceHelper.swift; sourceTree = ""; }; - 12C35624281194D500672B42 /* OptimobileUserDefaultsKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimobileUserDefaultsKey.swift; sourceTree = ""; }; - 12C35625281194D500672B42 /* AppGroupsHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppGroupsHelper.swift; sourceTree = ""; }; - 12C35626281194D500672B42 /* OptimobileHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimobileHelper.swift; sourceTree = ""; }; - 12C35627281194D500672B42 /* PendingNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingNotification.swift; sourceTree = ""; }; - 12C35628281194D500672B42 /* PendingNotificationHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PendingNotificationHelper.swift; sourceTree = ""; }; - 12C35629281194D500672B42 /* MediaHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaHelper.swift; sourceTree = ""; }; - 12C35652281196AB00672B42 /* OptimoveNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OptimoveNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 12C35659281196AB00672B42 /* OptimoveNotificationServiceExtension-Unit.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimoveNotificationServiceExtension-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 12C35668281197A800672B42 /* OptimoveNotificationExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptimoveNotificationExtension.h; sourceTree = ""; }; - 12C3567D28119AD600672B42 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; - 12C3567F28119AFC00672B42 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/Library/Frameworks/UserNotifications.framework; sourceTree = DEVELOPER_DIR; }; - 12C3568128119B0200672B42 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 135B5AB561246273DAD07CE1 /* MockSynchronizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSynchronizer.swift; sourceTree = ""; }; + 11A5E8AF0D04EA97AA273293 /* OptimoveInApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveInApp.swift; sourceTree = ""; }; + 122C3D0E6C2CD0AF1A51CDFD /* PendingNotificationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingNotificationHelper.swift; sourceTree = ""; }; + 13EF34D1DAF7ADB95EAD9DA5 /* Optimobile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Optimobile.swift; sourceTree = ""; }; 1444FD543ED01363BB8CB274 /* ProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessInfo.swift; sourceTree = ""; }; 147C9BEF1567B21AF4FB6CB4 /* SDKInitializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKInitializer.swift; sourceTree = ""; }; + 14A02A48A58BD785A723E329 /* Optimobile+DeepLinking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+DeepLinking.swift"; sourceTree = ""; }; 197CDA59D9D767513A115BDF /* TenantConfigFixture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigFixture.swift; sourceTree = ""; }; 1BB88B00B9C963F44DC8B5BD /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; 1BC4935D2FE2C45DF3CE8086 /* OptistreamQueueImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamQueueImpl.swift; sourceTree = ""; }; + 1CCCFCA414EC7FAB65526C40 /* TenantConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigTests.swift; sourceTree = ""; }; 1CD663863AF1C42A2374A638 /* OptistreamEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamEvent.swift; sourceTree = ""; }; - 1CED5C535C1EC8A385B8976A /* MockLocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLocationService.swift; sourceTree = ""; }; 1F9045DB7CC19B7319FF581C /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; - 2027ED43354F4EB835FA0AA0 /* KVOExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KVOExpectation.swift; sourceTree = ""; }; 21E3D6232CC0A82FDD03F70F /* InstallationIdGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallationIdGenerator.swift; sourceTree = ""; }; 24AF4563527F35B0569B44CE /* RealtimeMetaData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeMetaData.swift; sourceTree = ""; }; 26931EEB560FA3B43177A022 /* RuntimeCodingKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeCodingKey.swift; sourceTree = ""; }; 2764B249D4CC9907122D2773 /* OptimoveCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OptimoveCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2B4DBAC7E85E0B9DB5C0E1DD /* RemoteConfigurationRequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteConfigurationRequestBuilder.swift; sourceTree = ""; }; + 2C3748E6F34B34958063B39F /* Optimobile+Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+Location.swift"; sourceTree = ""; }; 2CAFA8674D956078D45613FD /* MigrationObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationObserver.swift; sourceTree = ""; }; 2D0CFD51DD85596306B721E0 /* NetworkClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkClient.swift; sourceTree = ""; }; 2D52112BF287F638A45398EB /* MobileProvision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MobileProvision.swift; sourceTree = ""; }; + 2DF42F6E1030D68E50E8B623 /* RealtimeComponentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealtimeComponentTests.swift; sourceTree = ""; }; + 2F31D9650475129AA4CEB54B /* AppGroupsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroupsHelper.swift; sourceTree = ""; }; 2F414A61CC748EA1580342F3 /* ScreenVisitValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenVisitValidator.swift; sourceTree = ""; }; 2F6D1C3E09195F4AA62DE80C /* String+random.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+random.swift"; sourceTree = ""; }; - 313AF75BEDDE3C3411F01615 /* OptimoveSDK-Unit.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimoveSDK-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 325B5F8B3BDBB034C3516AAB /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; - 329CE901655C81D4751CB22B /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; - 35C421DD075F5131CFD24CA6 /* OptitrackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptitrackTests.swift; sourceTree = ""; }; + 313AF75BEDDE3C3411F01615 /* OptimoveSDK-Unit.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "OptimoveSDK-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 325B5F8B3BDBB034C3516AAB /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = ""; }; + 329CE901655C81D4751CB22B /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = ""; }; + 3475E992634550F7F93076FC /* PendingNotificationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingNotificationHelper.swift; sourceTree = ""; }; + 34D65364A8DE8DCCC7C91AB5 /* RemoteConfigurationRequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteConfigurationRequestBuilderTests.swift; sourceTree = ""; }; 36CB93F7FDDCB7374DA1CF9A /* OptimoveKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveKeys.swift; sourceTree = ""; }; 383CD5703B6EE2B92C5406EC /* InMemoryBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InMemoryBuffer.swift; sourceTree = ""; }; 38596994C26D889219B1828C /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; - 38D5D03A189D6E46D85E120B /* configs.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = configs.json; sourceTree = ""; }; - 3E1C1A66CA07D50B6692CA7B /* MockConfigurationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockConfigurationRepository.swift; sourceTree = ""; }; + 3A9927C4B1D1B10899A43D19 /* OptimoveNotificationServiceExtension-Unit.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "OptimoveNotificationServiceExtension-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B613A036D30F7735F7F325F /* AnalyticsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHelper.swift; sourceTree = ""; }; 402BB9498BB39F670471DC50 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; 41F1FDC6F647A5DD31FCB29D /* NewUserHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewUserHandler.swift; sourceTree = ""; }; + 424C0E3A1B4058EA4F789D44 /* Optimobile+Analytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+Analytics.swift"; sourceTree = ""; }; 426EC561F9EB6986A2F5AF76 /* Managed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Managed.swift; sourceTree = ""; }; + 427D452311AC9642F4EAD787 /* KSHttp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KSHttp.swift; sourceTree = ""; }; 432D5D39398212165A5C8188 /* StubEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubEvent.swift; sourceTree = ""; }; 436C5AA2215F8E91D2D754E3 /* NetworkResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkResult.swift; sourceTree = ""; }; - 44F0DCFD3F00AA505DC781F4 /* OptimoveFileManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveFileManagerTests.swift; sourceTree = ""; }; 4592839140B76A8D32F05DC8 /* RemoteLoggerStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteLoggerStream.swift; sourceTree = ""; }; - 485BDCB56EA98CD3DD5AE9DE /* TenantConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigTests.swift; sourceTree = ""; }; 48695180D12E3F6E69B27A64 /* CoreDataFetchIndexDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataFetchIndexDescription.swift; sourceTree = ""; }; + 499FB65BC432D40BBB409525 /* PendingNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingNotification.swift; sourceTree = ""; }; + 4ACB5B8925C674D4B3D2811A /* MockConfigurationRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockConfigurationRepository.swift; sourceTree = ""; }; + 4B17EE5D9F063E3BBCB9A394 /* PageVisitEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageVisitEventTests.swift; sourceTree = ""; }; + 4C03DD4D5F885584BA44C723 /* AppGroupsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroupsHelper.swift; sourceTree = ""; }; 4CC2D600BED2FFBD180627A1 /* CoreDataMigrationStep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigrationStep.swift; sourceTree = ""; }; 4DB8B22F680152DE4E7C00A7 /* String+Split.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Split.swift"; sourceTree = ""; }; 4E4E1BBE35E94BDE9796DE21 /* Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; 4E527862BE390ACDCE2EE444 /* EmailValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailValidator.swift; sourceTree = ""; }; 4F0710E98EE949C1E5B12D69 /* AsyncOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncOperation.swift; sourceTree = ""; }; - 4F585C5327FECCFA005E7BB4 /* InAppPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAppPresenter.swift; sourceTree = ""; }; - 4F585C5427FECCFA005E7BB4 /* InAppManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAppManager.swift; sourceTree = ""; }; - 4F585C5527FECCFA005E7BB4 /* InAppModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InAppModels.swift; sourceTree = ""; }; - 4F585C5627FECCFA005E7BB4 /* OptimoveConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimoveConfig.swift; sourceTree = ""; }; - 4F585C5727FECCFA005E7BB4 /* Optimobile+DeepLinking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optimobile+DeepLinking.swift"; sourceTree = ""; }; - 4F585C5827FECCFA005E7BB4 /* SessionHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionHelper.swift; sourceTree = ""; }; - 4F585C5A27FECCFA005E7BB4 /* OptimoveInApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimoveInApp.swift; sourceTree = ""; }; - 4F585C5B27FECCFA005E7BB4 /* CwlSysctl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlSysctl.swift; sourceTree = ""; }; - 4F585C5D27FECCFA005E7BB4 /* Optimobile+Push.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optimobile+Push.swift"; sourceTree = ""; }; - 4F585C5E27FECCFA005E7BB4 /* Optimobile+Stats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optimobile+Stats.swift"; sourceTree = ""; }; - 4F585C6027FECCFA005E7BB4 /* Optimobile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Optimobile.swift; sourceTree = ""; }; - 4F585C6127FECCFA005E7BB4 /* UrlBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UrlBuilder.swift; sourceTree = ""; }; - 4F585C6327FECCFA005E7BB4 /* OptimoveUserNotificationCenterDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimoveUserNotificationCenterDelegate.swift; sourceTree = ""; }; - 4F585C6427FECCFA005E7BB4 /* Optimobile+Analytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Optimobile+Analytics.swift"; sourceTree = ""; }; - 4F585C6527FECCFA005E7BB4 /* DeepLinkFingerprinter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkFingerprinter.swift; sourceTree = ""; }; - 4F585C8827FECD3E005E7BB4 /* CategoryManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryManager.swift; sourceTree = ""; }; - 4FA8F61627FEE872005CB88E /* OptimobileBadgeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileBadgeObserver.swift; sourceTree = ""; }; - 4FA8FC4F280C410B005CB88E /* OptimoveNotificationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptimoveNotificationService.swift; sourceTree = ""; }; 4FD4BAAECE0E2C8D6DAD6232 /* RemoteConfigurationNetworking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteConfigurationNetworking.swift; sourceTree = ""; }; - 4FE394EA27C78933005FABB0 /* Mocker.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Mocker.xcframework; path = Carthage/Build/Mocker.xcframework; sourceTree = ""; }; 506941ABF70087E99952FFD6 /* AppOpenEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenEvent.swift; sourceTree = ""; }; 5120297307C3C5A364386C92 /* CoreDataEntityDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataEntityDescription.swift; sourceTree = ""; }; + 519339A7CE43CB33F054E48C /* MockDateTimeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDateTimeProvider.swift; sourceTree = ""; }; + 54CE007CEFA3504B48265FAA /* SetUserIdEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserIdEventTests.swift; sourceTree = ""; }; 558B0FF7FB691AD7EF1BC356 /* GlobalConfigFixture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigFixture.swift; sourceTree = ""; }; 566B20B2B1E2E316902899F3 /* Assembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assembly.swift; sourceTree = ""; }; + 5820E8A2D77B2A2DC2D76830 /* ConfigurationBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationBuilderTests.swift; sourceTree = ""; }; + 5880EDB70E63EEF7CB2440A2 /* AnalyticsHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsHelper.swift; sourceTree = ""; }; + 58C61CE5499A164610267AD2 /* OptitrackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptitrackTests.swift; sourceTree = ""; }; + 58F74929F41D70EC7E3F9770 /* EnterForegroundObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterForegroundObserverTests.swift; sourceTree = ""; }; 59CFEFE7F3B5B02C084AB068 /* KeyPath+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyPath+Extension.swift"; sourceTree = ""; }; + 5A8395C246A7545F57AD323D /* OnStartEventGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnStartEventGeneratorTests.swift; sourceTree = ""; }; 5B2476035D945779F9130EAD /* NetworkingFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingFactory.swift; sourceTree = ""; }; 5D74FD73F62F2896D05BAFD1 /* NewTenantInfoHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTenantInfoHandler.swift; sourceTree = ""; }; - 5D76E087E475DC20866F2BF4 /* NewUserIDHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewUserIDHandlerTests.swift; sourceTree = ""; }; 5D85DCA28C5381DEE1370C6D /* OptiLoggerOutputStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptiLoggerOutputStream.swift; sourceTree = ""; }; + 5D92D7E5297901568A91938B /* TenantConfigurationDownloaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigurationDownloaderTests.swift; sourceTree = ""; }; 5F400A7074360186390E1B18 /* CoreDataRelationshipDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataRelationshipDescription.swift; sourceTree = ""; }; + 5F60CE8D6E405DAC4EBCEE3C /* OptimoveNotificationExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveNotificationExtensionTests.swift; sourceTree = ""; }; 5FC57145A54E5033A5CECAF0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 5FE216E57E65CEC3F6D9F4CE /* String+isBlank.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+isBlank.swift"; sourceTree = ""; }; - 615F8FAE93C5D0A6AC301070 /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; + 615F8FAE93C5D0A6AC301070 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = ""; }; 63C7EC2263685823B37EC99A /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; 6424915844F66E0315561874 /* RealTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealTime.swift; sourceTree = ""; }; - 64AAD2B0BFFF64DCB3907ECE /* OptimoveCore-Unit.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OptimoveCore-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 64AAD2B0BFFF64DCB3907ECE /* OptimoveCore-Unit.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "OptimoveCore-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 65CA140085BC23AFEE47F451 /* Dictionary+CompactMapKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+CompactMapKeys.swift"; sourceTree = ""; }; + 66905FCA4315A6615953B49B /* OptimobileUserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileUserDefaultsKey.swift; sourceTree = ""; }; 669DFBB1484B628AAF9DB0DB /* PageVisitEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageVisitEvent.swift; sourceTree = ""; }; 66A8F39D35D2D3237AD0F678 /* NetworkRequestFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkRequestFactory.swift; sourceTree = ""; }; 673FD2495FF2C13EFC81D1AA /* ComponentFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentFactory.swift; sourceTree = ""; }; 6766A447E9CDA51F2CE3D91B /* EventCDv1ToEventCDv2MappingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCDv1ToEventCDv2MappingModel.swift; sourceTree = ""; }; 67A3329FC290A675F44BEBFE /* OptimoveTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveTestCase.swift; sourceTree = ""; }; + 67F3D2B3855E155D386037EE /* MockSynchronizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSynchronizer.swift; sourceTree = ""; }; + 6905325DDD3A3EAAB1BEB8DB /* NewEmailHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewEmailHandlerTests.swift; sourceTree = ""; }; 6A5795C174DB5BE5833F0373 /* MainFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFactory.swift; sourceTree = ""; }; 6A8B6A229AC03981F9F889C5 /* NewEmailHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewEmailHandler.swift; sourceTree = ""; }; 6C3181EDC81DAA89624DFD4B /* OptiLoggerStreamsContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptiLoggerStreamsContainer.swift; sourceTree = ""; }; 6CB578140EEA0C61258F4C95 /* ProcessInfo+OsVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+OsVersion.swift"; sourceTree = ""; }; - 70EC39175948194604CEA34B /* StringSplitByLenghtExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringSplitByLenghtExtensionsTests.swift; sourceTree = ""; }; + 6E72A9C1BDFDE095054F0E9F /* InstallationIdTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallationIdTests.swift; sourceTree = ""; }; 7296983D1D2B5111D175002E /* CoreDataModelDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataModelDescription.swift; sourceTree = ""; }; + 738B25C939FAE2104D09DB7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 75D46D778B83D1E41AA1FADB /* DeepLinkFingerprinter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLinkFingerprinter.swift; sourceTree = ""; }; 75F5659456F795700A0533BA /* Merging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Merging.swift; sourceTree = ""; }; - 7709EE79BECC8179B83190A3 /* SetUserIdEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserIdEventTests.swift; sourceTree = ""; }; 79935407BEFEEDD1A3D2B0A9 /* SetUserIdEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserIdEvent.swift; sourceTree = ""; }; - 799B1ECA74F09CE9EFDCC893 /* SetUserAgentEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserAgentEventTests.swift; sourceTree = ""; }; 7AA021ACCF4173B1F67D03BD /* utsname+DeviceModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "utsname+DeviceModel.swift"; sourceTree = ""; }; 7DAFF319BE8F13B7DAAE338D /* OptistreamEventBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamEventBuilder.swift; sourceTree = ""; }; - 809CCE6596151864378607B5 /* InstallationIdTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallationIdTests.swift; sourceTree = ""; }; + 7E4B3747D4FE3D271EBADC2C /* KeyValPersistenceHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValPersistenceHelper.swift; sourceTree = ""; }; + 805AAE3A60691F585A7EDD39 /* CategoryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryManager.swift; sourceTree = ""; }; 810A2719EF2B688A621CC8E4 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = ""; }; - 81BC45AB12DCB12A09904FB2 /* EnterForegroundObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterForegroundObserverTests.swift; sourceTree = ""; }; 81CC3FB85E375007177F218A /* FileManager+Optimove.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Optimove.swift"; sourceTree = ""; }; 8228C916C97D8339F724B907 /* ConsoleLoggerStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsoleLoggerStream.swift; sourceTree = ""; }; + 8290F6F2D17FBA5D0D19383C /* OptimoveFileManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveFileManagerTests.swift; sourceTree = ""; }; 84B5B5EC7877594E3E96DBCC /* OptiTrack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptiTrack.swift; sourceTree = ""; }; - 85C981D5B3D94C295BE60C2A /* RemoteConfigurationRequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteConfigurationRequestBuilderTests.swift; sourceTree = ""; }; + 86F4EE2D46B15E8B8B8EA016 /* AppOpenEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenEventTests.swift; sourceTree = ""; }; 877F4A8A9B50FDB1E7C91CF4 /* String+alphanumeric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+alphanumeric.swift"; sourceTree = ""; }; 87EC09BC1C5CB77E5AD50317 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; + 88CF3369980060D3BBC1DE9C /* EventValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventValidatorTests.swift; sourceTree = ""; }; + 89E228831AFE1D61F55AFBC0 /* SetUserAgentEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserAgentEventTests.swift; sourceTree = ""; }; 89E7B8102C3B8854279817C1 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; + 8A074E950BB365437E67630D /* OptiTrackMockQueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptiTrackMockQueueTests.swift; sourceTree = ""; }; 8D97B467542E88DEE0300315 /* ParametersDecorator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParametersDecorator.swift; sourceTree = ""; }; 8E0C43BC7A683ABFD56EE6F3 /* MigrationWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationWork.swift; sourceTree = ""; }; 8ED38876830A5D18E84DF284 /* StatisticService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticService.swift; sourceTree = ""; }; @@ -476,63 +490,75 @@ 92ADAFC4543BF9DE8E088E61 /* ServiceLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceLocator.swift; sourceTree = ""; }; 93BD2C49D756A97FA8D57EEC /* DeviceStateObserverFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStateObserverFactory.swift; sourceTree = ""; }; 9571161A3D28F4EBCEC79233 /* EventValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventValidator.swift; sourceTree = ""; }; - 99FBF8FEACC0C375A4C64F59 /* AppOpenEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenEventTests.swift; sourceTree = ""; }; + 9619B5935F5144458B85A194 /* SetUserEmailEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserEmailEventTests.swift; sourceTree = ""; }; + 99EF83EFAF52070E59C5A389 /* KSHttp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KSHttp.swift; sourceTree = ""; }; 9ABF630842AEE0342583B677 /* TenantConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfig.swift; sourceTree = ""; }; 9BDF25EC5B91861187E65D19 /* ComponentHandlers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComponentHandlers.swift; sourceTree = ""; }; - 9CBAAF543B9FFEE56AFCA272 /* CoreDataMigratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigratorTests.swift; sourceTree = ""; }; - 9E0C85115B44FC36030D67CE /* EventValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventValidatorTests.swift; sourceTree = ""; }; + 9FA39149BAE18208F17B07DB /* OptimoveNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OptimoveNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9FCE651A819A7B8E43FB3E38 /* FirstRunTimestampGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstRunTimestampGenerator.swift; sourceTree = ""; }; 9FD3E821350C903F200ABE66 /* EventCDv1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCDv1.swift; sourceTree = ""; }; + A16A5BA2BFD07BCE1E201ADE /* MergeRemoteConfigurationOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MergeRemoteConfigurationOperationTests.swift; sourceTree = ""; }; A1FFBD8E3E3EC13859EAA9E9 /* FileAccessible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileAccessible.swift; sourceTree = ""; }; + A26871854B50CF09EED86457 /* MediaHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaHelper.swift; sourceTree = ""; }; A2F5EA13B0969C648189790E /* LogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogLevel.swift; sourceTree = ""; }; A435A55F6D788D0ACF8085E2 /* Querying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Querying.swift; sourceTree = ""; }; A483534D00B52DA236BB0B05 /* NewVisitorIdGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewVisitorIdGenerator.swift; sourceTree = ""; }; - A4D0445351BA8E72B53C89A3 /* NewEmailHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewEmailHandlerTests.swift; sourceTree = ""; }; - A50E294635F099DB396E68C2 /* Events-2590.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Events-2590.sqlite"; sourceTree = ""; }; A6952311F3B4BB669CE43372 /* TenantEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantEvent.swift; sourceTree = ""; }; A7F57DE7E2FE4814F1B86846 /* ConfigurationBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationBuilder.swift; sourceTree = ""; }; A9007CBB1C44B51A5BA3DF62 /* CoreDataAttributeDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataAttributeDescription.swift; sourceTree = ""; }; + A9526C15EA2A7A5548367647 /* OptimobileBadgeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileBadgeObserver.swift; sourceTree = ""; }; + A9B7CAD06AF20B0ACA56C962 /* NewTenantInfoHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTenantInfoHandlerTests.swift; sourceTree = ""; }; AAAF6DB20C4C312785D90075 /* StorageFacade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageFacade.swift; sourceTree = ""; }; AAF333FF2B62FF3501A4009A /* EventCDv2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCDv2.swift; sourceTree = ""; }; AC0D8804B2EC84EE6FC4B506 /* RunningFlagsContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningFlagsContainer.swift; sourceTree = ""; }; ADF1A285E540507DACCA9630 /* LoggerStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggerStream.swift; sourceTree = ""; }; - AE5ED65D35DAEDBE1D34995A /* .gitkeep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitkeep; sourceTree = ""; }; + AE5ED65D35DAEDBE1D34995A /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = ""; }; + B0B0B3B23068620884E438CB /* Events-2590.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Events-2590.sqlite"; sourceTree = ""; }; B14E1CAE6DCFA63AB3C31D76 /* TenantConfigurationDownloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigurationDownloader.swift; sourceTree = ""; }; B1AEF7257DAA1A2E7FB12680 /* GlobalFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalFunctions.swift; sourceTree = ""; }; - B1B51D44551B095F9BA4EDBD /* KeyValueStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueStorageTests.swift; sourceTree = ""; }; B250C7CF8C880EF6A147DE7E /* Components.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Components.swift; sourceTree = ""; }; + B271013567534CB962F6D4B7 /* Optimobile+Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+Stats.swift"; sourceTree = ""; }; B41BBBBB921C848D02E2BE6B /* SDKVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDKVersion.swift; sourceTree = ""; }; B4713C0DA9400A929216B24D /* MultiplexLoggerStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiplexLoggerStream.swift; sourceTree = ""; }; - B6E63EA52943734C001959E5 /* Optimobile+Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+Location.swift"; sourceTree = ""; }; - B8467A40C1D544CA8220AAE2 /* OptimoveStorageFacadeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveStorageFacadeTests.swift; sourceTree = ""; }; + B5AFB035DD1E2D7DC2B47931 /* Optimobile+Push.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optimobile+Push.swift"; sourceTree = ""; }; B8CF0105BA68C767A4105F8B /* MetaDataEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDataEvent.swift; sourceTree = ""; }; - B90E69482E5CEF73C23265A7 /* SetUserEmailEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserEmailEventTests.swift; sourceTree = ""; }; B9F196F7C13C8C1950D369FA /* Initialization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Initialization.swift; sourceTree = ""; }; - B9F1D9A9EC40981BD427CB4C /* OnStartEventGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnStartEventGeneratorTests.swift; sourceTree = ""; }; B9FE5A14C58728AE872409BB /* UserDefaults+Optimove.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Optimove.swift"; sourceTree = ""; }; BB19792511783857E3051963 /* NetworkResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkResponse.swift; sourceTree = ""; }; - BBF221484A7B1A433DB7FAD1 /* GlobalConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigTests.swift; sourceTree = ""; }; - BBF56D64273E803F0F9A6ACA /* GlobalConfigurationDownloaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfigurationDownloaderTests.swift; sourceTree = ""; }; - BCD3B739367D0848F4CB234E /* MergeRemoteConfigurationOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MergeRemoteConfigurationOperationTests.swift; sourceTree = ""; }; + BFA43948B8DBCBDF5A334FC9 /* StringSplitByLenghtExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringSplitByLenghtExtensionsTests.swift; sourceTree = ""; }; C032549A1F8BD134783F0F90 /* UserValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserValidator.swift; sourceTree = ""; }; C04629380902B7E31CF43D52 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; + C1F3F81B42DD7AA8AB1BEE7A /* OptimobileHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileHelper.swift; sourceTree = ""; }; + C2797AD0BB5BD176932C38C6 /* NewUserIDHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewUserIDHandlerTests.swift; sourceTree = ""; }; C2D5405AF08AADF9DA4ED566 /* UserAgentGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentGenerator.swift; sourceTree = ""; }; - C8411A92C5ADEF8363F217CD /* PageVisitEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageVisitEventTests.swift; sourceTree = ""; }; + C3CA128410EF6CAFF5355761 /* CoreDataMigratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigratorTests.swift; sourceTree = ""; }; + C53585DB5D3958C136A7AA42 /* CwlSysctl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CwlSysctl.swift; sourceTree = ""; }; + C7AFA2A8587C5DCA93A30108 /* OptimobileUserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileUserDefaultsKey.swift; sourceTree = ""; }; + C8241EEFCB9733F06963B4E9 /* dev.tid.107.optipush.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = dev.tid.107.optipush.json; sourceTree = ""; }; C91AEC3B6BA8441109CBF58E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; C95FC1B779C18A7446E2845C /* EventConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventConfig.swift; sourceTree = ""; }; + CAEAF62F3CA25FB3BE2AFE9D /* UserIDValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIDValidatorTests.swift; sourceTree = ""; }; + CAF62F1525B39D043E850569 /* OptimoveConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveConfig.swift; sourceTree = ""; }; + CAFC9209245A84DF915EF074 /* CoreEventFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreEventFactoryTests.swift; sourceTree = ""; }; CC0EB99EF51D86C5B64583FB /* CoreDataMigrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigrator.swift; sourceTree = ""; }; - CC14F9097C510CCDFC24ED44 /* OptiTrackMockQueueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptiTrackMockQueueTests.swift; sourceTree = ""; }; CC23809D9F4BD02A13F8C661 /* RingBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingBuffer.swift; sourceTree = ""; }; + CCB2E66162C8123C0D0A74A8 /* MockOptistreamQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOptistreamQueue.swift; sourceTree = ""; }; CE4FD77A1B209FBAA7B1ABAF /* SdkEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SdkEnvironment.swift; sourceTree = ""; }; - CED0FDAA1CED867DD491988C /* TenantConfigurationDownloaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TenantConfigurationDownloaderTests.swift; sourceTree = ""; }; + CF7096F588EBF070FC5E5A05 /* OptimoveNotificationExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OptimoveNotificationExtension.h; sourceTree = ""; }; D071F1B59DBD7E6F9C8165F1 /* CoreDataFetchedPropertyDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataFetchedPropertyDescription.swift; sourceTree = ""; }; + D073FA862A2FB4E726ACB520 /* AppOpenObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenObserver.swift; sourceTree = ""; }; D0E365016FD32E91448DAD12 /* OptistreamQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamQueue.swift; sourceTree = ""; }; D1F2CF1316A8FD7BEFB64F3C /* OptistreamNetworkingMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamNetworkingMock.swift; sourceTree = ""; }; D3C7E4CB736102AA3142CF32 /* Bundle+AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+AppVersion.swift"; sourceTree = ""; }; + D47F4CC9BEB348E9F9D32891 /* MockLocationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLocationService.swift; sourceTree = ""; }; D5217E6590AD8BD80A6985CC /* LoggerInitializator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggerInitializator.swift; sourceTree = ""; }; D5D46EC93293B7579E9D7389 /* ConfigurationFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationFetcher.swift; sourceTree = ""; }; D5DCCD1C9CFAC7AA464E02A4 /* Pipeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pipeline.swift; sourceTree = ""; }; + D7D1A7DA485740F9E353A414 /* InAppModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppModels.swift; sourceTree = ""; }; + D7F841AF4345B15514C71B49 /* PendingNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingNotification.swift; sourceTree = ""; }; + D99B316C7AB5823A04CDE046 /* NetworkClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkClientTests.swift; sourceTree = ""; }; DA418E3FDBEB318519B1F183 /* Optimove.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Optimove.swift; sourceTree = ""; }; + DB82DA87D962D6F82EFAB7F2 /* SessionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionHelper.swift; sourceTree = ""; }; DCD4DEFD23225D3D5FDDAF5B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; DD0A274FE5BD042E03429284 /* FileStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileStorage.swift; sourceTree = ""; }; DE0B5F1859EF1DA75FD01507 /* CoreEventFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreEventFactory.swift; sourceTree = ""; }; @@ -540,17 +566,20 @@ DF010CD78C12263BE8ED0CDD /* OptitrackMetaData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptitrackMetaData.swift; sourceTree = ""; }; DF4268499EEA7348C481371C /* ConfigurationFixture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationFixture.swift; sourceTree = ""; }; DF4712B5B2BEABC3056055F6 /* PersistentContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistentContainer.swift; sourceTree = ""; }; - E0F41B5FDAD6DB908750FDF0 /* UserIDValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIDValidatorTests.swift; sourceTree = ""; }; E1449C522124FFE0217C05F5 /* SetUserAgent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetUserAgent.swift; sourceTree = ""; }; - E1C9108020CAF36768579AA7 /* MockStatisticService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockStatisticService.swift; sourceTree = ""; }; E2913A221183842BA07EF8F5 /* Operations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operations.swift; sourceTree = ""; }; E301AF207069DC3417330D23 /* ISO+format.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ISO+format.swift"; sourceTree = ""; }; E36EE80C309330F735D037E2 /* SdkPlatform.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SdkPlatform.swift; sourceTree = ""; }; E5F014AB9AE645C920DD038B /* NetworkRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = ""; }; E6C2AA83233AE32D981F3555 /* GlobalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfig.swift; sourceTree = ""; }; + E6E56A6CE9F936B2F897953F /* KVOExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KVOExpectation.swift; sourceTree = ""; }; + E81A4955301970EC4DFBDA13 /* KeyValueStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueStorageTests.swift; sourceTree = ""; }; + EA2B4035AC1EEB59B3534409 /* InAppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppManager.swift; sourceTree = ""; }; + EA680F149CF17AE295CEA268 /* configs.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = configs.json; sourceTree = ""; }; EAE898BE82A77234095B3BE0 /* ResignActiveObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResignActiveObserver.swift; sourceTree = ""; }; EB486286AFEC603E2B5A5B71 /* AppOpenOnStartGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppOpenOnStartGenerator.swift; sourceTree = ""; }; ECFE1A26CB2C36CBBE414871 /* OperationFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationFactory.swift; sourceTree = ""; }; + ED41094AA6F15AAEC368096A /* OptimobileHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileHelper.swift; sourceTree = ""; }; EDEDE4BE8CAAD487F2893395 /* TimeInterval+Seconds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimeInterval+Seconds.swift"; sourceTree = ""; }; EE2A46DD2F42545E3AD9B152 /* StubVariables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubVariables.swift; sourceTree = ""; }; EECA51F0B0A4A890AD8AC1B7 /* OptimoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveEvent.swift; sourceTree = ""; }; @@ -558,45 +587,39 @@ F107FD1650EBED990862F73F /* Parameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parameter.swift; sourceTree = ""; }; F195D6A74F16DC039009B692 /* OptimoveSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OptimoveSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F19A915CFE10EE5B80BD3AC2 /* DeviceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStateObserver.swift; sourceTree = ""; }; + F251A2E671B4575611FC81D5 /* KeyValPersistenceHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValPersistenceHelper.swift; sourceTree = ""; }; F317F849DA6211A6DBB52A93 /* CoreDataMigrationVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigrationVersion.swift; sourceTree = ""; }; F37DA0C731A733771D08D4AE /* Result+Successful.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+Successful.swift"; sourceTree = ""; }; F43F7C2632F53C9F5CD85B4E /* LogLevelCore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogLevelCore.swift; sourceTree = ""; }; F521F3899C0EF7438BF1B510 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; - F6303DE7E28C8787FD8F3FA0 /* NetworkClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkClientTests.swift; sourceTree = ""; }; + F686E9E2A2C29366BCDF0A37 /* OptimoveNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveNotificationService.swift; sourceTree = ""; }; F6A19CA28B9B8E5119C61AE0 /* NSManagedObjectContext+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Utilities.swift"; sourceTree = ""; }; F723E006AF5D7BDA0DBF4DC0 /* OptistreamNetworking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptistreamNetworking.swift; sourceTree = ""; }; - FB929F27ECD0720A4201056D /* CoreEventFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreEventFactoryTests.swift; sourceTree = ""; }; + FB3C7B3C0173ACAD5BF630DE /* OptimoveStorageFacadeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveStorageFacadeTests.swift; sourceTree = ""; }; + FC4CBD77D8548EB171560ED4 /* UrlBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlBuilder.swift; sourceTree = ""; }; FC92AA41EF0FDB2098B2E829 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + FC97786EB5AC1048109A3199 /* OptimoveUserNotificationCenterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimoveUserNotificationCenterDelegate.swift; sourceTree = ""; }; FD108B5E64EF357FD2D9FEE1 /* OnStartEventGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnStartEventGenerator.swift; sourceTree = ""; }; FD7BE307B3A9F9AABA03961C /* DateTimeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeProvider.swift; sourceTree = ""; }; FD7C8A11E380D28029ED47E5 /* LogBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogBody.swift; sourceTree = ""; }; - FD86A64C2F3772F4CCCBB335 /* MockOptistreamQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockOptistreamQueue.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 12C3564F281196AB00672B42 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 12C3568028119AFC00672B42 /* UserNotifications.framework in Frameworks */, - 12C3568228119B0200672B42 /* UIKit.framework in Frameworks */, - 12C3567E28119AD600672B42 /* CoreData.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 12C35656281196AB00672B42 /* Frameworks */ = { + 4AB35C16151E46BADA43EF35 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 12C3565A281196AB00672B42 /* OptimoveNotificationServiceExtension.framework in Frameworks */, + 8BD11324583CA0D4625E3036 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4AB35C16151E46BADA43EF35 /* Frameworks */ = { + 7900655B7311D8F8B85E52D2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8BD11324583CA0D4625E3036 /* Foundation.framework in Frameworks */, + B6A376B7681D9D6532B84D50 /* OptimoveCore.framework in Frameworks */, + D17587E6A1F4700D55C6C9A1 /* UserNotifications.framework in Frameworks */, + 219417667A6FFDD03148C7ED /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -604,8 +627,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1277E48B2811B2AF0097AC3B /* Mocker.xcframework in Frameworks */, 14F57E7FCA077C242AAE0A3C /* OptimoveSDK.framework in Frameworks */, + 1ABDB154E19C9B5366833376 /* Mocker in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -621,12 +644,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B21D98E7E8A46F29F131C751 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E98189436A82989CCA2EE581 /* OptimoveNotificationServiceExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; EA23C81747C1812DFA448CC9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1277E48A2811B2AA0097AC3B /* Mocker.xcframework in Frameworks */, 87034323076ABC016360E1A9 /* OptimoveCore.framework in Frameworks */, + B188D431C30BFE47AE949B8E /* Mocker in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -643,6 +674,14 @@ path = Logger; sourceTree = ""; }; + 03CF1E7D11F883149F445412 /* Resources */ = { + isa = PBXGroup; + children = ( + B0B0B3B23068620884E438CB /* Events-2590.sqlite */, + ); + path = Resources; + sourceTree = ""; + }; 059971E08A10B8A4891F2794 /* Events */ = { isa = PBXGroup; children = ( @@ -656,10 +695,9 @@ 073DE8112B0BD3298C0B0748 /* Classes */ = { isa = PBXGroup; children = ( - 4F585C5627FECCFA005E7BB4 /* OptimoveConfig.swift */, - DA418E3FDBEB318519B1F183 /* Optimove.swift */, - 4F585C5027FECCFA005E7BB4 /* Optimobile */, 329CE901655C81D4751CB22B /* .gitkeep */, + DA418E3FDBEB318519B1F183 /* Optimove.swift */, + CAF62F1525B39D043E850569 /* OptimoveConfig.swift */, 7A701B350A9A47124CB6F501 /* Components */, E8767E4F26EABC231D3BF727 /* Configuration */, F5B9321DDE62D40FE2B0B980 /* Constants */, @@ -674,6 +712,8 @@ 1A6565B66BC70AFB47005124 /* Migration */, 0CEE3CCD7B14A0976E778A76 /* Observers */, 6B5BFEAF9F7D336231486959 /* OnStartHelpers */, + 540AF437CD5791488878914D /* Optimobile */, + F5877C596178A3E105007D40 /* OptimobileShared */, BEA1D6AD863A30A999D5E6B2 /* Pipeline */, F6D0C30CA75C18FEF95CD647 /* Providers */, 15D585D36C5DBE64170F3791 /* Provisioning */, @@ -686,91 +726,61 @@ 0CEE3CCD7B14A0976E778A76 /* Observers */ = { isa = PBXGroup; children = ( + D073FA862A2FB4E726ACB520 /* AppOpenObserver.swift */, F19A915CFE10EE5B80BD3AC2 /* DeviceStateObserver.swift */, 2CAFA8674D956078D45613FD /* MigrationObserver.swift */, EAE898BE82A77234095B3BE0 /* ResignActiveObserver.swift */, - 1277E48E2812AF650097AC3B /* AppOpenObserver.swift */, ); path = Observers; sourceTree = ""; }; - 0EB46CB2A2B3AA95D3576048 /* CoreEvents */ = { - isa = PBXGroup; - children = ( - 99FBF8FEACC0C375A4C64F59 /* AppOpenEventTests.swift */, - C8411A92C5ADEF8363F217CD /* PageVisitEventTests.swift */, - 799B1ECA74F09CE9EFDCC893 /* SetUserAgentEventTests.swift */, - B90E69482E5CEF73C23265A7 /* SetUserEmailEventTests.swift */, - 7709EE79BECC8179B83190A3 /* SetUserIdEventTests.swift */, - ); - path = CoreEvents; - sourceTree = ""; - }; - 0FF4DF40AC6AAC3B8661208C = { - isa = PBXGroup; - children = ( - 927AE68A807CDE5763F8AFC4 /* OptimoveCore */, - 6C9D60733B2558CD13EFD55E /* OptimoveCore-Unit */, - 12C35620281194D500672B42 /* OptimobileShared */, - 68DACECC39D7663A9751DF27 /* OptimoveSDK */, - 73AB4DC2F7D8C311EF1E8D81 /* OptimoveSDK-Unit */, - BF01C3C8DA3E3AB555E387A5 /* Shared-Unit */, - 12C35653281196AB00672B42 /* OptimoveNotificationServiceExtension */, - 129D63E128199276005DCB7F /* OptimoveNotificationServiceExtension-Unit */, - 8D2AF8410718437694C833BA /* Frameworks */, - 29EA001D961347964D199369 /* Products */, - ); - sourceTree = ""; - }; - 129D63E128199276005DCB7F /* OptimoveNotificationServiceExtension-Unit */ = { - isa = PBXGroup; - children = ( - 129D63E228199276005DCB7F /* Sources */, - ); - name = "OptimoveNotificationServiceExtension-Unit"; - path = OptimoveNotificationServiceExtension/Tests; - sourceTree = ""; - }; - 129D63E228199276005DCB7F /* Sources */ = { + 0D29E193202474CD8C2DE86A /* Sources */ = { isa = PBXGroup; children = ( - 129D63E328199276005DCB7F /* OptimoveNotificationExtensionTests.swift */, + C3CA128410EF6CAFF5355761 /* CoreDataMigratorTests.swift */, + E6E56A6CE9F936B2F897953F /* KVOExpectation.swift */, + 735255B1638651CBE96FDE4D /* Components */, + 2D0EE06E4B5DA0078DCAD1D9 /* Events */, + C9A53764C503794D2CEF6700 /* Extensions */, + 6A1D0086A1AC0BA98FC95C20 /* Generators */, + 4A062331EF1117427AEBBE1D /* Handlers */, + 7D4783CBCC36CD59C6CE3158 /* Mocks */, + 5E00E7B2E4F749F537C583DA /* Network */, + BD6535923F8688FAB8D0C8CF /* Observers */, + 7703ED033E35B45055EF7C85 /* Operations */, + 14187602A97DEF7D77F45C60 /* Validator */, ); path = Sources; sourceTree = ""; }; - 12C35620281194D500672B42 /* OptimobileShared */ = { + 0FA3B86FECEBB7D44232A1DC /* Tests */ = { isa = PBXGroup; children = ( - 12C35621281194D500672B42 /* KSHttp.swift */, - 12C35622281194D500672B42 /* AnalyticsHelper.swift */, - 12C35623281194D500672B42 /* KeyValPersistenceHelper.swift */, - 12C35624281194D500672B42 /* OptimobileUserDefaultsKey.swift */, - 12C35625281194D500672B42 /* AppGroupsHelper.swift */, - 12C35626281194D500672B42 /* OptimobileHelper.swift */, - 12C35627281194D500672B42 /* PendingNotification.swift */, - 12C35628281194D500672B42 /* PendingNotificationHelper.swift */, - 12C35629281194D500672B42 /* MediaHelper.swift */, + 3428672D4A490DE0327C53B9 /* Resources */, + B092173B54AE46147345B298 /* Sources */, ); - path = OptimobileShared; + path = Tests; sourceTree = ""; }; - 12C35653281196AB00672B42 /* OptimoveNotificationServiceExtension */ = { + 0FF4DF40AC6AAC3B8661208C = { isa = PBXGroup; children = ( - 12C35667281197A800672B42 /* Sources */, + 927AE68A807CDE5763F8AFC4 /* OptimoveCore */, + CB3C39A7EDBD99408369C4D0 /* OptimoveNotificationServiceExtension */, + 68DACECC39D7663A9751DF27 /* OptimoveSDK */, + BF01C3C8DA3E3AB555E387A5 /* Shared-Unit */, + 8D2AF8410718437694C833BA /* Frameworks */, + 29EA001D961347964D199369 /* Products */, ); - path = OptimoveNotificationServiceExtension; sourceTree = ""; }; - 12C35667281197A800672B42 /* Sources */ = { + 14187602A97DEF7D77F45C60 /* Validator */ = { isa = PBXGroup; children = ( - 12C35668281197A800672B42 /* OptimoveNotificationExtension.h */, - 4FA8FC4F280C410B005CB88E /* OptimoveNotificationService.swift */, - 4F585C8827FECD3E005E7BB4 /* CategoryManager.swift */, + 88CF3369980060D3BBC1DE9C /* EventValidatorTests.swift */, + CAEAF62F3CA25FB3BE2AFE9D /* UserIDValidatorTests.swift */, ); - path = Sources; + path = Validator; sourceTree = ""; }; 142A73B100EA48488907672A /* Sources */ = { @@ -830,15 +840,6 @@ path = Migration; sourceTree = ""; }; - 1ABA1417B2D66EECF3AD47FA /* Components */ = { - isa = PBXGroup; - children = ( - E8DD9ABEF7740FCB8768F6D8 /* OptiTrack */, - 63F6334316D17AF57E0ABF5E /* Realtime */, - ); - path = Components; - sourceTree = ""; - }; 1E2E4021D93C2D82EF7D0D8B /* OptiTrack */ = { isa = PBXGroup; children = ( @@ -847,32 +848,14 @@ path = OptiTrack; sourceTree = ""; }; - 1ECED98ED8DB9067C2F2CBC5 /* Tenant */ = { + 24C80799987FE821D9857659 /* Configurations */ = { isa = PBXGroup; children = ( - 485BDCB56EA98CD3DD5AE9DE /* TenantConfigTests.swift */, + 5820E8A2D77B2A2DC2D76830 /* ConfigurationBuilderTests.swift */, + 9F0FB4123723933F01931497 /* Global */, + 31D057A24CB1355EA39E329B /* Tenant */, ); - path = Tenant; - sourceTree = ""; - }; - 234E48529AB40ED1D8D2EF5E /* Handlers */ = { - isa = PBXGroup; - children = ( - A4D0445351BA8E72B53C89A3 /* NewEmailHandlerTests.swift */, - 0E1E54304B64D97CC42E8D49 /* NewTenantInfoHandlerTests.swift */, - 5D76E087E475DC20866F2BF4 /* NewUserIDHandlerTests.swift */, - ); - path = Handlers; - sourceTree = ""; - }; - 26D806BC34E70703FD10DBEC /* Storage */ = { - isa = PBXGroup; - children = ( - B1B51D44551B095F9BA4EDBD /* KeyValueStorageTests.swift */, - 44F0DCFD3F00AA505DC781F4 /* OptimoveFileManagerTests.swift */, - B8467A40C1D544CA8220AAE2 /* OptimoveStorageFacadeTests.swift */, - ); - path = Storage; + path = Configurations; sourceTree = ""; }; 2899BE94E7142454E41D3515 /* Migration */ = { @@ -890,14 +873,23 @@ children = ( 64AAD2B0BFFF64DCB3907ECE /* OptimoveCore-Unit.xctest */, 2764B249D4CC9907122D2773 /* OptimoveCore.framework */, + 3A9927C4B1D1B10899A43D19 /* OptimoveNotificationServiceExtension-Unit.xctest */, + 9FA39149BAE18208F17B07DB /* OptimoveNotificationServiceExtension.framework */, 313AF75BEDDE3C3411F01615 /* OptimoveSDK-Unit.xctest */, F195D6A74F16DC039009B692 /* OptimoveSDK.framework */, - 12C35652281196AB00672B42 /* OptimoveNotificationServiceExtension.framework */, - 12C35659281196AB00672B42 /* OptimoveNotificationServiceExtension-Unit.xctest */, ); name = Products; sourceTree = ""; }; + 2D0EE06E4B5DA0078DCAD1D9 /* Events */ = { + isa = PBXGroup; + children = ( + CAFC9209245A84DF915EF074 /* CoreEventFactoryTests.swift */, + E4A96204D19CB3049FDD3C84 /* CoreEvents */, + ); + path = Events; + sourceTree = ""; + }; 2EE3A3201CC89F94569FE7E4 /* DataStructs */ = { isa = PBXGroup; children = ( @@ -906,6 +898,14 @@ path = DataStructs; sourceTree = ""; }; + 31D057A24CB1355EA39E329B /* Tenant */ = { + isa = PBXGroup; + children = ( + 1CCCFCA414EC7FAB65526C40 /* TenantConfigTests.swift */, + ); + path = Tenant; + sourceTree = ""; + }; 32023D2509AE094416A62A3C /* Factories */ = { isa = PBXGroup; children = ( @@ -928,11 +928,11 @@ path = Repository; sourceTree = ""; }; - 360BFCE94FF668F66CFDB7E1 /* Resources */ = { + 3428672D4A490DE0327C53B9 /* Resources */ = { isa = PBXGroup; children = ( - 38D5D03A189D6E46D85E120B /* configs.json */, - 0B00D121B7D35C23D9DE8B8E /* dev.tid.107.optipush.json */, + EA680F149CF17AE295CEA268 /* configs.json */, + C8241EEFCB9733F06963B4E9 /* dev.tid.107.optipush.json */, ); path = Resources; sourceTree = ""; @@ -945,21 +945,12 @@ path = RealTime; sourceTree = ""; }; - 379092B0B4B42F9D6DD3C975 /* Resources */ = { - isa = PBXGroup; - children = ( - A50E294635F099DB396E68C2 /* Events-2590.sqlite */, - ); - path = Resources; - sourceTree = ""; - }; - 37A6EA4549C29E7B916E3F1C /* Validator */ = { + 38AB0C6E5F52592BE2DE1EFD /* Sources */ = { isa = PBXGroup; children = ( - 9E0C85115B44FC36030D67CE /* EventValidatorTests.swift */, - E0F41B5FDAD6DB908750FDF0 /* UserIDValidatorTests.swift */, + 5F60CE8D6E405DAC4EBCEE3C /* OptimoveNotificationExtensionTests.swift */, ); - path = Validator; + path = Sources; sourceTree = ""; }; 397BA35C85B5B3A82E6E7611 /* Extension */ = { @@ -976,14 +967,6 @@ path = Extension; sourceTree = ""; }; - 3AFBE266E8ED5428EC335C1B /* Observers */ = { - isa = PBXGroup; - children = ( - 81BC45AB12DCB12A09904FB2 /* EnterForegroundObserverTests.swift */, - ); - path = Observers; - sourceTree = ""; - }; 3C1453E511EA0EE267D20A04 /* Mocks */ = { isa = PBXGroup; children = ( @@ -1002,53 +985,24 @@ path = DI; sourceTree = ""; }; - 4A802689AFE69F115DC0B92F /* Services */ = { - isa = PBXGroup; - children = ( - 035801D597864BD02A3F3C22 /* LocationService.swift */, - 92ADAFC4543BF9DE8E088E61 /* ServiceLocator.swift */, - 8ED38876830A5D18E84DF284 /* StatisticService.swift */, - ); - path = Services; - sourceTree = ""; - }; - 4C46E5E7FF3426E1DE9E9405 /* Extensions */ = { + 4A062331EF1117427AEBBE1D /* Handlers */ = { isa = PBXGroup; children = ( - 70EC39175948194604CEA34B /* StringSplitByLenghtExtensionsTests.swift */, + 6905325DDD3A3EAAB1BEB8DB /* NewEmailHandlerTests.swift */, + A9B7CAD06AF20B0ACA56C962 /* NewTenantInfoHandlerTests.swift */, + C2797AD0BB5BD176932C38C6 /* NewUserIDHandlerTests.swift */, ); - path = Extensions; - sourceTree = ""; - }; - 4F585C5027FECCFA005E7BB4 /* Optimobile */ = { - isa = PBXGroup; - children = ( - 4F585C5227FECCFA005E7BB4 /* InApp */, - 4F585C6027FECCFA005E7BB4 /* Optimobile.swift */, - 4F585C5A27FECCFA005E7BB4 /* OptimoveInApp.swift */, - 4F585C5E27FECCFA005E7BB4 /* Optimobile+Stats.swift */, - 4F585C6427FECCFA005E7BB4 /* Optimobile+Analytics.swift */, - 4F585C5D27FECCFA005E7BB4 /* Optimobile+Push.swift */, - 4F585C5727FECCFA005E7BB4 /* Optimobile+DeepLinking.swift */, - 4F585C5827FECCFA005E7BB4 /* SessionHelper.swift */, - 4F585C5B27FECCFA005E7BB4 /* CwlSysctl.swift */, - 4F585C6127FECCFA005E7BB4 /* UrlBuilder.swift */, - 4F585C6327FECCFA005E7BB4 /* OptimoveUserNotificationCenterDelegate.swift */, - 4F585C6527FECCFA005E7BB4 /* DeepLinkFingerprinter.swift */, - 4FA8F61627FEE872005CB88E /* OptimobileBadgeObserver.swift */, - B6E63EA52943734C001959E5 /* Optimobile+Location.swift */, - ); - path = Optimobile; + path = Handlers; sourceTree = ""; }; - 4F585C5227FECCFA005E7BB4 /* InApp */ = { + 4A802689AFE69F115DC0B92F /* Services */ = { isa = PBXGroup; children = ( - 4F585C5327FECCFA005E7BB4 /* InAppPresenter.swift */, - 4F585C5427FECCFA005E7BB4 /* InAppManager.swift */, - 4F585C5527FECCFA005E7BB4 /* InAppModels.swift */, + 035801D597864BD02A3F3C22 /* LocationService.swift */, + 92ADAFC4543BF9DE8E088E61 /* ServiceLocator.swift */, + 8ED38876830A5D18E84DF284 /* StatisticService.swift */, ); - path = InApp; + path = Services; sourceTree = ""; }; 517F8BBB89498042BB4C4B44 /* Coding */ = { @@ -1071,6 +1025,16 @@ path = Queue; sourceTree = ""; }; + 528171259FF0A5A9D92E2ADF /* InApp */ = { + isa = PBXGroup; + children = ( + EA2B4035AC1EEB59B3534409 /* InAppManager.swift */, + D7D1A7DA485740F9E353A414 /* InAppModels.swift */, + 0953B68FEE43AF812A9D2D4C /* InAppPresenter.swift */, + ); + path = InApp; + sourceTree = ""; + }; 5367733B1DB715A9D82CE9F6 /* Fixture */ = { isa = PBXGroup; children = ( @@ -1081,6 +1045,27 @@ path = Fixture; sourceTree = ""; }; + 540AF437CD5791488878914D /* Optimobile */ = { + isa = PBXGroup; + children = ( + C53585DB5D3958C136A7AA42 /* CwlSysctl.swift */, + 75D46D778B83D1E41AA1FADB /* DeepLinkFingerprinter.swift */, + 13EF34D1DAF7ADB95EAD9DA5 /* Optimobile.swift */, + 424C0E3A1B4058EA4F789D44 /* Optimobile+Analytics.swift */, + 14A02A48A58BD785A723E329 /* Optimobile+DeepLinking.swift */, + 2C3748E6F34B34958063B39F /* Optimobile+Location.swift */, + B5AFB035DD1E2D7DC2B47931 /* Optimobile+Push.swift */, + B271013567534CB962F6D4B7 /* Optimobile+Stats.swift */, + A9526C15EA2A7A5548367647 /* OptimobileBadgeObserver.swift */, + 11A5E8AF0D04EA97AA273293 /* OptimoveInApp.swift */, + FC97786EB5AC1048109A3199 /* OptimoveUserNotificationCenterDelegate.swift */, + DB82DA87D962D6F82EFAB7F2 /* SessionHelper.swift */, + FC4CBD77D8548EB171560ED4 /* UrlBuilder.swift */, + 528171259FF0A5A9D92E2ADF /* InApp */, + ); + path = Optimobile; + sourceTree = ""; + }; 566034C512FEC1CBCF5B6176 /* Tenant */ = { isa = PBXGroup; children = ( @@ -1104,38 +1089,45 @@ path = Constants; sourceTree = ""; }; - 5BEE89DE2E3119DB79322D75 /* Global */ = { + 5A6148BD0F3ACC0B88A0E297 /* Realtime */ = { isa = PBXGroup; children = ( - E6C2AA83233AE32D981F3555 /* GlobalConfig.swift */, + 2DF42F6E1030D68E50E8B623 /* RealtimeComponentTests.swift */, ); - path = Global; + path = Realtime; sourceTree = ""; }; - 62279A0F1575985188E9BAED /* Resources */ = { + 5B37E063B1B5109A9ED1E8A3 /* OptiTrack */ = { isa = PBXGroup; children = ( - 0FA5B03E91EC1B9C8B7A921A /* core_events.json */, + 8A074E950BB365437E67630D /* OptiTrackMockQueueTests.swift */, + 58C61CE5499A164610267AD2 /* OptitrackTests.swift */, ); - path = Resources; + path = OptiTrack; sourceTree = ""; }; - 625516C79EDE91C560CC8D69 /* Sources */ = { + 5BEE89DE2E3119DB79322D75 /* Global */ = { isa = PBXGroup; children = ( - F6303DE7E28C8787FD8F3FA0 /* NetworkClientTests.swift */, - 7B3BBE2A6593310E8259E4B7 /* Configurations */, - 26D806BC34E70703FD10DBEC /* Storage */, + E6C2AA83233AE32D981F3555 /* GlobalConfig.swift */, ); - path = Sources; + path = Global; sourceTree = ""; }; - 63F6334316D17AF57E0ABF5E /* Realtime */ = { + 5E00E7B2E4F749F537C583DA /* Network */ = { isa = PBXGroup; children = ( - 03D1D1DEC05E2AED5EB69424 /* RealtimeComponentTests.swift */, + 34D65364A8DE8DCCC7C91AB5 /* RemoteConfigurationRequestBuilderTests.swift */, ); - path = Realtime; + path = Network; + sourceTree = ""; + }; + 62279A0F1575985188E9BAED /* Resources */ = { + isa = PBXGroup; + children = ( + 0FA5B03E91EC1B9C8B7A921A /* core_events.json */, + ); + path = Resources; sourceTree = ""; }; 63FBAEFE4B1A81063673C13D /* Operations */ = { @@ -1164,10 +1156,20 @@ children = ( 926CB4784BDFA967F9B33111 /* Info.plist */, D85980716F84947A9D9B2474 /* Sources */, + EBFBC488118D3AEA46EF0E7A /* Tests */, ); path = OptimoveSDK; sourceTree = ""; }; + 6A1D0086A1AC0BA98FC95C20 /* Generators */ = { + isa = PBXGroup; + children = ( + 6E72A9C1BDFDE095054F0E9F /* InstallationIdTests.swift */, + 5A8395C246A7545F57AD323D /* OnStartEventGeneratorTests.swift */, + ); + path = Generators; + sourceTree = ""; + }; 6B5BFEAF9F7D336231486959 /* OnStartHelpers */ = { isa = PBXGroup; children = ( @@ -1186,16 +1188,6 @@ path = OnStartHelpers; sourceTree = ""; }; - 6C9D60733B2558CD13EFD55E /* OptimoveCore-Unit */ = { - isa = PBXGroup; - children = ( - 360BFCE94FF668F66CFDB7E1 /* Resources */, - 625516C79EDE91C560CC8D69 /* Sources */, - ); - name = "OptimoveCore-Unit"; - path = OptimoveCore/Tests; - sourceTree = ""; - }; 6F6FFC9B91E6C9D52749E6A7 /* JSON */ = { isa = PBXGroup; children = ( @@ -1227,14 +1219,13 @@ path = Pipes; sourceTree = ""; }; - 73AB4DC2F7D8C311EF1E8D81 /* OptimoveSDK-Unit */ = { + 735255B1638651CBE96FDE4D /* Components */ = { isa = PBXGroup; children = ( - 379092B0B4B42F9D6DD3C975 /* Resources */, - B31CC3B308E42CCE7765FA3B /* Sources */, + 5B37E063B1B5109A9ED1E8A3 /* OptiTrack */, + 5A6148BD0F3ACC0B88A0E297 /* Realtime */, ); - name = "OptimoveSDK-Unit"; - path = OptimoveSDK/Tests; + path = Components; sourceTree = ""; }; 7662316982793EED67541C0F /* GlobalScope */ = { @@ -1245,6 +1236,16 @@ path = GlobalScope; sourceTree = ""; }; + 7703ED033E35B45055EF7C85 /* Operations */ = { + isa = PBXGroup; + children = ( + 0F791A0A07B1FC8F38A4B300 /* GlobalConfigurationDownloaderTests.swift */, + A16A5BA2BFD07BCE1E201ADE /* MergeRemoteConfigurationOperationTests.swift */, + 5D92D7E5297901568A91938B /* TenantConfigurationDownloaderTests.swift */, + ); + path = Operations; + sourceTree = ""; + }; 776ADB05496F268948C26A02 /* Optistream */ = { isa = PBXGroup; children = ( @@ -1281,25 +1282,15 @@ path = Components; sourceTree = ""; }; - 7B3BBE2A6593310E8259E4B7 /* Configurations */ = { - isa = PBXGroup; - children = ( - 0C5351C31727563488889DE5 /* ConfigurationBuilderTests.swift */, - C4875599FAD599C6A25A0C02 /* Global */, - 1ECED98ED8DB9067C2F2CBC5 /* Tenant */, - ); - path = Configurations; - sourceTree = ""; - }; - 83B95874A3BCF31B5E3A8455 /* Mocks */ = { + 7D4783CBCC36CD59C6CE3158 /* Mocks */ = { isa = PBXGroup; children = ( - 3E1C1A66CA07D50B6692CA7B /* MockConfigurationRepository.swift */, - 12C1E626E9F4FECB13D350B0 /* MockDateTimeProvider.swift */, - 1CED5C535C1EC8A385B8976A /* MockLocationService.swift */, - FD86A64C2F3772F4CCCBB335 /* MockOptistreamQueue.swift */, - E1C9108020CAF36768579AA7 /* MockStatisticService.swift */, - 135B5AB561246273DAD07CE1 /* MockSynchronizer.swift */, + 4ACB5B8925C674D4B3D2811A /* MockConfigurationRepository.swift */, + 519339A7CE43CB33F054E48C /* MockDateTimeProvider.swift */, + D47F4CC9BEB348E9F9D32891 /* MockLocationService.swift */, + CCB2E66162C8123C0D0A74A8 /* MockOptistreamQueue.swift */, + 001618E0FA4F7439090C2029 /* MockStatisticService.swift */, + 67F3D2B3855E155D386037EE /* MockSynchronizer.swift */, ); path = Mocks; sourceTree = ""; @@ -1307,10 +1298,6 @@ 8D2AF8410718437694C833BA /* Frameworks */ = { isa = PBXGroup; children = ( - 12C3568128119B0200672B42 /* UIKit.framework */, - 12C3567F28119AFC00672B42 /* UserNotifications.framework */, - 12C3567D28119AD600672B42 /* CoreData.framework */, - 4FE394EA27C78933005FABB0 /* Mocker.xcframework */, C91AEC3B6BA8441109CBF58E /* CoreData.framework */, FC92AA41EF0FDB2098B2E829 /* Foundation.framework */, 5FC57145A54E5033A5CECAF0 /* UIKit.framework */, @@ -1324,6 +1311,7 @@ children = ( DCD4DEFD23225D3D5FDDAF5B /* Info.plist */, 142A73B100EA48488907672A /* Sources */, + 0FA3B86FECEBB7D44232A1DC /* Tests */, ); path = OptimoveCore; sourceTree = ""; @@ -1371,6 +1359,14 @@ path = Configurations; sourceTree = ""; }; + 9F0FB4123723933F01931497 /* Global */ = { + isa = PBXGroup; + children = ( + 00AD8964C31889A296AF6ACE /* GlobalConfigTests.swift */, + ); + path = Global; + sourceTree = ""; + }; A5252A6E2E5FAD79133267EA /* Initializer */ = { isa = PBXGroup; children = ( @@ -1401,30 +1397,23 @@ path = Descriptions; sourceTree = ""; }; - AA81ADF695C82CF49700A70D /* Events */ = { + AD1BDA0F0066C3B2A1E28935 /* Sources */ = { isa = PBXGroup; children = ( - FB929F27ECD0720A4201056D /* CoreEventFactoryTests.swift */, - 0EB46CB2A2B3AA95D3576048 /* CoreEvents */, + 805AAE3A60691F585A7EDD39 /* CategoryManager.swift */, + CF7096F588EBF070FC5E5A05 /* OptimoveNotificationExtension.h */, + F686E9E2A2C29366BCDF0A37 /* OptimoveNotificationService.swift */, + EE530923279B1BB20A3A9491 /* OptimobileShared */, ); - path = Events; + path = Sources; sourceTree = ""; }; - B31CC3B308E42CCE7765FA3B /* Sources */ = { + B092173B54AE46147345B298 /* Sources */ = { isa = PBXGroup; children = ( - 9CBAAF543B9FFEE56AFCA272 /* CoreDataMigratorTests.swift */, - 2027ED43354F4EB835FA0AA0 /* KVOExpectation.swift */, - 1ABA1417B2D66EECF3AD47FA /* Components */, - AA81ADF695C82CF49700A70D /* Events */, - 4C46E5E7FF3426E1DE9E9405 /* Extensions */, - F268D2394BFA7585E9B8FE8B /* Generators */, - 234E48529AB40ED1D8D2EF5E /* Handlers */, - 83B95874A3BCF31B5E3A8455 /* Mocks */, - EEB9E0C6101B3951E6943A2F /* Network */, - 3AFBE266E8ED5428EC335C1B /* Observers */, - FC3095C5C64830371BF0A4DE /* Operations */, - 37A6EA4549C29E7B916E3F1C /* Validator */, + D99B316C7AB5823A04CDE046 /* NetworkClientTests.swift */, + 24C80799987FE821D9857659 /* Configurations */, + D55B7939B18244614B66A9B9 /* Storage */, ); path = Sources; sourceTree = ""; @@ -1437,6 +1426,14 @@ path = Assets; sourceTree = ""; }; + B7A852A6E69C3B511A34B826 /* Tests */ = { + isa = PBXGroup; + children = ( + 38AB0C6E5F52592BE2DE1EFD /* Sources */, + ); + path = Tests; + sourceTree = ""; + }; B7E0C4FAAB0D1A333D7859D0 /* CoreEvents */ = { isa = PBXGroup; children = ( @@ -1450,6 +1447,14 @@ path = CoreEvents; sourceTree = ""; }; + BD6535923F8688FAB8D0C8CF /* Observers */ = { + isa = PBXGroup; + children = ( + 58F74929F41D70EC7E3F9770 /* EnterForegroundObserverTests.swift */, + ); + path = Observers; + sourceTree = ""; + }; BEA1D6AD863A30A999D5E6B2 /* Pipeline */ = { isa = PBXGroup; children = ( @@ -1485,12 +1490,32 @@ path = Events; sourceTree = ""; }; - C4875599FAD599C6A25A0C02 /* Global */ = { + C9A53764C503794D2CEF6700 /* Extensions */ = { isa = PBXGroup; children = ( - BBF221484A7B1A433DB7FAD1 /* GlobalConfigTests.swift */, + BFA43948B8DBCBDF5A334FC9 /* StringSplitByLenghtExtensionsTests.swift */, ); - path = Global; + path = Extensions; + sourceTree = ""; + }; + CB3C39A7EDBD99408369C4D0 /* OptimoveNotificationServiceExtension */ = { + isa = PBXGroup; + children = ( + 738B25C939FAE2104D09DB7B /* Info.plist */, + AD1BDA0F0066C3B2A1E28935 /* Sources */, + B7A852A6E69C3B511A34B826 /* Tests */, + ); + path = OptimoveNotificationServiceExtension; + sourceTree = ""; + }; + D55B7939B18244614B66A9B9 /* Storage */ = { + isa = PBXGroup; + children = ( + E81A4955301970EC4DFBDA13 /* KeyValueStorageTests.swift */, + 8290F6F2D17FBA5D0D19383C /* OptimoveFileManagerTests.swift */, + FB3C7B3C0173ACAD5BF630DE /* OptimoveStorageFacadeTests.swift */, + ); + path = Storage; sourceTree = ""; }; D85980716F84947A9D9B2474 /* Sources */ = { @@ -1532,6 +1557,18 @@ path = NetworkClient; sourceTree = ""; }; + E4A96204D19CB3049FDD3C84 /* CoreEvents */ = { + isa = PBXGroup; + children = ( + 86F4EE2D46B15E8B8B8EA016 /* AppOpenEventTests.swift */, + 4B17EE5D9F063E3BBCB9A394 /* PageVisitEventTests.swift */, + 89E228831AFE1D61F55AFBC0 /* SetUserAgentEventTests.swift */, + 9619B5935F5144458B85A194 /* SetUserEmailEventTests.swift */, + 54CE007CEFA3504B48265FAA /* SetUserIdEventTests.swift */, + ); + path = CoreEvents; + sourceTree = ""; + }; E8767E4F26EABC231D3BF727 /* Configuration */ = { isa = PBXGroup; children = ( @@ -1543,39 +1580,54 @@ path = Configuration; sourceTree = ""; }; - E8DD9ABEF7740FCB8768F6D8 /* OptiTrack */ = { + EA38BCA90CA160B46A3B5692 /* Legacy */ = { isa = PBXGroup; children = ( - CC14F9097C510CCDFC24ED44 /* OptiTrackMockQueueTests.swift */, - 35C421DD075F5131CFD24CA6 /* OptitrackTests.swift */, + AC0D8804B2EC84EE6FC4B506 /* RunningFlagsContainer.swift */, + 00E1883C492D6A712EF3979F /* Logger */, ); - path = OptiTrack; + path = Legacy; sourceTree = ""; }; - EA38BCA90CA160B46A3B5692 /* Legacy */ = { + EBFBC488118D3AEA46EF0E7A /* Tests */ = { isa = PBXGroup; children = ( - AC0D8804B2EC84EE6FC4B506 /* RunningFlagsContainer.swift */, - 00E1883C492D6A712EF3979F /* Logger */, + 03CF1E7D11F883149F445412 /* Resources */, + 0D29E193202474CD8C2DE86A /* Sources */, ); - path = Legacy; + path = Tests; sourceTree = ""; }; - EEB9E0C6101B3951E6943A2F /* Network */ = { + EE530923279B1BB20A3A9491 /* OptimobileShared */ = { isa = PBXGroup; children = ( - 85C981D5B3D94C295BE60C2A /* RemoteConfigurationRequestBuilderTests.swift */, + 5880EDB70E63EEF7CB2440A2 /* AnalyticsHelper.swift */, + 2F31D9650475129AA4CEB54B /* AppGroupsHelper.swift */, + 7E4B3747D4FE3D271EBADC2C /* KeyValPersistenceHelper.swift */, + 99EF83EFAF52070E59C5A389 /* KSHttp.swift */, + 07BBE644C3487EC57B169E6B /* MediaHelper.swift */, + ED41094AA6F15AAEC368096A /* OptimobileHelper.swift */, + 66905FCA4315A6615953B49B /* OptimobileUserDefaultsKey.swift */, + 499FB65BC432D40BBB409525 /* PendingNotification.swift */, + 3475E992634550F7F93076FC /* PendingNotificationHelper.swift */, ); - path = Network; + path = OptimobileShared; sourceTree = ""; }; - F268D2394BFA7585E9B8FE8B /* Generators */ = { + F5877C596178A3E105007D40 /* OptimobileShared */ = { isa = PBXGroup; children = ( - 809CCE6596151864378607B5 /* InstallationIdTests.swift */, - B9F1D9A9EC40981BD427CB4C /* OnStartEventGeneratorTests.swift */, + 3B613A036D30F7735F7F325F /* AnalyticsHelper.swift */, + 4C03DD4D5F885584BA44C723 /* AppGroupsHelper.swift */, + F251A2E671B4575611FC81D5 /* KeyValPersistenceHelper.swift */, + 427D452311AC9642F4EAD787 /* KSHttp.swift */, + A26871854B50CF09EED86457 /* MediaHelper.swift */, + C1F3F81B42DD7AA8AB1BEE7A /* OptimobileHelper.swift */, + C7AFA2A8587C5DCA93A30108 /* OptimobileUserDefaultsKey.swift */, + D7F841AF4345B15514C71B49 /* PendingNotification.swift */, + 122C3D0E6C2CD0AF1A51CDFD /* PendingNotificationHelper.swift */, ); - path = Generators; + path = OptimobileShared; sourceTree = ""; }; F5B9321DDE62D40FE2B0B980 /* Constants */ = { @@ -1594,16 +1646,6 @@ path = Providers; sourceTree = ""; }; - FC3095C5C64830371BF0A4DE /* Operations */ = { - isa = PBXGroup; - children = ( - BBF56D64273E803F0F9A6ACA /* GlobalConfigurationDownloaderTests.swift */, - BCD3B739367D0848F4CB234E /* MergeRemoteConfigurationOperationTests.swift */, - CED0FDAA1CED867DD491988C /* TenantConfigurationDownloaderTests.swift */, - ); - path = Operations; - sourceTree = ""; - }; FFFC29B1AC74FAB765D1156E /* Validators */ = { isa = PBXGroup; children = ( @@ -1617,52 +1659,53 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 12C3564D281196AB00672B42 /* Headers */ = { + 2CBF2FC09266D7C14FBF8DE6 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 12C35669281197A800672B42 /* OptimoveNotificationExtension.h in Headers */, + 5DF5F01D307C2628D8F1933E /* OptimoveNotificationExtension.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 12C35651281196AB00672B42 /* OptimoveNotificationServiceExtension */ = { + 2B74709896BBDCB01D227E99 /* OptimoveNotificationServiceExtension-Unit */ = { isa = PBXNativeTarget; - buildConfigurationList = 12C35661281196AB00672B42 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension" */; + buildConfigurationList = F64309E27387162F2741A1E9 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension-Unit" */; buildPhases = ( - 12C3564D281196AB00672B42 /* Headers */, - 12C3564E281196AB00672B42 /* Sources */, - 12C3564F281196AB00672B42 /* Frameworks */, - 12C35650281196AB00672B42 /* Resources */, + 4149A339AA1956B9DA4305D4 /* Sources */, + 7FAE8478B11C46F7BE02D5D8 /* Resources */, + B21D98E7E8A46F29F131C751 /* Frameworks */, + 03E0AABEBB3BEAB185CCF4FA /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 3C7F30AFE8F58F6019CB61C1 /* PBXTargetDependency */, ); - name = OptimoveNotificationServiceExtension; - productName = OptimoveNotificationExtension; - productReference = 12C35652281196AB00672B42 /* OptimoveNotificationServiceExtension.framework */; - productType = "com.apple.product-type.framework"; + name = "OptimoveNotificationServiceExtension-Unit"; + productName = "OptimoveNotificationServiceExtension-Unit"; + productReference = 3A9927C4B1D1B10899A43D19 /* OptimoveNotificationServiceExtension-Unit.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; }; - 12C35658281196AB00672B42 /* OptimoveNotificationServiceExtension-Unit */ = { + 43B4740CB2055B0FBF0587A0 /* OptimoveNotificationServiceExtension */ = { isa = PBXNativeTarget; - buildConfigurationList = 12C35664281196AB00672B42 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension-Unit" */; + buildConfigurationList = FFD81B2D83B4FE60621F8B92 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension" */; buildPhases = ( - 12C35655281196AB00672B42 /* Sources */, - 12C35656281196AB00672B42 /* Frameworks */, - 12C35657281196AB00672B42 /* Resources */, + 2CBF2FC09266D7C14FBF8DE6 /* Headers */, + 358B0F80C190B6F2577BE3AD /* Sources */, + 7900655B7311D8F8B85E52D2 /* Frameworks */, ); buildRules = ( ); dependencies = ( - 12C3565C281196AB00672B42 /* PBXTargetDependency */, + B7654AD6A84073556B4A1495 /* PBXTargetDependency */, ); - name = "OptimoveNotificationServiceExtension-Unit"; - productName = OptimoveNotificationExtensionTests; - productReference = 12C35659281196AB00672B42 /* OptimoveNotificationServiceExtension-Unit.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; + name = OptimoveNotificationServiceExtension; + productName = OptimoveNotificationServiceExtension; + productReference = 9FA39149BAE18208F17B07DB /* OptimoveNotificationServiceExtension.framework */; + productType = "com.apple.product-type.framework"; }; 4E6035250BAA805CC4049A9E /* OptimoveSDK */ = { isa = PBXNativeTarget; @@ -1712,6 +1755,9 @@ FA66F188105ECBB0A0DF8303 /* PBXTargetDependency */, ); name = "OptimoveSDK-Unit"; + packageProductDependencies = ( + ACA40D16D367805D921E4139 /* Mocker */, + ); productName = "OptimoveSDK-Unit"; productReference = 313AF75BEDDE3C3411F01615 /* OptimoveSDK-Unit.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -1731,6 +1777,9 @@ 1332D7EEA2D30F7BC962489A /* PBXTargetDependency */, ); name = "OptimoveCore-Unit"; + packageProductDependencies = ( + ADE980548010DA03B6C49B05 /* Mocker */, + ); productName = "OptimoveCore-Unit"; productReference = 64AAD2B0BFFF64DCB3907ECE /* OptimoveCore-Unit.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -1741,19 +1790,13 @@ F048C3E62DBD311754F63BD1 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1330; - LastUpgradeCheck = 1330; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; TargetAttributes = { - 12C35651281196AB00672B42 = { - CreatedOnToolsVersion = 13.3; - }; - 12C35658281196AB00672B42 = { - CreatedOnToolsVersion = 13.3; - }; }; }; buildConfigurationList = 05A4DEC880B8C9907862CC6F /* Build configuration list for PBXProject "Optimove" */; - compatibilityVersion = "Xcode 10.0"; + compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -1761,50 +1804,47 @@ en, ); mainGroup = 0FF4DF40AC6AAC3B8661208C; + packageReferences = ( + 2EF54C2A59B62D0EA19BFE82 /* XCRemoteSwiftPackageReference "Mocker" */, + ); projectDirPath = ""; projectRoot = ""; targets = ( 7013308FB86B06E91BDD05C2 /* OptimoveCore */, CBCF3AE39B9CAAD0103EC2B2 /* OptimoveCore-Unit */, + 43B4740CB2055B0FBF0587A0 /* OptimoveNotificationServiceExtension */, + 2B74709896BBDCB01D227E99 /* OptimoveNotificationServiceExtension-Unit */, 4E6035250BAA805CC4049A9E /* OptimoveSDK */, 7D5D7FF23E7F4742889FFFED /* OptimoveSDK-Unit */, - 12C35651281196AB00672B42 /* OptimoveNotificationServiceExtension */, - 12C35658281196AB00672B42 /* OptimoveNotificationServiceExtension-Unit */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 12C35650281196AB00672B42 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 12C35657281196AB00672B42 /* Resources */ = { + 30C0A98019632B1308F404A9 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4D9E6D1B430F63500E3BE7C1 /* configs.json in Resources */, + D3126FACD3A8EED32268202F /* core_events.json in Resources */, + 5925077A28967E98CF5186C8 /* dev.tid.107.optipush.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 30C0A98019632B1308F404A9 /* Resources */ = { + 6BA1DF3DEABEE368BBACB2C8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 54F23EA51AD50E499F2D44AF /* configs.json in Resources */, - D3126FACD3A8EED32268202F /* core_events.json in Resources */, - EC8157C51B383BD1B3BD9095 /* dev.tid.107.optipush.json in Resources */, + 9FEDC2520A6FBFF95FC6F9E2 /* Events-2590.sqlite in Resources */, + 7CAF4566492123A582434AD8 /* core_events.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6BA1DF3DEABEE368BBACB2C8 /* Resources */ = { + 7FAE8478B11C46F7BE02D5D8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - ED3B6FA3936A2C173102E487 /* Events-2590.sqlite in Resources */, - 7CAF4566492123A582434AD8 /* core_events.json in Resources */, + 32D946F7508437FFF4870EA8 /* core_events.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1815,45 +1855,45 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2D5CC37EBB1EFCC1DAB9C396 /* AppOpenEventTests.swift in Sources */, + 88545DD026AD8D8E19F3F074 /* AppOpenEventTests.swift in Sources */, 24AB2C2FB4F38FB0FFA4F61F /* ConfigurationFixture.swift in Sources */, - 39EC499624AEE7CFC0B677B5 /* CoreDataMigratorTests.swift in Sources */, - B0B632040ED242B1CFAB93E2 /* CoreEventFactoryTests.swift in Sources */, - 03A06957E14DE9C264FD3BF4 /* EnterForegroundObserverTests.swift in Sources */, - 106BA1705BF376B6A7D81815 /* EventValidatorTests.swift in Sources */, + CC79D3062081B1037A5138A0 /* CoreDataMigratorTests.swift in Sources */, + 61D2F706F2433B8CBFD3353E /* CoreEventFactoryTests.swift in Sources */, + 1109CC1061D9544E838C29E9 /* EnterForegroundObserverTests.swift in Sources */, + 6EE18CD5F112D6AE7F1AB025 /* EventValidatorTests.swift in Sources */, D002E78C7BFBD4BEE5F9FECC /* FileAccessible.swift in Sources */, D88E575BBA436CE7BD3ED0D3 /* GlobalConfigFixture.swift in Sources */, - EC6FCE53F6000850B92B2511 /* GlobalConfigurationDownloaderTests.swift in Sources */, - 567FF1C790FA8B2A7FAC4F7F /* InstallationIdTests.swift in Sources */, - 9839623196598C955928FEA0 /* KVOExpectation.swift in Sources */, - D9E82D512D6810F3203A98D4 /* MergeRemoteConfigurationOperationTests.swift in Sources */, - 19FAAD1B5B8F3A83CCE1681A /* MockConfigurationRepository.swift in Sources */, - 1EC0331B7F3631CAFF5B4BE7 /* MockDateTimeProvider.swift in Sources */, - 98F9B9E29920E18313F20771 /* MockLocationService.swift in Sources */, + 75F3E331C128231A1447AE8F /* GlobalConfigurationDownloaderTests.swift in Sources */, + A87DE47E621356B33E682E75 /* InstallationIdTests.swift in Sources */, + E147D2E305837E0D739D1C05 /* KVOExpectation.swift in Sources */, + 891CCE01D5422F4D4E00B469 /* MergeRemoteConfigurationOperationTests.swift in Sources */, + B494048CD01D26D8FEE2A870 /* MockConfigurationRepository.swift in Sources */, + 241379B33EC9E7F315FE2E8C /* MockDateTimeProvider.swift in Sources */, + 8C2A67FF1C272E8180249A3A /* MockLocationService.swift in Sources */, A6D704D18C74065D0101020A /* MockOptimoveStorage.swift in Sources */, - 94F0C89849632523B9598FA4 /* MockOptistreamQueue.swift in Sources */, - CBA3D6BD2269778218266AD5 /* MockStatisticService.swift in Sources */, - CF0221B39C0839E2FEE69AE5 /* MockSynchronizer.swift in Sources */, - E7B65A20C54C58E9FE0572A1 /* NewEmailHandlerTests.swift in Sources */, - 6D08783D81F2B6D01BC5EA96 /* NewTenantInfoHandlerTests.swift in Sources */, - 9FD12FE96EA86F95AFBF7824 /* NewUserIDHandlerTests.swift in Sources */, - 45AEE0276D250CF2208C644E /* OnStartEventGeneratorTests.swift in Sources */, - 86D018D4B3FDD1E5654A80B3 /* OptiTrackMockQueueTests.swift in Sources */, + F670819778DAFCB8BD88988E /* MockOptistreamQueue.swift in Sources */, + 49A29F260B5CF8363DFD6A72 /* MockStatisticService.swift in Sources */, + 3E1BFD924A9840F55AD60E52 /* MockSynchronizer.swift in Sources */, + 7556ED67ED844CC556897F49 /* NewEmailHandlerTests.swift in Sources */, + 957510FD9374B0360E0B2495 /* NewTenantInfoHandlerTests.swift in Sources */, + 329179D5BF60BC810A939B9A /* NewUserIDHandlerTests.swift in Sources */, + 4F8B14A78177D5D88B803A09 /* OnStartEventGeneratorTests.swift in Sources */, + 9D326D5880402C668760EEB9 /* OptiTrackMockQueueTests.swift in Sources */, CB4AC43D9576A580D0C217DA /* OptimoveTestCase.swift in Sources */, DBD21C31B247D71522605231 /* OptistreamNetworkingMock.swift in Sources */, - 94CE3D9CC6C61823F42F022E /* OptitrackTests.swift in Sources */, - 34F891B25C0607047E535D8D /* PageVisitEventTests.swift in Sources */, - BBC3825F222CB6EDD09E8B11 /* RealtimeComponentTests.swift in Sources */, - 1F0A3376596C3A8290383CD0 /* RemoteConfigurationRequestBuilderTests.swift in Sources */, - 419EFD0DCB8F3A6D4017D32B /* SetUserAgentEventTests.swift in Sources */, - 54B57794ADCCA618D003408C /* SetUserEmailEventTests.swift in Sources */, - C071798869C6349DEC23D89B /* SetUserIdEventTests.swift in Sources */, - 7718B45F3E6F2D43C6A5ED3F /* StringSplitByLenghtExtensionsTests.swift in Sources */, + B1E8DC1836EBD8D9924B1153 /* OptitrackTests.swift in Sources */, + 52C8D4888B17B9C62D68D6E2 /* PageVisitEventTests.swift in Sources */, + EC47D3A2A0C0F3589770B712 /* RealtimeComponentTests.swift in Sources */, + 862030422F6926A50EB96D6B /* RemoteConfigurationRequestBuilderTests.swift in Sources */, + B76405565985A5F8DA43A145 /* SetUserAgentEventTests.swift in Sources */, + A065AC8BE5A5705439533508 /* SetUserEmailEventTests.swift in Sources */, + 29157AAD85CBDBAC17C3A62A /* SetUserIdEventTests.swift in Sources */, + 419C1099146E429DD1D1B87A /* StringSplitByLenghtExtensionsTests.swift in Sources */, 6AE6747FCF19E211146D3E1C /* StubEvent.swift in Sources */, 370BDBC6F608BEE16E9B7439 /* StubVariables.swift in Sources */, 9CF7237135A4CC033D355E3F /* TenantConfigFixture.swift in Sources */, - A5B65BA10A3B356CAACADB8D /* TenantConfigurationDownloaderTests.swift in Sources */, - 83F8B837C82ED3DCCCF9F7FF /* UserIDValidatorTests.swift in Sources */, + 3C4DED7A2092B00C6092CE9B /* TenantConfigurationDownloaderTests.swift in Sources */, + 2A639EA131398E39B22B6D62 /* UserIDValidatorTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1861,57 +1901,56 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 12C3562A281194D500672B42 /* KSHttp.swift in Sources */, + 9D44CC1A12340665FCAF5A30 /* AnalyticsHelper.swift in Sources */, + 82BC01FC37CB7BFFECFD693F /* AppGroupsHelper.swift in Sources */, 167EF8E42EABC80FEB2D2A1A /* AppOpenEvent.swift in Sources */, + 5324FCF377FE827FDE0A97F3 /* AppOpenObserver.swift in Sources */, B9D3F1723BB20889FD2817A6 /* AppOpenOnStartGenerator.swift in Sources */, 454AB713344799303679A602 /* Assembly.swift in Sources */, 722BC1AC4D6531387A33F03C /* Bundle+Identifiers.swift in Sources */, 41E93887039BA10C580D3F60 /* ComponentFactory.swift in Sources */, C323AD127E24F3444D868D46 /* ComponentHandlers.swift in Sources */, D84FA7E0419D5AA96CE24553 /* Components.swift in Sources */, - 12C3562F281194D500672B42 /* OptimobileHelper.swift in Sources */, 1A4FD956C218500F124C94B1 /* ConfigurationFetcher.swift in Sources */, 5EFB943F708BFECD8C7122C4 /* Container.swift in Sources */, A6CC7197F19B7D0922575FC4 /* CoreDataAttributeDescription.swift in Sources */, E92EC16E27036BFFD16F5DF2 /* CoreDataEntityDescription.swift in Sources */, - 4F585C7027FECCFA005E7BB4 /* CwlSysctl.swift in Sources */, 5231F567663FDB98A45B2BB7 /* CoreDataFetchIndexDescription.swift in Sources */, - 4F585C7727FECCFA005E7BB4 /* Optimobile+Analytics.swift in Sources */, AD6686AAC3B244EE9A85108E /* CoreDataFetchedPropertyDescription.swift in Sources */, D450B85E3B94ED96ED2F3849 /* CoreDataMigrationStep.swift in Sources */, 321BFE49BBD5B3C8C0F24618 /* CoreDataMigrationVersion.swift in Sources */, B177625EF698C25631CC290E /* CoreDataMigrator.swift in Sources */, 7896AC2FA8B7D13761660979 /* CoreDataModelDescription.swift in Sources */, - 1277E48F2812AF650097AC3B /* AppOpenObserver.swift in Sources */, 6E486EE6C7212E4017EE5F1A /* CoreDataRelationshipDescription.swift in Sources */, 1D3E9806CE83FC237BAD4EB4 /* CoreEventFactory.swift in Sources */, + 1093F068DD247478DC5D67C5 /* CwlSysctl.swift in Sources */, 79B848B05EF3742A8A5F5BED /* DateTimeProvider.swift in Sources */, + 8A548FA8E34257081564E4C3 /* DeepLinkFingerprinter.swift in Sources */, 866DC15E07B22C2BFE8F3EE8 /* DeviceStateObserver.swift in Sources */, 6DF6C1462D8DE0D23050BC75 /* DeviceStateObserverFactory.swift in Sources */, 98C5A68EE8133BD14877F57B /* Dictionary+CompactMapKeys.swift in Sources */, 8D229B5DC22108C54B21D53B /* EmailValidator.swift in Sources */, AFC2BAC060B346BD49B8A68F /* EventCDv1.swift in Sources */, E1B7BB8C96DEC557EDFA7F6D /* EventCDv1ToEventCDv2MappingModel.swift in Sources */, - 12C3562E281194D500672B42 /* AppGroupsHelper.swift in Sources */, 82CC6AF0987CCEDF01CBF175 /* EventCDv1ToEventCDv2MigrationPolicy.swift in Sources */, - 4F585C6F27FECCFA005E7BB4 /* OptimoveInApp.swift in Sources */, 3CA51DAAF7A58E28A27F04AE /* EventCDv2.swift in Sources */, - 4F585C7427FECCFA005E7BB4 /* Optimobile.swift in Sources */, - 4F585C7627FECCFA005E7BB4 /* OptimoveUserNotificationCenterDelegate.swift in Sources */, A136F00619AFA98D1D61695F /* EventValidator.swift in Sources */, C6439A52CCEF9F1BCE79519E /* FirstRunTimestampGenerator.swift in Sources */, 05FCC9633BD5578A77355ABF /* GlobalConfigurationDownloader.swift in Sources */, - 4F585C6A27FECCFA005E7BB4 /* InAppModels.swift in Sources */, + 64D81E877A58866CDD528539 /* InAppManager.swift in Sources */, + F54F5C30E5253F81BCDE4AA3 /* InAppModels.swift in Sources */, + E0290A63EA4AF5F9CE836C50 /* InAppPresenter.swift in Sources */, ABCBC196572B66EA38C77669 /* InMemoryBuffer.swift in Sources */, - 4F585C7827FECCFA005E7BB4 /* DeepLinkFingerprinter.swift in Sources */, - 12C35630281194D500672B42 /* PendingNotification.swift in Sources */, AC722DB369A32C507F882EFD /* InstallationIdGenerator.swift in Sources */, + BC248EC1C9EF19594422EF11 /* KSHttp.swift in Sources */, 9025A728FB6F87551D520BE6 /* KeyPath+Extension.swift in Sources */, + 5C4AC13BA561A2D0EE691A7D /* KeyValPersistenceHelper.swift in Sources */, 7946547A4A94770AE03156AE /* LocationService.swift in Sources */, FCC20433D011E60F2C404BA8 /* LogLevel.swift in Sources */, 1ECCB650EA8E2C46B9C74A6B /* LoggerInitializator.swift in Sources */, E454A59BDF3B9A9F68DB6139 /* MainFactory.swift in Sources */, BC1825E2A93DCDAF68D16389 /* Managed.swift in Sources */, + 40B1374F1803D46BB3783951 /* MediaHelper.swift in Sources */, 7BE7BAF7F0270B023402E320 /* MergeRemoteConfigurationOperation.swift in Sources */, F20E19FEEEF9B200E5321625 /* MetaDataEvent.swift in Sources */, E1E7F62209130B79A66B39EC /* MigrationObserver.swift in Sources */, @@ -1919,41 +1958,46 @@ 10D8FDCAB2DEDFDC34E715E9 /* MobileProvision.swift in Sources */, 1FB88D00B177B21B5D2C3BC2 /* NSManagedObjectContext+Utilities.swift in Sources */, 50B6E591AC81B656E87934F7 /* NetworkRequestFactory.swift in Sources */, - B6E63EA62943734C001959E5 /* Optimobile+Location.swift in Sources */, 0E86E3145ADEEE0A91734327 /* NetworkingFactory.swift in Sources */, A8F415A6B21DA9A79ACC8546 /* NewEmailHandler.swift in Sources */, 8A615E8D19A27C22DC4DF552 /* NewTenantInfoHandler.swift in Sources */, 58C3F746E854C6C27FF1CF12 /* NewUserHandler.swift in Sources */, 2831D1D6A605C2B8A6B57080 /* NewVisitorIdGenerator.swift in Sources */, 599FA52041C9CB1EDAD6D399 /* Notification.swift in Sources */, - 4F585C6827FECCFA005E7BB4 /* InAppPresenter.swift in Sources */, - 12C3562B281194D500672B42 /* AnalyticsHelper.swift in Sources */, 8D28D0CF3F9FFB3CFCDD6B6F /* OnStartEventGenerator.swift in Sources */, - 12C3562C281194D500672B42 /* KeyValPersistenceHelper.swift in Sources */, - 12C35632281194D500672B42 /* MediaHelper.swift in Sources */, 55754C0209B72C6239CCE64E /* OperationFactory.swift in Sources */, - 4F585C6B27FECCFA005E7BB4 /* OptimoveConfig.swift in Sources */, 39F0A8EF590E06C63B8AA931 /* Operations.swift in Sources */, - 4F585C6D27FECCFA005E7BB4 /* SessionHelper.swift in Sources */, 432EE244D778884AEA4A9208 /* OptiLoggerOutputStream.swift in Sources */, - 4F585C6927FECCFA005E7BB4 /* InAppManager.swift in Sources */, 2EA9D0284826D6D32BFA3219 /* OptiLoggerStreamsContainer.swift in Sources */, 8D24DBF32623CCCAB9652019 /* OptiTrack.swift in Sources */, + 17E31410E98A8F445EAE07DA /* Optimobile+Analytics.swift in Sources */, + 0F0AE34073703DC410DD4F4C /* Optimobile+DeepLinking.swift in Sources */, + 717BAF1D2639397092D4F216 /* Optimobile+Location.swift in Sources */, + 82DD6003F6614083DF6595C0 /* Optimobile+Push.swift in Sources */, + 503930654F8FCECBDE14DA5B /* Optimobile+Stats.swift in Sources */, + 7AEB43BFC0E814FEBEE5BC1F /* Optimobile.swift in Sources */, + 2E41CAC99770B430CCA80976 /* OptimobileBadgeObserver.swift in Sources */, + 72D7D833022337E4C0CF9A11 /* OptimobileHelper.swift in Sources */, + 40F8D5713430223076ED4DA8 /* OptimobileUserDefaultsKey.swift in Sources */, 499D5BF06BBCC8EBB94263E4 /* Optimove.swift in Sources */, + F80582ECAF50E9E3597299E6 /* OptimoveConfig.swift in Sources */, FE6961AE12E4BCB6A294FB85 /* OptimoveEvent.swift in Sources */, + 187A9CE9D150CF733D6496B7 /* OptimoveInApp.swift in Sources */, 7C3ABD85CE679B016ACD1C54 /* OptimoveKeys.swift in Sources */, + 42822ABF4ACA9B04100FAF90 /* OptimoveUserNotificationCenterDelegate.swift in Sources */, 9CB2C5384B4414B52C02DBBD /* OptistreamQueue.swift in Sources */, 4E1437373721EFA52C894174 /* OptistreamQueueImpl.swift in Sources */, 91EFA9B02C815F93C7725986 /* PageVisitEvent.swift in Sources */, 5CAA99328294F84AB95EF9D2 /* ParametersDecorator.swift in Sources */, 95D574CDBD1AD0C0416C0CA2 /* ParametersNormalizer.swift in Sources */, + 372E500B05099415082BF745 /* PendingNotification.swift in Sources */, + 60E4C4DA168F42BD72990C1D /* PendingNotificationHelper.swift in Sources */, 78B7E961DD94BC6F19DF9A86 /* PersistentContainer.swift in Sources */, 61942EEA31C1310BA660F131 /* Pipe.swift in Sources */, 92292E5A182ECEBFFDF259AE /* Pipeline.swift in Sources */, 1CF1B6182320C994F7F4FC45 /* ProcessInfo.swift in Sources */, 751E3FAF2723291C46042204 /* RealTime.swift in Sources */, F9A93090DC0B4B5ABC51C35F /* RemoteConfigurationNetworking.swift in Sources */, - 4FA8F61727FEE872005CB88E /* OptimobileBadgeObserver.swift in Sources */, 8C71F306E9E7351F124BE516 /* RemoteConfigurationRequestBuilder.swift in Sources */, C3054B47A6ED4A4BF2277F02 /* ResignActiveObserver.swift in Sources */, 5A08B9EDBA80168AC667425D /* RingBuffer.swift in Sources */, @@ -1961,77 +2005,82 @@ 5AF8B551D48AF8A7B37B2054 /* SDKInitializer.swift in Sources */, E04C734BCB92039C3B747495 /* ScreenVisitValidator.swift in Sources */, B44B56B11935E11D4A3DFDAC /* ServiceLocator.swift in Sources */, + D436E32EB5FF0A1108878C06 /* SessionHelper.swift in Sources */, C2A001E9BC1DD27508D7B8C6 /* SetUserAgent.swift in Sources */, 6EBAAB8917D02E887688A33D /* SetUserEmailEvent.swift in Sources */, F4463BD44A499220DDE80852 /* SetUserIdEvent.swift in Sources */, BDB72CFA372352BF226C045D /* StatisticService.swift in Sources */, 64C373178EC3796339003DA1 /* String+SHA1.swift in Sources */, - 12C3562D281194D500672B42 /* OptimobileUserDefaultsKey.swift in Sources */, - 4F585C7527FECCFA005E7BB4 /* UrlBuilder.swift in Sources */, 4B583BA9BF1C2FA8274AACD3 /* String+Split.swift in Sources */, - 4F585C6C27FECCFA005E7BB4 /* Optimobile+DeepLinking.swift in Sources */, 529587C2B105ADD76A48F003 /* String+alphanumeric.swift in Sources */, D3442290F4766F3C2835815D /* String+isBlank.swift in Sources */, 68FA63CCDADAD13FA979A68B /* String+random.swift in Sources */, - 4F585C7227FECCFA005E7BB4 /* Optimobile+Stats.swift in Sources */, - 12C35631281194D500672B42 /* PendingNotificationHelper.swift in Sources */, 79CD25EC4E940F6CEC7C0F03 /* String.swift in Sources */, A3DAFD3DEABDBCEEA6899527 /* TenantConfigurationDownloader.swift in Sources */, DDD6774A89DE3F27E8F12D0B /* TenantEvent.swift in Sources */, + A2D0C4B960835388427190D5 /* UrlBuilder.swift in Sources */, A6F87FEA3C9AF4C52FC4E4DB /* User.swift in Sources */, 6F2F6C1080B6763E7EE538D2 /* UserAgentGenerator.swift in Sources */, 695F98AE4990411750376C41 /* UserValidator.swift in Sources */, - 4F585C7127FECCFA005E7BB4 /* Optimobile+Push.swift in Sources */, AAB7C3B91AA0AD65E7A6AC9B /* Version.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 12C3564E281196AB00672B42 /* Sources */ = { + 2718D3A4F681CCDDBABBC5AA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 12C356752811992B00672B42 /* AnalyticsHelper.swift in Sources */, - 12C356772811993100672B42 /* OptimobileUserDefaultsKey.swift in Sources */, - 12C356722811987C00672B42 /* OptimoveNotificationService.swift in Sources */, - 12C356782811993400672B42 /* AppGroupsHelper.swift in Sources */, - 12C356732811987C00672B42 /* CategoryManager.swift in Sources */, - 12C356762811992E00672B42 /* KeyValPersistenceHelper.swift in Sources */, - 12C3567C2811993F00672B42 /* MediaHelper.swift in Sources */, - 12C3567A2811993A00672B42 /* PendingNotification.swift in Sources */, - 12C356792811993700672B42 /* OptimobileHelper.swift in Sources */, - 12C3567B2811993C00672B42 /* PendingNotificationHelper.swift in Sources */, - 12C356742811992800672B42 /* KSHttp.swift in Sources */, + 5E1A337AFFC98DDAB8BBE389 /* ConfigurationBuilderTests.swift in Sources */, + F366378361753D8AC34D9449 /* ConfigurationFixture.swift in Sources */, + 626B1AF99FD89EB1053D308D /* FileAccessible.swift in Sources */, + A7B58760AD7154C5D5616A52 /* GlobalConfigFixture.swift in Sources */, + 2EE7C3F42D91857A85DB8A5B /* GlobalConfigTests.swift in Sources */, + EF285892FEC9D49538D50B0C /* KeyValueStorageTests.swift in Sources */, + EAEE293A4A4E489DB7C9E6AC /* MockOptimoveStorage.swift in Sources */, + CFC4BA74FBC9CD6629372AB0 /* NetworkClientTests.swift in Sources */, + 8EE975D03F10EEBA319452CD /* OptimoveFileManagerTests.swift in Sources */, + BE5803E4A1CBB7C280C8BB8E /* OptimoveStorageFacadeTests.swift in Sources */, + 885DA88EB22848769955C0B7 /* OptimoveTestCase.swift in Sources */, + A52447C34C7025C5FA5766A4 /* OptistreamNetworkingMock.swift in Sources */, + E362BF6DD8888742811D98A0 /* StubEvent.swift in Sources */, + 431DE4439C07216FF2020D9E /* StubVariables.swift in Sources */, + 16A2E2E9FFB751FC02A26BA3 /* TenantConfigFixture.swift in Sources */, + 5B7214C0497E11CCE22E934C /* TenantConfigTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 12C35655281196AB00672B42 /* Sources */ = { + 358B0F80C190B6F2577BE3AD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 129D63E428199276005DCB7F /* OptimoveNotificationExtensionTests.swift in Sources */, + A77F8D3AA2953EC27506C754 /* AnalyticsHelper.swift in Sources */, + BCB5E93DE8C40BFCC84D9B95 /* AppGroupsHelper.swift in Sources */, + C26C07FBBDCCA505B88B0F82 /* CategoryManager.swift in Sources */, + AA64749A1A517EC2636A22B4 /* KSHttp.swift in Sources */, + FBEDA772B460CEDF5A9CD453 /* KeyValPersistenceHelper.swift in Sources */, + B90744D2826B1CC61479CB09 /* MediaHelper.swift in Sources */, + C6D90CD8E2120D32C952FFF5 /* OptimobileHelper.swift in Sources */, + 718D7492799EC4068EF80F67 /* OptimobileUserDefaultsKey.swift in Sources */, + 72AE4BC46B4A6A97E92622C3 /* OptimoveNotificationService.swift in Sources */, + 375F0DD93BA5A985979D5FB8 /* PendingNotification.swift in Sources */, + F13364D158937A2C22431F54 /* PendingNotificationHelper.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2718D3A4F681CCDDBABBC5AA /* Sources */ = { + 4149A339AA1956B9DA4305D4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C2FD2CDE73EBFF5EE2610920 /* ConfigurationBuilderTests.swift in Sources */, - F366378361753D8AC34D9449 /* ConfigurationFixture.swift in Sources */, - 626B1AF99FD89EB1053D308D /* FileAccessible.swift in Sources */, - A7B58760AD7154C5D5616A52 /* GlobalConfigFixture.swift in Sources */, - 04B351D1EFFA33FBD8A9D3CB /* GlobalConfigTests.swift in Sources */, - 69B4B6E228E5E2309F8FA445 /* KeyValueStorageTests.swift in Sources */, - EAEE293A4A4E489DB7C9E6AC /* MockOptimoveStorage.swift in Sources */, - 080AE4F487F030AAC3EC2A30 /* NetworkClientTests.swift in Sources */, - 3A758813E0D3A1DFD74286FB /* OptimoveFileManagerTests.swift in Sources */, - E56294EED7434283D6BB6337 /* OptimoveStorageFacadeTests.swift in Sources */, - 885DA88EB22848769955C0B7 /* OptimoveTestCase.swift in Sources */, - A52447C34C7025C5FA5766A4 /* OptistreamNetworkingMock.swift in Sources */, - E362BF6DD8888742811D98A0 /* StubEvent.swift in Sources */, - 431DE4439C07216FF2020D9E /* StubVariables.swift in Sources */, - 16A2E2E9FFB751FC02A26BA3 /* TenantConfigFixture.swift in Sources */, - A975E13C75A90B4150DCFF04 /* TenantConfigTests.swift in Sources */, + DFBFE8B289F51A514282B44A /* ConfigurationFixture.swift in Sources */, + 40745C5D6447231E96262ACB /* FileAccessible.swift in Sources */, + 36D0BE577A817ED7B5076112 /* GlobalConfigFixture.swift in Sources */, + FD6B210141F97A6B47D3B50B /* MockOptimoveStorage.swift in Sources */, + 929E35FD131B942202950B5B /* OptimoveNotificationExtensionTests.swift in Sources */, + 2BBFB2D03A135BE343DCB352 /* OptimoveTestCase.swift in Sources */, + 28892C11EFABDB720CA7F4DE /* OptistreamNetworkingMock.swift in Sources */, + D40627451576BB6978A11EB0 /* StubEvent.swift in Sources */, + A7EE33E084DB5B80D844E56C /* StubVariables.swift in Sources */, + B12432B9CACFCBD8052F2987 /* TenantConfigFixture.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2092,11 +2141,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 12C3565C281196AB00672B42 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 12C35651281196AB00672B42 /* OptimoveNotificationServiceExtension */; - targetProxy = 12C3565B281196AB00672B42 /* PBXContainerItemProxy */; - }; 1332D7EEA2D30F7BC962489A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7013308FB86B06E91BDD05C2 /* OptimoveCore */; @@ -2107,6 +2151,16 @@ target = 7013308FB86B06E91BDD05C2 /* OptimoveCore */; targetProxy = 7029B7FEB9FDB98D7F38992E /* PBXContainerItemProxy */; }; + 3C7F30AFE8F58F6019CB61C1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 43B4740CB2055B0FBF0587A0 /* OptimoveNotificationServiceExtension */; + targetProxy = DD314B46AF786059D0227C9B /* PBXContainerItemProxy */; + }; + B7654AD6A84073556B4A1495 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7013308FB86B06E91BDD05C2 /* OptimoveCore */; + targetProxy = 29FCBF7A2B772CC3F0B6F87B /* PBXContainerItemProxy */; + }; FA66F188105ECBB0A0DF8303 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4E6035250BAA805CC4049A9E /* OptimoveSDK */; @@ -2119,11 +2173,8 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = LDTF4M4FTC; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OptimoveSDK/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2185,7 +2236,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -2197,121 +2248,68 @@ }; name = Debug; }; - 12C35662281196AB00672B42 /* Debug */ = { + 1999E9C34677AD785B23E781 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", + BUNDLE_LOADER = "$(TEST_HOST)"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OptimoveSDK/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 22F806572DE9FAECA52ABDA6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + INFOPLIST_FILE = OptimoveNotificationServiceExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.OptimoveNotificationExtension; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; + SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 12C35663281196AB00672B42 /* Release */ = { + 2F66E3E6464749EB491DBF7E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_FILE = OptimoveNotificationServiceExtension/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.OptimoveNotificationExtension; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.extension.notificationservice; + SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 12C35665281196AB00672B42 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.extension.OptimoveNotificationExtensionTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - 12C35666281196AB00672B42 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.extension.OptimoveNotificationExtensionTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 1999E9C34677AD785B23E781 /* Debug */ = { + 3E2E371B4B13AC132AC62C0E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = LDTF4M4FTC; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OptimoveNotificationServiceExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2320,12 +2318,12 @@ SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; - name = Debug; + name = Release; }; 4A27E1E9D26058C86424147C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = NO; + APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; @@ -2350,11 +2348,8 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = LDTF4M4FTC; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OptimoveCore/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2369,18 +2364,39 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = LDTF4M4FTC; - FRAMEWORK_SEARCH_PATHS = ( + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OptimoveCore/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", + "@executable_path/Frameworks", + "@loader_path/Frameworks", ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 637E5E27537E8A4E1D8359F4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = OptimoveNotificationServiceExtension/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", - "@loader_path/Frameworks", ); + PRODUCT_BUNDLE_IDENTIFIER = com.optimove.sdk.extension.notificationservice; SDKROOT = iphoneos; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; @@ -2429,7 +2445,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2489,7 +2505,7 @@ B0F2997F877D21FFF64C1DC7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = NO; + APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; @@ -2522,24 +2538,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; - 12C35661281196AB00672B42 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 12C35662281196AB00672B42 /* Debug */, - 12C35663281196AB00672B42 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 12C35664281196AB00672B42 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension-Unit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 12C35665281196AB00672B42 /* Debug */, - 12C35666281196AB00672B42 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; 36C3A164DE9EDC011F57D0E9 /* Build configuration list for PBXNativeTarget "OptimoveCore-Unit" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2576,7 +2574,49 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + F64309E27387162F2741A1E9 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension-Unit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 22F806572DE9FAECA52ABDA6 /* Debug */, + 3E2E371B4B13AC132AC62C0E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + FFD81B2D83B4FE60621F8B92 /* Build configuration list for PBXNativeTarget "OptimoveNotificationServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F66E3E6464749EB491DBF7E /* Debug */, + 637E5E27537E8A4E1D8359F4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 2EF54C2A59B62D0EA19BFE82 /* XCRemoteSwiftPackageReference "Mocker" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/WeTransfer/Mocker"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.0.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + ACA40D16D367805D921E4139 /* Mocker */ = { + isa = XCSwiftPackageProductDependency; + package = 2EF54C2A59B62D0EA19BFE82 /* XCRemoteSwiftPackageReference "Mocker" */; + productName = Mocker; + }; + ADE980548010DA03B6C49B05 /* Mocker */ = { + isa = XCSwiftPackageProductDependency; + package = 2EF54C2A59B62D0EA19BFE82 /* XCRemoteSwiftPackageReference "Mocker" */; + productName = Mocker; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = F048C3E62DBD311754F63BD1 /* Project object */; } diff --git a/Optimove.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Optimove.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index 54782e32..00000000 --- a/Optimove.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded - - - diff --git a/Optimove.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Optimove.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..49ba33f8 --- /dev/null +++ b/Optimove.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "mocker", + "kind" : "remoteSourceControl", + "location" : "https://github.com/WeTransfer/Mocker", + "state" : { + "revision" : "4384e015cae4916a6828252467a4437173c7ae17", + "version" : "3.0.1" + } + } + ], + "version" : 2 +} diff --git a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveCore.xcscheme b/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveCore.xcscheme index 9935f800..1ba402da 100644 --- a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveCore.xcscheme +++ b/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveCore.xcscheme @@ -1,10 +1,11 @@ + LastUpgradeVersion = "1430" + version = "1.7"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> + shouldUseLaunchSchemeArgsEnv = "YES" + onlyGenerateCoverageForSpecifiedTargets = "NO"> + + + + @@ -39,6 +50,8 @@ + + + + + + + + + + + LastUpgradeVersion = "1430" + version = "1.7"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> @@ -26,19 +27,31 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + onlyGenerateCoverageForSpecifiedTargets = "NO"> + + + + + + + + + + + + + + diff --git a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK-Unit.xcscheme b/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK-Unit.xcscheme deleted file mode 100644 index f112d096..00000000 --- a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK-Unit.xcscheme +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK.xcscheme b/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK.xcscheme index 5b3a1cb0..ab52cef0 100644 --- a/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK.xcscheme +++ b/Optimove.xcodeproj/xcshareddata/xcschemes/OptimoveSDK.xcscheme @@ -1,10 +1,11 @@ + LastUpgradeVersion = "1430" + version = "1.7"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> + shouldUseLaunchSchemeArgsEnv = "YES" + onlyGenerateCoverageForSpecifiedTargets = "NO"> + + + + @@ -39,6 +50,8 @@ + + + + + + + + + + + LastUpgradeVersion = "1430" + version = "1.7"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> + + + + + shouldUseLaunchSchemeArgsEnv = "YES" + onlyGenerateCoverageForSpecifiedTargets = "NO"> + + + + + + - + - + diff --git a/OptimoveNotificationServiceExtension/Info.plist b/OptimoveNotificationServiceExtension/Info.plist new file mode 100644 index 00000000..323e5ecf --- /dev/null +++ b/OptimoveNotificationServiceExtension/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/input.xcfilelist b/input.xcfilelist deleted file mode 100644 index f5259c65..00000000 --- a/input.xcfilelist +++ /dev/null @@ -1,3 +0,0 @@ -$(SRCROOT)/Carthage/Build/iOS/OptimoveCore.framework -$(SRCROOT)/Carthage/Build/iOS/OptimoveSDK.framework -$(SRCROOT)/Carthage/Build/iOS/OptimoveNotificationServiceExtension.framework \ No newline at end of file diff --git a/output.xcfilelist b/output.xcfilelist deleted file mode 100644 index b2fe7109..00000000 --- a/output.xcfilelist +++ /dev/null @@ -1,3 +0,0 @@ -$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/OptimoveCore.framework -$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/OptimoveSDK.framework -$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/OptimoveNotificationServiceExtension.framework \ No newline at end of file diff --git a/project.yml b/project.yml index cd605dca..6c9b6242 100644 --- a/project.yml +++ b/project.yml @@ -1,7 +1,12 @@ name: Optimove options: - deploymentTarget: - iOS: "10" + deploymentTarget: + iOS: "12" + +packages: + Mocker: + url: https://github.com/WeTransfer/Mocker + from: 3.0.0 schemes: UnitTests: @@ -11,7 +16,7 @@ schemes: OptimoveSDK-Unit: [test] OptimoveNotificationServiceExtension-Unit: [test] test: - targets: + targets: - OptimoveCore-Unit - OptimoveSDK-Unit - OptimoveNotificationServiceExtension-Unit @@ -21,7 +26,7 @@ targets: OptimoveCore: type: framework platform: iOS - sources: + sources: - path: OptimoveCore excludes: - "Tests/**/*" @@ -42,7 +47,7 @@ targets: OptimoveSDK: type: framework platform: iOS - sources: + sources: - path: OptimoveSDK excludes: - "Tests/**/*" @@ -56,7 +61,7 @@ targets: - OptimoveSDK-Unit settings: PRODUCT_BUNDLE_IDENTIFIER: com.optimove.sdk - dependencies: + dependencies: - target: OptimoveCore - sdk: UIKit.framework - sdk: UserNotifications.framework @@ -66,7 +71,7 @@ targets: OptimoveNotificationServiceExtension: type: framework platform: iOS - sources: + sources: - path: OptimoveNotificationServiceExtension excludes: - "Tests/**/*" @@ -85,49 +90,58 @@ targets: - target: OptimoveCore - sdk: UserNotifications.framework - sdk: Foundation.framework - + # unit-test OptimoveCore-Unit: type: bundle.unit-test platform: iOS - sources: - - path: OptimoveCore/Tests/ - name: OptimoveCore-Unit + sources: + - path: OptimoveCore excludes: - - .gitkeep + - "Sources/**/*" + - "Info.plist" + - ".gitkeep" - path: Shared name: Shared-Unit + settings: + GENERATE_INFOPLIST_FILE: YES dependencies: - target: OptimoveCore - - carthage: Mocker + - package: Mocker OptimoveSDK-Unit: type: bundle.unit-test platform: iOS - scheme: - commandLineArguments: - "-com.optimove.track.test": true - sources: - - path: OptimoveSDK/Tests/ - name: OptimoveSDK-Unit + # scheme: + # commandLineArguments: + # "-com.optimove.track.test": true + sources: + - path: OptimoveSDK excludes: - - .gitkeep + - "Sources/**/*" + - "Info.plist" + - ".gitkeep" - path: Shared name: Shared-Unit + settings: + GENERATE_INFOPLIST_FILE: YES dependencies: - target: OptimoveSDK - - carthage: Mocker + - package: Mocker OptimoveNotificationServiceExtension-Unit: type: bundle.unit-test platform: iOS sources: - - path: OptimoveNotificationServiceExtension/Tests/ - name: OptimoveNotificationServiceExtension-Unit + - path: OptimoveNotificationServiceExtension excludes: - - .gitkeep + - "Sources/**/*" + - "Info.plist" + - ".gitkeep" - path: Shared name: Shared-Unit + settings: + GENERATE_INFOPLIST_FILE: YES dependencies: - - target: OptimoveNotificationServiceExtension \ No newline at end of file + - target: OptimoveNotificationServiceExtension From 925c2aadbf14eb12e9592fecaddc08f7b3bf4ef1 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Mon, 20 Nov 2023 20:57:58 +0200 Subject: [PATCH 08/42] fix: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8101592..b1ffa1a0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/optimove-tech/Optimove-SDK-iOS?style=flat-square)](https://github.com/optimove-tech/Optimove-SDK-iOS/releases/latest) [![CI](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml/badge.svg)](https://github.com/optimove-tech/Optimove-SDK-iOS/actions/workflows/main.yml?query=branch%3Amaster) -![SwiftPM comppatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) +![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-success?style=flat-square) ![Cocoapods platforms](https://img.shields.io/cocoapods/p/OptimoveSDK?color=brightgreen&label=CocoaPods&style=flat-square) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square)](https://github.com/Carthage/Carthage) ![GitHub](https://img.shields.io/github/license/optimove-tech/Optimove-SDK-iOS?style=flat-square) From 9e83cd51940b554a7c4cb8659f9fc50876f6e85e Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 21 Nov 2023 00:43:52 +0200 Subject: [PATCH 09/42] feat(API): add track Open Notification metric API (#78) --- .github/workflows/main.yml | 8 ++-- CHANGELOG.md | 1 + OptimobileShared/OptimobileEvent.swift | 20 +++++++++ OptimobileShared/OptimobileHelper.swift | 4 -- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ---- .../Sources/OptimoveNotificationService.swift | 2 +- .../Optimobile/InApp/InAppManager.swift | 2 +- .../Optimobile/Optimobile+Analytics.swift | 6 +-- .../Classes/Optimobile/Optimobile+Push.swift | 25 +++++------ .../Classes/Optimobile/Optimobile.swift | 18 -------- OptimoveSDK/Sources/Classes/Optimove.swift | 6 +++ configurations/test.xcconfig | 5 +++ scripts/bootstrap.sh | 42 +++++++++++++++++++ scripts/build-for-testing.sh | 31 ++++++++++++++ scripts/test-without-building.sh | 21 ++++++++++ 15 files changed, 142 insertions(+), 57 deletions(-) create mode 100644 OptimobileShared/OptimobileEvent.swift delete mode 100644 Optimove.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 configurations/test.xcconfig create mode 100644 scripts/bootstrap.sh create mode 100755 scripts/build-for-testing.sh create mode 100755 scripts/test-without-building.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b37e6220..7826be1d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,9 +5,7 @@ jobs: runs-on: macOS-latest steps: - uses: actions/checkout@v1 - - run: brew install xcbeautify - name: Install dependencies - - run: set -o pipefail && xcodebuild build-for-testing -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 14" | xcbeautify - name: Build - - run: set -o pipefail && xcodebuild test-without-building -project Optimove.xcodeproj -scheme UnitTests -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 14" | xcbeautify + - run: ./scripts/build-for-testing.sh + name: Build for testing + - run: ./scripts/test-without-building.sh name: Test diff --git a/CHANGELOG.md b/CHANGELOG.md index e62cc595..745cfeae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 5.5.0 +- Add a new public API `Optimove.trackOpenMetric(userInfo: [AnyHashable: Any])` - to track the open metric of a push notification, when UserNotificationCenter delegate is not available. - Increased the minimum supported iOS version to 12.0 for Carthage builds. ## 5.4.0 diff --git a/OptimobileShared/OptimobileEvent.swift b/OptimobileShared/OptimobileEvent.swift new file mode 100644 index 00000000..0186135d --- /dev/null +++ b/OptimobileShared/OptimobileEvent.swift @@ -0,0 +1,20 @@ +// Copyright © 2023 Optimove. All rights reserved. + +enum OptimobileEvent : String { + case DEEP_LINK_MATCHED = "k.deepLink.matched" + case DEVICE_UNSUBSCRIBED = "k.push.deviceUnsubscribed" + case ENGAGE_BEACON_ENTERED_PROXIMITY = "k.engage.beaconEnteredProximity" + case ENGAGE_LOCATION_UPDATED = "k.engage.locationUpdated" + case IN_APP_CONSENT_CHANGED = "k.inApp.statusUpdated" + case MESSAGE_DELETED_FROM_INBOX = "k.message.inbox.deleted" + case MESSAGE_DELIVERED = "k.message.delivered" + case MESSAGE_DISMISSED = "k.message.dismissed" + case MESSAGE_OPENED = "k.message.opened" + case MESSAGE_READ = "k.message.read" + case PUSH_DEVICE_REGISTER = "k.push.deviceRegistered" + case STATS_ASSOCIATE_USER = "k.stats.userAssociated" + case STATS_BACKGROUND = "k.bg" + case STATS_CALL_HOME = "k.stats.installTracked" + case STATS_FOREGROUND = "k.fg" + case STATS_USER_ASSOCIATION_CLEARED = "k.stats.userAssociationCleared" +} diff --git a/OptimobileShared/OptimobileHelper.swift b/OptimobileShared/OptimobileHelper.swift index f6944ff2..48947ab0 100644 --- a/OptimobileShared/OptimobileHelper.swift +++ b/OptimobileShared/OptimobileHelper.swift @@ -4,10 +4,6 @@ import Foundation internal let KS_MESSAGE_TYPE_PUSH = 1 -internal enum KumulosSharedEvent : String { - case MESSAGE_DELIVERED = "k.message.delivered" -} - internal class OptimobileHelper { private static let installIdLock = DispatchSemaphore(value: 1) diff --git a/Optimove.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Optimove.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/Optimove.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift index c45a9f5f..7a73910a 100644 --- a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift +++ b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift @@ -225,7 +225,7 @@ public class OptimoveNotificationService { dispatchGroup.enter() - analyticsHelper.trackEvent(eventType: KumulosSharedEvent.MESSAGE_DELIVERED.rawValue, atTime: Date(), properties: props, immediateFlush: true, onSyncComplete: {err in + analyticsHelper.trackEvent(eventType: OptimobileEvent.MESSAGE_DELIVERED.rawValue, atTime: Date(), properties: props, immediateFlush: true, onSyncComplete: {err in self.syncBarrier.signal() }) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift index f3260743..9e3605b1 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift @@ -618,7 +618,7 @@ internal class InAppManager { private func trackMessageDelivery(messages: [[AnyHashable : Any]]) -> Void { for message in messages { let props: [String:Any] = ["type" : MESSAGE_TYPE_IN_APP, "id":message["id"] as! Int] - Optimobile.trackEvent(eventType: KumulosSharedEvent.MESSAGE_DELIVERED.rawValue, properties: props) + Optimobile.trackEvent(eventType: OptimobileEvent.MESSAGE_DELIVERED, properties: props) } } diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Analytics.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Analytics.swift index e842835e..9ed8805d 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Analytics.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Analytics.swift @@ -6,11 +6,7 @@ extension Optimobile { static func trackEvent(eventType: OptimobileEvent, properties: [String:Any]?, immediateFlush: Bool = false) { getInstance().analyticsHelper.trackEvent(eventType: eventType.rawValue, properties: properties, immediateFlush: immediateFlush) } - - static func trackEvent(eventType: KumulosSharedEvent, properties: [String:Any]?, immediateFlush: Bool = false) { - getInstance().analyticsHelper.trackEvent(eventType: eventType.rawValue, properties: properties, immediateFlush: immediateFlush) - } - + static func trackEvent(eventType: String, atTime: Date, properties: [String:Any]?, immediateFlush: Bool = false, onSyncComplete:SyncCompletedBlock? = nil) { getInstance().analyticsHelper.trackEvent(eventType: eventType, atTime: atTime, properties: properties, immediateFlush: immediateFlush, onSyncComplete: onSyncComplete) } diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift index f52b1129..9f535a7c 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift @@ -209,27 +209,22 @@ extension Optimobile { Parameters: - notification: The notification which triggered the action */ - static func pushTrackOpen(notification: PushNotification?) { - guard let notification = notification else { + static func pushTrackOpen(notification: PushNotification) { + if notification.id == 0 { + Logger.warn(""" + Ignoring push notification open. + Reason: Invalid notification id (== 0). + Payload: \(notification). + """) return } - let params = ["type": KS_MESSAGE_TYPE_PUSH, "id": notification.id] Optimobile.trackEvent(eventType: OptimobileEvent.MESSAGE_OPENED, properties:params) } - @available(iOS 9.0, *) - internal func pushHandleOpen(withUserInfo: [AnyHashable: Any]?) { - guard let userInfo = withUserInfo else { - return - } - + static func pushTrackOpen(userInfo: [AnyHashable: Any]) { let notification = PushNotification(userInfo: userInfo) - if notification.id == 0 { - return - } - - self.pushHandleOpen(notification: notification) + Optimobile.pushTrackOpen(notification: notification) } @available(iOS 10.0, *) @@ -485,6 +480,6 @@ class PushHelper { } let props: [String:Any] = ["type" : KS_MESSAGE_TYPE_PUSH, "id": notification.id] - Optimobile.trackEvent(eventType: KumulosSharedEvent.MESSAGE_DELIVERED, properties:props, immediateFlush: true) + Optimobile.trackEvent(eventType: OptimobileEvent.MESSAGE_DELIVERED, properties:props, immediateFlush: true) } } diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift index c8df9ca4..f1e8075a 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift @@ -3,24 +3,6 @@ import Foundation import UserNotifications -internal enum OptimobileEvent : String { - case STATS_FOREGROUND = "k.fg" - case STATS_BACKGROUND = "k.bg" - case STATS_CALL_HOME = "k.stats.installTracked" - case STATS_ASSOCIATE_USER = "k.stats.userAssociated" - case STATS_USER_ASSOCIATION_CLEARED = "k.stats.userAssociationCleared" - case PUSH_DEVICE_REGISTER = "k.push.deviceRegistered" - case ENGAGE_BEACON_ENTERED_PROXIMITY = "k.engage.beaconEnteredProximity" - case ENGAGE_LOCATION_UPDATED = "k.engage.locationUpdated" - case DEVICE_UNSUBSCRIBED = "k.push.deviceUnsubscribed" - case IN_APP_CONSENT_CHANGED = "k.inApp.statusUpdated" - case MESSAGE_OPENED = "k.message.opened" - case MESSAGE_DISMISSED = "k.message.dismissed" - case MESSAGE_DELETED_FROM_INBOX = "k.message.inbox.deleted" - case DEEP_LINK_MATCHED = "k.deepLink.matched" - case MESSAGE_READ = "k.message.read" -} - public typealias InAppDeepLinkHandlerBlock = (InAppButtonPress) -> Void public typealias PushOpenedHandlerBlock = (PushNotification) -> Void diff --git a/OptimoveSDK/Sources/Classes/Optimove.swift b/OptimoveSDK/Sources/Classes/Optimove.swift index cfde9f0a..57ab050e 100644 --- a/OptimoveSDK/Sources/Classes/Optimove.swift +++ b/OptimoveSDK/Sources/Classes/Optimove.swift @@ -367,6 +367,12 @@ extension Optimove { Optimobile.trackIBeaconProximity(beacon: beacon) } + /// Records a notification open event + /// - Parameter userInfo - The userInfo dictionary you received in the push notification payload + @objc public func trackOpenMetric(userInfo: [AnyHashable: Any]) { + Optimobile.pushTrackOpen(userInfo: userInfo) + } + /** Records a proximity event for an Eddystone beacon. */ diff --git a/configurations/test.xcconfig b/configurations/test.xcconfig new file mode 100644 index 00000000..ed464480 --- /dev/null +++ b/configurations/test.xcconfig @@ -0,0 +1,5 @@ +SCHEME="UnitTests" +PROJECT="Optimove.xcodeproj" +SDK="iphonesimulator" +DESTANATION="platform=iOS Simulator,name=iPhone 14" +CONFIGURATION="Debug" \ No newline at end of file diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100644 index 00000000..e9200ad0 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Stop the script if any command fails +set -e -o pipefail + +# Print the info +echo "----------------------------------------------------------------------------------------------------" +echo "Root: $ROOT" +echo "Project: $PROJECT" +echo "Scheme: $SCHEME" +echo "Configuration: $CONFIGURATION" +echo "SDK: $SDK" +echo "Destination: $DESTANATION" +echo "----------------------------------------------------------------------------------------------------" + +echo "Checking dependencies..." + +# Check if xcodebuild is installed +if ! command -v xcodebuild &>/dev/null; then + echo "xcodebuild is not installed. Please install Xcode from the App Store or update your PATH." + exit 1 +fi + +# Check if Homebrew is installed +if ! command -v brew &>/dev/null; then + echo "Error: Homebrew is not installed. Cannot install XcodeGen." + exit 1 +fi + +# Check if XcodeGen is installed, if not, attempt to install it +if ! command -v xcodegen &>/dev/null; then + echo "XcodeGen is not installed. Attempting to install using Homebrew..." + brew install xcodegen +fi + +# Check if xcbeautify is installed, if not, attempt to install it +if ! command -v xcbeautify &>/dev/null; then + echo "xcbeautify is not installed. Attempting to install using Homebrew..." + brew install xcbeautify +fi + +echo "Dependencies are installed." diff --git a/scripts/build-for-testing.sh b/scripts/build-for-testing.sh new file mode 100755 index 00000000..2c918c78 --- /dev/null +++ b/scripts/build-for-testing.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Set the root directory +export ROOT=$PWD + +# Set the project variables +source $ROOT/configurations/test.xcconfig + +# Bootstrap the project +source $ROOT/scripts/bootstrap.sh + +# Run XcodeGen to regenerate the project +echo "Removing existing Xcode project..." +rm -rf "$PROJECT" + +echo "Generating new Xcode project with XcodeGen..." +xcodegen + +echo "----------------------------------------------------------------------------------------------------" + +# Build the project +echo "Building the iOS project..." +xcodebuild build-for-testing \ + -scheme "$SCHEME" \ + -project "$PROJECT" \ + -destination "$DESTANATION" \ + -sdk "$SDK" \ + -configuration "$CONFIGURATION" | + xcbeautify + +echo "Process completed successfully." diff --git a/scripts/test-without-building.sh b/scripts/test-without-building.sh new file mode 100755 index 00000000..10cfd8d7 --- /dev/null +++ b/scripts/test-without-building.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Set the root directory +export ROOT=$PWD + +# Set the project variables +source $ROOT/configurations/test.xcconfig + +# Bootstrap the project +source $ROOT/scripts/bootstrap.sh + +# Run the tests +xcodebuild test-without-building \ + -scheme "$SCHEME" \ + -project "$PROJECT" \ + -destination "$DESTANATION" \ + -sdk "$SDK" \ + -configuration "$CONFIGURATION" | + xcbeautify + +echo "Process completed successfully." From dd49411b06e090b8365615bccd90d0955b49ceb1 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 21 Nov 2023 00:53:22 +0200 Subject: [PATCH 10/42] chore: update homebrew check --- scripts/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index e9200ad0..245e76af 100644 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -23,7 +23,7 @@ fi # Check if Homebrew is installed if ! command -v brew &>/dev/null; then - echo "Error: Homebrew is not installed. Cannot install XcodeGen." + echo "Error: Homebrew is not installed. Please install Homebrew from https://brew.sh/" exit 1 fi From 3e6aa6cc6f4a5491c73cc2197aacb1241d71ab3c Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 21 Nov 2023 00:59:57 +0200 Subject: [PATCH 11/42] chore: bootstrap --- scripts/bootstrap.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 245e76af..e75bb561 100644 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -3,7 +3,7 @@ # Stop the script if any command fails set -e -o pipefail -# Print the info +# Print the environment variables echo "----------------------------------------------------------------------------------------------------" echo "Root: $ROOT" echo "Project: $PROJECT" @@ -40,3 +40,5 @@ if ! command -v xcbeautify &>/dev/null; then fi echo "Dependencies are installed." + +echo "----------------------------------------------------------------------------------------------------" From efae80b6c421759d187a1938f5334b5b96b25579 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 21 Nov 2023 01:00:11 +0200 Subject: [PATCH 12/42] fix: add missing fileref --- Optimove.xcodeproj/project.pbxproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Optimove.xcodeproj/project.pbxproj b/Optimove.xcodeproj/project.pbxproj index dad3264a..b22b67d8 100644 --- a/Optimove.xcodeproj/project.pbxproj +++ b/Optimove.xcodeproj/project.pbxproj @@ -165,6 +165,7 @@ 929E35FD131B942202950B5B /* OptimoveNotificationExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F60CE8D6E405DAC4EBCEE3C /* OptimoveNotificationExtensionTests.swift */; }; 957510FD9374B0360E0B2495 /* NewTenantInfoHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B7CAD06AF20B0ACA56C962 /* NewTenantInfoHandlerTests.swift */; }; 95D574CDBD1AD0C0416C0CA2 /* ParametersNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CFA35DE83F5306D2EB306C1 /* ParametersNormalizer.swift */; }; + 975697C5309B40D22C37B171 /* OptimobileEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6D30D3726F5ED92D84512FB /* OptimobileEvent.swift */; }; 98C5A68EE8133BD14877F57B /* Dictionary+CompactMapKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65CA140085BC23AFEE47F451 /* Dictionary+CompactMapKeys.swift */; }; 9CB2C5384B4414B52C02DBBD /* OptistreamQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E365016FD32E91448DAD12 /* OptistreamQueue.swift */; }; 9CF7237135A4CC033D355E3F /* TenantConfigFixture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197CDA59D9D767513A115BDF /* TenantConfigFixture.swift */; }; @@ -250,6 +251,7 @@ E147D2E305837E0D739D1C05 /* KVOExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6E56A6CE9F936B2F897953F /* KVOExpectation.swift */; }; E1B7BB8C96DEC557EDFA7F6D /* EventCDv1ToEventCDv2MappingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6766A447E9CDA51F2CE3D91B /* EventCDv1ToEventCDv2MappingModel.swift */; }; E1E7F62209130B79A66B39EC /* MigrationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAFA8674D956078D45613FD /* MigrationObserver.swift */; }; + E25DA148253CD764023C91BD /* OptimobileEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6218043D6E4B30B504B25EAC /* OptimobileEvent.swift */; }; E362BF6DD8888742811D98A0 /* StubEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432D5D39398212165A5C8188 /* StubEvent.swift */; }; E454A59BDF3B9A9F68DB6139 /* MainFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A5795C174DB5BE5833F0373 /* MainFactory.swift */; }; E55BD25E76886EA7EFA887F2 /* EventConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C95FC1B779C18A7446E2845C /* EventConfig.swift */; }; @@ -442,6 +444,7 @@ 5FC57145A54E5033A5CECAF0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 5FE216E57E65CEC3F6D9F4CE /* String+isBlank.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+isBlank.swift"; sourceTree = ""; }; 615F8FAE93C5D0A6AC301070 /* .gitkeep */ = {isa = PBXFileReference; path = .gitkeep; sourceTree = ""; }; + 6218043D6E4B30B504B25EAC /* OptimobileEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileEvent.swift; sourceTree = ""; }; 63C7EC2263685823B37EC99A /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; 6424915844F66E0315561874 /* RealTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealTime.swift; sourceTree = ""; }; 64AAD2B0BFFF64DCB3907ECE /* OptimoveCore-Unit.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = "OptimoveCore-Unit.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -572,6 +575,7 @@ E36EE80C309330F735D037E2 /* SdkPlatform.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SdkPlatform.swift; sourceTree = ""; }; E5F014AB9AE645C920DD038B /* NetworkRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = ""; }; E6C2AA83233AE32D981F3555 /* GlobalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConfig.swift; sourceTree = ""; }; + E6D30D3726F5ED92D84512FB /* OptimobileEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimobileEvent.swift; sourceTree = ""; }; E6E56A6CE9F936B2F897953F /* KVOExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KVOExpectation.swift; sourceTree = ""; }; E81A4955301970EC4DFBDA13 /* KeyValueStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueStorageTests.swift; sourceTree = ""; }; EA2B4035AC1EEB59B3534409 /* InAppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppManager.swift; sourceTree = ""; }; @@ -1606,6 +1610,7 @@ 7E4B3747D4FE3D271EBADC2C /* KeyValPersistenceHelper.swift */, 99EF83EFAF52070E59C5A389 /* KSHttp.swift */, 07BBE644C3487EC57B169E6B /* MediaHelper.swift */, + E6D30D3726F5ED92D84512FB /* OptimobileEvent.swift */, ED41094AA6F15AAEC368096A /* OptimobileHelper.swift */, 66905FCA4315A6615953B49B /* OptimobileUserDefaultsKey.swift */, 499FB65BC432D40BBB409525 /* PendingNotification.swift */, @@ -1622,6 +1627,7 @@ F251A2E671B4575611FC81D5 /* KeyValPersistenceHelper.swift */, 427D452311AC9642F4EAD787 /* KSHttp.swift */, A26871854B50CF09EED86457 /* MediaHelper.swift */, + 6218043D6E4B30B504B25EAC /* OptimobileEvent.swift */, C1F3F81B42DD7AA8AB1BEE7A /* OptimobileHelper.swift */, C7AFA2A8587C5DCA93A30108 /* OptimobileUserDefaultsKey.swift */, D7F841AF4345B15514C71B49 /* PendingNotification.swift */, @@ -1977,6 +1983,7 @@ 503930654F8FCECBDE14DA5B /* Optimobile+Stats.swift in Sources */, 7AEB43BFC0E814FEBEE5BC1F /* Optimobile.swift in Sources */, 2E41CAC99770B430CCA80976 /* OptimobileBadgeObserver.swift in Sources */, + E25DA148253CD764023C91BD /* OptimobileEvent.swift in Sources */, 72D7D833022337E4C0CF9A11 /* OptimobileHelper.swift in Sources */, 40F8D5713430223076ED4DA8 /* OptimobileUserDefaultsKey.swift in Sources */, 499D5BF06BBCC8EBB94263E4 /* Optimove.swift in Sources */, @@ -2059,6 +2066,7 @@ AA64749A1A517EC2636A22B4 /* KSHttp.swift in Sources */, FBEDA772B460CEDF5A9CD453 /* KeyValPersistenceHelper.swift in Sources */, B90744D2826B1CC61479CB09 /* MediaHelper.swift in Sources */, + 975697C5309B40D22C37B171 /* OptimobileEvent.swift in Sources */, C6D90CD8E2120D32C952FFF5 /* OptimobileHelper.swift in Sources */, 718D7492799EC4068EF80F67 /* OptimobileUserDefaultsKey.swift in Sources */, 72AE4BC46B4A6A97E92622C3 /* OptimoveNotificationService.swift in Sources */, From 60b4bdb37cdc754f6951085a76cf0f396cb0384a Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Fri, 24 Nov 2023 18:11:08 +0200 Subject: [PATCH 13/42] fix: do not generate user_agent from webkit --- .../OnStartHelpers/UserAgentGenerator.swift | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift b/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift index 3254af1f..8e2dc04c 100644 --- a/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift +++ b/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift @@ -1,43 +1,36 @@ // Copyright © 2019 Optimove. All rights reserved. -import Foundation import OptimoveCore -import WebKit +import UIKit final class UserAgentGenerator { - private var storage: OptimoveStorage private let synchronizer: Pipeline private let coreEventFactory: CoreEventFactory - private var webView: WKWebView? init(storage: OptimoveStorage, synchronizer: Pipeline, - coreEventFactory: CoreEventFactory) { + coreEventFactory: CoreEventFactory) + { self.storage = storage self.synchronizer = synchronizer self.coreEventFactory = coreEventFactory } func generate() { - guard Thread.isMainThread else { - DispatchQueue.main.async { - self.generate() - } - return + func generateUserAgent() -> String { + let deviceName = UIDevice.current.model + let osName = UIDevice.current.systemName + let osVersion = UIDevice.current.systemVersion + let locale = Locale.current.identifier + let timeZone = TimeZone.current.identifier + + return "\(deviceName); \(osName) \(osVersion); \(locale); \(timeZone)" } - webView = WKWebView(frame: .zero) - webView?.evaluateJavaScript("navigator.userAgent") { (result, error) in - if let error = error { - Logger.error(error.localizedDescription) - } - self.storage.userAgent = (result as? String) ?? "user_agent_undefined" - tryCatch { - let event = try self.coreEventFactory.createEvent(.setUserAgent) - self.synchronizer.deliver(.report(events: [event])) - } - self.webView = nil + self.storage.userAgent = generateUserAgent() + tryCatch { + let event = try self.coreEventFactory.createEvent(.setUserAgent) + self.synchronizer.deliver(.report(events: [event])) } } - } From 47f0cbea655735e99e77cf95d4c87daffe3fb17a Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Fri, 8 Dec 2023 17:09:22 +0200 Subject: [PATCH 14/42] build: version 5.7.0 --- OptimoveCore.podspec | 2 +- OptimoveCore/Sources/Classes/Constants/SDKVersion.swift | 2 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index e4a98448..b18c6443 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index 0728ad67..46339007 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.6.0" +public let SDKVersion = "5.7.0" diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 6c35f25d..963a1b4e 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index e703ffdf..e5fb70cf 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' From 78c4929970d3bad0dca3ee851a575c6c42a2e214 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Fri, 8 Dec 2023 17:26:12 +0200 Subject: [PATCH 15/42] refactor: badge arithmetic --- .../Sources/Classes/OptimobileHelper.swift | 31 +++++-------------- .../Sources/Classes/PushNotification.swift | 6 ++-- .../Tests/Sources/PushNotificationTests.swift | 2 +- .../Sources/OptimoveNotificationService.swift | 20 ++---------- .../Classes/Optimobile/Optimobile+Push.swift | 9 +++--- 5 files changed, 17 insertions(+), 51 deletions(-) diff --git a/OptimoveCore/Sources/Classes/OptimobileHelper.swift b/OptimoveCore/Sources/Classes/OptimobileHelper.swift index f94a5f6c..2e90014d 100644 --- a/OptimoveCore/Sources/Classes/OptimobileHelper.swift +++ b/OptimoveCore/Sources/Classes/OptimobileHelper.swift @@ -42,31 +42,14 @@ public struct OptimobileHelper { return installId() } - // FIXME: Use PushNotifcation - public func getBadgeFromUserInfo(userInfo: [AnyHashable: Any]) -> NSNumber? { - let custom = userInfo["custom"] as? [AnyHashable: Any] - let aps = userInfo["aps"] as? [AnyHashable: Any] - - if custom == nil || aps == nil { - return nil - } - - let incrementBy: NSNumber? = custom!["badge_inc"] as? NSNumber - let badge: NSNumber? = aps!["badge"] as? NSNumber - - if badge == nil { - return nil - } - - var newBadge: NSNumber? = badge - if let incrementBy = incrementBy, let currentVal: NSNumber = storage[.badgeCount] { - newBadge = NSNumber(value: currentVal.intValue + incrementBy.intValue) - - if newBadge!.intValue < 0 { - newBadge = 0 - } + public func getBadge(notification: PushNotification) -> Int? { + if let incrementBy = notification.badgeIncrement, + let current: Int = storage[.badgeCount] + { + let badge = current + incrementBy + return badge < 0 ? 0 : badge } - return newBadge + return notification.aps.badge } } diff --git a/OptimoveCore/Sources/Classes/PushNotification.swift b/OptimoveCore/Sources/Classes/PushNotification.swift index 39d5a366..03507d62 100644 --- a/OptimoveCore/Sources/Classes/PushNotification.swift +++ b/OptimoveCore/Sources/Classes/PushNotification.swift @@ -76,7 +76,7 @@ public struct PushNotification: Decodable { public let aps: Aps public let attachment: PushNotification.Attachment? /// Optimove badge - public let badge: Int? + public let badgeIncrement: Int? public let buttons: [PushNotification.Button]? public let deeplink: PushNotification.Data? public let message: PushNotification.Data @@ -86,7 +86,7 @@ public struct PushNotification: Decodable { case a case aps case attachments - case badge = "badge_inc" + case badgeIncrement = "badge_inc" case buttons = "k.buttons" case custom case deeplink = "k.deepLink" @@ -106,7 +106,7 @@ public struct PushNotification: Decodable { self.attachment = try container.decodeIfPresent(Attachment.self, forKey: .attachments) let custom = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .custom) - self.badge = try custom.decodeIfPresent(Int.self, forKey: .badge) + self.badgeIncrement = try custom.decodeIfPresent(Int.self, forKey: .badgeIncrement) self.url = try custom.decodeIfPresent(URL.self, forKey: .u) let a = try custom.nestedContainer(keyedBy: CodingKeys.self, forKey: .a) diff --git a/OptimoveCore/Tests/Sources/PushNotificationTests.swift b/OptimoveCore/Tests/Sources/PushNotificationTests.swift index 8f0cac7f..fbea0fa0 100644 --- a/OptimoveCore/Tests/Sources/PushNotificationTests.swift +++ b/OptimoveCore/Tests/Sources/PushNotificationTests.swift @@ -18,7 +18,7 @@ final class PushNotificationTests: XCTestCase, FileAccessible { fileName = "notification-badge.json" let decoder = JSONDecoder() let notification = try decoder.decode(PushNotification.self, from: data) - XCTAssertEqual(notification.badge, 42) + XCTAssertEqual(notification.badgeIncrement, 42) } func test_decode_buttons() throws { diff --git a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift index 5deb96c9..6c775a02 100644 --- a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift +++ b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift @@ -48,9 +48,9 @@ public enum OptimoveNotificationService { bestAttemptContent.attachments = [attachment] } let optimobileHelper = OptimobileHelper(storage: storage) - if let badge = maybeSetBadge(userInfo: userInfo, optimobileHelper: optimobileHelper) { + if let badge = optimobileHelper.getBadge(notification: notification) { storage.set(value: badge, key: .badgeCount) - bestAttemptContent.badge = badge + bestAttemptContent.badge = NSNumber(integerLiteral: badge) } let pendingNoticationHelper = PendingNotificationHelper(storage: storage) pendingNoticationHelper.add( @@ -130,20 +130,4 @@ public enum OptimoveNotificationService { url: tempURL ) } - - static func maybeSetBadge( - userInfo: [AnyHashable: Any], - optimobileHelper: OptimobileHelper - ) -> NSNumber? { - let aps = userInfo["aps"] as! [AnyHashable: Any] - if let contentAvailable = aps["content-available"] as? Int, contentAvailable == 1 { - return nil - } - - let newBadge: NSNumber? = optimobileHelper.getBadgeFromUserInfo(userInfo: userInfo) - if newBadge == nil { - return nil - } - return newBadge - } } diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift index d2e88bf3..c5eea925 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+Push.swift @@ -348,7 +348,7 @@ class PushHelper { let notification = try PushNotification(userInfo: userInfo) let hasInApp = notification.deeplink != nil - self.setBadge(userInfo: userInfo) + self.setBadge(notification: notification) self.trackPushDelivery(notification: notification) if existingDidReceive == nil, !hasInApp { @@ -419,10 +419,9 @@ class PushHelper { self.optimobileHelper = optimobileHelper } - private func setBadge(userInfo: [AnyHashable: Any]) { - let badge: NSNumber? = optimobileHelper.getBadgeFromUserInfo(userInfo: userInfo) - if let newBadge = badge { - UIApplication.shared.applicationIconBadgeNumber = newBadge.intValue + private func setBadge(notification: PushNotification) { + if let badge = optimobileHelper.getBadge(notification: notification) { + UIApplication.shared.applicationIconBadgeNumber = badge } } From 4cdcefa52b4fc4b639e4a8160011ac14e1bdfdcc Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Sun, 31 Dec 2023 16:56:32 +0200 Subject: [PATCH 16/42] chore: delete user agent event --- .../Classes/Storage/StorageFacade.swift | 19 ---------- .../Classes/Constants/OptimoveKeys.swift | 1 - OptimoveSDK/Sources/Classes/DI/Assembly.swift | 1 + .../Events/CoreEvents/SetUserAgent.swift | 22 ------------ .../Classes/Factories/CoreEventFactory.swift | 9 ----- .../Classes/Migration/MigrationWork.swift | 19 +++++++--- .../Sources/Classes/Migration/Version.swift | 1 + .../OnStartEventGenerator.swift | 5 --- .../OnStartHelpers/UserAgentGenerator.swift | 36 ------------------- 9 files changed, 17 insertions(+), 96 deletions(-) delete mode 100644 OptimoveSDK/Sources/Classes/Events/CoreEvents/SetUserAgent.swift delete mode 100644 OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift diff --git a/OptimoveCore/Sources/Classes/Storage/StorageFacade.swift b/OptimoveCore/Sources/Classes/Storage/StorageFacade.swift index 863ae2d0..ef5752ad 100644 --- a/OptimoveCore/Sources/Classes/Storage/StorageFacade.swift +++ b/OptimoveCore/Sources/Classes/Storage/StorageFacade.swift @@ -17,7 +17,6 @@ public enum StorageKey: String, CaseIterable { case tenantToken case visitorID case version - case userAgent case deviceResolutionWidth case deviceResolutionHeight case advertisingIdentifier @@ -45,7 +44,6 @@ public protocol StorageValue { var tenantToken: String? { get set } var visitorID: String? { get set } var version: String? { get set } - var userAgent: String? { get set } var deviceResolutionWidth: Float? { get set } var deviceResolutionHeight: Float? { get set } var advertisingIdentifier: String? { get set } @@ -64,7 +62,6 @@ public protocol StorageValue { func getTenantToken() throws -> String func getVisitorID() throws -> String func getVersion() throws -> String - func getUserAgent() throws -> String func getDeviceResolutionWidth() throws -> Float func getDeviceResolutionHeight() throws -> Float /// Called when a migration is finished for the version. @@ -302,15 +299,6 @@ public extension KeyValueStorage where Self: StorageValue { } } - var userAgent: String? { - get { - return self[.userAgent] - } - set { - self[.userAgent] = newValue - } - } - var deviceResolutionWidth: Float? { get { return self[.deviceResolutionWidth] @@ -472,13 +460,6 @@ public extension KeyValueStorage where Self: StorageValue { return value } - func getUserAgent() throws -> String { - guard let value = userAgent else { - throw StorageError.noValue(.userAgent) - } - return value - } - func getDeviceResolutionWidth() throws -> Float { guard let value = deviceResolutionWidth else { throw StorageError.noValue(.deviceResolutionWidth) diff --git a/OptimoveSDK/Sources/Classes/Constants/OptimoveKeys.swift b/OptimoveSDK/Sources/Classes/Constants/OptimoveKeys.swift index 7e53359f..573f734e 100644 --- a/OptimoveSDK/Sources/Classes/Constants/OptimoveKeys.swift +++ b/OptimoveSDK/Sources/Classes/Constants/OptimoveKeys.swift @@ -23,7 +23,6 @@ enum OptimoveKeys { case userId = "user_id" case realtimeUserId = "userId" case realtimeupdatedVisitorId = "updatedVisitorId" - case setUserAgent = "user_agent_header_event" case email } } diff --git a/OptimoveSDK/Sources/Classes/DI/Assembly.swift b/OptimoveSDK/Sources/Classes/DI/Assembly.swift index 5b85aa56..7f2b4e01 100644 --- a/OptimoveSDK/Sources/Classes/DI/Assembly.swift +++ b/OptimoveSDK/Sources/Classes/DI/Assembly.swift @@ -33,6 +33,7 @@ final class Assembly { private func migrate() { let migrations: [MigrationWork] = [ MigrationWork_3_3_0(), + MigrationWork_5_7_0() ] migrations .filter { $0.isAllowToMiragte(SDKVersion) } diff --git a/OptimoveSDK/Sources/Classes/Events/CoreEvents/SetUserAgent.swift b/OptimoveSDK/Sources/Classes/Events/CoreEvents/SetUserAgent.swift deleted file mode 100644 index 0e52571f..00000000 --- a/OptimoveSDK/Sources/Classes/Events/CoreEvents/SetUserAgent.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright © 2019 Optimove. All rights reserved. - -final class SetUserAgent: Event { - enum Constants { - static let name = OptimoveKeys.Configuration.setUserAgent.rawValue - static let userAgentSliceLenght: Int = 255 - static let userAgentHeaderBase = "user_agent_header" - } - - init(userAgent: String) { - super.init( - name: Constants.name, - context: userAgent - .split(by: Constants.userAgentSliceLenght) - .enumerated() - .reduce(into: [String: Any]()) { result, userAgent in - let key = Constants.userAgentHeaderBase + String(userAgent.offset + 1) - result[key] = userAgent.element - } - ) - } -} diff --git a/OptimoveSDK/Sources/Classes/Factories/CoreEventFactory.swift b/OptimoveSDK/Sources/Classes/Factories/CoreEventFactory.swift index f16b47dc..d8739915 100644 --- a/OptimoveSDK/Sources/Classes/Factories/CoreEventFactory.swift +++ b/OptimoveSDK/Sources/Classes/Factories/CoreEventFactory.swift @@ -6,7 +6,6 @@ import OptimoveCore enum CoreEventType { case appOpen case metaData - case setUserAgent case setUserEmail(email: String) case setUser(user: User) case pageVisit(title: String, category: String?) @@ -45,8 +44,6 @@ extension CoreEventFactoryImpl: CoreEventFactory { return try createMetaDataEvent() case let .pageVisit(title: t, category: c): return createPageVisitEvent(title: t, category: c) - case .setUserAgent: - return try createSetUserAgentEvent() case let .setUserEmail(email): return try createSetUserEmailEvent(email: email) } @@ -96,12 +93,6 @@ private extension CoreEventFactoryImpl { return try unwrap(event) } - func createSetUserAgentEvent() throws -> SetUserAgent { - return try SetUserAgent( - userAgent: storage.getUserAgent() - ) - } - func createPageVisitEvent(title: String, category: String?) -> PageVisitEvent { return PageVisitEvent( title: title, diff --git a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift index 4deddd58..6a4008f0 100644 --- a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift +++ b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift @@ -57,9 +57,10 @@ class MigrationWorkerWithStorage: MigrationWorker { final class MigrationWork_2_10_0: MigrationWorkerWithStorage { private let synchronizer: Pipeline - init(synchronizer: Pipeline, - storage: OptimoveStorage) - { + init( + synchronizer: Pipeline, + storage: OptimoveStorage + ) { self.synchronizer = synchronizer super.init(storage: storage, newVersion: .v_2_10_0) } @@ -139,7 +140,6 @@ extension MigrationWork_3_3_0 { .tenantToken, .visitorID, .version, - .userAgent, .deviceResolutionWidth, .deviceResolutionHeight, .advertisingIdentifier, @@ -229,3 +229,14 @@ extension MigrationWork_3_3_0 { } } } + +final class MigrationWork_5_7_0: MigrationWorker { + init() { + super.init(newVersion: .v_5_7_0) + } + + override func runMigration() { + try? UserDefaults.optimove().removeObject(forKey: "userAgent") + super.runMigration() + } +} diff --git a/OptimoveSDK/Sources/Classes/Migration/Version.swift b/OptimoveSDK/Sources/Classes/Migration/Version.swift index e55b4653..c1c172ca 100644 --- a/OptimoveSDK/Sources/Classes/Migration/Version.swift +++ b/OptimoveSDK/Sources/Classes/Migration/Version.swift @@ -4,4 +4,5 @@ enum Version: String { case v_2_10_0 = "2.10.0" case v_3_0_0 = "3.0.0" case v_3_3_0 = "3.3.0" + case v_5_7_0 = "5.7.0" } diff --git a/OptimoveSDK/Sources/Classes/OnStartHelpers/OnStartEventGenerator.swift b/OptimoveSDK/Sources/Classes/OnStartHelpers/OnStartEventGenerator.swift index 12d878f8..edd4fc6e 100644 --- a/OptimoveSDK/Sources/Classes/OnStartHelpers/OnStartEventGenerator.swift +++ b/OptimoveSDK/Sources/Classes/OnStartHelpers/OnStartEventGenerator.swift @@ -30,11 +30,6 @@ final class OnStartEventGenerator { } private func asyncGenerate() { - UserAgentGenerator( - storage: storage, - synchronizer: synchronizer, - coreEventFactory: coreEventFactory - ).generate() AppOpenOnStartGenerator( synchronizer: synchronizer, coreEventFactory: coreEventFactory diff --git a/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift b/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift deleted file mode 100644 index 8e2dc04c..00000000 --- a/OptimoveSDK/Sources/Classes/OnStartHelpers/UserAgentGenerator.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright © 2019 Optimove. All rights reserved. - -import OptimoveCore -import UIKit - -final class UserAgentGenerator { - private var storage: OptimoveStorage - private let synchronizer: Pipeline - private let coreEventFactory: CoreEventFactory - - init(storage: OptimoveStorage, - synchronizer: Pipeline, - coreEventFactory: CoreEventFactory) - { - self.storage = storage - self.synchronizer = synchronizer - self.coreEventFactory = coreEventFactory - } - - func generate() { - func generateUserAgent() -> String { - let deviceName = UIDevice.current.model - let osName = UIDevice.current.systemName - let osVersion = UIDevice.current.systemVersion - let locale = Locale.current.identifier - let timeZone = TimeZone.current.identifier - - return "\(deviceName); \(osName) \(osVersion); \(locale); \(timeZone)" - } - self.storage.userAgent = generateUserAgent() - tryCatch { - let event = try self.coreEventFactory.createEvent(.setUserAgent) - self.synchronizer.deliver(.report(events: [event])) - } - } -} From 21cdd594a96071cd7e3e585327eb3876c52fb6c9 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 2 Jan 2024 14:16:30 +0200 Subject: [PATCH 17/42] tests: fix tests --- .../Events/CoreEventFactoryTests.swift | 9 --- .../CoreEvents/SetUserAgentEventTests.swift | 56 ------------------- .../OnStartEventGeneratorTests.swift | 4 -- Shared/Sources/OptimoveTestCase.swift | 1 - 4 files changed, 70 deletions(-) delete mode 100644 OptimoveSDK/Tests/Sources/Events/CoreEvents/SetUserAgentEventTests.swift diff --git a/OptimoveSDK/Tests/Sources/Events/CoreEventFactoryTests.swift b/OptimoveSDK/Tests/Sources/Events/CoreEventFactoryTests.swift index c90a95bc..575b0203 100644 --- a/OptimoveSDK/Tests/Sources/Events/CoreEventFactoryTests.swift +++ b/OptimoveSDK/Tests/Sources/Events/CoreEventFactoryTests.swift @@ -49,15 +49,6 @@ class CoreEventFactoryTests: OptimoveTestCase { wait(for: [expectation], timeout: defaultTimeout) } - func test_create_setUserAgent() throws { - prefillStorageAsVisitor() - let expectation = XCTestExpectation(description: "Event creation failed for \(#function)") - let event = try factory.createEvent(.setUserAgent) - XCTAssert(event.name == SetUserAgent.Constants.name) - expectation.fulfill() - wait(for: [expectation], timeout: defaultTimeout) - } - func test_create_pageVisit() throws { let expectation = XCTestExpectation(description: "Event creation failed for \(#function)") let event = try factory.createEvent(.pageVisit(title: "", category: "")) diff --git a/OptimoveSDK/Tests/Sources/Events/CoreEvents/SetUserAgentEventTests.swift b/OptimoveSDK/Tests/Sources/Events/CoreEvents/SetUserAgentEventTests.swift deleted file mode 100644 index 1a0158dc..00000000 --- a/OptimoveSDK/Tests/Sources/Events/CoreEvents/SetUserAgentEventTests.swift +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © 2019 Optimove. All rights reserved. - -@testable import OptimoveSDK -import XCTest - -class SetUserAgentEventTests: XCTestCase { - func test_event_name() { - // given - let userAgent = "" - - // when - let event = SetUserAgent(userAgent: userAgent) - - // then - XCTAssert(event.name == SetUserAgent.Constants.name) - } - - func test_event_long_useragent() { - // given - let userAgentLenght = 600 - let userAgent = Array(repeating: "a", count: userAgentLenght).joined() - let expectedParameterCount = (Float(userAgentLenght) / Float(SetUserAgent.Constants.userAgentSliceLenght)).rounded(.up) - - // when - let event = SetUserAgent(userAgent: userAgent) - - // then - XCTAssert(event.context.count == Int(expectedParameterCount)) - } - - func test_event_short_useragent() { - // given - let userAgentLenght = 100 - let userAgent = Array(repeating: "a", count: userAgentLenght).joined() - let expectedParameterCount = (Float(userAgentLenght) / Float(SetUserAgent.Constants.userAgentSliceLenght)).rounded(.up) - - // when - let event = SetUserAgent(userAgent: userAgent) - - // then - XCTAssert(event.context.count == Int(expectedParameterCount)) - } - - func test_event_useragent_key_started_with_1() { - // given - let userAgentLenght = 100 - let userAgent = Array(repeating: "a", count: userAgentLenght).joined() - - // when - let event = SetUserAgent(userAgent: userAgent) - - // then - let first = event.context.first - XCTAssert(first?.key == SetUserAgent.Constants.userAgentHeaderBase + String(1)) - } -} diff --git a/OptimoveSDK/Tests/Sources/Generators/OnStartEventGeneratorTests.swift b/OptimoveSDK/Tests/Sources/Generators/OnStartEventGeneratorTests.swift index a2dc6683..07c93730 100644 --- a/OptimoveSDK/Tests/Sources/Generators/OnStartEventGeneratorTests.swift +++ b/OptimoveSDK/Tests/Sources/Generators/OnStartEventGeneratorTests.swift @@ -32,7 +32,6 @@ final class OnStartEventGeneratorTests: OptimoveTestCase { // then let metaDataEventExpectation = expectation(description: "MetaDataEvent was not generated.") - let userAgentEventExpectation = expectation(description: "SetUserAgent was not generated.") let appOpenEventExpectation = expectation(description: "AppOpenEvent was not generated.") synchronizer.assertFunction = { operation in switch operation { @@ -41,8 +40,6 @@ final class OnStartEventGeneratorTests: OptimoveTestCase { switch event.name { case MetaDataEvent.Constants.name: metaDataEventExpectation.fulfill() - case SetUserAgent.Constants.name: - userAgentEventExpectation.fulfill() case AppOpenEvent.Constants.name: appOpenEventExpectation.fulfill() default: @@ -60,7 +57,6 @@ final class OnStartEventGeneratorTests: OptimoveTestCase { wait( for: [ metaDataEventExpectation, - userAgentEventExpectation, appOpenEventExpectation, ], // Additional second to complete the async operation and prevent a flickering. diff --git a/Shared/Sources/OptimoveTestCase.swift b/Shared/Sources/OptimoveTestCase.swift index 2fdb61aa..c9596e4a 100644 --- a/Shared/Sources/OptimoveTestCase.swift +++ b/Shared/Sources/OptimoveTestCase.swift @@ -27,7 +27,6 @@ open class OptimoveTestCase: XCTestCase { public func prefillStorageWithTheFirstLaunch() { prefillStorageWithConfiguration() storage.installationID = UUID().uuidString - storage.userAgent = "user-agent" storage.firstRunTimestamp = Date().timeIntervalSince1970.seconds } From f6fd4c09f74274a40462cf79650c71a23bd2908f Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 2 Jan 2024 14:16:43 +0200 Subject: [PATCH 18/42] chore: auto updated scheme --- .../xcshareddata/xcschemes/UnitTests.xcscheme | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Optimove.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme b/Optimove.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme index 10e34e24..aa1295fa 100644 --- a/Optimove.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme +++ b/Optimove.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme @@ -11,15 +11,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - @@ -67,7 +58,7 @@ From 8eaf717f465d88855afdbf22ed81d7fa597400db Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 09:45:23 +0200 Subject: [PATCH 19/42] chore: migration version 6.0.0 --- OptimoveSDK/Sources/Classes/DI/Assembly.swift | 2 +- OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift | 4 ++-- OptimoveSDK/Sources/Classes/Migration/Version.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/DI/Assembly.swift b/OptimoveSDK/Sources/Classes/DI/Assembly.swift index 32349912..7a87c0a6 100644 --- a/OptimoveSDK/Sources/Classes/DI/Assembly.swift +++ b/OptimoveSDK/Sources/Classes/DI/Assembly.swift @@ -33,7 +33,7 @@ final class Assembly { private func migrate() { let migrations: [MigrationWork] = [ MigrationWork_3_3_0(), - MigrationWork_5_7_0(), + MigrationWork_6_0_0(), ] migrations .filter { $0.isAllowToMiragte(SDKVersion) } diff --git a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift index f58a501a..4decf8de 100644 --- a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift +++ b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift @@ -232,9 +232,9 @@ extension MigrationWork_3_3_0 { } /// Migration from Kumulos UserDefaults to Optimove UserDefaults. -final class MigrationWork_5_7_0: MigrationWorker { +final class MigrationWork_6_0_0: MigrationWorker { init() { - super.init(newVersion: .v_5_7_0) + super.init(newVersion: .v_6_0_0) } override func isAllowToMiragte(_: String) -> Bool { diff --git a/OptimoveSDK/Sources/Classes/Migration/Version.swift b/OptimoveSDK/Sources/Classes/Migration/Version.swift index c1c172ca..d35ae1f4 100644 --- a/OptimoveSDK/Sources/Classes/Migration/Version.swift +++ b/OptimoveSDK/Sources/Classes/Migration/Version.swift @@ -4,5 +4,5 @@ enum Version: String { case v_2_10_0 = "2.10.0" case v_3_0_0 = "3.0.0" case v_3_3_0 = "3.3.0" - case v_5_7_0 = "5.7.0" + case v_6_0_0 = "6.0.0" } From 6d2fe1ea2f86f0d894586d8cbcac3650d5970077 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 11:12:21 +0200 Subject: [PATCH 20/42] chore: add debug product --- OptimoveDebug/Sources/ApplicationInfo.swift | 9 +++ OptimoveDebug/Sources/StateService.swift | 68 +++++++++++++++++++++ Package.swift | 11 ++++ 3 files changed, 88 insertions(+) create mode 100644 OptimoveDebug/Sources/ApplicationInfo.swift create mode 100644 OptimoveDebug/Sources/StateService.swift diff --git a/OptimoveDebug/Sources/ApplicationInfo.swift b/OptimoveDebug/Sources/ApplicationInfo.swift new file mode 100644 index 00000000..9d789498 --- /dev/null +++ b/OptimoveDebug/Sources/ApplicationInfo.swift @@ -0,0 +1,9 @@ +// Copyright © 2024 Optimove. All rights reserved. + +import Foundation + +public enum ApplicationInfo { + public static let bundleIdentifier = Bundle.main.bundleIdentifier! + public static let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String + public static let build = Bundle.main.infoDictionary!["CFBundleVersion"] as! String +} diff --git a/OptimoveDebug/Sources/StateService.swift b/OptimoveDebug/Sources/StateService.swift new file mode 100644 index 00000000..f097ada4 --- /dev/null +++ b/OptimoveDebug/Sources/StateService.swift @@ -0,0 +1,68 @@ +// Copyright © 2024 Optimove. All rights reserved. + +import Foundation +import OptimoveCore +@testable import OptimoveSDK + +public final class StateService { + public enum State { + case app_version + case sdk_version + case installation + case tenant + case initial_visitor + case customer + case update_visitor + case email + } + + private enum Constants { + static let undefined = "" + } + + public static var shared: StateService = .init() + + private let storage: any OptimoveStorage + + private init() { + do { + storage = try StorageFacade( + standardStorage: UserDefaults.optimove(), + appGroupStorage: UserDefaults.optimoveAppGroup(), + inMemoryStorage: InMemoryStorage(), + fileStorage: FileStorageImpl( + persistentStorageURL: FileManager.optimoveURL(), + temporaryStorageURL: FileManager.temporaryURL() + ) + ) + } catch { + fatalError(error.localizedDescription) + } + } + + public func getState(_ state: State) -> String { + switch state { + case .app_version: + return "\(ApplicationInfo.version) build: \(ApplicationInfo.build)" + case .sdk_version: + return Optimove.version + case .installation: + return storage.installationID ?? Constants.undefined + case .tenant: + guard let tenantID = storage.tenantID else { return Constants.undefined } + return String(tenantID) + case .initial_visitor: + return storage.initialVisitorId ?? Constants.undefined + case .customer: + return storage.customerID ?? Constants.undefined + case .email: + return storage.userEmail ?? Constants.undefined + case .update_visitor: + return storage.visitorID ?? Constants.undefined + } + } + + public subscript(state: State) -> String { + return StateService.shared.getState(state) + } +} diff --git a/Package.swift b/Package.swift index 73b21dea..d0394087 100644 --- a/Package.swift +++ b/Package.swift @@ -21,6 +21,10 @@ let package = Package( name: "OptimoveNotificationServiceExtension", targets: ["OptimoveNotificationServiceExtension"] ), + .library( + name: "OptimoveDebug", + targets: ["OptimoveDebug"] + ), ], dependencies: [ .package(url: "https://github.com/WeTransfer/Mocker", from: "3.0.1"), @@ -54,6 +58,13 @@ let package = Package( .process("Resources"), ] ), + .target( + name: "OptimoveDebug", + dependencies: [ + "OptimoveSDK", + ], + path: "OptimoveDebug/Sources" + ), .testTarget( name: "OptimoveSDKTests", dependencies: [ From a64a40a08b9b0eb954e3adcd5b50433c60eedff8 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 13:25:25 +0200 Subject: [PATCH 21/42] feat: expose sdk state --- OptimoveDebug/Sources/ApplicationInfo.swift | 9 --- OptimoveDebug/Sources/StateService.swift | 68 ------------------- .../Extensions/Bundle+AppVersion.swift | 4 ++ OptimoveSDK/Sources/Classes/Optimove.swift | 24 ++++++- .../Sources/Classes/States/SdkState.swift | 25 +++++++ Package.swift | 11 --- 6 files changed, 52 insertions(+), 89 deletions(-) delete mode 100644 OptimoveDebug/Sources/ApplicationInfo.swift delete mode 100644 OptimoveDebug/Sources/StateService.swift create mode 100644 OptimoveSDK/Sources/Classes/States/SdkState.swift diff --git a/OptimoveDebug/Sources/ApplicationInfo.swift b/OptimoveDebug/Sources/ApplicationInfo.swift deleted file mode 100644 index 9d789498..00000000 --- a/OptimoveDebug/Sources/ApplicationInfo.swift +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright © 2024 Optimove. All rights reserved. - -import Foundation - -public enum ApplicationInfo { - public static let bundleIdentifier = Bundle.main.bundleIdentifier! - public static let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String - public static let build = Bundle.main.infoDictionary!["CFBundleVersion"] as! String -} diff --git a/OptimoveDebug/Sources/StateService.swift b/OptimoveDebug/Sources/StateService.swift deleted file mode 100644 index f097ada4..00000000 --- a/OptimoveDebug/Sources/StateService.swift +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2024 Optimove. All rights reserved. - -import Foundation -import OptimoveCore -@testable import OptimoveSDK - -public final class StateService { - public enum State { - case app_version - case sdk_version - case installation - case tenant - case initial_visitor - case customer - case update_visitor - case email - } - - private enum Constants { - static let undefined = "" - } - - public static var shared: StateService = .init() - - private let storage: any OptimoveStorage - - private init() { - do { - storage = try StorageFacade( - standardStorage: UserDefaults.optimove(), - appGroupStorage: UserDefaults.optimoveAppGroup(), - inMemoryStorage: InMemoryStorage(), - fileStorage: FileStorageImpl( - persistentStorageURL: FileManager.optimoveURL(), - temporaryStorageURL: FileManager.temporaryURL() - ) - ) - } catch { - fatalError(error.localizedDescription) - } - } - - public func getState(_ state: State) -> String { - switch state { - case .app_version: - return "\(ApplicationInfo.version) build: \(ApplicationInfo.build)" - case .sdk_version: - return Optimove.version - case .installation: - return storage.installationID ?? Constants.undefined - case .tenant: - guard let tenantID = storage.tenantID else { return Constants.undefined } - return String(tenantID) - case .initial_visitor: - return storage.initialVisitorId ?? Constants.undefined - case .customer: - return storage.customerID ?? Constants.undefined - case .email: - return storage.userEmail ?? Constants.undefined - case .update_visitor: - return storage.visitorID ?? Constants.undefined - } - } - - public subscript(state: State) -> String { - return StateService.shared.getState(state) - } -} diff --git a/OptimoveSDK/Sources/Classes/Extensions/Bundle+AppVersion.swift b/OptimoveSDK/Sources/Classes/Extensions/Bundle+AppVersion.swift index 6970cb20..8fefc29f 100644 --- a/OptimoveSDK/Sources/Classes/Extensions/Bundle+AppVersion.swift +++ b/OptimoveSDK/Sources/Classes/Extensions/Bundle+AppVersion.swift @@ -6,4 +6,8 @@ extension Bundle { var appVersion: String { return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "undefined" } + + var buildVersion: String { + return Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "undefined" + } } diff --git a/OptimoveSDK/Sources/Classes/Optimove.swift b/OptimoveSDK/Sources/Classes/Optimove.swift index 73efa480..57380eb8 100644 --- a/OptimoveSDK/Sources/Classes/Optimove.swift +++ b/OptimoveSDK/Sources/Classes/Optimove.swift @@ -18,7 +18,7 @@ typealias Logger = OptimoveCore.Logger /// The shared instance of Optimove SDK. @objc public static let shared: Optimove = .init() - private let container: Container + let container: Container private var config: OptimoveConfig! override private init() { @@ -312,6 +312,28 @@ public extension Optimove { } } } + + enum Debug { + enum Constants { + static let undefined = "" + } + + public static var state: SdkState { + return Optimove.shared.container.resolve { locator in + let storage = locator.storage() + return SdkState( + appVersion: "\(Bundle.main.appVersion) build: \(Bundle.main.buildVersion)", + sdkVersion: Optimove.version, + installation: storage.installationID ?? Constants.undefined, + tenant: storage.tenantID?.description ?? Constants.undefined, + initialVisitor: storage.initialVisitorId ?? Constants.undefined, + customer: storage.customerID ?? Constants.undefined, + email: storage.userEmail ?? Constants.undefined, + updateVisitor: storage.visitorID ?? Constants.undefined + ) + } ?? SdkState.empty + } + } } // MARK: - Optimobile APIs diff --git a/OptimoveSDK/Sources/Classes/States/SdkState.swift b/OptimoveSDK/Sources/Classes/States/SdkState.swift new file mode 100644 index 00000000..7952588e --- /dev/null +++ b/OptimoveSDK/Sources/Classes/States/SdkState.swift @@ -0,0 +1,25 @@ +// Copyright © 2024 Optimove. All rights reserved. + +import Foundation + +public struct SdkState { + public let appVersion: String + public let sdkVersion: String + public let installation: String + public let tenant: String + public let initialVisitor: String + public let customer: String + public let email: String + public let updateVisitor: String + + static let empty = SdkState( + appVersion: "", + sdkVersion: "", + installation: "", + tenant: "", + initialVisitor: "", + customer: "", + email: "", + updateVisitor: "" + ) +} diff --git a/Package.swift b/Package.swift index d0394087..73b21dea 100644 --- a/Package.swift +++ b/Package.swift @@ -21,10 +21,6 @@ let package = Package( name: "OptimoveNotificationServiceExtension", targets: ["OptimoveNotificationServiceExtension"] ), - .library( - name: "OptimoveDebug", - targets: ["OptimoveDebug"] - ), ], dependencies: [ .package(url: "https://github.com/WeTransfer/Mocker", from: "3.0.1"), @@ -58,13 +54,6 @@ let package = Package( .process("Resources"), ] ), - .target( - name: "OptimoveDebug", - dependencies: [ - "OptimoveSDK", - ], - path: "OptimoveDebug/Sources" - ), .testTarget( name: "OptimoveSDKTests", dependencies: [ From 1f677e8530109ccb365962eb2cc854e9048df8fa Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 13:26:42 +0200 Subject: [PATCH 22/42] fix: return back access level of OptimoveInApp --- OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift index e2f4f9db..a530f6e6 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift @@ -81,7 +81,7 @@ struct InAppInboxSummary { typealias InboxUpdatedHandlerBlock = () -> Void typealias InboxSummaryBlock = (InAppInboxSummary?) -> Void -enum OptimoveInApp { +public enum OptimoveInApp { private static var _inboxUpdatedHandlerBlock: InboxUpdatedHandlerBlock? static func updateConsent(forUser consentGiven: Bool) { From c8fb2997e7d0ef80ee316d0e3f437ab242338f6d Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 13:27:30 +0200 Subject: [PATCH 23/42] refactor: rename method --- .../Sources/OptimoveNotificationService.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift index 6c775a02..0140c4d7 100644 --- a/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift +++ b/OptimoveNotificationServiceExtension/Sources/OptimoveNotificationService.swift @@ -37,7 +37,7 @@ public enum OptimoveNotificationService { let data = try JSONSerialization.data(withJSONObject: userInfo) let notification = try JSONDecoder().decode(PushNotification.self, from: data) if bestAttemptContent.categoryIdentifier.isEmpty { - bestAttemptContent.categoryIdentifier = await buildCategory(notification: notification) + bestAttemptContent.categoryIdentifier = await registerCategory(notification: notification) } if let storage = try? UserDefaults.optimoveAppGroup() { let mediaHelper = MediaHelper(storage: storage) @@ -94,7 +94,7 @@ public enum OptimoveNotificationService { } } - static func buildCategory(notification: PushNotification) async -> String { + static func registerCategory(notification: PushNotification) async -> String { let categoryIdentifier = CategoryManager.getCategoryId(messageId: notification.message.id) let category = UNNotificationCategory( identifier: categoryIdentifier, From 332bb01b9c795ba8f044b1e9eec8af69afbd3381 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 6 Feb 2024 14:08:31 +0200 Subject: [PATCH 24/42] docs: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d748d2..e51ffdff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 6.0.0 + +- Minimum supported iOS version is now 13.0. + ## 5.6.0 - Support the delayed configuration for SDK. Add new public APIs: From 1f2427de5fa3a8e1c0f9736947f7c49cfdf119ba Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Wed, 7 Feb 2024 12:54:34 +0200 Subject: [PATCH 25/42] chore: move back access level of in-app --- .../Classes/Optimobile/OptimoveInApp.swift | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift index a530f6e6..b233a8d4 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift @@ -4,15 +4,15 @@ import CoreData import Foundation import OptimoveCore -class InAppInboxItem { - private(set) var id: Int64 - private(set) var title: String - private(set) var subtitle: String - private(set) var availableFrom: Date? - private(set) var availableTo: Date? - private(set) var dismissedAt: Date? - private(set) var sentAt: Date - private(set) var data: NSDictionary? +public class InAppInboxItem { + public private(set) var id: Int64 + public private(set) var title: String + public private(set) var subtitle: String + public private(set) var availableFrom: Date? + public private(set) var availableTo: Date? + public private(set) var dismissedAt: Date? + public private(set) var sentAt: Date + public private(set) var data: NSDictionary? private var readAt: Date? private var imagePath: String? @@ -43,7 +43,7 @@ class InAppInboxItem { imagePath = inboxConfig["imagePath"] as? String } - func isAvailable() -> Bool { + public func isAvailable() -> Bool { if availableFrom != nil, availableFrom!.timeIntervalSinceNow > 0 { return false } else if availableTo != nil, availableTo!.timeIntervalSinceNow < 0 { @@ -53,15 +53,15 @@ class InAppInboxItem { return true } - func isRead() -> Bool { + public func isRead() -> Bool { return readAt != nil } - func getImageUrl() -> URL? { + public func getImageUrl() -> URL? { return getImageUrl(width: InAppInboxItem.defaultImageWidth) } - func getImageUrl(width: UInt) -> URL? { + public func getImageUrl(width: UInt) -> URL? { if let imagePathNotNil = imagePath { return try? mediaHelper.getCompletePictureUrl( pictureUrlString: imagePathNotNil, @@ -73,18 +73,18 @@ class InAppInboxItem { } } -struct InAppInboxSummary { - let totalCount: Int64 - let unreadCount: Int64 +public struct InAppInboxSummary { + public let totalCount: Int64 + public let unreadCount: Int64 } -typealias InboxUpdatedHandlerBlock = () -> Void -typealias InboxSummaryBlock = (InAppInboxSummary?) -> Void +public typealias InboxUpdatedHandlerBlock = () -> Void +public typealias InboxSummaryBlock = (InAppInboxSummary?) -> Void public enum OptimoveInApp { private static var _inboxUpdatedHandlerBlock: InboxUpdatedHandlerBlock? - static func updateConsent(forUser consentGiven: Bool) { + public static func updateConsent(forUser consentGiven: Bool) { if Optimobile.inAppConsentStrategy != InAppConsentStrategy.explicitByUser { NSException(name: NSExceptionName(rawValue: "Optimobile: Invalid In-app consent strategy"), reason: "You can only manage in-app messaging consent when the feature is enabled and strategy is set to InAppConsentStrategyExplicitByUser", userInfo: nil).raise() @@ -94,14 +94,21 @@ public enum OptimoveInApp { Optimobile.sharedInstance.inAppManager.updateUserConsent(consentGiven: consentGiven) } - static func setDisplayMode(mode: InAppDisplayMode) { + public static func setDisplayMode(mode: InAppDisplayMode) { Optimobile.sharedInstance.inAppManager.presenter.setDisplayMode(mode) } - static func getDisplayMode() -> InAppDisplayMode { + public static func getDisplayMode() -> InAppDisplayMode { return Optimobile.sharedInstance.inAppManager.presenter.getDisplayMode() } + public static func getInboxItems() -> [InAppInboxItem] { + return Optimove.shared.container.resolve { locator in + let storage = locator.storage() + return getInboxItems(storage: storage) + } ?? [] + } + static func getInboxItems(storage: OptimoveStorage) -> [InAppInboxItem] { guard let context = Optimobile.sharedInstance.inAppManager.messagesContext else { return [] @@ -145,7 +152,7 @@ public enum OptimoveInApp { return results } - static func presentInboxMessage(item: InAppInboxItem) -> InAppMessagePresentationResult { + public static func presentInboxMessage(item: InAppInboxItem) -> InAppMessagePresentationResult { if getDisplayMode() == .paused { return .PAUSED } @@ -159,11 +166,11 @@ public enum OptimoveInApp { return result ? InAppMessagePresentationResult.PRESENTED : InAppMessagePresentationResult.FAILED } - static func deleteMessageFromInbox(item: InAppInboxItem) -> Bool { + public static func deleteMessageFromInbox(item: InAppInboxItem) -> Bool { return Optimobile.sharedInstance.inAppManager.deleteMessageFromInbox(withId: item.id) } - static func markAsRead(item: InAppInboxItem) -> Bool { + public static func markAsRead(item: InAppInboxItem) -> Bool { if item.isRead() { return false } @@ -173,15 +180,15 @@ public enum OptimoveInApp { return res } - static func markAllInboxItemsAsRead() -> Bool { + public static func markAllInboxItemsAsRead() -> Bool { return Optimobile.sharedInstance.inAppManager.markAllInboxItemsAsRead() } - static func setOnInboxUpdated(inboxUpdatedHandlerBlock: InboxUpdatedHandlerBlock?) { + public static func setOnInboxUpdated(inboxUpdatedHandlerBlock: InboxUpdatedHandlerBlock?) { _inboxUpdatedHandlerBlock = inboxUpdatedHandlerBlock } - static func getInboxSummaryAsync(inboxSummaryBlock: @escaping InboxSummaryBlock) { + public static func getInboxSummaryAsync(inboxSummaryBlock: @escaping InboxSummaryBlock) { Optimobile.sharedInstance.inAppManager.readInboxSummary(inboxSummaryBlock: inboxSummaryBlock) } From 6efe532d2b7b87d34d87b04f875f2898ae88a0e9 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Wed, 7 Feb 2024 12:55:08 +0200 Subject: [PATCH 26/42] chore: add in-app into optimove class --- OptimoveSDK/Sources/Classes/Optimove.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/OptimoveSDK/Sources/Classes/Optimove.swift b/OptimoveSDK/Sources/Classes/Optimove.swift index 57380eb8..daa193b6 100644 --- a/OptimoveSDK/Sources/Classes/Optimove.swift +++ b/OptimoveSDK/Sources/Classes/Optimove.swift @@ -12,6 +12,7 @@ typealias Logger = OptimoveCore.Logger /// - WARNING: /// To initialize and configure SDK using `Optimove.configure(for:)` first. @objc public final class Optimove: NSObject { + public typealias InApp = OptimoveInApp /// The current OptimoveSDK version string value. public static let version = OptimoveCore.SDKVersion From 4323989a8bb8d8069d8f54aab40f0ecbc7ca4b30 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Wed, 7 Feb 2024 17:22:38 +0200 Subject: [PATCH 27/42] fix: switch in-app manager to optimove storage --- .../Optimobile/InApp/InAppManager.swift | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift index 19d748c5..7b6d6059 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift @@ -173,7 +173,7 @@ class InAppManager { func userConsented() -> Bool { // Note if this implementation is changed there is a usage in the main Optimobile initialisation path // that should be considered. - return UserDefaults.standard.bool(forKey: OptimobileUserDefaultsKey.IN_APP_CONSENTED.rawValue) + return storage[.inAppConsented] ?? false } func updateUserConsent(consentGiven: Bool) { @@ -182,7 +182,7 @@ class InAppManager { Optimobile.trackEventImmediately(eventType: OptimobileEvent.IN_APP_CONSENT_CHANGED.rawValue, properties: props) if consentGiven { - UserDefaults.standard.set(consentGiven, forKey: OptimobileUserDefaultsKey.IN_APP_CONSENTED.rawValue) + storage.set(value: consentGiven, key: .inAppConsented) handleEnrollmentAndSyncSetup() } else { DispatchQueue.global(qos: .default).async { @@ -237,9 +237,9 @@ class InAppManager { } NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) - UserDefaults.standard.removeObject(forKey: OptimobileUserDefaultsKey.IN_APP_CONSENTED.rawValue) - UserDefaults.standard.removeObject(forKey: OptimobileUserDefaultsKey.IN_APP_LAST_SYNCED_AT.rawValue) - UserDefaults.standard.removeObject(forKey: OptimobileUserDefaultsKey.IN_APP_MOST_RECENT_UPDATED_AT.rawValue) + storage.set(value: nil, key: .inAppConsented) + storage.set(value: nil, key: .inAppLastSyncedAt) + storage.set(value: nil, key: .inAppMostRecentUpdateAt) context.performAndWait { let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Message") @@ -267,23 +267,23 @@ class InAppManager { // MARK: Message management func syncDebounced(_ onComplete: InAppSyncCompletionHandler? = nil) { - syncQueue.async { - let lastSyncedAt = UserDefaults.standard.object(forKey: OptimobileUserDefaultsKey.IN_APP_LAST_SYNCED_AT.rawValue) as? Date ?? Date(timeIntervalSince1970: 0) - - if lastSyncedAt.timeIntervalSinceNow < self.SYNC_DEBOUNCE_SECONDS { + syncQueue.async { [unowned self] in + let lastSyncedAt = storage.value(for: .inAppLastSyncedAt) as? Date ?? Date(timeIntervalSince1970: 0) + if lastSyncedAt.timeIntervalSinceNow < SYNC_DEBOUNCE_SECONDS { return } - self.sync(onComplete) + sync(onComplete) } } func sync(_ onComplete: InAppSyncCompletionHandler? = nil) { let currentUserIdentifier = optimobileHelper.currentUserIdentifier() - syncQueue.async { + syncQueue.async { [unowned self] in let syncBarrier = DispatchSemaphore(value: 0) - let mostRecentUpdate = UserDefaults.standard.object(forKey: OptimobileUserDefaultsKey.IN_APP_MOST_RECENT_UPDATED_AT.rawValue) as? NSDate + let mostRecentUpdate = storage.value(for: .inAppMostRecentUpdateAt) as? Date + var after = "" if let mostRecentUpdate = mostRecentUpdate { @@ -298,9 +298,9 @@ class InAppManager { let encodedIdentifier = KSHttpUtil.urlEncode(currentUserIdentifier) let path = "/v1/users/\(encodedIdentifier!)/messages\(after)" - self.httpClient.sendRequest(.GET, toPath: path, data: nil, onSuccess: { _, decodedBody in + httpClient.sendRequest(.GET, toPath: path, data: nil, onSuccess: { [weak self] _, decodedBody in defer { - UserDefaults.standard.set(Date(), forKey: OptimobileUserDefaultsKey.IN_APP_LAST_SYNCED_AT.rawValue) + self?.storage.set(value: Date(), key: .inAppLastSyncedAt) syncBarrier.signal() } @@ -310,7 +310,7 @@ class InAppManager { return } - self.persistInAppMessages(messages: messagesToPersist!) + self?.persistInAppMessages(messages: messagesToPersist!) onComplete?(1) DispatchQueue.main.async { @@ -318,9 +318,15 @@ class InAppManager { return } - DispatchQueue.global(qos: .default).async { - let messagesToPresent = self.getMessagesToPresent([InAppPresented.IMMEDIATELY.rawValue]) - self.presenter.queueMessagesForPresentation(messages: messagesToPresent, tickleIds: self.pendingTickleIds) + DispatchQueue.global(qos: .default).async { [weak self] in + if let messagesToPresent = self?.getMessagesToPresent([InAppPresented.IMMEDIATELY.rawValue]), + let pendingTickleIds = self?.pendingTickleIds + { + self?.presenter.queueMessagesForPresentation( + messages: messagesToPresent, + tickleIds: pendingTickleIds + ) + } } } }, onFailure: { _, _, _ in @@ -447,8 +453,7 @@ class InAppManager { removeNotificationTickle(id: idEvicted) } - UserDefaults.standard.set(mostRecentUpdate, forKey: OptimobileUserDefaultsKey.IN_APP_MOST_RECENT_UPDATED_AT.rawValue) - + storage.set(value: mostRecentUpdate, key: .inAppMostRecentUpdateAt) trackMessageDelivery(messages: messages) let inboxUpdated = fetchedWithInbox || evictedWithInbox || evictedExceedersWithInbox From 0bd132ade1d57dffc2e8ce721ca9c9b7b0a9f4b4 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Thu, 14 Mar 2024 14:49:02 -0400 Subject: [PATCH 28/42] Added a privacy manifest --- Optimove.xcodeproj/project.pbxproj | 2 + OptimoveCore/PrivacyInfo.xcprivacy | 62 ++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 OptimoveCore/PrivacyInfo.xcprivacy diff --git a/Optimove.xcodeproj/project.pbxproj b/Optimove.xcodeproj/project.pbxproj index 1cef58c0..f8a0fa9f 100644 --- a/Optimove.xcodeproj/project.pbxproj +++ b/Optimove.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXFileReference section */ + 58371F3A2BA358CB00791552 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; FE31495485A751448C7DF822 /* SDK */ = {isa = PBXFileReference; lastKnownFileType = folder; name = SDK; path = .; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -14,6 +15,7 @@ 0FF4DF40AC6AAC3B8661208C = { isa = PBXGroup; children = ( + 58371F3A2BA358CB00791552 /* PrivacyInfo.xcprivacy */, 9BB5B51B953402330D6DC400 /* Packages */, ); sourceTree = ""; diff --git a/OptimoveCore/PrivacyInfo.xcprivacy b/OptimoveCore/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..aa800898 --- /dev/null +++ b/OptimoveCore/PrivacyInfo.xcprivacy @@ -0,0 +1,62 @@ + + + + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + NSPrivacyCollectedDataTypePurposeProductPersonalization + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeUserID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + NSPrivacyCollectedDataTypePurposeProductPersonalization + + + + NSPrivacyCollectedDataType + + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + 1C8F.1 + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + From bf012dc25f7ccca84522aa6c116023fb2e15d809 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Thu, 14 Mar 2024 15:35:23 -0400 Subject: [PATCH 29/42] Added a self prefix in a closure to allow compilation on pre 5.8 swift versions --- OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift index 02f12b31..ee8d1c5e 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/InApp/InAppManager.swift @@ -42,7 +42,7 @@ class InAppManager { finishedInitializationToken = NotificationCenter.default .addObserver(forName: .optimobileInializationFinished, object: nil, queue: nil) { [weak self] notification in guard let self = self else { return } - handleEnrollmentAndSyncSetup() + self.handleEnrollmentAndSyncSetup() Logger.debug("Notification \(notification.name.rawValue) was processed") } } From 9b9f5280ab09da048039e0dc5b8af383b4146753 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Thu, 14 Mar 2024 15:43:29 -0400 Subject: [PATCH 30/42] Updated version to 5.7.0, changelog --- CHANGELOG.md | 5 +++++ OptimoveCore.podspec | 2 +- OptimoveCore/Sources/Classes/Constants/SDKVersion.swift | 2 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d748d2..150dceb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 5.7.0 + +- Add Privacy Manifest +- Fix explicit `self` for `weak self` captures to allow pre 5.8 Swift compilation + ## 5.6.0 - Support the delayed configuration for SDK. Add new public APIs: diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index e4a98448..b18c6443 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index 0728ad67..46339007 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.6.0" +public let SDKVersion = "5.7.0" diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 6c35f25d..963a1b4e 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index e703ffdf..e5fb70cf 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.6.0' + s.version = '5.7.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' From 8ae6a761dec1b8537c7d8beb784d6ec25cff312a Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Thu, 21 Mar 2024 19:49:17 -0400 Subject: [PATCH 31/42] Added the privacy to podspec resource_bundles --- OptimoveNotificationServiceExtension.podspec | 3 +++ .../PrivacyInfo.xcprivacy | 23 +++++++++++++++++++ OptimoveSDK.podspec | 3 +++ .../PrivacyInfo.xcprivacy | 12 ---------- 4 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 OptimoveNotificationServiceExtension/PrivacyInfo.xcprivacy rename {OptimoveCore => OptimoveSDK}/PrivacyInfo.xcprivacy (83%) diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 963a1b4e..e234a275 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -12,5 +12,8 @@ Pod::Spec.new do |s| s.swift_version = '5' base_dir = "OptimoveNotificationServiceExtension/" s.source_files = base_dir + 'Sources/**/*', 'OptimobileShared/**/*' + s.resource_bundles = { + 'OptimoveNotificationServiceExtension' => ['OptimoveNotificationServiceExtension/PrivacyInfo.xcprivacy'] + } s.frameworks = 'Foundation', 'UserNotifications', 'UIKit' end diff --git a/OptimoveNotificationServiceExtension/PrivacyInfo.xcprivacy b/OptimoveNotificationServiceExtension/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..19f89636 --- /dev/null +++ b/OptimoveNotificationServiceExtension/PrivacyInfo.xcprivacy @@ -0,0 +1,23 @@ + + + + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + 1C8F.1 + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index e5fb70cf..e2489fd4 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -14,6 +14,9 @@ Pod::Spec.new do |s| s.swift_version = '5' base_dir = "OptimoveSDK/" s.source_files = base_dir + 'Sources/Classes/**/*', 'OptimobileShared/**/*' + s.resource_bundles = { + 'OptimoveSDK' => ['OptimoveSDK/PrivacyInfo.xcprivacy'] + } s.dependency 'OptimoveCore', s.version.to_s s.frameworks = 'Foundation', 'UIKit', 'SystemConfiguration', 'UserNotifications', 'CoreData' end diff --git a/OptimoveCore/PrivacyInfo.xcprivacy b/OptimoveSDK/PrivacyInfo.xcprivacy similarity index 83% rename from OptimoveCore/PrivacyInfo.xcprivacy rename to OptimoveSDK/PrivacyInfo.xcprivacy index aa800898..7d35afb2 100644 --- a/OptimoveCore/PrivacyInfo.xcprivacy +++ b/OptimoveSDK/PrivacyInfo.xcprivacy @@ -30,18 +30,6 @@ NSPrivacyCollectedDataTypePurposeProductPersonalization - - NSPrivacyCollectedDataType - - NSPrivacyCollectedDataTypeLinked - - NSPrivacyCollectedDataTypeTracking - - NSPrivacyCollectedDataTypePurposes - - - - NSPrivacyAccessedAPITypes From a6278a4278855bf37a8d92c2f4be9778232414b1 Mon Sep 17 00:00:00 2001 From: Eli Gutovsky Date: Tue, 26 Mar 2024 21:19:14 +0200 Subject: [PATCH 32/42] add identifiable --- OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift index b233a8d4..39fa95f2 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/OptimoveInApp.swift @@ -4,7 +4,7 @@ import CoreData import Foundation import OptimoveCore -public class InAppInboxItem { +public class InAppInboxItem: Identifiable { public private(set) var id: Int64 public private(set) var title: String public private(set) var subtitle: String @@ -103,8 +103,8 @@ public enum OptimoveInApp { } public static func getInboxItems() -> [InAppInboxItem] { - return Optimove.shared.container.resolve { locator in - let storage = locator.storage() + return Optimove.shared.container.resolve { container in + let storage = container.storage() return getInboxItems(storage: storage) } ?? [] } From e36001ef191aa572964798bf0cfcd1c6e1772dc2 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin <51291769+k-antipochkin@users.noreply.github.com> Date: Mon, 1 Apr 2024 08:40:07 -0400 Subject: [PATCH 33/42] Remove web to app banner (#102) * Removed web to app banner * Updated changelog --------- Co-authored-by: Konstantin Antipochkin --- CHANGELOG.md | 1 + .../Optimobile/DeepLinkFingerprinter.swift | 129 ------------------ .../Optimobile/Optimobile+DeepLinking.swift | 85 +----------- 3 files changed, 2 insertions(+), 213 deletions(-) delete mode 100644 OptimoveSDK/Sources/Classes/Optimobile/DeepLinkFingerprinter.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 150dceb7..21690abd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add Privacy Manifest - Fix explicit `self` for `weak self` captures to allow pre 5.8 Swift compilation +- Remove web to app banner code ## 5.6.0 diff --git a/OptimoveSDK/Sources/Classes/Optimobile/DeepLinkFingerprinter.swift b/OptimoveSDK/Sources/Classes/Optimobile/DeepLinkFingerprinter.swift deleted file mode 100644 index d2e8556a..00000000 --- a/OptimoveSDK/Sources/Classes/Optimobile/DeepLinkFingerprinter.swift +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright © 2022 Optimove. All rights reserved. - -import Foundation -import WebKit - -private enum PrintDustMessage: String { - case clientReady = "READY" - case clientFingerprintGeneraged = "FINGERPRINT_GENERATED" - case requestFingerprint = "REQUEST_FINGERPRINT" -} - -private enum DeferredState { - case pending - case resolved(R) -} - -private class Deferred { - var state: DeferredState - var pendingWatchers: [(R) -> Void] - - init() { - state = .pending - pendingWatchers = [] - } - - func resolve(result: R) { - DispatchQueue.main.async { - switch self.state { - case .resolved: return - default: break - } - - self.state = DeferredState.resolved(result) - - self.pendingWatchers.forEach { cb in - cb(result) - } - - self.pendingWatchers.removeAll() - } - } - - func then(onResult: @escaping (R) -> Void) { - DispatchQueue.main.async { - switch self.state { - case .pending: - self.pendingWatchers.append(onResult) - case let .resolved(result): - onResult(result) - } - } - } -} - -class DeepLinkFingerprinter: NSObject, WKScriptMessageHandler, WKNavigationDelegate { - fileprivate static let printDustRuntimeUrl = "https://pd.app.delivery" - fileprivate static let printDustHandlerName = "printHandler" - - fileprivate var webView: WKWebView? - fileprivate let fingerprint: Deferred<[String: String]> - - override init() { - let controller = WKUserContentController() - let config = WKWebViewConfiguration() - config.userContentController = controller - - webView = WKWebView(frame: UIScreen.main.bounds, configuration: config) - fingerprint = Deferred() - - super.init() - - controller.add(self, name: DeepLinkFingerprinter.printDustHandlerName) - - let request = URLRequest(url: URL(string: DeepLinkFingerprinter.printDustRuntimeUrl)!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 10) - webView?.load(request) - } - - func getFingerprintComponents(_ onGenerated: @escaping ([String: String]) -> Void) { - fingerprint.then(onResult: onGenerated) - } - - func userContentController(_: WKUserContentController, didReceive message: WKScriptMessage) { - if message.name != DeepLinkFingerprinter.printDustHandlerName { - return - } - - let body = message.body as! NSDictionary - let type = body["type"] as! String - - switch type { - case PrintDustMessage.clientReady.rawValue: - postClientMessage(type: PrintDustMessage.requestFingerprint.rawValue, data: nil) - case PrintDustMessage.clientFingerprintGeneraged.rawValue: - guard let data = body["data"] as? [String: AnyObject], - let components = data["components"] as? [String: String] - else { - return - } - fingerprint.resolve(result: components) - DispatchQueue.main.async { self.cleanUpWebView() } - default: - print("Unhandled message: \(type)") - } - } - - func webView(_: WKWebView, didFail _: WKNavigation!, withError _: Error) { - DispatchQueue.main.async { self.cleanUpWebView() } - } - - fileprivate func postClientMessage(type: String, data: Any?) { - do { - let msg: [String: Any] = ["type": type, "data": data != nil ? data! : NSNull()] - let json: Data = try JSONSerialization.data(withJSONObject: msg, options: JSONSerialization.WritingOptions(rawValue: 0)) - - let jsonMsg = String(data: json, encoding: .utf8) - let evalString = String(format: "postHostMessage(%@);", jsonMsg!) - - webView?.evaluateJavaScript(evalString, completionHandler: nil) - } catch { - // Noop - } - } - - fileprivate func cleanUpWebView() { - webView?.stopLoading() - webView?.configuration.userContentController.removeScriptMessageHandler(forName: DeepLinkFingerprinter.printDustHandlerName) - webView = nil - } -} diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift index f47b984b..f8d84166 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift @@ -47,15 +47,12 @@ final class DeepLinkHelper { let config: OptimobileConfig let httpClient: KSHttpClient - var anyContinuationHandled: Bool var cachedLink: CachedLink? - var cachedFingerprintComponents: [String: String]? var finishedInitializationToken: NSObjectProtocol? init(_ config: OptimobileConfig, httpClient: KSHttpClient) { self.config = config self.httpClient = httpClient - anyContinuationHandled = false finishedInitializationToken = NotificationCenter.default .addObserver(forName: .optimobileInializationFinished, object: nil, queue: nil) { [weak self] notification in @@ -69,10 +66,6 @@ final class DeepLinkHelper { handleDeepLinkUrl(cachedLink.url, wasDeferred: cachedLink.wasDeferred) self.cachedLink = nil } - if let cachedFingerprintComponents = cachedFingerprintComponents { - handleFingerprintComponents(components: cachedFingerprintComponents) - self.cachedFingerprintComponents = nil - } } func checkForNonContinuationLinkMatch() { @@ -85,12 +78,6 @@ final class DeepLinkHelper { @objc func appBecameActive() { NotificationCenter.default.removeObserver(self) - - if anyContinuationHandled { - return - } - - checkForWebToAppBannerTap() } private func checkForDeferredLinkOnClipboard() -> Bool { @@ -117,17 +104,7 @@ final class DeepLinkHelper { return handled } - - private func checkForWebToAppBannerTap() { - let fp = DeepLinkFingerprinter() - - fp.getFingerprintComponents { components in - DispatchQueue.global().async { - self.handleFingerprintComponents(components: components) - } - } - } - + private func urlShouldBeHandled(_ url: URL) -> Bool { guard let host = url.host else { return false @@ -181,64 +158,6 @@ final class DeepLinkHelper { }) } - private func handleFingerprintComponents(components: [String: String]) { - guard let componentJson = try? JSONSerialization.data(withJSONObject: components, options: JSONSerialization.WritingOptions(rawValue: 0)), - let encodedComponents = KSHttpUtil.urlEncode(componentJson.base64EncodedString()) - else { - return - } - - let path = "/v1/deeplinks/_taps?fingerprint=\(encodedComponents)" - - httpClient.sendRequest(.GET, toPath: path, data: nil, onSuccess: { res, data in - switch res?.statusCode { - case 200: - guard let jsonData = data as? Data, - let response = try? JSONSerialization.jsonObject(with: jsonData) as? [AnyHashable: Any], - let urlString = response["linkUrl"] as? String, - let url = URL(string: urlString), - let link = DeepLink(for: url, from: jsonData) - else { - // Fingerprint matches that fail to parse correctly can't know the URL so - // don't invoke any error handler. - return - } - - self.invokeDeepLinkHandler(.linkMatched(link)) - - let linkProps = ["url": url.absoluteString, "wasDeferred": false] as [String: Any] - Optimobile.getInstance().analyticsHelper.trackEvent(eventType: OptimobileEvent.DEEP_LINK_MATCHED.rawValue, properties: linkProps, immediateFlush: false) - default: - // Noop - break - } - }, onFailure: { res, error, data in - if let error = error { - if case HttpAuthorizationError.missingAuthHeader = error { - self.cachedFingerprintComponents = components - return - } - } - guard let jsonData = data as? Data, - let response = try? JSONSerialization.jsonObject(with: jsonData) as? [AnyHashable: Any], - let urlString = response["linkUrl"] as? String, - let url = URL(string: urlString) - else { - return - } - - switch res?.statusCode { - case 410: - self.invokeDeepLinkHandler(.linkExpired(url)) - case 429: - self.invokeDeepLinkHandler(.linkLimitExceeded(url)) - default: - // Noop - break - } - }) - } - private func invokeDeepLinkHandler(_ resolution: DeepLinkResolution) { DispatchQueue.main.async { self.config.deepLinkHandler?(resolution) @@ -259,8 +178,6 @@ final class DeepLinkHelper { return false } - anyContinuationHandled = true - handleDeepLinkUrl(url) return true } From f733e4c4d33d9549c8e35b83c53b584b5f74902c Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Fri, 5 Apr 2024 14:10:51 -0400 Subject: [PATCH 34/42] Fixed the deeplink decoding, exposed a new urlOpened API --- .../Optimobile/Optimobile+DeepLinking.swift | 38 ++++++++++++++----- OptimoveSDK/Sources/Classes/Optimove.swift | 7 ++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift index f8d84166..2a22fcc0 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile+DeepLinking.swift @@ -12,11 +12,10 @@ public struct DeepLink { public let url: URL public let content: DeepLinkContent public let data: [AnyHashable: Any?] - - init?(for url: URL, from jsonData: Data) { - guard let response = try? JSONSerialization.jsonObject(with: jsonData) as? [AnyHashable: Any], - let linkData = response["linkData"] as? [AnyHashable: Any?], - let content = response["content"] as? [AnyHashable: Any?] + + init?(for url: URL, from jsonData: [AnyHashable: Any]) { + guard let linkData = jsonData["linkData"] as? [AnyHashable: Any?], + let content = jsonData["content"] as? [AnyHashable: Any?] else { return nil } @@ -124,8 +123,8 @@ final class DeepLinkHelper { httpClient.sendRequest(.GET, toPath: path, data: nil, onSuccess: { res, data in switch res?.statusCode { case 200: - guard let jsonData = data as? Data, - let link = DeepLink(for: url, from: jsonData) + guard let dictionary = data as? [AnyHashable: Any], + let link = DeepLink(for: url, from: dictionary) else { self.invokeDeepLinkHandler(.lookupFailed(url)) return @@ -172,18 +171,39 @@ final class DeepLinkHelper { } guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, - let url = userActivity.webpageURL, - urlShouldBeHandled(url) + let url = userActivity.webpageURL else { return false } + return handleContinuation(for: url) + } + + @discardableResult + fileprivate func handleContinuation(for url: URL) -> Bool { + if config.deepLinkHandler == nil { + print("Optimobile deep link handler not configured, aborting...") + return false + } + + return handleUrl(url: url) + } + + fileprivate func handleUrl(url: URL) -> Bool { + if !urlShouldBeHandled(url) { + return false + } + handleDeepLinkUrl(url) return true } } extension Optimobile { + static func urlOpened(url: URL) -> Bool { + return getInstance().deepLinkHelper?.handleContinuation(for: url) ?? false + } + static func application(_: UIApplication, continue userActivity: NSUserActivity, restorationHandler _: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { return getInstance().deepLinkHelper?.handleContinuation(for: userActivity) ?? false } diff --git a/OptimoveSDK/Sources/Classes/Optimove.swift b/OptimoveSDK/Sources/Classes/Optimove.swift index f8ffccfb..d3655ab9 100644 --- a/OptimoveSDK/Sources/Classes/Optimove.swift +++ b/OptimoveSDK/Sources/Classes/Optimove.swift @@ -359,6 +359,13 @@ public extension Optimove { @objc func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { return Optimobile.application(application, continue: userActivity, restorationHandler: restorationHandler) } + + /** + Used for Deferred Deep Linking to pass the continuation url to the Optimove SDK to be processed. + */ + @objc func urlOpened(url: URL) -> Bool { + return Optimobile.urlOpened(url: url) + } /** Used for Deferred Deep Linking to pass the continuation to the Optimove SDK to be processed in scene-based apps. From c9d8b65ffbb1b6a1eb621222dd73de875417e8a4 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Fri, 5 Apr 2024 14:44:01 -0400 Subject: [PATCH 35/42] Updated version to 5.8.0 --- CHANGELOG.md | 5 +++++ OptimoveCore.podspec | 2 +- OptimoveCore/Sources/Classes/Constants/SDKVersion.swift | 2 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21690abd..914b718f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 5.8.0 + +- Add a new public API `Optimove.shared.urlOpened(url: url)` to allow easily forwarding urls to Optimove instead of relying on AppDeletegate's `application(_:continue:restorationHandler:)` +- Fix deeplink decoding issue + ## 5.7.0 - Add Privacy Manifest diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index b18c6443..74ea1191 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.7.0' + s.version = '5.8.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index 46339007..cde0da16 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.7.0" +public let SDKVersion = "5.8.0" diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index e234a275..8ab9e71c 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.7.0' + s.version = '5.8.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index e2489fd4..50463a86 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.7.0' + s.version = '5.8.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' From fb4f02948e30830a3374011a41797c8c9f66b646 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 10 Apr 2024 11:18:56 -0400 Subject: [PATCH 36/42] fixed the immediate initialization --- OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift | 4 ++-- OptimoveSDK/Sources/Classes/OptimoveConfig.swift | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift index 5f0b44c4..b15fe913 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift @@ -116,9 +116,9 @@ final class Optimobile { throw Error.configurationIsMissing } - writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) - instance = Optimobile(config: config) + + writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) instance!.initializeHelpers() diff --git a/OptimoveSDK/Sources/Classes/OptimoveConfig.swift b/OptimoveSDK/Sources/Classes/OptimoveConfig.swift index 80d599c3..bb467dd8 100644 --- a/OptimoveSDK/Sources/Classes/OptimoveConfig.swift +++ b/OptimoveSDK/Sources/Classes/OptimoveConfig.swift @@ -160,6 +160,7 @@ open class OptimoveConfigBuilder: NSObject { do { if let optimoveCredentials = optimoveCredentials, !optimoveCredentials.isEmpty { let args = try OptimoveArguments(base64: optimoveCredentials) + features.insert(.optimove) _tenantToken = args.tenantToken _configName = args.configName } @@ -169,6 +170,7 @@ open class OptimoveConfigBuilder: NSObject { do { if let optimobileCredentials = optimobileCredentials, !optimobileCredentials.isEmpty { let args = try OptimobileArguments(base64: optimobileCredentials) + features.insert(.optimobile) credentials = args.credentials region = args.region } From 9ac681bca07372ace3f8d7602b17a45fc6f15b84 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 10 Apr 2024 11:21:10 -0400 Subject: [PATCH 37/42] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 914b718f..ef56e276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add a new public API `Optimove.shared.urlOpened(url: url)` to allow easily forwarding urls to Optimove instead of relying on AppDeletegate's `application(_:continue:restorationHandler:)` - Fix deeplink decoding issue +- Fix immediate initialization of the SDK ## 5.7.0 From 716ed387fadd489c1786d48801dffd0f83897e77 Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 10 Apr 2024 11:39:22 -0400 Subject: [PATCH 38/42] Undo setting credentials before initializing Optimobile --- OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift index b15fe913..6eb09b0f 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift @@ -115,11 +115,11 @@ final class Optimobile { guard let config = optimoveConfig.optimobileConfig else { throw Error.configurationIsMissing } + + writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) instance = Optimobile(config: config) - writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) - instance!.initializeHelpers() if #available(iOS 10.0, *) { From 84384fd505d0702b95eafe04f1345ddc4236bf7b Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 10 Apr 2024 12:11:41 -0400 Subject: [PATCH 39/42] Initializing Optimobile before setting credentials --- OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift index 6eb09b0f..c15da995 100644 --- a/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift +++ b/OptimoveSDK/Sources/Classes/Optimobile/Optimobile.swift @@ -116,9 +116,9 @@ final class Optimobile { throw Error.configurationIsMissing } - writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) - instance = Optimobile(config: config) + + writeDefaultsKeys(config: config, initialVisitorId: initialVisitorId) instance!.initializeHelpers() From 81a2d280c14423b8105c15859123c3869933731b Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 8 May 2024 12:04:35 -0400 Subject: [PATCH 40/42] Changed the migration version to be 5_9_0 --- OptimoveSDK/Sources/Classes/DI/Assembly.swift | 2 +- OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift | 4 ++-- OptimoveSDK/Sources/Classes/Migration/Version.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OptimoveSDK/Sources/Classes/DI/Assembly.swift b/OptimoveSDK/Sources/Classes/DI/Assembly.swift index 7f2b4e01..79ea3757 100644 --- a/OptimoveSDK/Sources/Classes/DI/Assembly.swift +++ b/OptimoveSDK/Sources/Classes/DI/Assembly.swift @@ -33,7 +33,7 @@ final class Assembly { private func migrate() { let migrations: [MigrationWork] = [ MigrationWork_3_3_0(), - MigrationWork_5_7_0() + MigrationWork_5_9_0() ] migrations .filter { $0.isAllowToMiragte(SDKVersion) } diff --git a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift index 6a4008f0..cd8e526a 100644 --- a/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift +++ b/OptimoveSDK/Sources/Classes/Migration/MigrationWork.swift @@ -230,9 +230,9 @@ extension MigrationWork_3_3_0 { } } -final class MigrationWork_5_7_0: MigrationWorker { +final class MigrationWork_5_9_0: MigrationWorker { init() { - super.init(newVersion: .v_5_7_0) + super.init(newVersion: .v_5_9_0) } override func runMigration() { diff --git a/OptimoveSDK/Sources/Classes/Migration/Version.swift b/OptimoveSDK/Sources/Classes/Migration/Version.swift index c1c172ca..0880b4d1 100644 --- a/OptimoveSDK/Sources/Classes/Migration/Version.swift +++ b/OptimoveSDK/Sources/Classes/Migration/Version.swift @@ -4,5 +4,5 @@ enum Version: String { case v_2_10_0 = "2.10.0" case v_3_0_0 = "3.0.0" case v_3_3_0 = "3.3.0" - case v_5_7_0 = "5.7.0" + case v_5_9_0 = "5.9.0" } From 750d9d2bb55c907c6ca1d2a41b3bb98d2f7de84b Mon Sep 17 00:00:00 2001 From: Konstantin Antipochkin Date: Wed, 8 May 2024 12:15:12 -0400 Subject: [PATCH 41/42] Updated version to 5.9.0 --- CHANGELOG.md | 4 ++++ OptimoveCore.podspec | 2 +- OptimoveCore/Sources/Classes/Constants/SDKVersion.swift | 2 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef56e276..aee4ed7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 5.9.0 + +- Remove `SetUserAgent` event + ## 5.8.0 - Add a new public API `Optimove.shared.urlOpened(url: url)` to allow easily forwarding urls to Optimove instead of relying on AppDeletegate's `application(_:continue:restorationHandler:)` diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index 74ea1191..d91f83b8 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.8.0' + s.version = '5.9.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index cde0da16..35790896 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.8.0" +public let SDKVersion = "5.9.0" diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 8ab9e71c..63373bf0 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.8.0' + s.version = '5.9.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index 50463a86..479407b7 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.8.0' + s.version = '5.9.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' From 6e9d521c121314fea672ea1ee5aba21317917b22 Mon Sep 17 00:00:00 2001 From: daniela-opti <142421223+daniela-opti@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:36:40 +0100 Subject: [PATCH 42/42] BA#218543 Add preference center functionality (#111) * Add pref center functionality * Update comment * Separate models into their own files * Initialise Preference Center as a separate instance * Replace var with let in struct * Remove getters * Add return to switch statement * Shuffle things around; expose Optimove.PreferenceCenter * Call it OptimovePreferenceCenter * Get closer to Android implementation * Add get config values func * Check customer + visitor id * Remove objc classes * Give preferenceCenterCredentials a default nil value, so it doesn't break existing apps * Add method for enabling preference center * Take care of delayed init * Do not initialize preference center if optimove creds are missing * Log errors * Use region instead of environment for region * Add coding keys, so we stay consistent with naming * Get config from Optimove, instead of storing it in pref center class * Take enum out of initializer, oops * Get into reviewable state * Use CustomStringConvertible protocol for enum * Add pref center docs link * Do not log error if preference center is not wanted (when building) * Update preferenceUpdate model name * Remove unused enum * Add new errorNotConfigured result type * Move channel into Preferences model * Show error when setting credentials for a feature that was not requested * Try to cover permutations of nullability * Allow setCredentials to be called with nil, nil, prefCenterCreds * Don't log error when delayed init and missing credentials * Remove logger.debug * Move public data structures under OptimovePC * Remove public keyword in ctor for topics and preferences * Address PR comments * Make isPreferenceCenterConfigured only look at the features; don't care about credentials * Bump versions * Add extra check for config being nil * Bring up to speed with Android * Bring close to original * Fix copy paste * Add an extra if statement to cover nil optimoveCredentials for delayed init * Clarify log * Make preference center behave like the other features when feature is requested but no credentials were provided * Make preference center behave like other features when it is not included in the feature set for delayed init, but credentials were provided * Remove iOS 13.0 requirement * Rename forgotten topics -> customerPreferences * Catch the cases where optimove credentials are empty - do not initialize pref center * Bring back Task and ios 13 * Remove client, only bring task * Remove redundant ios 13 requirements * Update major version to 6 * mention 2nd breaking change --------- Co-authored-by: Vladislav Voicehovich --- CHANGELOG.md | 10 + OptimoveCore.podspec | 2 +- .../Classes/Constants/SDKVersion.swift | 2 +- .../NetworkClient/NetworkRequest.swift | 21 +- OptimoveNotificationServiceExtension.podspec | 2 +- OptimoveSDK.podspec | 2 +- OptimoveSDK/Sources/Classes/Optimove.swift | 43 +++- .../Sources/Classes/OptimoveConfig.swift | 144 ++++++++++- .../PreferenceCenter/Models/OptimovePC.swift | 66 +++++ .../Models/PreferenceCenterConfig.swift | 5 + .../OptimovePreferenceCenter.swift | 239 ++++++++++++++++++ .../Classes/Services/ServiceLocator.swift | 1 - README.md | 1 + 13 files changed, 516 insertions(+), 22 deletions(-) create mode 100644 OptimoveSDK/Sources/Classes/PreferenceCenter/Models/OptimovePC.swift create mode 100644 OptimoveSDK/Sources/Classes/PreferenceCenter/Models/PreferenceCenterConfig.swift create mode 100644 OptimoveSDK/Sources/Classes/PreferenceCenter/OptimovePreferenceCenter.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index aee4ed7a..4227d6fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 6.0.0 + +- Add Preference Center feature. The new functionality is available through the following methods: + - `OptimovePreferenceCenter.getInstance().setCustomerPreferencesAsync()` + - `OptimovePreferenceCenter.getInstance().getPreferencesAsync()` + +Breaking changes: +- iOS 13 required for using Preference Center +- removed `OptimoveConfigBuilder.setCredentials` unintentionally public method + ## 5.9.0 - Remove `SetUserAgent` event diff --git a/OptimoveCore.podspec b/OptimoveCore.podspec index d91f83b8..a78a98df 100644 --- a/OptimoveCore.podspec +++ b/OptimoveCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveCore' - s.version = '5.9.0' + s.version = '6.0.0' s.summary = 'Official Optimove SDK for iOS. Core framework.' s.description = 'The core framework is used to share code-base between other Optimove frameworks.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift index 35790896..97cc0984 100644 --- a/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift +++ b/OptimoveCore/Sources/Classes/Constants/SDKVersion.swift @@ -1,3 +1,3 @@ // Copyright © 2019 Optimove. All rights reserved. -public let SDKVersion = "5.9.0" +public let SDKVersion = "6.0.0" diff --git a/OptimoveCore/Sources/Classes/NetworkClient/NetworkRequest.swift b/OptimoveCore/Sources/Classes/NetworkClient/NetworkRequest.swift index a525c872..74e80b91 100644 --- a/OptimoveCore/Sources/Classes/NetworkClient/NetworkRequest.swift +++ b/OptimoveCore/Sources/Classes/NetworkClient/NetworkRequest.swift @@ -87,17 +87,32 @@ public extension HTTPHeader { enum Fields: String { case contentType = "Content-Type" case userAgent = "User-Agent" + case tenantId = "X-Tenant-Id" + case accept } - enum Values: String { - case json = "application/json" + enum Values: CustomStringConvertible { + case json + case tenantId(id: String) + case textplain + + public var description: String { + switch self { + case .json: + return "application/json" + case .tenantId(let id): + return id + case .textplain: + return "text/plain" + } + } } } public extension HTTPHeader { init(field: Fields, value: Values) { self.field = field.rawValue - self.value = value.rawValue + self.value = String(describing: value) } } diff --git a/OptimoveNotificationServiceExtension.podspec b/OptimoveNotificationServiceExtension.podspec index 63373bf0..7238fd81 100644 --- a/OptimoveNotificationServiceExtension.podspec +++ b/OptimoveNotificationServiceExtension.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveNotificationServiceExtension' - s.version = '5.9.0' + s.version = '6.0.0' s.summary = 'Official Optimove SDK for iOS. Notification service extension framework.' s.description = 'The notification service extension is used for handling additional content in push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK.podspec b/OptimoveSDK.podspec index 479407b7..62bb1ff1 100644 --- a/OptimoveSDK.podspec +++ b/OptimoveSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'OptimoveSDK' - s.version = '5.9.0' + s.version = '6.0.0' s.summary = 'Official Optimove SDK for iOS.' s.description = 'The Optimove SDK framework is used for reporting events and receive push notifications.' s.homepage = 'https://github.com/optimove-tech/Optimove-SDK-iOS' diff --git a/OptimoveSDK/Sources/Classes/Optimove.swift b/OptimoveSDK/Sources/Classes/Optimove.swift index d3655ab9..fd6a22b8 100644 --- a/OptimoveSDK/Sources/Classes/Optimove.swift +++ b/OptimoveSDK/Sources/Classes/Optimove.swift @@ -61,20 +61,57 @@ typealias Logger = OptimoveCore.Logger throw GuardError.custom("Failed on OptimobileSDK initialization. Reason: \(error.localizedDescription)") } } + } + + if config.isPreferenceCenterConfigured() { + guard config.isOptimoveConfigured() else { + Logger.error("Preference Center requires the optimove feature enabled.") + return + } + + shared.container.resolve { serviceLocator in + do { + try OptimovePreferenceCenter.initialize(with: config, storage: serviceLocator.storage(), networkClient: NetworkClientImpl()) + } catch { + throw GuardError.custom("Failed on PreferenceCenter initialization. Reason: \(error.localizedDescription)") + } + } } } + static func getConfig() -> OptimoveConfig? { + return shared.config + } + /// Set the credentials for the Optimove server. Intent to use as a step for the delayed initialization. - public static func setCredentials(optimoveCredentials: String?, optimobileCredentials: String?) { + private static func setCredentialsInternal(optimoveCredentials: String?, optimobileCredentials: String?, preferenceCenterCredentials: String? = nil) { guard let currentConfig = shared.config else { Logger.error("Optimove SDK is not configured yet. Please call Optimove.initialize(with:) first.") return } + let builder = OptimoveConfigBuilder(from: currentConfig) - builder.setCredentials(optimoveCredentials: optimoveCredentials, optimobileCredentials: optimobileCredentials) + builder.setCredentials( + optimoveCredentials: optimoveCredentials, + optimobileCredentials: optimobileCredentials, + preferenceCenterCredentials: preferenceCenterCredentials + ) + let config = builder.build() initialize(with: config) } + + public static func setCredentials(optimoveCredentials: String?, optimobileCredentials: String?) { + setCredentialsInternal(optimoveCredentials: optimoveCredentials, optimobileCredentials: optimobileCredentials) + } + + public static func setCredentials(optimoveCredentials: String?, optimobileCredentials: String?, preferenceCenterCredentials: String?) { + setCredentialsInternal( + optimoveCredentials: optimoveCredentials, + optimobileCredentials: optimobileCredentials, + preferenceCenterCredentials: preferenceCenterCredentials + ) + } public static func isFeatureRunning(_ feature: Feature) -> Bool { switch feature { @@ -82,6 +119,8 @@ typealias Logger = OptimoveCore.Logger return Optimobile.isSdkRunning case .optimove: return RunningFlagsIndication.isSdkRunning + case .preferenceCenter: + return OptimovePreferenceCenter.isSdkRunning default: return false } diff --git a/OptimoveSDK/Sources/Classes/OptimoveConfig.swift b/OptimoveSDK/Sources/Classes/OptimoveConfig.swift index bb467dd8..1abe9cd3 100644 --- a/OptimoveSDK/Sources/Classes/OptimoveConfig.swift +++ b/OptimoveSDK/Sources/Classes/OptimoveConfig.swift @@ -13,6 +13,8 @@ public struct Feature: OptionSet, @unchecked Sendable, CustomStringConvertible { public static let optimobile = Feature(rawValue: 1 << 1) /// Optimove feature. public static let optimove = Feature(rawValue: 1 << 2) + /// Preference center feature. + public static let preferenceCenter = Feature(rawValue: 1 << 4) static let delayedConfiguration = Feature(rawValue: 1 << 3) public init(rawValue: Int) { @@ -30,6 +32,9 @@ public struct Feature: OptionSet, @unchecked Sendable, CustomStringConvertible { if contains(.delayedConfiguration) { descriptions.append("Delayed Configuration") } + if contains(.preferenceCenter) { + descriptions.append("Preference Center") + } return descriptions.isEmpty ? "No Features" : descriptions.joined(separator: ", ") } @@ -39,6 +44,7 @@ public struct OptimoveConfig { let features: Feature let tenantInfo: OptimoveTenantInfo? let optimobileConfig: OptimobileConfig? + let preferenceCenterConfig: PreferenceCenterConfig? func isOptimoveConfigured() -> Bool { return features.contains(.optimove) @@ -47,6 +53,14 @@ public struct OptimoveConfig { func isOptimobileConfigured() -> Bool { return features.contains(.optimobile) } + + func isPreferenceCenterConfigured() -> Bool { + return features.contains(.preferenceCenter) + } + + func getPreferenceCenterConfig() -> PreferenceCenterConfig? { + return preferenceCenterConfig + } } @objc public class OptimoveTenantInfo: NSObject { @@ -89,6 +103,7 @@ public typealias Region = OptimobileConfig.Region open class OptimoveConfigBuilder: NSObject { private var credentials: OptimobileCredentials? + private var preferenceCenterCredentials: String? public private(set) var features: Feature var region: OptimobileConfig.Region? var urlBuilder: UrlBuilder @@ -153,29 +168,44 @@ open class OptimoveConfigBuilder: NSObject { super.init() } - @discardableResult public func setCredentials(optimoveCredentials: String?, optimobileCredentials: String?) -> OptimoveConfigBuilder { - if optimoveCredentials == nil, optimoveCredentials == nil { + @discardableResult func setCredentials( + optimoveCredentials: String?, + optimobileCredentials: String?, + preferenceCenterCredentials: String? = nil + ) -> OptimoveConfigBuilder { + if optimoveCredentials == nil, optimobileCredentials == nil { assertionFailure("Should provide at least optimove or optimobile credentials") } - do { - if let optimoveCredentials = optimoveCredentials, !optimoveCredentials.isEmpty { + + if let optimoveCredentials = optimoveCredentials, !optimoveCredentials.isEmpty { + do { let args = try OptimoveArguments(base64: optimoveCredentials) features.insert(.optimove) _tenantToken = args.tenantToken _configName = args.configName + } catch { + Logger.error("Invalid Optimove credentials: \(error.localizedDescription)") } - } catch { - Logger.error(error.localizedDescription) } - do { - if let optimobileCredentials = optimobileCredentials, !optimobileCredentials.isEmpty { + + if let optimobileCredentials = optimobileCredentials, !optimobileCredentials.isEmpty { + do { let args = try OptimobileArguments(base64: optimobileCredentials) features.insert(.optimobile) credentials = args.credentials region = args.region + } catch { + Logger.error("Invalid Optimobile credentials: \(error.localizedDescription)") + } + } + + if let preferenceCenterCredentials = preferenceCenterCredentials, !preferenceCenterCredentials.isEmpty { + if optimoveCredentials == nil || optimoveCredentials == "" { + Logger.error("Preference Center requires optimove credentials set"); + } else { + self.preferenceCenterCredentials = preferenceCenterCredentials + features.insert(.preferenceCenter) } - } catch { - Logger.error(error.localizedDescription) } return self @@ -224,6 +254,14 @@ open class OptimoveConfigBuilder: NSObject { return self } + @discardableResult public func enablePreferenceCenter(credentials: String) -> OptimoveConfigBuilder + { + features.insert(.preferenceCenter) + preferenceCenterCredentials = credentials + + return self + } + /** Internal SDK embedding API to support override of stats data in x-plat SDKs. Do not call or depend on this method in your app */ @@ -301,16 +339,51 @@ open class OptimoveConfigBuilder: NSObject { return nil }() + let preferenceCenterConfig: PreferenceCenterConfig? = { + if !features.contains(.optimove), + tenantInfo == nil, + !features.contains(.delayedConfiguration) { + Logger.error("Preference center cannot be inialized without optimove") + return nil + } + + if preferenceCenterCredentials == nil { + if !features.contains(.delayedConfiguration) { + Logger.error("Preference center could not be initialized due to missing credentials.") + } + return nil + } + + return getPreferenceCenterConfig(from: preferenceCenterCredentials) + }() + + return OptimoveConfig( features: features, tenantInfo: tenantInfo, - optimobileConfig: optimobileConfig + optimobileConfig: optimobileConfig, + preferenceCenterConfig: preferenceCenterConfig ) } + + private func getPreferenceCenterConfig(from credentials: String?) -> PreferenceCenterConfig? { + do { + let args = try PreferenceCenterArguments(base64: credentials!) + + return PreferenceCenterConfig( + region: args.region, + tenantId: args.tenantId, + brandGroupId: args.brandGroupId + ) + } catch { + Logger.error("Invalid preference center credentials: \(error.localizedDescription)") + return nil + } + } } public extension OptimobileConfig { - enum Region: String, CaseIterable { + enum Region: String, CaseIterable, Codable { case DEV = "uk-1" case EU = "eu-central-2" case US = "us-east-1" @@ -427,3 +500,50 @@ struct OptimobileArguments: Decodable { credentials = OptimobileCredentials(apiKey: apiKey, secretKey: secretKey) } } + +struct PreferenceCenterArguments: Decodable { + enum Error: Foundation.LocalizedError { + case emptyBase64 + case failedDecodingBase64(String) + + var errorDescription: String? { + switch self { + case .emptyBase64: + return "The base64 string is empty" + case let .failedDecodingBase64(string): + return "Failed on decoding base64 the value \(string)" + } + } + } + + let version: String + let region: String + let tenantId: Int + let brandGroupId: String + + enum CodingKeys: String, CodingKey { + case version + case environment + case tenantId + case brandGroupId + } + + init(base64: String) throws { + guard !base64.isEmpty else { + throw Error.emptyBase64 + } + guard let data = Data(base64Encoded: base64) else { + throw Error.failedDecodingBase64(base64) + } + self = try JSONDecoder().decode(PreferenceCenterArguments.self, from: data) + } + + init(from decoder: Decoder) throws { + var container = try decoder.unkeyedContainer() + + version = try container.decode(String.self) + region = try container.decode(String.self) + tenantId = try container.decode(Int.self) + brandGroupId = try container.decode(String.self) + } +} diff --git a/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/OptimovePC.swift b/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/OptimovePC.swift new file mode 100644 index 00000000..6a642d5c --- /dev/null +++ b/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/OptimovePC.swift @@ -0,0 +1,66 @@ +import Foundation + +public struct OptimovePC { + public enum Channel: Int, Codable { + case mobilePush = 489 + case webPush = 490 + case sms = 493 + case inApp = 427 + case whatsapp = 498 + case mail = 15 + case inbox = 495 + } + + public struct Topic: Codable { + public let id: String + public let name: String + public let description: String + public let subscribedChannels: [Channel] + + init(id: String, name: String, description: String, subscribedChannels: [Channel]) { + self.id = id + self.name = name + self.description = description + self.subscribedChannels = subscribedChannels + } + + enum CodingKeys: String, CodingKey { + case id = "topicId" + case name = "topicName" + case description = "topicDescription" + case subscribedChannels = "channelSubscription" + } + } + + public struct Preferences: Codable { + public let customerPreferences: [Topic] + public let configuredChannels: [Channel] + + init(customerPreferences: [Topic], configuredChannels: [Channel]) { + self.customerPreferences = customerPreferences + self.configuredChannels = configuredChannels + } + + enum CodingKeys: String, CodingKey { + case customerPreferences = "topics" + case configuredChannels = "channels" + } + } + + public struct PreferenceUpdate: Codable { + public let topicId: String + public let subscribedChannels: [Channel] + + public init(topicId: String, subscribedChannels: [Channel]) { + self.topicId = topicId + self.subscribedChannels = subscribedChannels + } + + enum CodingKeys: String, CodingKey { + case topicId = "topicId" + case subscribedChannels = "channelSubscription" + } + } +} + + diff --git a/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/PreferenceCenterConfig.swift b/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/PreferenceCenterConfig.swift new file mode 100644 index 00000000..d9c5c6c9 --- /dev/null +++ b/OptimoveSDK/Sources/Classes/PreferenceCenter/Models/PreferenceCenterConfig.swift @@ -0,0 +1,5 @@ +struct PreferenceCenterConfig: Codable { + let region: String + let tenantId: Int + let brandGroupId: String +} diff --git a/OptimoveSDK/Sources/Classes/PreferenceCenter/OptimovePreferenceCenter.swift b/OptimoveSDK/Sources/Classes/PreferenceCenter/OptimovePreferenceCenter.swift new file mode 100644 index 00000000..636a5bf2 --- /dev/null +++ b/OptimoveSDK/Sources/Classes/PreferenceCenter/OptimovePreferenceCenter.swift @@ -0,0 +1,239 @@ +import Foundation +import OptimoveCore + +public class OptimovePreferenceCenter { + enum Error: LocalizedError { + case alreadyInitialized + case notInitialized + case configurationIsMissing + + var errorDescription: String? { + switch self { + case .alreadyInitialized: + return "The PreferenceCenterSDK has already been initialized." + case .notInitialized: + return "Preference center has not been initialized." + case .configurationIsMissing: + return "Preference center configuration is missing, but the feauture was requested. Please provide valid credentials." + } + } + } + + private static var instance: OptimovePreferenceCenter? + private var networkClient: NetworkClient? + private var storage: OptimoveStorage? + + static var isSdkRunning: Bool { + return Optimove.getConfig()?.getPreferenceCenterConfig() != nil + } + + public enum ResultType { + case success + case errorUserNotSet + case errorCredentialsNotSet + case error + } + + public typealias PreferencesGetHandler = (_ result: ResultType, _ preferences: OptimovePC.Preferences?) -> Void + public typealias PreferencesSetHandler = (_ result: ResultType) -> Void + + public static func getInstance() throws -> OptimovePreferenceCenter { + guard let instance = instance else { + throw Error.notInitialized + } + return instance + } + + static func initialize(with optimoveConfig: OptimoveConfig, storage: OptimoveStorage, networkClient: NetworkClient) throws { + if instance !== nil, optimoveConfig.features.contains(.delayedConfiguration) { + guard optimoveConfig.preferenceCenterConfig != nil else { + throw Error.configurationIsMissing + } + return + } + + guard instance == nil else { + assertionFailure(Error.alreadyInitialized.localizedDescription) + throw Error.alreadyInitialized + } + + instance = OptimovePreferenceCenter(storage: storage, networkClient: networkClient) + } + + private init(storage: OptimoveStorage, networkClient: NetworkClient) { + self.networkClient = networkClient + self.storage = storage + } + + @available(iOS 13.0, *) + public func getPreferencesAsync(completion: @escaping PreferencesGetHandler) { + guard let config = Optimove.getConfig()?.getPreferenceCenterConfig() else { + Logger.error("Preference center credentials are not set") + completion(.errorCredentialsNotSet, nil) + return + } + + guard + let customerId = try? storage?.getCustomerID(), + let visitorId = try? storage?.getVisitorID(), + customerId != visitorId + else { + Logger.warn("Customer ID is not set") + completion(.errorUserNotSet, nil) + return + } + + Task { + do { + let request = try createGetPreferencesRequest(for: customerId, with: config) + + networkClient?.perform(request) { [self] result in + switch result { + case .success(let response): + do { + let preferences = try response.decode(to: OptimovePC.Preferences.self) + DispatchQueue.main.async { + completion(.success, preferences) + } + } catch { + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error, nil) + } + } + case .failure(let error): + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error, nil) + } + } + } + + } catch { + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error, nil) + } + } + } + } + private func createGetPreferencesRequest( + for customerId: String, + with config: PreferenceCenterConfig) throws -> NetworkRequest { + let (region, brandGroupId, tenantId) = getConfigValues(from: config) + + return NetworkRequest( + method: .get, + baseURL: URL(string: "https://preference-center-\(region).optimove.net")!, + path: "/api/v1/preferences", + headers: [ + HTTPHeader(field: .accept, value: .textplain), + HTTPHeader(field: .tenantId, value: .tenantId(id: tenantId)) + ], + queryItems: [ + URLQueryItem(name: "customerId", value: customerId), + URLQueryItem(name: "brandGroupId", value: brandGroupId) + ] + ) + } + + private func getConfigValues(from config: PreferenceCenterConfig) -> (region: String, brandGroupId: String, tenantId: String) { + let region = config.region + let brandGroupId = config.brandGroupId + let tenantId = config.tenantId.description + return (region, brandGroupId, tenantId) + } + + + @available(iOS 13.0, *) + public func setCustomerPreferencesAsync(completion: @escaping PreferencesSetHandler, updates: [OptimovePC.PreferenceUpdate]) { + guard let config = Optimove.getConfig()?.getPreferenceCenterConfig() else { + Logger.error("Preference center credentials are not set") + completion(.errorCredentialsNotSet) + return + } + + guard + let customerId = try? storage?.getCustomerID(), + let visitorId = try? storage?.getVisitorID(), + customerId != visitorId else { + Logger.warn("Customer ID is not set") + completion(.errorUserNotSet) + return + } + + Task { + do { + let request = try createSetPreferencesRequest(for: customerId, with: config, updates: updates) + + networkClient?.perform(request) { [self] result in + switch result { + case .success(let response): + do { + _ = try response.unwrap() + DispatchQueue.main.async { + completion(.success) + } + } catch { + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error) + } + } + case .failure(let error): + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error) + } + } + } + + } catch { + logFailedResponse(error) + DispatchQueue.main.async { + completion(.error) + } + } + } + } + + private func createSetPreferencesRequest( + for customerId: String, + with config: PreferenceCenterConfig, + updates: [OptimovePC.PreferenceUpdate]) throws -> NetworkRequest { + let (region, brandGroupId, tenantId) = getConfigValues(from: config) + + return try NetworkRequest( + method: .put, + baseURL: URL(string: "https://preference-center-\(region).optimove.net")!, + path: "/api/v1/preferences", + headers: [ + HTTPHeader(field: .accept, value: .textplain), + HTTPHeader(field: .tenantId, value: .tenantId(id: tenantId)) + ], + queryItems: [ + URLQueryItem(name: "customerId", value: customerId), + URLQueryItem(name: "brandGroupId", value: brandGroupId) + ], + body: updates + ) + } + + private func logFailedResponse(_ error: Swift.Error) { + Logger.error("Request failed with error: \(error.localizedDescription)") + } + + private func logFailedResponse(_ response: URLResponse) { + if let httpResponse = response as? HTTPURLResponse { + let code = httpResponse.statusCode; + let msg = "Request failed with code \(code): \(HTTPURLResponse.localizedString(forStatusCode: code))." + + switch httpResponse.statusCode { + case 400: + Logger.error("\(msg) Check preference center configuration"); + default: + Logger.error(msg) + } + } + } +} diff --git a/OptimoveSDK/Sources/Classes/Services/ServiceLocator.swift b/OptimoveSDK/Sources/Classes/Services/ServiceLocator.swift index fb893649..74cdb1f6 100644 --- a/OptimoveSDK/Sources/Classes/Services/ServiceLocator.swift +++ b/OptimoveSDK/Sources/Classes/Services/ServiceLocator.swift @@ -106,7 +106,6 @@ final class ServiceLocator { func deviceStateObserver() -> DeviceStateObserver { return _deviceStateObserver } - // MARK: - Factories func componentFactory() -> ComponentFactory { diff --git a/README.md b/README.md index b1ffa1a0..406b1949 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ In this guide we will go through the following steps necessary to have the basic 1. [Tracking custom events](https://github.com/optimove-tech/Optimove-SDK-iOS/wiki/Tracking-custom-events) 2. [Location and Beacons](https://github.com/optimove-tech/Optimove-SDK-iOS/wiki/Location-and-Beacons) +3. [Preference Center](https://github.com/optimove-tech/Optimove-SDK-iOS/wiki/Preference-Center) ## Mobile Messaging