diff --git a/RevenueCatUI/Data/TemplateViewConfiguration.swift b/RevenueCatUI/Data/TemplateViewConfiguration.swift index 08df0a0582..7788ece8be 100644 --- a/RevenueCatUI/Data/TemplateViewConfiguration.swift +++ b/RevenueCatUI/Data/TemplateViewConfiguration.swift @@ -46,7 +46,7 @@ extension TemplateViewConfiguration { enum PackageConfiguration: Equatable { case single(Package) - case multiple(first: Package, all: [Package]) + case multiple(first: Package, default: Package, all: [Package]) } @@ -62,21 +62,31 @@ extension TemplateViewConfiguration.PackageConfiguration { switch self { case let .single(package): return package - case let .multiple(first, _): + case let .multiple(first, _, _): return first } } - /// Returns all packages, useful for templates that expect multiple packages + /// Returns all packages, useful for templates that expect multiple packages. var all: [TemplateViewConfiguration.Package] { switch self { case let .single(package): return [package] - case let .multiple(_, packages): + case let .multiple(_, _, packages): return packages } } + /// Returns the package to be selected by default. + var `default`: TemplateViewConfiguration.Package { + switch self { + case let .single(package): + return package + case let .multiple(_, defaultPackage, _): + return defaultPackage + } + } + } // MARK: - Creation @@ -89,6 +99,7 @@ extension TemplateViewConfiguration.PackageConfiguration { static func create( with packages: [RevenueCat.Package], filter: [PackageType], + default: PackageType?, localization: PaywallData.LocalizedConfiguration, setting: TemplateViewConfiguration.PackageSetting, locale: Locale = .current @@ -113,7 +124,13 @@ extension TemplateViewConfiguration.PackageConfiguration { case .single: return .single(firstPackage) case .multiple: - return .multiple(first: firstPackage, all: filtered) + let defaultPackage = filtered + .first { $0.content.packageType == `default` } + ?? firstPackage + + return .multiple(first: firstPackage, + default: defaultPackage, + all: filtered) } } diff --git a/RevenueCatUI/Templates/MultiPackageTemplate.swift b/RevenueCatUI/Templates/MultiPackageTemplate.swift index e0508b69bd..38f67620e2 100644 --- a/RevenueCatUI/Templates/MultiPackageTemplate.swift +++ b/RevenueCatUI/Templates/MultiPackageTemplate.swift @@ -44,7 +44,7 @@ private struct MultiPackageTemplateContent: View { private var dismiss init(configuration: TemplateViewConfiguration, introEligibility: [Package: IntroEligibilityStatus]) { - self._selectedPackage = .init(initialValue: configuration.packages.single.content) + self._selectedPackage = .init(initialValue: configuration.packages.default.content) self.configuration = configuration self.introEligibility = introEligibility diff --git a/RevenueCatUI/Templates/TemplateViewType.swift b/RevenueCatUI/Templates/TemplateViewType.swift index f5cbf80490..ab494fa4a6 100644 --- a/RevenueCatUI/Templates/TemplateViewType.swift +++ b/RevenueCatUI/Templates/TemplateViewType.swift @@ -54,6 +54,7 @@ extension PaywallData { mode: mode, packages: try .create(with: offering.availablePackages, filter: self.config.packages, + default: self.config.defaultPackage, localization: self.localizedConfiguration, setting: self.template.packageSetting, locale: locale), diff --git a/Sources/Paywalls/PaywallData.swift b/Sources/Paywalls/PaywallData.swift index b236f8ca60..2d2f88532a 100644 --- a/Sources/Paywalls/PaywallData.swift +++ b/Sources/Paywalls/PaywallData.swift @@ -11,6 +11,8 @@ // // Created by Nacho Soto on 7/10/23. +// swiftlint:disable file_length + import Foundation /// The data necessary to display a paywall using the `RevenueCatUI` library. @@ -141,6 +143,9 @@ extension PaywallData { /// The list of package types this paywall will display public var packages: [PackageType] + /// The package to be selected by default. + public var defaultPackage: PackageType? + /// The names for image assets. public var imageNames: [String] { get { self._imageNames } @@ -177,6 +182,7 @@ extension PaywallData { // swiftlint:disable:next missing_docs public init( packages: [PackageType], + defaultPackage: PackageType? = nil, imageNames: [String], colors: ColorInformation, blurredBackgroundImage: Bool = false, @@ -187,6 +193,7 @@ extension PaywallData { assert(!imageNames.isEmpty) self.packages = packages + self.defaultPackage = defaultPackage self._imageNames = imageNames self.colors = colors self._blurredBackgroundImage = blurredBackgroundImage @@ -334,6 +341,7 @@ extension PaywallData.Configuration: Codable { private enum CodingKeys: String, CodingKey { case packages + case defaultPackage case _imageNames = "images" case _blurredBackgroundImage = "blurredBackgroundImage" case _displayRestorePurchases = "displayRestorePurchases" diff --git a/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift b/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift index 110c97997a..c802927a48 100644 --- a/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift +++ b/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift @@ -32,6 +32,7 @@ func checkPaywallConfiguration(_ config: PaywallData.Configuration, imageNames: [""], colors: colors) let _: PaywallData.Configuration = .init(packages: [.monthly, .annual], + defaultPackage: .monthly, imageNames: [""], colors: colors, blurredBackgroundImage: true, @@ -39,6 +40,7 @@ func checkPaywallConfiguration(_ config: PaywallData.Configuration, termsOfServiceURL: URL(string: ""), privacyURL: URL(string: "")) let _: [PackageType] = config.packages + let _: PackageType? = config.defaultPackage let _: [String] = config.imageNames let _: PaywallData.Configuration.ColorInformation = config.colors let _: Bool = config.blurredBackgroundImage diff --git a/Tests/RevenueCatUITests/Data/TemplateViewConfigurationTests.swift b/Tests/RevenueCatUITests/Data/TemplateViewConfigurationTests.swift index e82a627b3c..8b85f5481f 100644 --- a/Tests/RevenueCatUITests/Data/TemplateViewConfigurationTests.swift +++ b/Tests/RevenueCatUITests/Data/TemplateViewConfigurationTests.swift @@ -23,6 +23,7 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests try Config.create( with: [], filter: [.monthly], + default: nil, localization: TestData.paywallWithIntroOffer.localizedConfiguration, setting: .single ) @@ -34,6 +35,7 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests try Config.create( with: [TestData.monthlyPackage], filter: [], + default: nil, localization: TestData.paywallWithIntroOffer.localizedConfiguration, setting: .single ) @@ -44,6 +46,7 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests let result = try Config.create( with: [TestData.monthlyPackage], filter: [.monthly], + default: nil, localization: Self.localization, setting: .single ) @@ -61,6 +64,7 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests let result = try Config.create( with: [TestData.monthlyPackage, TestData.annualPackage, TestData.weeklyPackage], filter: [.annual, .monthly], + default: .monthly, localization: Self.localization, setting: .multiple ) @@ -68,8 +72,10 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests switch result { case .single: fail("Invalid result: \(result)") - case let .multiple(first, packages): + case let .multiple(first, defaultPackage, packages): expect(first.content) === TestData.annualPackage + expect(defaultPackage.content) === TestData.monthlyPackage + expect(packages).to(haveCount(2)) let annual = packages[0] diff --git a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json index 4b7c5f0452..5094a0ebe9 100644 --- a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json +++ b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json @@ -20,6 +20,7 @@ "default_locale": "en_US", "config": { "packages": ["$rc_monthly", "$rc_annual"], + "default_package": "$rc_annual", "images": ["asset_name.png"], "blurredBackgroundImage": true, "display_restore_purchases": false, diff --git a/Tests/UnitTests/Networking/Responses/OfferingsDecodingTests.swift b/Tests/UnitTests/Networking/Responses/OfferingsDecodingTests.swift index ad833a3629..577e181580 100644 --- a/Tests/UnitTests/Networking/Responses/OfferingsDecodingTests.swift +++ b/Tests/UnitTests/Networking/Responses/OfferingsDecodingTests.swift @@ -113,6 +113,7 @@ class OfferingsDecodingTests: BaseHTTPResponseTest { try expect(paywall.assetBaseURL) == XCTUnwrap(URL(string: "https://rc-paywalls.s3.amazonaws.com")) expect(paywall.config.packages) == [.monthly, .annual] + expect(paywall.config.defaultPackage).to(beNil()) expect(paywall.config.imageNames) == ["asset_1", "asset_2"] let enConfig = try XCTUnwrap(paywall.config(for: Locale(identifier: "en_US"))) diff --git a/Tests/UnitTests/Paywalls/PaywallDataTests.swift b/Tests/UnitTests/Paywalls/PaywallDataTests.swift index 4570766cb4..8e4bc502c7 100644 --- a/Tests/UnitTests/Paywalls/PaywallDataTests.swift +++ b/Tests/UnitTests/Paywalls/PaywallDataTests.swift @@ -33,6 +33,7 @@ class PaywallDataTests: BaseHTTPResponseTest { expect(paywall.defaultLocale) == Locale(identifier: Self.defaultLocale) expect(paywall.assetBaseURL) == URL(string: "https://rc-paywalls.s3.amazonaws.com")! expect(paywall.config.packages) == [.monthly, .annual] + expect(paywall.config.defaultPackage) == .annual expect(paywall.config.imageNames) == ["asset_name.png"] expect(paywall.config.blurredBackgroundImage) == true expect(paywall.config.displayRestorePurchases) == false