Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paywalls: multi-package horizontal template #2949

Merged
merged 3 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 62 additions & 4 deletions RevenueCatUI/Data/TestData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,30 @@ internal enum TestData {
)
static let monthlyProduct = TestStoreProduct(
localizedTitle: "Monthly",
price: 12.99,
localizedPriceString: "$12.99",
price: 6.99,
localizedPriceString: "$6.99",
productIdentifier: "com.revenuecat.product_2",
productType: .autoRenewableSubscription,
localizedDescription: "PRO monthly",
subscriptionGroupIdentifier: "group",
subscriptionPeriod: .init(value: 1, unit: .month),
introductoryDiscount: Self.intro(7, .day)
)
static let sixMonthProduct = TestStoreProduct(
localizedTitle: "Monthly",
price: 34.99,
localizedPriceString: "$34.99",
productIdentifier: "com.revenuecat.product_5",
productType: .autoRenewableSubscription,
localizedDescription: "PRO monthly",
subscriptionGroupIdentifier: "group",
subscriptionPeriod: .init(value: 6, unit: .month),
introductoryDiscount: Self.intro(7, .day)
)
static let annualProduct = TestStoreProduct(
localizedTitle: "Annual",
price: 69.49,
localizedPriceString: "$69.49",
price: 53.99,
localizedPriceString: "$53.99",
productIdentifier: "com.revenuecat.product_3",
productType: .autoRenewableSubscription,
localizedDescription: "PRO annual",
Expand Down Expand Up @@ -101,6 +112,12 @@ internal enum TestData {
storeProduct: Self.monthlyProduct.toStoreProduct(),
offeringIdentifier: Self.offeringIdentifier
)
static let sixMonthPackage = Package(
identifier: PackageType.sixMonth.identifier,
packageType: .sixMonth,
storeProduct: Self.sixMonthProduct.toStoreProduct(),
offeringIdentifier: Self.offeringIdentifier
)
static let annualPackage = Package(
identifier: PackageType.annual.identifier,
packageType: .annual,
Expand Down Expand Up @@ -256,6 +273,47 @@ internal enum TestData {
Self.annualPackage]
)

static let offeringWithMultiPackageHorizontalPaywall = Offering(
identifier: Self.offeringIdentifier,
serverDescription: "Offering",
metadata: [:],
paywall: .init(
template: .multiPackageHorizontal,
config: .init(
packages: [PackageType.monthly.identifier,
PackageType.sixMonth.identifier,
PackageType.annual.identifier],
defaultPackage: PackageType.sixMonth.identifier,
images: .init(
background: "background.jpg"
),
colors: .init(
light: .init(
background: "#FFFFFF",
text1: "#111111",
callToActionBackground: "#06357D",
callToActionForeground: "#FFFFFF",
accent1: "#D4B5FC",
accent2: "#DFDFDF"
)
),
termsOfServiceURL: URL(string: "https://revenuecat.com/tos")!
),
localization: .init(
title: "Get _unlimited_ access",
callToAction: "Continue",
offerDetails: "",
offerDetailsWithIntroOffer: "Includes {{ intro_duration }} **free** trial",
offerName: "{{ subscription_duration }}",
features: []
),
assetBaseURL: Bundle.module.resourceURL ?? Bundle.module.bundleURL
),
availablePackages: [TestData.monthlyPackage,
TestData.sixMonthPackage,
TestData.annualPackage]
)

static let lightColors: PaywallData.Configuration.Colors = .init(
background: "#FFFFFF",
text1: "#000000",
Expand Down
88 changes: 87 additions & 1 deletion RevenueCatUI/Modifiers/ViewExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ extension View {
}
}

}

// MARK: - Scrolling

@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
extension View {

@ViewBuilder
func scrollable(
_ axes: Axis.Set = .vertical,
Expand Down Expand Up @@ -60,6 +67,12 @@ extension View {
}
}
}
}

// MARK: - Size changes

@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
extension View {

/// Invokes the given closure whethever the view size changes.
func onSizeChange(_ closure: @escaping (CGSize) -> Void) -> some View {
Expand All @@ -74,9 +87,82 @@ extension View {
.onPreferenceChange(ViewSizePreferenceKey.self, perform: closure)
}

/// Invokes the given closure with the dimension specified by `axis` changes whenever it changes.
func onSizeChange(
_ axis: Axis,
_ closure: @escaping (CGFloat) -> Void
) -> some View {
self
.overlay(
GeometryReader { geometry in
Color.clear
.preference(
key: ViewDimensionPreferenceKey.self,
value: axis == .horizontal
? geometry.size.width
: geometry.size.height
)
}
)
.onPreferenceChange(ViewDimensionPreferenceKey.self, perform: closure)
}

}

// MARK: -
// MARK: - Rounded corners

#if canImport(UIKit)

@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
extension View {

func roundedCorner(
_ radius: CGFloat,
corners: UIRectCorner,
edgesIgnoringSafeArea edges: Edge.Set = []
) -> some View {
self.mask(
RoundedCorner(radius: radius, corners: corners)
.edgesIgnoringSafeArea(edges)
)
}

}

@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.2, *)
private struct RoundedCorner: Shape {

var radius: CGFloat
var corners: UIRectCorner

func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect,
byRoundingCorners: self.corners,
cornerRadii: CGSize(width: self.radius, height: self.radius))
return Path(path.cgPath)
}

}

#endif

// MARK: - Preference Keys

/// `PreferenceKey` for keeping track of a view dimension.
private struct ViewDimensionPreferenceKey: PreferenceKey {

typealias Value = CGFloat

static var defaultValue: Value = 10

static func reduce(value: inout Value, nextValue: () -> Value) {
let newValue = max(value, nextValue())
if newValue != value {
value = newValue
}
}

}

/// `PreferenceKey` for keeping track of view size.
private struct ViewSizePreferenceKey: PreferenceKey {
Expand Down
1 change: 1 addition & 0 deletions RevenueCatUI/PaywallView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ private extension PaywallTemplate {
case .onePackageStandard: return "single"
case .multiPackageBold: return "multi"
case .onePackageWithFeatures: return "features"
case .multiPackageHorizontal: return "horizontal"
}
}

Expand Down
Loading