Skip to content

Commit

Permalink
Paywalls added individual previews for templates (#2924)
Browse files Browse the repository at this point in the history
This makes it easier to preview and iterate on each individual template
instead of doing that through `PaywallView`. I extracted a lot of the
common code into a new `PreviewHelpers` for this.
  • Loading branch information
NachoSoto committed Jul 31, 2023
1 parent a7dfb57 commit 7326fc7
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 21 deletions.
29 changes: 29 additions & 0 deletions RevenueCatUI/Helpers/PaywallData+Default.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation
import RevenueCat
import SwiftUI

#if canImport(SwiftUI) && swift(>=5.7)

Expand Down Expand Up @@ -65,4 +66,32 @@ private extension PaywallData {

}

// MARK: -

#if DEBUG

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(watchOS, unavailable)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
struct DefaultPaywall_Previews: PreviewProvider {

static var previews: some View {
PreviewableTemplate(offering: Self.offering) {
MultiPackageBoldTemplate($0)
}
}

static let offering = Offering(
identifier: "offering",
serverDescription: "Main offering",
metadata: [:],
paywall: .default,
availablePackages: TestData.packages
)

}

#endif

#endif
84 changes: 84 additions & 0 deletions RevenueCatUI/Helpers/PreviewHelpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// PreviewHelpers.swift
//
//
// Created by Nacho Soto on 7/29/23.
//

import RevenueCat
import SwiftUI

#if DEBUG

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(watchOS, unavailable)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
@MainActor
enum PreviewHelpers {

static let introEligibilityChecker: TrialOrIntroEligibilityChecker =
.producing(eligibility: .eligible)
.with(delay: .seconds(0.5))
static let purchaseHandler: PurchaseHandler =
.mock()
.with(delay: .seconds(0.5))

}

/// Creates an easily previewable `TemplateViewType`.
/// Usage:
/// ```swift
/// PreviewableTemplate(
/// offering: TestData.testOffering
/// ) {
/// PaywallTemplate($0)
/// }
/// ```
@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(macOS, unavailable)
struct PreviewableTemplate<T: TemplateViewType>: View {

typealias Creator = @Sendable @MainActor (TemplateViewConfiguration) -> T

private let creator: Creator
private let configuration: Result<TemplateViewConfiguration, Error>

@StateObject
private var introEligibilityViewModel = IntroEligibilityViewModel(
introEligibilityChecker: PreviewHelpers.introEligibilityChecker
)

init(
offering: Offering,
creator: @escaping Creator
) {
self.configuration = offering.paywall!.configuration(
for: offering,
mode: .fullScreen,
locale: .current
)
self.creator = creator
}

var body: some View {
switch self.configuration {
case let .success(configuration):
self.creator(configuration)
.environmentObject(self.introEligibilityViewModel)
.environmentObject(PreviewHelpers.purchaseHandler)
.task {
await self.introEligibilityViewModel.computeEligibility(
for: configuration.packages
)
}

case let .failure(error):
DebugErrorView("Invalid configuration: \(error)",
releaseBehavior: .fatalError)
}
}

}

#endif
11 changes: 2 additions & 9 deletions RevenueCatUI/PaywallView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,22 +226,15 @@ struct PaywallView_Previews: PreviewProvider {
PaywallView(
offering: offering,
mode: mode,
introEligibility: Self.introEligibility,
purchaseHandler: Self.purchaseHandler
introEligibility: PreviewHelpers.introEligibilityChecker,
purchaseHandler: PreviewHelpers.purchaseHandler
)
.previewLayout(mode.layout)
.previewDisplayName("\(offering.paywall?.template.name ?? "")-\(mode)")
}
}
}

private static let introEligibility: TrialOrIntroEligibilityChecker =
.producing(eligibility: .eligible)
.with(delay: .seconds(0.5))
private static let purchaseHandler: PurchaseHandler =
.mock()
.with(delay: .seconds(1))

private static let offerings: [Offering] = [
TestData.offeringWithIntroOffer,
TestData.offeringWithMultiPackagePaywall,
Expand Down
20 changes: 20 additions & 0 deletions RevenueCatUI/Templates/MultiPackageBoldTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,23 @@ private extension MultiPackageBoldTemplate {
}

}

// MARK: -

#if DEBUG

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(watchOS, unavailable)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
struct MultiPackageBoldTemplate_Previews: PreviewProvider {

static var previews: some View {
PreviewableTemplate(offering: TestData.offeringWithMultiPackagePaywall) {
MultiPackageBoldTemplate($0)
}
}

}

#endif
20 changes: 20 additions & 0 deletions RevenueCatUI/Templates/OnePackageStandardTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,23 @@ private extension PaywallViewMode {
}

}

// MARK: -

#if DEBUG

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(watchOS, unavailable)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
struct OnePackageStandardTemplate_Previews: PreviewProvider {

static var previews: some View {
PreviewableTemplate(offering: TestData.offeringWithIntroOffer) {
OnePackageStandardTemplate($0)
}
}

}

#endif
20 changes: 20 additions & 0 deletions RevenueCatUI/Templates/OnePackageWithFeaturesTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,23 @@ private struct FeatureView: View {
private static let cutoffForHorizontalLayout: DynamicTypeSize = .xxxLarge

}

// MARK: -

#if DEBUG

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
@available(watchOS, unavailable)
@available(macOS, unavailable)
@available(macCatalyst, unavailable)
struct OnePackageWithFeaturesTemplate_Previews: PreviewProvider {

static var previews: some View {
PreviewableTemplate(offering: TestData.offeringWithSinglePackageFeaturesPaywall) {
OnePackageWithFeaturesTemplate($0)
}
}

}

#endif
2 changes: 1 addition & 1 deletion RevenueCatUI/Templates/TemplateViewType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ extension PaywallData {
}
}

private func configuration(
func configuration(
for offering: Offering,
mode: PaywallViewMode,
locale: Locale
Expand Down
6 changes: 1 addition & 5 deletions RevenueCatUI/Views/FooterView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,10 @@ struct Footer_Previews: PreviewProvider {
privacyURL: privacyURL
),
color: TestData.colors.text1Color,
purchaseHandler: Self.handler
purchaseHandler: PreviewHelpers.purchaseHandler
)
}

private static let handler: PurchaseHandler =
.mock()
.with(delay: .seconds(0.5))

}

#endif
8 changes: 2 additions & 6 deletions RevenueCatUI/Views/PurchaseButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,14 @@ struct PurchaseButton_Previews: PreviewProvider {
localization: TestData.localization1.processVariables(with: Self.package, locale: .current),
introEligibility: self.eligibility,
mode: self.mode,
purchaseHandler: Self.purchaseHandler
purchaseHandler: PreviewHelpers.purchaseHandler
)
.task {
self.eligibility = await Self.eligibilityChecker.eligibility(for: Self.package)
self.eligibility = await PreviewHelpers.introEligibilityChecker.eligibility(for: Self.package)
}
}

private static let package: Package = TestData.packageWithIntroOffer
private static let eligibilityChecker: TrialOrIntroEligibilityChecker = .producing(eligibility: .eligible)
.with(delay: .seconds(0.3))
private static let purchaseHandler: PurchaseHandler = .mock()
.with(delay: .seconds(0.5))

}

Expand Down

0 comments on commit 7326fc7

Please sign in to comment.