diff --git a/Sources/Support/PaywallExtensions.swift b/Sources/Support/PaywallExtensions.swift index faf9309b76..a2ee906244 100644 --- a/Sources/Support/PaywallExtensions.swift +++ b/Sources/Support/PaywallExtensions.swift @@ -59,6 +59,8 @@ extension SubscriptionStoreView { /// with custom marketing content. /// When the user purchases products through this paywall, the `RevenueCat` SDK will handle /// the result automatically. All you need to do is to dismiss the paywall + /// + /// - Seealso: ``CurrentOfferingSubscriptionStoreView`` public init( offering: Offering, @ViewBuilder marketingContent: () -> (Content) @@ -71,6 +73,8 @@ extension SubscriptionStoreView { /// Creates a ``SubscriptionStoreView`` from an ``Offering`` /// that doesn't take a custom view to use for marketing content. + /// + /// - Seealso: ``CurrentOfferingSubscriptionStoreView`` public init( offering: Offering ) where Content == AutomaticSubscriptionStoreMarketingContent { @@ -79,6 +83,55 @@ extension SubscriptionStoreView { } +/// ``_StoreKit_SwiftUI/SubscriptionStoreView`` that displays subscription products in the current ``Offering``. +@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *) +public struct CurrentOfferingSubscriptionStoreView: View { + + @State + private var currentOffering: Offering? + private let marketingContent: (() -> Content)? + + /// Creates a view to load all subscriptions in a subscription group from the App Store. + /// + /// When the user purchases products through this paywall, the `RevenueCat` SDK will handle + /// the result automatically. All you need to do is to dismiss the paywall + public init() where Content == AutomaticSubscriptionStoreMarketingContent { + self.marketingContent = nil + } + + /// Creates a view to load all subscriptions in a subscription group from the App Store, and merchandise + /// them with a custom marketing content. + /// + /// When the user purchases products through this paywall, the `RevenueCat` SDK will handle + /// the result automatically. All you need to do is to dismiss the paywall + public init(@ViewBuilder marketingContent: @escaping () -> Content) { + self.marketingContent = marketingContent + } + + // swiftlint:disable:next missing_docs + public var body: some View { + Group { + if let currentOffering { + if let marketingContent { + SubscriptionStoreView(offering: currentOffering, + marketingContent: marketingContent) + } else { + SubscriptionStoreView(offering: currentOffering) + } + } else { + ProgressView() + .progressViewStyle(.circular) + } + } + .task { + if let offering = try? await Purchases.shared.offerings().current { + self.currentOffering = offering + } + } + } + +} + private extension Offering { @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) diff --git a/Tests/APITesters/SwiftAPITester/SwiftAPITester/OtherAPI.swift b/Tests/APITesters/SwiftAPITester/SwiftAPITester/OtherAPI.swift index be6f142cb2..56afc0f7c7 100644 --- a/Tests/APITesters/SwiftAPITester/SwiftAPITester/OtherAPI.swift +++ b/Tests/APITesters/SwiftAPITester/SwiftAPITester/OtherAPI.swift @@ -48,6 +48,11 @@ struct PaywallViews: View { SubscriptionStoreView(offering: self.offering) { Text("Marketing content") } + + CurrentOfferingSubscriptionStoreView() + CurrentOfferingSubscriptionStoreView { + Text("Marketing content") + } } }