-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Motivation It was a little unclear how and when to use the different `PaywallView` modes (`.fullscreen`, `.card`, and `.condensedCard`). The actual functionality of the modes is great but they seemed like three different components in one view and it was just trying to do too much for one public API. This change will... - Remove modes from being a public parameter in `PaywallView` and only allow it to be full screen - Create a new `PaywallFooterView` which will combine `.footer` (previously `.card`) and `.condensedFooter` (previously `.condensedCard`) - Removed the `modes` parameter from `PaywallView` ### New `PaywallFooterView` - Wraps `PaywallView` and will only choose between `.footer` and `.footerCondensed` - Currently offers a `condensed` parameter but this might be switched to being a remote setting inside of `PaywalData` ### New `.paywallFooter()` view modifier - Easy way for developers to place `PaywallFooterView` where it is supposed to be placed - This places the view in `.safeAreaInset(edge: .bottom)` - This works on any view but is ideal in `ScrollView` as it will automatically handle adjusting the scroll insets with the paywalls size ### New footer structure and animation (with some hacks) - No parts of `PaywallFooterView` uses `.overlay` anymore - The whole grows in `.condensedFooter` when "All Plans" is toggled ## Demo ### My sample app https://github.com/RevenueCat/purchases-ios/assets/401294/17c52bba-956d-404e-b991-a2272e7fc4f1 ### Simple sample app https://github.com/RevenueCat/purchases-ios/assets/401294/4ea94156-8367-4dea-9640-0cce8ffa1deb --------- Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
- Loading branch information
1 parent
b18f5e5
commit 01fa3ce
Showing
13 changed files
with
330 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// | ||
// PaywallFooterView.swift | ||
// | ||
// | ||
// Created by Josh Holtz on 8/21/23. | ||
// | ||
|
||
import RevenueCat | ||
import SwiftUI | ||
|
||
/// A SwiftUI view for displaying a `PaywallData` for an `Offering`. | ||
/// | ||
/// ### Related Articles | ||
/// [Documentation](https://rev.cat/paywalls) | ||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
@available(watchOS, unavailable, message: "RevenueCatUI does not support watchOS yet") | ||
@available(macOS, unavailable, message: "RevenueCatUI does not support macOS yet") | ||
@available(tvOS, unavailable, message: "RevenueCatUI does not support tvOS yet") | ||
@available(macCatalyst, unavailable, message: "RevenueCatUI does not support Catalyst yet") | ||
internal struct PaywallFooterView: View { | ||
|
||
private let condensed: Bool | ||
private let fonts: PaywallFontProvider | ||
private let introEligibility: TrialOrIntroEligibilityChecker? | ||
private let purchaseHandler: PurchaseHandler? | ||
|
||
private var offering: Offering? | ||
|
||
/// Create a view that loads the `Offerings.current`. | ||
/// - Note: If loading the current `Offering` fails (if the user is offline, for example), | ||
/// an error will be displayed. | ||
/// - Warning: `Purchases` must have been configured prior to displaying it. | ||
/// If you want to handle that, you can use ``init(offering:mode:)`` instead. | ||
init( | ||
condensed: Bool = false, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider() | ||
) { | ||
self.init( | ||
offering: nil, | ||
condensed: condensed, | ||
fonts: fonts, | ||
introEligibility: .default(), | ||
purchaseHandler: .default() | ||
) | ||
} | ||
|
||
/// Create a view for the given `Offering`. | ||
/// - Note: if `offering` does not have a current paywall, or it fails to load due to invalid data, | ||
/// a default paywall will be displayed. | ||
/// - Warning: `Purchases` must have been configured prior to displaying it. | ||
init( | ||
offering: Offering, | ||
condensed: Bool = false, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider() | ||
) { | ||
self.init( | ||
offering: offering, | ||
condensed: condensed, | ||
fonts: fonts, | ||
introEligibility: .default(), | ||
purchaseHandler: .default() | ||
) | ||
} | ||
|
||
internal init( | ||
offering: Offering?, | ||
condensed: Bool, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider(), | ||
introEligibility: TrialOrIntroEligibilityChecker?, | ||
purchaseHandler: PurchaseHandler? | ||
) { | ||
self.offering = offering | ||
self.introEligibility = introEligibility | ||
self.purchaseHandler = purchaseHandler | ||
self.condensed = condensed | ||
self.fonts = fonts | ||
} | ||
|
||
var body: some View { | ||
PaywallView( | ||
offering: self.offering, | ||
mode: self.condensed ? .condensedFooter : .footer, | ||
fonts: self.fonts, | ||
introEligibility: self.introEligibility, | ||
purchaseHandler: self.purchaseHandler | ||
) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// | ||
// View+PresentPaywallFooter.swift | ||
// | ||
// | ||
// Created by Josh Holtz on 8/18/23. | ||
// | ||
|
||
import RevenueCat | ||
import SwiftUI | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
@available(macOS, unavailable, message: "RevenueCatUI does not support macOS yet") | ||
@available(tvOS, unavailable, message: "RevenueCatUI does not support tvOS yet") | ||
extension View { | ||
|
||
/// Presents a ``PaywallFooterView`` at the bottom of a view that loads the `Offerings.current`. | ||
/// ```swift | ||
/// var body: some View { | ||
/// YourPaywall() | ||
/// .paywallFooter() | ||
/// } | ||
/// ``` | ||
/// | ||
/// ### Related Articles | ||
/// [Documentation](https://rev.cat/paywalls) | ||
public func paywallFooter( | ||
condensed: Bool = false, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider(), | ||
purchaseCompleted: PurchaseCompletedHandler? = nil | ||
) -> some View { | ||
return self.paywallFooter( | ||
offering: nil, | ||
condensed: condensed, | ||
fonts: fonts, | ||
introEligibility: nil, | ||
purchaseCompleted: purchaseCompleted | ||
) | ||
} | ||
|
||
/// Presents a ``PaywallFooterView`` at the bottom of a view with the given offering. | ||
/// ```swift | ||
/// var body: some View { | ||
/// YourPaywall() | ||
/// .paywallFooter(offering: offering) | ||
/// } | ||
/// ``` | ||
/// | ||
/// ### Related Articles | ||
/// [Documentation](https://rev.cat/paywalls) | ||
public func paywallFooter( | ||
offering: Offering, | ||
condensed: Bool = false, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider(), | ||
purchaseCompleted: PurchaseCompletedHandler? = nil | ||
) -> some View { | ||
return self.paywallFooter( | ||
offering: offering, | ||
condensed: condensed, | ||
fonts: fonts, | ||
introEligibility: nil, | ||
purchaseCompleted: purchaseCompleted | ||
) | ||
} | ||
|
||
func paywallFooter( | ||
offering: Offering?, | ||
condensed: Bool = false, | ||
fonts: PaywallFontProvider = DefaultPaywallFontProvider(), | ||
introEligibility: TrialOrIntroEligibilityChecker? = nil, | ||
purchaseHandler: PurchaseHandler? = nil, | ||
purchaseCompleted: PurchaseCompletedHandler? = nil | ||
) -> some View { | ||
return self | ||
.modifier(PresentingPaywallFooterModifier( | ||
offering: offering, | ||
condensed: condensed, | ||
purchaseCompleted: purchaseCompleted, | ||
fontProvider: fonts, | ||
introEligibility: introEligibility, | ||
purchaseHandler: purchaseHandler | ||
)) | ||
} | ||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, *) | ||
@available(macOS, unavailable) | ||
@available(tvOS, unavailable) | ||
private struct PresentingPaywallFooterModifier: ViewModifier { | ||
|
||
let offering: Offering? | ||
let condensed: Bool | ||
|
||
let purchaseCompleted: PurchaseCompletedHandler? | ||
let fontProvider: PaywallFontProvider | ||
let introEligibility: TrialOrIntroEligibilityChecker? | ||
let purchaseHandler: PurchaseHandler? | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.safeAreaInset(edge: .bottom) { | ||
PaywallFooterView( | ||
offering: self.offering, | ||
condensed: self.condensed, | ||
fonts: self.fontProvider, | ||
introEligibility: self.introEligibility ?? .default(), | ||
purchaseHandler: self.purchaseHandler ?? .default() | ||
) | ||
.onPurchaseCompleted { | ||
self.purchaseCompleted?($0) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.