Until we improve the presentation of already-subscribed products this is
just a no-op. This will at least help developers know why nothing is
happening.
This abstracts away the logic to ensure layouts are consistent when
selecting different packages in multi-package templates, in a way that
the content doesn't move around.
This is a better fix than #3235. Instead of marking the view as
disabled, which is also used by `PurchaseHandler` to signal that a
purchase is in progress, we simply make that view not accept touches.
Which has the actual effect that we want (not being interactive),
without messing with how it's displayed).

Rename "card" to "footer" to because that is how we expect developers to
use the current implementation of the non-fullscreen modes as a footer
to their custom paywalls.
- Renamed `card` to `footer`
- Renamed `condensedCard` to `condensedFooter`
---------
Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
I've moved `PaywallViewMode` from `RevenueCatUI` to `RevenueCat`. This
uses the same approach as #2645. This method is `public` so it can be
used from `RevenueCatUI`, but the documentation stays its purpose.
The behavior is covered with integration tests and a snapshot test.
Depends on https://github.com/RevenueCat/khepri/pull/6364.
`PaywallView` and `PaywallViewController` (along with the extensions)
still require iOS 16, but this paves the way to support iOS 15 down the
road if we need to.
### Main Changes:
- Changed all `@available` annotations
- Added CI tests
- Replaced `ViewThatFits` with the "biggest" version
- Because of that, `scrollableIfNeeded` is always scrollable
- Double `Regex` implementation (keeping the modern one), so once we
drop support for iOS 15 we can just keep the modern one.
### TODO:
- [x] Add snapshots
- [x] Test paywalls
- [x] Updated APITester to verify this
- Added `bold` parameter, necessary for upcoming template
- Avoid scaling beyond largest dynamic type sizes
- Scale separator view with dynamic type setting to ensure consistency
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.
This allows `PaywallView` to handle state handling during a purchase:
instead of the previous behavior where only `PurchaseButton` would
disable itself, now the entire `PaywallView` is disabled.
I extracted `PackageButtonStyle` so any template with multi-package
selection can get this same behavior: the package selection also becomes
disabled, as well as any other button (like restore purchases).
I've also cleaned up the templates since we no longer needed the
"Content" inside view, and they can be simplified with a single type.
By making `PurchaseHandler` `@MainActor` we also ensure that all these
state transitions lead to UI changes happening exclusively on the main
thread.
- Added support for `PackageSetting.multiple`
- Changed `PackageConfiguration.multiple` to ensure at compile time that
the list of packages is not empty
- Renamed `Example1Template` to `SinglePackageTemplate`
- Extracted `RemoteImage`
- Added snapshot tests
<img width="196" alt="screenshot_2023-07-20_at_16 01 14"
src="https://github.com/RevenueCat/purchases-ios/assets/685609/c7d6ae58-a608-414a-b5b1-11638e1a2a67">
Another small refactor, follow up to #2837.
Slowly taking implementation details from `Example1Template` to make it
easier to implement more templates.