diff --git a/CHANGELOG.md b/CHANGELOG.md index f80b5cf1d4..bc6b093a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup ### Enhancements - Adds microphone permission request support. +- Adds post purchase actions support. ## 4.12.4 diff --git a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessage.swift b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessage.swift index c2df39b06e..63d1777e82 100644 --- a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessage.swift +++ b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessage.swift @@ -51,7 +51,7 @@ enum PaywallMessage: Decodable, Equatable { case openUrlInSafari(_ url: URL) case openPaymentSheet(_ url: URL) case openDeepLink(url: URL) - case purchase(productId: String) + case purchase(productId: String, shouldDismiss: Bool) case custom(data: String) case customPlacement(name: String, params: JSON) case userAttributesUpdated(attributes: JSON) @@ -101,9 +101,11 @@ enum PaywallMessage: Decodable, Equatable { } // Everyone write to eventName, other may use the remaining keys + // Note: JSONDecoder.fromSnakeCase converts snake_case keys to camelCase automatically private enum CodingKeys: String, CodingKey { case messageType = "eventName" case productId = "productIdentifier" + case shouldDismiss case url case link case data @@ -141,7 +143,8 @@ enum PaywallMessage: Decodable, Equatable { return case .purchase: if let productId = try? values.decode(String.self, forKey: .productId) { - self = .purchase(productId: productId) + let shouldDismiss = try values.decodeIfPresent(Bool.self, forKey: .shouldDismiss) ?? true + self = .purchase(productId: productId, shouldDismiss: shouldDismiss) return } case .restore: diff --git a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandler.swift b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandler.swift index eead0d9d33..1d6773753a 100644 --- a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandler.swift +++ b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandler.swift @@ -126,16 +126,25 @@ final class PaywallMessageHandler: WebEventDelegate { await self.pass(placement: transactionStart, from: paywall) } case let .transactionComplete(trialEndDate, productIdentifier): - let freeTrialStart = SuperwallEventObjc.freeTrialStart.description Task { - var payload: [String: Any] = ["product_identifier": productIdentifier] + // Send transaction_complete to trigger post-purchase actions + let transactionComplete = SuperwallEventObjc.transactionComplete.description + await self.pass( + placement: transactionComplete, + from: paywall, + payload: ["product_identifier": productIdentifier] + ) + + // Send freeTrial_start for notification scheduling + let freeTrialStart = SuperwallEventObjc.freeTrialStart.description + var freeTrialPayload: [String: Any] = ["product_identifier": productIdentifier] if let trialEndDate { - payload["trial_end_date"] = Int(trialEndDate.timeIntervalSince1970 * 1000) + freeTrialPayload["trial_end_date"] = Int(trialEndDate.timeIntervalSince1970 * 1000) } await self.pass( placement: freeTrialStart, from: paywall, - payload: payload + payload: freeTrialPayload ) } case .transactionFail: @@ -163,8 +172,8 @@ final class PaywallMessageHandler: WebEventDelegate { openDeepLink(url) case .restore: restorePurchases() - case .purchase(productId: let id): - purchaseProduct(withId: id) + case let .purchase(productId: id, shouldDismiss: shouldDismiss): + purchaseProduct(withId: id, shouldDismiss: shouldDismiss) case .custom(data: let name): handleCustomEvent(name) case let .customPlacement(name: name, params: params): @@ -431,10 +440,18 @@ final class PaywallMessageHandler: WebEventDelegate { delegate?.eventDidOccur(.initiateRestore) } - private func purchaseProduct(withId id: String) { + private func purchaseProduct( + withId id: String, + shouldDismiss: Bool + ) { detectHiddenPaywallEvent("purchase") hapticFeedback() - delegate?.eventDidOccur(.initiatePurchase(productId: id)) + delegate?.eventDidOccur( + .initiatePurchase( + productId: id, + shouldDismiss: shouldDismiss + ) + ) } private func handleCustomEvent(_ customEvent: String) { diff --git a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallWebEvent.swift b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallWebEvent.swift index e8962e21d8..6c5ac9df4c 100644 --- a/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallWebEvent.swift +++ b/Sources/SuperwallKit/Paywall/View Controller/Web View/Message Handling/PaywallWebEvent.swift @@ -9,7 +9,10 @@ import Foundation enum PaywallWebEvent: Equatable { case closed - case initiatePurchase(productId: String) + case initiatePurchase( + productId: String, + shouldDismiss: Bool + ) case initiateRestore case custom(string: String) case openedURL(url: URL) diff --git a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/PurchaseSource.swift b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/PurchaseSource.swift index 4eec5096a8..c33f7f83fa 100644 --- a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/PurchaseSource.swift +++ b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/PurchaseSource.swift @@ -8,7 +8,7 @@ /// The source of the purchase initiation. enum PurchaseSource { /// The purchase was initiated internally by the SDK. - case `internal`(String, PaywallViewController) + case `internal`(String, PaywallViewController, Bool) /// The purchase was initiated externally by the user calling ``Superwall/purchase(_:)-7gwwe``. case purchaseFunc(StoreProduct) @@ -17,7 +17,7 @@ enum PurchaseSource { func toRestoreSource() -> RestoreSource { switch self { - case .internal(_, let paywallViewController): return .internal(paywallViewController) + case .internal(_, let paywallViewController, _): return .internal(paywallViewController) case .purchaseFunc: return .external case .observeFunc: return .external } diff --git a/Sources/SuperwallKit/StoreKit/Transactions/TransactionManager.swift b/Sources/SuperwallKit/StoreKit/Transactions/TransactionManager.swift index a2c7f52726..3585327e92 100644 --- a/Sources/SuperwallKit/StoreKit/Transactions/TransactionManager.swift +++ b/Sources/SuperwallKit/StoreKit/Transactions/TransactionManager.swift @@ -61,7 +61,7 @@ final class TransactionManager { let product: StoreProduct switch purchaseSource { - case .internal(let productId, _): + case .internal(let productId, _, _): guard let storeProduct = await storeKitManager.productsById[productId] else { Logger.debug( logLevel: .error, @@ -126,7 +126,7 @@ final class TransactionManager { case .observing: break case .purchasing(let purchaseSource): - if case let .internal(_, paywallViewController) = purchaseSource { + if case let .internal(_, paywallViewController, _) = purchaseSource { await paywallViewController.togglePaywallSpinner(isHidden: true) } } @@ -459,7 +459,7 @@ final class TransactionManager { } switch source { - case .internal(_, let paywallViewController): + case .internal(_, let paywallViewController, _): Logger.debug( logLevel: .debug, scope: .transactions, @@ -559,7 +559,7 @@ final class TransactionManager { let shouldTrackTransactionStart = !(purchaseManager.isUsingSK2 && isObserved) switch purchaseSource { - case .internal(_, let paywallViewController): + case .internal(_, let paywallViewController, _): Logger.debug( logLevel: .debug, scope: .transactions, @@ -633,7 +633,7 @@ final class TransactionManager { } switch source { - case .internal(_, let paywallViewController): + case let .internal(_, paywallViewController, shouldDismiss): guard let product = await coordinator.product else { return } @@ -658,12 +658,18 @@ final class TransactionManager { await trackTransactionDidSucceed(transaction) let superwallOptions = factory.makeSuperwallOptions() - if superwallOptions.paywalls.automaticallyDismiss { + let shouldDismissPaywall = superwallOptions.paywalls.automaticallyDismiss && shouldDismiss + if shouldDismissPaywall { await Superwall.shared.dismiss( paywallViewController, result: .purchased(product) ) } + if !shouldDismissPaywall { + await MainActor.run { + paywallViewController.togglePaywallSpinner(isHidden: true) + } + } case .purchaseFunc, .observeFunc: Logger.debug( @@ -704,7 +710,7 @@ final class TransactionManager { } switch source { - case .internal(_, let paywallViewController): + case .internal(_, let paywallViewController, _): Logger.debug( logLevel: .debug, scope: .transactions, @@ -764,7 +770,7 @@ final class TransactionManager { } switch source { - case .internal(_, let paywallViewController): + case .internal(_, let paywallViewController, _): Logger.debug( logLevel: .debug, scope: .transactions, @@ -894,7 +900,7 @@ final class TransactionManager { let eventSource: InternalSuperwallEvent.Transaction.Source let trialEndDate = product.trialPeriodEndDate switch source { - case .internal(_, let paywallViewController): + case .internal(_, let paywallViewController, _): paywallInfo = await paywallViewController.info eventSource = .internal await paywallViewController.webView.messageHandler diff --git a/Sources/SuperwallKit/Superwall.swift b/Sources/SuperwallKit/Superwall.swift index 5565306f96..6bb24562b9 100644 --- a/Sources/SuperwallKit/Superwall.swift +++ b/Sources/SuperwallKit/Superwall.swift @@ -1307,13 +1307,13 @@ extension Superwall: PaywallViewControllerEventDelegate { result: .declined, closeReason: .manualClose ) - case .initiatePurchase(let productId): + case let .initiatePurchase(productId, shouldDismiss): if purchaseTask != nil { return } purchaseTask = Task { await dependencyContainer.transactionManager.purchase( - .internal(productId, paywallViewController) + .internal(productId, paywallViewController, shouldDismiss) ) purchaseTask = nil } diff --git a/SuperwallKit.xcodeproj/project.pbxproj b/SuperwallKit.xcodeproj/project.pbxproj index 8e3c720db4..6a41395f8e 100644 --- a/SuperwallKit.xcodeproj/project.pbxproj +++ b/SuperwallKit.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 09AA071B4A67A6256D00BDD6 /* PaywallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 187934D3C89220C605299A17 /* PaywallManager.swift */; }; 0A0BD14265AA8CE75A84940E /* TaskCoalescer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7F90791145963999DDA319 /* TaskCoalescer.swift */; }; 0A1366F15DD3C1761C095DF5 /* SuperwallOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFDA311A030FDFC45AEE248A /* SuperwallOptions.swift */; }; + 0A35D3D8CCC8D043628A0A4F /* TrackingAuthorizationStatusConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC92F1146FA9FA76AF25227 /* TrackingAuthorizationStatusConversionTests.swift */; }; 0A5EFFC920E6BB29814BD66B /* Foundation+ASN1Coder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80281364A23252E30DEEA1AA /* Foundation+ASN1Coder.swift */; }; 0AB9CCC164DD87C81318AAB0 /* PublicIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4493EE88B00CADF85EF1196 /* PublicIdentity.swift */; }; 0B5A0C6EA2D1C98B32110FD9 /* NotificationScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C5DCFB58EF4DBC9084A6B89 /* NotificationScheduler.swift */; }; @@ -62,10 +63,12 @@ 1A6C6E6DAD8C0236FA24FF10 /* CheckNoPaywallAlreadyPresented.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582CE0C5BA6EA57C7FE3EE43 /* CheckNoPaywallAlreadyPresented.swift */; }; 1BA9EC022F0016E72A5EB01A /* PaywallPresentationRequestStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC211BFF9364E4B10418695B /* PaywallPresentationRequestStatus.swift */; }; 1BDB91B70EAEC10097941381 /* SWBounceButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 299F91895EE88281B5ED8320 /* SWBounceButton.swift */; }; + 1D27BDC498FDFA24FFFD49EB /* PermissionHandler+Microphone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFE48C68EEF60E63D5B39FD /* PermissionHandler+Microphone.swift */; }; 1E0D00DF75A6779C78145750 /* SurveyPresentationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B66B5A624F8A2E225EACA69 /* SurveyPresentationResult.swift */; }; 1E7EBE0C39AC302D9B5BFF27 /* PublicGameController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 010F0F8FCE0A86D8F2823A47 /* PublicGameController.swift */; }; 1E81A71ADE8A5EAD9E609E1D /* AppSessionManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B78FB9232236AF44369EA92 /* AppSessionManagerMock.swift */; }; 1F20D775BC035F8A75B79323 /* PaywallMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF61DCA9CF170E0AFC507BAE /* PaywallMessageHandler.swift */; }; + 1F9AE04458B942D070FC4832 /* FakeTrackingAuthorizationStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FE43B98D847BB6DE291F0B4 /* FakeTrackingAuthorizationStatusTests.swift */; }; 1FB66F276E4FD5AEC37EC14A /* ContactStoreProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F35F68AF572F7CDF174320C /* ContactStoreProxy.swift */; }; 1FFADB97F7E05549750E14E9 /* TaskExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A21ED2D8CB4DDA70E228E8BC /* TaskExecutor.swift */; }; 205B0A0F4179E2680B07172D /* WebArchiveManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5180737863E22145980065 /* WebArchiveManager.swift */; }; @@ -316,7 +319,9 @@ A73497BB3DCD881318A5CD86 /* ConfigLogicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97D7F499B2CBFFF0A61F8D72 /* ConfigLogicTests.swift */; }; A74BBEF8CCF5A35AB19BB70C /* ProductPurchaserLogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A413B6FF46B130D90A428B4 /* ProductPurchaserLogic.swift */; }; A78DC9BD71DD85831025D620 /* SuperwallGraveyard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36898353ABCE620BA7AEE59 /* SuperwallGraveyard.swift */; }; + A7D83FE18FC0A70BCD5A3B2C /* PermissionsHandler+Tracking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20DA18E503D82C213BC5567B /* PermissionsHandler+Tracking.swift */; }; A8B37372F3F4ED9FAD76CE87 /* PostbackAssignmentWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0D2AB91DA66490A73D1CB5 /* PostbackAssignmentWrapper.swift */; }; + A9B924A1211117378743A534 /* MicrophonePermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABD045A5C4A47B1CA9365285 /* MicrophonePermissionTests.swift */; }; A9F9A35AEC72D17C7C15DAD4 /* PaywallArchiveManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB580546C647ED707C43FEC /* PaywallArchiveManager.swift */; }; AA86FF87863EB7A7917969D3 /* PermissionHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D0B6F781D32B2DCDBE689C /* PermissionHandling.swift */; }; AACC7BEE37DDDD7068A1E48C /* TransactionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646E6799FE4934BF76A06F34 /* TransactionManager.swift */; }; @@ -334,6 +339,7 @@ B0AD4A89AD5101360F93652D /* SubscriptionTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ACDC7427B6340E9D86F9B0F /* SubscriptionTransaction.swift */; }; B0B0AD9409CEFE7CA8225146 /* Array+SafeRemove.swift in Sources */ = {isa = PBXBuildFile; fileRef = C855DE8F5341D67C614E3AF5 /* Array+SafeRemove.swift */; }; B0DC8290B081B74CC65E9305 /* CELEvaluatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79E9DBDDA7FEE63C15FBEAF /* CELEvaluatorTests.swift */; }; + B0F7F66E24C7AEDE460F34FE /* FakeTrackingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F38AD737B1CFECEB2AAF85 /* FakeTrackingManager.swift */; }; B10030CC414C2C341487F4B8 /* PaywallViewControllerDelegateAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 990461F7A9B2F3ED62B3A628 /* PaywallViewControllerDelegateAdapter.swift */; }; B146C134ABE092C3C9ACADEC /* PurchaseResult+Internal.swift in Sources */ = {isa = PBXBuildFile; fileRef = A524F7AAE90E48C3B8D7E99A /* PurchaseResult+Internal.swift */; }; B15607185B9E4229C6C4F240 /* SK2StoreTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B96E2A1A289D96267EC0BC /* SK2StoreTransaction.swift */; }; @@ -345,6 +351,7 @@ B49470D3579E0050818348A7 /* PlacementsQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3CE3353B30F2484EFE283E /* PlacementsQueue.swift */; }; B4C9FECB4894151E42A34F85 /* Date+TimeIntervalMilliseconds.swift in Sources */ = {isa = PBXBuildFile; fileRef = E51D0B38180377D9CD3E65DA /* Date+TimeIntervalMilliseconds.swift */; }; B5647878BFFEBFCC0D009E12 /* PermissionHandler+Photos.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB80534B838976548EFB8562 /* PermissionHandler+Photos.swift */; }; + B56EAF200278DBF3F92A4D97 /* PostPurchaseAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA3EAC5E77EBEBD621354601 /* PostPurchaseAction.swift */; }; B5AE7BCDCB6D49FC8493D55B /* DecodingError+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EDC14C0D6958144679F149D /* DecodingError+Extensions.swift */; }; B5B83CE0D021A82950A51C47 /* String+CamelCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16AFE9C93A441CFB6A95F10 /* String+CamelCase.swift */; }; B60C3A3AD25CE2E2C513A2D2 /* Stubbable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3BFF03C1812D7239003448A /* Stubbable.swift */; }; @@ -358,6 +365,7 @@ BBC0ADE1AAB3E8C2DC5E4F01 /* ASN1Decoder+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B17A8801A2A9454E66D892 /* ASN1Decoder+Utils.swift */; }; BC526F821C0BDAC76D7B3769 /* LocationAuthorizationStatusConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD9CFF209DA6B8B42B405D20 /* LocationAuthorizationStatusConversionTests.swift */; }; BC8A62869C7BACE6D0867195 /* AssignmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7180900DD0767487E671639 /* AssignmentTests.swift */; }; + BCD5EA74E59F7BC43B0816C5 /* TrackingManagerProxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8E506778E9750512E9F9D3 /* TrackingManagerProxyTests.swift */; }; BCF808C7AC319C2B1F0AD52D /* ConfigResponseLogicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4827295A4E093CAEE2207DDF /* ConfigResponseLogicTests.swift */; }; BCFF20903199DDDE379D81E0 /* InAppReceiptPayloadContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 862888AB2869D09AA55A017D /* InAppReceiptPayloadContainer.swift */; }; BD152F3BA0BC197A5C6C8CC1 /* InAppReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0695B39826F85AACBA833B77 /* InAppReceipt.swift */; }; @@ -408,6 +416,7 @@ CE411644469AB99AC9DBB492 /* SWWebViewLoadingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D9545633A97A2E63FEDF78A /* SWWebViewLoadingHandler.swift */; }; CE43399599386456DCCD1FDC /* FakeLocationAuthorizationStatusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3529B422EB2D09B69265B591 /* FakeLocationAuthorizationStatusTests.swift */; }; CE5307A037FCFD8CB8380EB5 /* GetPaywallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3781CF21200CD2333F6779A /* GetPaywallManager.swift */; }; + CE821667CB6676EA02510FE9 /* TrackingManagerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A78C5C57C3C92444EBAC2E38 /* TrackingManagerProxy.swift */; }; CF2064883604B915C8768FC5 /* ASIdManagerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF989B3D90DC3D88FACC4D45 /* ASIdManagerProxy.swift */; }; CF3683E2AD703237EC0CE22E /* PaywallProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C95DABA23C6CBEF0AAA63C0 /* PaywallProducts.swift */; }; CFEB0D797815E8EDFB059767 /* Superwall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F7EDB6D68D0AEDD332E40BB /* Superwall.swift */; }; @@ -464,6 +473,7 @@ E95C8C0485512D77E37703C5 /* ASN1Templates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AFD6EE9BED296D075A9618 /* ASN1Templates.swift */; }; E984458E465D5A834CC52302 /* CacheMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67602AF9B2543CAD0B42F3CF /* CacheMock.swift */; }; E986B0CF98B8C09AAA961E94 /* AppSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC89718EBDD71E09AB5F41DA /* AppSessionManager.swift */; }; + E9D95044254D79D2439D7B3E /* FakeTrackingAuthorizationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 019FA4010BA11D24C68B8544 /* FakeTrackingAuthorizationStatus.swift */; }; E9E0BD599F353CC471B7A546 /* PresentationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00CE1D40C874F73A3BEC090 /* PresentationInfo.swift */; }; E9F80BA7BCAB71270E0E1CC1 /* AttributionFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64EAB177118BC78B02C3C00A /* AttributionFetcher.swift */; }; EB1964816A8297CE133F96BF /* PurchaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E522F5BCABB3A95B97549E /* PurchaseError.swift */; }; @@ -535,6 +545,7 @@ 00736909A4B4A1C2F2C356BC /* Sk1StoreProduct.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sk1StoreProduct.swift; sourceTree = ""; }; 010F0F8FCE0A86D8F2823A47 /* PublicGameController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicGameController.swift; sourceTree = ""; }; 018F5856F39FC33AFE9740D4 /* ConfirmHoldoutAssignmentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmHoldoutAssignmentTests.swift; sourceTree = ""; }; + 019FA4010BA11D24C68B8544 /* FakeTrackingAuthorizationStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeTrackingAuthorizationStatus.swift; sourceTree = ""; }; 01E54BC1CA38F828AC77F774 /* PublicPresentation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicPresentation.swift; sourceTree = ""; }; 03347D6B3B672A878CA2A7CA /* SurveyOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurveyOption.swift; sourceTree = ""; }; 03471273DF4C875227102BE2 /* ReceiptManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptManagerTests.swift; sourceTree = ""; }; @@ -583,11 +594,13 @@ 1B1A6ADFFB9FA982BF69C134 /* MockSKPaymentTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSKPaymentTransaction.swift; sourceTree = ""; }; 1B78FB9232236AF44369EA92 /* AppSessionManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSessionManagerMock.swift; sourceTree = ""; }; 1C16CBCBF2093DD9C5F3E105 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; + 1CC92F1146FA9FA76AF25227 /* TrackingAuthorizationStatusConversionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackingAuthorizationStatusConversionTests.swift; sourceTree = ""; }; 1D275ED98D2EE298F06708AF /* UIWindow+SwizzleSendEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+SwizzleSendEvent.swift"; sourceTree = ""; }; 1EBE35B7BB7FEBE02C8992D8 /* EntitlementsResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntitlementsResponse.swift; sourceTree = ""; }; 2031E7FE7D2ECC7AFF8519AE /* CustomerInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomerInfo.swift; sourceTree = ""; }; 20365697A9C396E8EC746B77 /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = ""; }; 20419CBCAD8CE28ADDD55E57 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; + 20DA18E503D82C213BC5567B /* PermissionsHandler+Tracking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PermissionsHandler+Tracking.swift"; sourceTree = ""; }; 2123B84F5C786278E128152D /* OccurrenceLogicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OccurrenceLogicTests.swift; sourceTree = ""; }; 214622367ACC8F66EB392105 /* AppSessionLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSessionLogic.swift; sourceTree = ""; }; 21903EACCA9AA13BB10917EC /* PermissionHandler+Camera.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PermissionHandler+Camera.swift"; sourceTree = ""; }; @@ -704,6 +717,7 @@ 5C2E30544869C5469AA31832 /* FactoryProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FactoryProtocols.swift; sourceTree = ""; }; 5C57C1CCAF97244AE0DC953F /* PaywallManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallManagerMock.swift; sourceTree = ""; }; 5CD130C74880AD07DCD2A7AA /* RedemptionResultObjc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedemptionResultObjc.swift; sourceTree = ""; }; + 5CFE48C68EEF60E63D5B39FD /* PermissionHandler+Microphone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PermissionHandler+Microphone.swift"; sourceTree = ""; }; 5D44CEC91693B4B900472C1C /* Survey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Survey.swift; sourceTree = ""; }; 5DD4E7007670C369DD8FF5D9 /* Date+IsWithinAnHourBeforeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+IsWithinAnHourBeforeTests.swift"; sourceTree = ""; }; 5EB5A772C1F2ECE6D0E0BD69 /* PaywallState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallState.swift; sourceTree = ""; }; @@ -777,6 +791,7 @@ 7B921746BEC8F63DDB65C634 /* LimitedQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LimitedQueue.swift; sourceTree = ""; }; 7E27997BBCEAC330E4FB3718 /* pt_BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt_BR; path = pt_BR.lproj/Localizable.strings; sourceTree = ""; }; 7FCE6A59348C9018F40D7AC5 /* LogScope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogScope.swift; sourceTree = ""; }; + 7FE43B98D847BB6DE291F0B4 /* FakeTrackingAuthorizationStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeTrackingAuthorizationStatusTests.swift; sourceTree = ""; }; 8012E350CCE22B0D892E0F96 /* PaywallManagerLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallManagerLogic.swift; sourceTree = ""; }; 80281364A23252E30DEEA1AA /* Foundation+ASN1Coder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Foundation+ASN1Coder.swift"; sourceTree = ""; }; 8087A8CD8F4FC7C745010428 /* ASN1Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASN1Types.swift; sourceTree = ""; }; @@ -871,6 +886,7 @@ A524F7AAE90E48C3B8D7E99A /* PurchaseResult+Internal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PurchaseResult+Internal.swift"; sourceTree = ""; }; A5C4AD6349F2D432132F36D5 /* MockSubscriptionPeriod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSubscriptionPeriod.swift; sourceTree = ""; }; A6B47DD5F59411CC529CD2DB /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; + A78C5C57C3C92444EBAC2E38 /* TrackingManagerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackingManagerProxy.swift; sourceTree = ""; }; A79E9DBDDA7FEE63C15FBEAF /* CELEvaluatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CELEvaluatorTests.swift; sourceTree = ""; }; A7C3FC26DCBF604D7319FBB2 /* zh_Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_Hant; path = zh_Hant.lproj/Localizable.strings; sourceTree = ""; }; A7D0B6F781D32B2DCDBE689C /* PermissionHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionHandling.swift; sourceTree = ""; }; @@ -881,6 +897,7 @@ AB3DC90549C10EDA52D96FF2 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; AB3F04AC933701EE33F5F325 /* IdentityLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityLogic.swift; sourceTree = ""; }; ABC1253C6D5DD8D967BE05D1 /* LocalizationGrouping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationGrouping.swift; sourceTree = ""; }; + ABD045A5C4A47B1CA9365285 /* MicrophonePermissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrophonePermissionTests.swift; sourceTree = ""; }; AC11F0D5B6B8A0F5EC5D200B /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; AC74F16DC5A17489E97061EA /* PushTransitionLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushTransitionLogic.swift; sourceTree = ""; }; AD23BBF9EA198ED8798A8F62 /* SystemInfo+NotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SystemInfo+NotificationName.swift"; sourceTree = ""; }; @@ -925,6 +942,7 @@ BBB580546C647ED707C43FEC /* PaywallArchiveManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallArchiveManager.swift; sourceTree = ""; }; BC211BFF9364E4B10418695B /* PaywallPresentationRequestStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallPresentationRequestStatus.swift; sourceTree = ""; }; BC8730F0D05BFDFA12AA6309 /* ProductVariable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductVariable.swift; sourceTree = ""; }; + BC8E506778E9750512E9F9D3 /* TrackingManagerProxyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackingManagerProxyTests.swift; sourceTree = ""; }; BCC728E79E36A4CDD87F3078 /* WebArchiveFileSytemManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebArchiveFileSytemManager.swift; sourceTree = ""; }; BD47D43BBBB5026D0913F5D8 /* MockSuperwallDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSuperwallDelegate.swift; sourceTree = ""; }; BD6BA222CB2EAA4B65F362C5 /* ProductsFetcherSK1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsFetcherSK1.swift; sourceTree = ""; }; @@ -963,6 +981,7 @@ C8EE9572F945C698DE4A2EAA /* InternallySetSubscriptionStatusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternallySetSubscriptionStatusTests.swift; sourceTree = ""; }; C937320625239F3E10FE8D8E /* PermissionsHandler+Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PermissionsHandler+Location.swift"; sourceTree = ""; }; C9B0C261DCC1ED74DD2BF3EA /* HiddenListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenListener.swift; sourceTree = ""; }; + CA3EAC5E77EBEBD621354601 /* PostPurchaseAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostPurchaseAction.swift; sourceTree = ""; }; CA65A320EE640CDB878F43E9 /* UIWindow+Landscape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Landscape.swift"; sourceTree = ""; }; CB8384E2DB0A3627BE1CCB7D /* PurchasingCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurchasingCoordinator.swift; sourceTree = ""; }; CB96F8411D5C857311D7811C /* TransactionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionType.swift; sourceTree = ""; }; @@ -994,6 +1013,7 @@ D5E2D026C30691F11D4E839F /* SurveyShowCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SurveyShowCondition.swift; sourceTree = ""; }; D6340ACDA40937ACAC66FA3D /* EntitlementPriorityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntitlementPriorityTests.swift; sourceTree = ""; }; D69BCC259F5FBE15AB02D662 /* PermissionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionHandler.swift; sourceTree = ""; }; + D6F38AD737B1CFECEB2AAF85 /* FakeTrackingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeTrackingManager.swift; sourceTree = ""; }; D7E232690489360042465DB2 /* Redeemable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Redeemable.swift; sourceTree = ""; }; D81D656CEA8B5B86458038D4 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = ""; }; D86C79B54278BF17FB1117E1 /* AudienceAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudienceAttributes.swift; sourceTree = ""; }; @@ -1240,6 +1260,17 @@ path = Operators; sourceTree = ""; }; + 159A87C9E66CFD7D70842652 /* Tracking */ = { + isa = PBXGroup; + children = ( + 019FA4010BA11D24C68B8544 /* FakeTrackingAuthorizationStatus.swift */, + D6F38AD737B1CFECEB2AAF85 /* FakeTrackingManager.swift */, + 20DA18E503D82C213BC5567B /* PermissionsHandler+Tracking.swift */, + A78C5C57C3C92444EBAC2E38 /* TrackingManagerProxy.swift */, + ); + path = Tracking; + sourceTree = ""; + }; 167BF9144FB641160A5BAAF8 /* App Session */ = { isa = PBXGroup; children = ( @@ -1332,9 +1363,11 @@ 22C5DE2B5BC6FC31BF31137D /* Permissions */ = { isa = PBXGroup; children = ( + ABD045A5C4A47B1CA9365285 /* MicrophonePermissionTests.swift */, 988E0E3F8D992744C9AC196F /* PermissionStatusTests.swift */, DFD2580D6C95C96CC3051BCB /* PermissionTypeTests.swift */, 8E656889D53C36053C472FF2 /* Location */, + 267D9A6611768B7308E16E21 /* Tracking */, ); path = Permissions; sourceTree = ""; @@ -1360,6 +1393,16 @@ path = Web2App; sourceTree = ""; }; + 267D9A6611768B7308E16E21 /* Tracking */ = { + isa = PBXGroup; + children = ( + 7FE43B98D847BB6DE291F0B4 /* FakeTrackingAuthorizationStatusTests.swift */, + 1CC92F1146FA9FA76AF25227 /* TrackingAuthorizationStatusConversionTests.swift */, + BC8E506778E9750512E9F9D3 /* TrackingManagerProxyTests.swift */, + ); + path = Tracking; + sourceTree = ""; + }; 29AF8407DB4560B41050C02F /* Web View */ = { isa = PBXGroup; children = ( @@ -1461,10 +1504,12 @@ isa = PBXGroup; children = ( 21903EACCA9AA13BB10917EC /* PermissionHandler+Camera.swift */, + 5CFE48C68EEF60E63D5B39FD /* PermissionHandler+Microphone.swift */, 405C59153A88E6B9D664585A /* PermissionHandler+Notification.swift */, BB80534B838976548EFB8562 /* PermissionHandler+Photos.swift */, 96687FD52B8221BB9EB0056D /* Contacts */, 4642DD08A5F9649FD8B6BD3B /* Location */, + 159A87C9E66CFD7D70842652 /* Tracking */, ); path = Handlers; sourceTree = ""; @@ -2812,6 +2857,7 @@ CC653A44D9B40812BDDD94E7 /* PaywallMessage.swift */, BF61DCA9CF170E0AFC507BAE /* PaywallMessageHandler.swift */, 260AE52B33B132D5A5C04911 /* PaywallWebEvent.swift */, + CA3EAC5E77EBEBD621354601 /* PostPurchaseAction.swift */, 0C39015ED9E8F5D9F0F78F1E /* RawWebMessageHandler.swift */, ); path = "Message Handling"; @@ -3025,6 +3071,7 @@ 158EBAAC2A96F73B93C48E15 /* ExpressionEvaluatorMock.swift in Sources */, 77ED3D92C176CC6D93D625B2 /* ExpressionLogicTests.swift in Sources */, CE43399599386456DCCD1FDC /* FakeLocationAuthorizationStatusTests.swift in Sources */, + 1F9AE04458B942D070FC4832 /* FakeTrackingAuthorizationStatusTests.swift in Sources */, AC7D527612F631AAADC7D225 /* FileManagerMigratorTests.swift in Sources */, D4B5A9708204AB6D58904733 /* GetPaywallVcOperatorTests.swift in Sources */, 64B962A8B59ACE514B0E48AE /* GetPresenterOperatorTests.swift in Sources */, @@ -3038,6 +3085,7 @@ 2BEA633247B24641D45A808C /* LocationManagerProxyTests.swift in Sources */, 40314E44991DCB66B4572C25 /* LocationPermissionDelegateTests.swift in Sources */, 4DE01655FC4CC148DD3D161C /* LoggerMock.swift in Sources */, + A9B924A1211117378743A534 /* MicrophonePermissionTests.swift in Sources */, B294572426111EC04F225289 /* MockExternalPurchaseControllerFactory.swift in Sources */, BA957415E2E1A38A25550B99 /* MockIntroductoryPeriod.swift in Sources */, 2ACC44D24F97934B1CBFC2B3 /* MockPurchaseController.swift in Sources */, @@ -3085,7 +3133,9 @@ 14D8827BA663A0EFD64DEC2C /* TemplateLogicTests.swift in Sources */, 7D47BABD89CE33CDD78DFCC6 /* TestFileManager.swift in Sources */, 4AA4E2CE223DC7CF1678E83C /* TrackTests.swift in Sources */, + 0A35D3D8CCC8D043628A0A4F /* TrackingAuthorizationStatusConversionTests.swift in Sources */, 9304297F3B76DB512F2F9D53 /* TrackingLogicTests.swift in Sources */, + BCD5EA74E59F7BC43B0816C5 /* TrackingManagerProxyTests.swift in Sources */, 744F0D34C800E17CF8462820 /* URLSessionRetryLogicTests.swift in Sources */, 8B200F99B71D706D45948339 /* Utils.swift in Sources */, 6C98C5DAAC3F493511A57AC3 /* WaitForEntitlementsAndConfigTests.swift in Sources */, @@ -3205,6 +3255,8 @@ BF47C2693495CB8C9DAD7C8D /* FakeContactsStore.swift in Sources */, 11798EDE58E5D225E5414F2E /* FakeLocationAuthorizationStatus.swift in Sources */, BD6ABB9DB883BC62D2407392 /* FakeLocationManager.swift in Sources */, + E9D95044254D79D2439D7B3E /* FakeTrackingAuthorizationStatus.swift in Sources */, + B0F7F66E24C7AEDE460F34FE /* FakeTrackingManager.swift in Sources */, E0F3648081AB86077201EB5D /* FeatureFlags.swift in Sources */, ED1C693657DA7FCBAE2DDDC6 /* FeatureGatingBehaviour.swift in Sources */, 767974DF68CE67AE2066E3D6 /* FileManagerMigrator.swift in Sources */, @@ -3311,6 +3363,7 @@ 3824D48F8E0AF35EEBED8FF4 /* PaywallViewControllerWrapper.swift in Sources */, BF9ADF5761C34F584EC416B1 /* PaywallWebEvent.swift in Sources */, E4A66E2235F7FE594EA82A06 /* PermissionHandler+Camera.swift in Sources */, + 1D27BDC498FDFA24FFFD49EB /* PermissionHandler+Microphone.swift in Sources */, 746FCA3A2499F7BAF653F205 /* PermissionHandler+Notification.swift in Sources */, B5647878BFFEBFCC0D009E12 /* PermissionHandler+Photos.swift in Sources */, FC7A0F08E317F745C3C46E51 /* PermissionHandler.swift in Sources */, @@ -3319,10 +3372,12 @@ 774699D4CCD6952F124FE333 /* PermissionType.swift in Sources */, 2D3950C4F1623B062FF3107D /* PermissionsHandler+Contacts.swift in Sources */, F2124CF2BE35ABD284EDCC45 /* PermissionsHandler+Location.swift in Sources */, + A7D83FE18FC0A70BCD5A3B2C /* PermissionsHandler+Tracking.swift in Sources */, B49470D3579E0050818348A7 /* PlacementsQueue.swift in Sources */, FA677CF601A228D5B485FFDE /* PopupTransition.swift in Sources */, 11719638C88CFCA506264531 /* PopupTransitionDelegate.swift in Sources */, E4500792C310C7758974A9CF /* PopupTransitionLogic.swift in Sources */, + B56EAF200278DBF3F92A4D97 /* PostPurchaseAction.swift in Sources */, BFF61333B8B38F56FC6AF44B /* PostbackAssignment.swift in Sources */, A8B37372F3F4ED9FAD76CE87 /* PostbackAssignmentWrapper.swift in Sources */, 30113C71D033ADDF01214C75 /* PreloadingDisabled.swift in Sources */, @@ -3450,6 +3505,7 @@ 78113F737BA99A2848850904 /* TrackableSuperwallEvent.swift in Sources */, BDECE549960DB9A5662939BE /* Tracking.swift in Sources */, E3F2F347326B8D206D341FB6 /* TrackingLogic.swift in Sources */, + CE821667CB6676EA02510FE9 /* TrackingManagerProxy.swift in Sources */, 369677E9A6E8754CFD20714D /* TrackingParameters.swift in Sources */, D0E19F665C7B230BF3FA122D /* TrackingResult.swift in Sources */, 8ACC4731031DA94C709915CF /* Transaction+LatestSince.swift in Sources */, diff --git a/Tests/SuperwallKitTests/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandlerTests.swift b/Tests/SuperwallKitTests/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandlerTests.swift index d2bdf55b23..e72853f3da 100644 --- a/Tests/SuperwallKitTests/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandlerTests.swift +++ b/Tests/SuperwallKitTests/Paywall/View Controller/Web View/Message Handling/PaywallMessageHandlerTests.swift @@ -266,9 +266,12 @@ struct PaywallMessageHandlerTests { ) messageHandler.delegate = delegate let productId = "abc" - messageHandler.handle(.purchase(productId: productId)) + messageHandler.handle(.purchase(productId: productId, shouldDismiss: true)) - #expect(delegate.eventDidOccur == .initiatePurchase(productId: productId)) + #expect(delegate.eventDidOccur == .initiatePurchase( + productId: productId, + shouldDismiss: true + )) } @Test @@ -386,4 +389,83 @@ struct PaywallMessageHandlerTests { #expect(fakePermissions.requestedPermissions == [.notification]) #expect(webView.willHandleJs == true) // Should have sent permission_result back } + + // MARK: - Purchase Message Decoding Tests + + @Test + func decodePurchase_noShouldDismiss_defaultsToTrue() throws { + let json = """ + { + "version": 1, + "payload": { + "events": [ + { + "eventName": "purchase", + "productIdentifier": "com.test.product" + } + ] + } + } + """ + let data = json.data(using: .utf8)! + let wrapped = try JSONDecoder.fromSnakeCase.decode(WrappedPaywallMessages.self, from: data) + let message = wrapped.payload.messages.first + + #expect(message == .purchase( + productId: "com.test.product", + shouldDismiss: true + )) + } + + @Test + func decodePurchase_shouldDismissFalse() throws { + let json = """ + { + "version": 1, + "payload": { + "events": [ + { + "eventName": "purchase", + "productIdentifier": "com.test.product", + "should_dismiss": false + } + ] + } + } + """ + let data = json.data(using: .utf8)! + let wrapped = try JSONDecoder.fromSnakeCase.decode(WrappedPaywallMessages.self, from: data) + let message = wrapped.payload.messages.first + + #expect(message == .purchase( + productId: "com.test.product", + shouldDismiss: false + )) + } + + @Test + func decodePurchase_shouldDismissTrue() throws { + let json = """ + { + "version": 1, + "payload": { + "events": [ + { + "eventName": "purchase", + "productIdentifier": "com.test.product", + "should_dismiss": true + } + ] + } + } + """ + let data = json.data(using: .utf8)! + let wrapped = try JSONDecoder.fromSnakeCase.decode(WrappedPaywallMessages.self, from: data) + let message = wrapped.payload.messages.first + + #expect(message == .purchase( + productId: "com.test.product", + shouldDismiss: true + )) + } }