From ef853d5b2ddfe671514cb00620645bb211f5a811 Mon Sep 17 00:00:00 2001 From: Alexey Goncharov Date: Tue, 26 Aug 2025 14:10:54 +0100 Subject: [PATCH 1/4] Onboardings: add support for webView.isInspectable (debug purposes) --- AdaptyUI/AdaptyUI+Onboardings.swift | 31 +++++++++++++++++-- .../Rendering/AdaptyOnboardingViewModel.swift | 12 ++++++- AdaptyUITesting/AdaptyUI+Testing.swift | 14 +++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/AdaptyUI/AdaptyUI+Onboardings.swift b/AdaptyUI/AdaptyUI+Onboardings.swift index 3bcf99696..2d70c61d5 100644 --- a/AdaptyUI/AdaptyUI+Onboardings.swift +++ b/AdaptyUI/AdaptyUI+Onboardings.swift @@ -20,13 +20,15 @@ public extension AdaptyUI { init( logId: String, - onboarding: AdaptyOnboarding + onboarding: AdaptyOnboarding, + inspectWebView: Bool ) { Log.ui.verbose("#\(logId)# init onboarding: \(onboarding.placement.id)") self.viewModel = AdaptyOnboardingViewModel( logId: logId, - onboarding: onboarding + onboarding: onboarding, + inspectWebView: inspectWebView ) } } @@ -47,7 +49,8 @@ public extension AdaptyUI { return OnboardingConfiguration( logId: Log.stamp, - onboarding: onboarding + onboarding: onboarding, + inspectWebView: false ) } @@ -71,4 +74,26 @@ public extension AdaptyUI { } } +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, visionOS 1.0, *) +@MainActor +package extension AdaptyUI { + static func getOnboardingConfiguration( + forOnboarding onboarding: AdaptyOnboarding, + inspectWebView: Bool + ) throws -> OnboardingConfiguration { + guard AdaptyUI.isActivated else { + let err = AdaptyUIError.adaptyNotActivated + Log.ui.error("AdaptyUI getViewConfiguration error: \(err)") + + throw err + } + + return OnboardingConfiguration( + logId: Log.stamp, + onboarding: onboarding, + inspectWebView: inspectWebView + ) + } +} + #endif diff --git a/AdaptyUI/Onboardings/Rendering/AdaptyOnboardingViewModel.swift b/AdaptyUI/Onboardings/Rendering/AdaptyOnboardingViewModel.swift index 15f8370e8..cc7df960f 100644 --- a/AdaptyUI/Onboardings/Rendering/AdaptyOnboardingViewModel.swift +++ b/AdaptyUI/Onboardings/Rendering/AdaptyOnboardingViewModel.swift @@ -20,14 +20,20 @@ private extension AdaptyUI { final class AdaptyOnboardingViewModel: ObservableObject { let logId: String let onboarding: AdaptyOnboarding + let inspectWebView: Bool var onMessage: ((AdaptyOnboardingsMessage) -> Void)? var onError: ((AdaptyUIError) -> Void)? private let webViewDelegate: AdaptyWebViewDelegate - init(logId: String, onboarding: AdaptyOnboarding) { + init( + logId: String, + onboarding: AdaptyOnboarding, + inspectWebView: Bool + ) { self.logId = logId self.onboarding = onboarding + self.inspectWebView = inspectWebView self.webViewDelegate = AdaptyWebViewDelegate(logId: logId) } @@ -49,6 +55,10 @@ final class AdaptyOnboardingViewModel: ObservableObject { webViewDelegate, name: AdaptyUI.webViewEventMessageName ) + + if #available(iOS 16.4, *) { + webView.isInspectable = inspectWebView + } self.webView = webView } diff --git a/AdaptyUITesting/AdaptyUI+Testing.swift b/AdaptyUITesting/AdaptyUI+Testing.swift index 7df188290..7c99a0b94 100644 --- a/AdaptyUITesting/AdaptyUI+Testing.swift +++ b/AdaptyUITesting/AdaptyUI+Testing.swift @@ -180,4 +180,18 @@ public extension View { } } +@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, visionOS 1.0, *) +@MainActor +public extension AdaptyUI { + static func getOnboardingConfigurationForTesting( + forOnboarding onboarding: AdaptyOnboarding, + inspectWebView: Bool + ) throws -> OnboardingConfiguration { + try AdaptyUI.getOnboardingConfiguration( + forOnboarding: onboarding, + inspectWebView: inspectWebView + ) + } +} + #endif From c99f45875b3228861063081a9bb6c5e6bb46a9e7 Mon Sep 17 00:00:00 2001 From: Aleksei Valiano Date: Tue, 2 Sep 2025 15:09:44 +0200 Subject: [PATCH 2/4] introduce CustomerIdentityParameters for cross-platform identity handling --- .../Requests/Request.Identify.swift | 6 ++--- Sources.AdaptyPlugin/cross_platform.yaml | 13 +++++++---- ...daptyConfiguration.Builder+Decodable.swift | 6 +++-- .../Entities/CustomerIdentityParameters.swift | 22 +++++++++++++++++++ 4 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 Sources/Profile/Entities/CustomerIdentityParameters.swift diff --git a/Sources.AdaptyPlugin/Requests/Request.Identify.swift b/Sources.AdaptyPlugin/Requests/Request.Identify.swift index b79c3854c..d11326809 100644 --- a/Sources.AdaptyPlugin/Requests/Request.Identify.swift +++ b/Sources.AdaptyPlugin/Requests/Request.Identify.swift @@ -13,15 +13,15 @@ extension Request { static let method = "identify" let customerUserId: String - let appAccountToken: UUID? + let parameters: CustomerIdentityParameters? enum CodingKeys: String, CodingKey { case customerUserId = "customer_user_id" - case appAccountToken = "app_account_token" + case parameters } func execute() async throws -> AdaptyJsonData { - try await Adapty.identify(customerUserId, withAppAccountToken: appAccountToken) + try await Adapty.identify(customerUserId, withAppAccountToken: parameters?.appAccountToken) return .success() } } diff --git a/Sources.AdaptyPlugin/cross_platform.yaml b/Sources.AdaptyPlugin/cross_platform.yaml index 26f4809b5..2a1a64593 100644 --- a/Sources.AdaptyPlugin/cross_platform.yaml +++ b/Sources.AdaptyPlugin/cross_platform.yaml @@ -288,7 +288,7 @@ $requests: properties: method: { const: "identify" } customer_user_id: { type: string } - app_account_token: { $ref: "#/$defs/UUID" } + parameters: { $ref: "#/$defs/CustomerIdentityParameters" } Identify.Response: #response type: object @@ -937,7 +937,7 @@ $defs: properties: api_key: { type: string } customer_user_id: { type: string } - app_account_token: { $ref: "#/$defs/UUID" , description: "used only if customer_user_id is not null"} + customer_identity_parameters: { $ref: "#/$defs/CustomerIdentityParameters" } observer_mode: { type: boolean, default: false } apple_idfa_collection_disabled: { type: boolean, default: false } google_adid_collection_disabled: { type: boolean, default: false } @@ -961,6 +961,13 @@ $defs: memory_storage_count_limit: { type: integer } disk_storage_size_limit: { type: integer, description: "bytes" } + CustomerIdentityParameters: #request + type: object + properties: + app_account_token: { $ref: "#/$defs/UUID", description: "iOS Only" } + obfuscated_account_id: { type: string, description: "Android Only" } + obfuscated_profile_id: { type: string, description: "Android Only" } + AdaptyPaywallProduct.Response: #response type: object required: @@ -1504,8 +1511,6 @@ $defs: description: "Android Only", } is_offer_personalized: { type: boolean, description: "Android Only" } - obfuscated_account_id: { type: string, description: "Android Only" } - obfuscated_profile_id: { type: string, description: "Android Only" } AdaptySubscriptionUpdateParameters: #request # Android Only diff --git a/Sources/Configuration/AdaptyConfiguration.Builder+Decodable.swift b/Sources/Configuration/AdaptyConfiguration.Builder+Decodable.swift index f245c14bb..d58f3fd75 100644 --- a/Sources/Configuration/AdaptyConfiguration.Builder+Decodable.swift +++ b/Sources/Configuration/AdaptyConfiguration.Builder+Decodable.swift @@ -11,7 +11,7 @@ extension AdaptyConfiguration.Builder: Decodable { private enum CodingKeys: String, CodingKey { case apiKey = "api_key" case customerUserId = "customer_user_id" - case appAccountToken = "app_account_token" + case customerIdentityParameters = "customer_identity_parameters" case observerMode = "observer_mode" case idfaCollectionDisabled = "apple_idfa_collection_disabled" case ipAddressCollectionDisabled = "ip_address_collection_disabled" @@ -50,10 +50,12 @@ extension AdaptyConfiguration.Builder: Decodable { nil } + let customerIdentityParameters = try container.decodeIfPresent(CustomerIdentityParameters.self, forKey: .customerIdentityParameters) + try self.init( apiKey: container.decode(String.self, forKey: .apiKey), customerUserId: container.decodeIfPresent(String.self, forKey: .customerUserId), - appAccountToken: container.decodeIfPresent(UUID.self, forKey: .appAccountToken), + appAccountToken: customerIdentityParameters?.appAccountToken, observerMode: container.decodeIfPresent(Bool.self, forKey: .observerMode), idfaCollectionDisabled: container.decodeIfPresent(Bool.self, forKey: .idfaCollectionDisabled), ipAddressCollectionDisabled: container.decodeIfPresent(Bool.self, forKey: .ipAddressCollectionDisabled), diff --git a/Sources/Profile/Entities/CustomerIdentityParameters.swift b/Sources/Profile/Entities/CustomerIdentityParameters.swift new file mode 100644 index 000000000..775bab6b7 --- /dev/null +++ b/Sources/Profile/Entities/CustomerIdentityParameters.swift @@ -0,0 +1,22 @@ +// +// CustomerIdentityParameters.swift +// AdaptySDK +// +// Created by Aleksei Valiano on 02.09.2025. +// +import Foundation + +package struct CustomerIdentityParameters { + package let appAccountToken: UUID? +} + +extension CustomerIdentityParameters: Decodable { + private enum CodingKeys: String, CodingKey { + case appAccountToken = "app_account_token" + } + + package init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.appAccountToken = try container.decodeIfPresent(UUID.self, forKey: .appAccountToken) + } +} From b634262bcaaa6efe1017344b025142b85268eb1c Mon Sep 17 00:00:00 2001 From: Alexey Goncharov Date: Tue, 23 Sep 2025 19:12:46 +0100 Subject: [PATCH 3/4] Update Readme.md --- README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fa1325f21..f1339dc71 100644 --- a/README.md +++ b/README.md @@ -81,14 +81,9 @@ Adapty.makePurchase(product: product) { [weak self] result in - View and analyze data by attributes, such as status, channels, campaigns, and more. - Filter, group, and measure metrics by attribution, platform, custom users' segments, and more in a few clicks. -## Examples of Adapty-Demo apps +## Adapty-Demo apps -This is a demo applications for Adapty. Before running the app, you will need to configure the project. - -### 1. [UIKit](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples/UIKit-Demo) -### 2. [SwiftUI](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples/SwiftUI-Demo) - -![Adapty: An example of the paywall is changed on the fly](https://adapty-portal-media-production.s3.amazonaws.com/github/swift-ui-example.jpg) +[Here](Examples/) you can find a demo application for Adapty. Before running the app, you will need to configure the project. ## Mobile App Monetization's Largest Community From a7056b3b179a02688988e321c46f2688c9e69d30 Mon Sep 17 00:00:00 2001 From: Aleksei Valiano Date: Wed, 24 Sep 2025 12:05:19 +0200 Subject: [PATCH 4/4] AdaptyPlugin: add google_enable_pending_prepaid_plans property in configuration --- Sources.AdaptyPlugin/cross_platform.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources.AdaptyPlugin/cross_platform.yaml b/Sources.AdaptyPlugin/cross_platform.yaml index 2a1a64593..e00fb9023 100644 --- a/Sources.AdaptyPlugin/cross_platform.yaml +++ b/Sources.AdaptyPlugin/cross_platform.yaml @@ -941,6 +941,7 @@ $defs: observer_mode: { type: boolean, default: false } apple_idfa_collection_disabled: { type: boolean, default: false } google_adid_collection_disabled: { type: boolean, default: false } + google_enable_pending_prepaid_plans: { type: boolean, default: false } ip_address_collection_disabled: { type: boolean, default: false } server_cluster: { type: string, enum: ["default", "eu", "cn"] } backend_base_url: { type: string }