Commit Graph
53 Commits
Author SHA1 Message Date
Facundo Menzella 6b5c430082 chore: Enable force_unwrapping for SwiftLint (#4820)
* enable force_unwrapping

* avoid force unwrap

* fixed all errors

* remove extra disable
2025-02-26 12:40:49 +01:00
Josh Holtz fc2138249a [Paywalls V2] Implement V2 variables and functions (#4633)
* This mostly works

* This mostly works

* Better tests and logic

* More tests

* Fixed onemore

* lint

* Fix tests

* Actually use this

* Fix for all quantity translation things

* More minor fixes

* Fix tests
2025-01-08 09:17:34 -06:00
James Borthwick 22ff468e88 Support to round+truncate prices displayed on paywalls for backend-specified countries (#4132)
## Rounds prices for certain locales.

The server now returns a list of storefront country codes where paywalls
should not display cents. This part of paywall data, in
`zero_decimal_place_countries`.

Prices are only truncated if the price ends in .00.
2024-08-16 11:00:38 -05:00
Cesar de la Vega fb7ea428fa Fix PaywallsTester by changing TestData DEBUG checks (#4092)
Round 2 on https://github.com/RevenueCat/purchases-ios/pull/4087. There
were still some stuff not being available to `PaywallsTester` on archive
2024-07-19 16:33:51 +02:00
Cesar de la Vega 0de331f5b6 Add missing @PublicForExternalTesting that broke PaywallsTester (#4087) 2024-07-19 14:18:17 +02:00
Josh Holtz 363bb0ce09 Added new paywall template to support multiple tiered subscriptions (#4022)
### Motivation

Template 5 but with multiple tiers 😊

### Description

Enabling Template 7 by changing `7_disabled` to `7`

- Changed a `header.jpg` to `header.heic` to try and fix issue with
weirdly failing snapshot UI test
- Changed visibility on `TestData` from `public` to `internal`
- Hides tier selector if only one tier
- Changed `color_overrides_by_tier` to `colors_by_tier` and
`image_overrides_by_tier` to `images_by_tier`
- The original implementation was going to default to existing color and
images configurations and then override by tier
- However, this turned out to be harder to implement on the
configuration side
- `Colors` got four new optional values
  - `tier_control_background`
  - `tier_control_foreground`
  - `tier_control_selected_background`
  - `tier_control_selected_foreground`

### Demo

#### Full Screen


https://github.com/RevenueCat/purchases-ios/assets/401294/e5317a53-428c-415e-a1a1-b4231d32a776

### Footer


https://github.com/RevenueCat/purchases-ios/assets/401294/8905b55e-0fa2-49f0-aa1c-d4c1e694fb5b

### Footer Condensed


https://github.com/RevenueCat/purchases-ios/assets/401294/311d78fb-bdeb-43cd-b601-9c60a8a54b6f
2024-07-17 07:04:42 -05:00
NachoSoto 2bcd0ce328 5.0.0 changes: support SK2 by default 2024-07-01 14:37:21 -05:00
James Borthwick 478dd26e64 Paywalls Tester: Enable Example Paywalls in Release Mode (#3885)
The paywalls examples weren't showing up when compiled in release mode.
Enabling it meant making a bunch of more internal things public via the
preprocessing script. `TestData` is no longer `#ifdef DEBUG`ed out, but
most of its data is still `#ifdef DEBUG`, and when it's compiled with an
`internal` modifier and thus nothing uses it, I'd expect what remains to
be stripped away during linking.
2024-05-15 12:06:05 -07:00
Andy BoedoandNachoSoto 56f7178145 Paywalls: fix empty description when using custom package type and {{ sub_period }} (#3495)
If you select a custom package type and set Offer Period, the paywall
would have an empty entry for that package.


<img width="802" alt="image"
src="https://github.com/RevenueCat/purchases-ios/assets/3922667/fa50e15b-b122-4caa-816e-3250f10d5d89">

| Before | After |
| :-: | :-: |
| ![IMG_908CED5B663B-1
(1)](https://github.com/RevenueCat/purchases-ios/assets/3922667/2519c74e-c0d2-44c1-a126-64bd78808384)
|
![IMG_B1CED574DF20-1](https://github.com/RevenueCat/purchases-ios/assets/3922667/1eaf17d6-75fd-4e20-86cf-ef93de2d74d3)
|

---------

Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
2023-12-08 07:17:49 +08:00
NachoSoto 6317f096cf Paywalls: watchOS support (#3291)
![simulator_screenshot_38A61F03-8048-40E2-AD3E-384DF4112771](https://github.com/RevenueCat/purchases-ios/assets/685609/b74e2c9d-ece1-4f00-920b-7bccb68acd82)

![simulator_screenshot_ADD7F6B5-8A39-473B-85E2-5175027F641C](https://github.com/RevenueCat/purchases-ios/assets/685609/6531d598-b859-4482-a669-34d2eaf5b8f1)
2023-11-16 12:49:53 -08:00
NachoSotoandAndy Boedo af08736775 RevenueCatUI: added support to other deployment targets (#3392)
Follow up to #3378.

This allows us to link both `RevenueCat` and `RevenueCatUI` from
`PurchasesHybridCommon` supporting the same platforms.
The actual types might not be available in some platforms / versions,
but we can detect that at compile time.

See
https://app.circleci.com/pipelines/github/RevenueCat/purchases-hybrid-common/2564/workflows/ea6a4e24-e1eb-4c7a-a930-173945732999/jobs/10352

---------

Co-authored-by: Andy Boedo <andresboedo@gmail.com>
2023-11-08 07:35:19 -08:00
NachoSoto 9f73b98a54 Paywall Tester: improve template 5 dark colors (#3358)
![Screenshot 2023-10-27 at 10 39
05](https://github.com/RevenueCat/purchases-ios/assets/685609/9332241d-447a-4f68-9114-83a5a28bc5d8)
2023-10-30 15:15:15 -07:00
NachoSoto 7048b2039e Paywalls: improve conversion from Color/UIColor to PaywallColor (#3357)
This wasn't fully required, but now we'll correctly encode
`stringRepresentation`.
Also fixed the math (dividing by 255 instead of 256), which was
technically producing slightly incorrect colors.

Also adds an overload for `UIColor` which allows us to use color
literals in Xcode:

![image](https://github.com/RevenueCat/purchases-ios/assets/685609/93bf581c-4522-4de8-8cc1-5c69f6bf0e83)
2023-10-30 15:14:24 -07:00
NachoSoto b124b90dd3 Paywalls: finished template 5 (#3340)
This wraps up color parity with the dashboard and "enables" the
template.

![RocketSim_Screenshot_iPhone_15_Pro_Max_2023-10-24_13 45
09](https://github.com/RevenueCat/purchases-ios/assets/685609/d658d581-6067-42bf-8d86-f29af122d2e1)
2023-10-25 21:15:11 -07:00
NachoSoto 5ba291105f Paywalls: don't display "Purchases restored successfully" if nothings was restored (#3233)
We can improve the logic here, but this is a simple improvement for the
obvious case where nothing was actually restored.
2023-09-20 15:19:23 -07:00
NachoSoto ac74b74172 Paywalls: refactored PurchaseHandler extracting protocol (#3196)
As suggested by @aboedo in
https://github.com/RevenueCat/purchases-ios/pull/3164#discussion_r1323603537
2023-09-14 18:28:11 -07:00
NachoSoto 6c345a514f Paywalls: send events to Purchases (#3164)
Last part, follow up to #3160.

This now makes `PaywallView` track events through the `RevenueCat` SDK.
2023-09-14 18:28:11 -07:00
NachoSoto b375d8e5b7 Paywalls: polish template 4 (#3183)
![image](https://github.com/RevenueCat/purchases-ios/assets/685609/d8c917ec-d086-462c-bc65-87e2719ffa5c)

![image](https://github.com/RevenueCat/purchases-ios/assets/685609/2aedc34c-0c96-4c3d-b0c3-35a62fa8541b)
2023-09-14 18:28:11 -07:00
NachoSoto 789d8f34a7 Paywalls: new {{ sub_duration_in_months }} variable (#3173) 2023-09-14 18:28:11 -07:00
NachoSoto d9b12fd1d2 Paywalls: {{ price_per_period }} now takes SubscriptionPeriod.value into account (#3133)
This was incorrect for `PackageType.threeMonth` and
`PackageType.sixMonth`.


![image](https://github.com/RevenueCat/purchases-ios/assets/685609/87b1ec00-04a0-4baa-ba73-edc4ce138388)
2023-09-14 18:28:11 -07:00
NachoSoto a3836ef077 Paywalls: template 5 (#3095) 2023-09-14 18:28:11 -07:00
NachoSoto 56de917d02 Paywalls: removed presentedPaywallViewMode (#3109)
We're going to track this in a different way in the future.
2023-09-14 18:28:11 -07:00
NachoSoto 8c587bcc65 Paywalls: validate PaywallData to ensure displayed data is always correct (#3019)
See
https://docs.google.com/document/d/1oLZR77apAjZf04hDzlrJpPaFV0xhuQ1-hApsNBohhfA/edit

This simplifies `PaywallView`: the validated `PaywallData` is what's
always displayed, and a `DebugErrorView` containing an error description
will potentially explain why a default paywall is being displayed.

### Validations:

- [x] `Offering` contains a `PaywallData`
- [x] `PaywallLocalizedConfiguration` contains no unrecognized variables
- [x] `PaywallIcon`s are all recognized
- [x] `PaywallTemplate` is recognized
2023-09-14 18:28:11 -07:00
NachoSoto 64c887d1b5 Paywalls: tweaking colors on template 2&3 (#3011) 2023-09-14 18:28:11 -07:00
NachoSoto 5c9b2a62c7 Paywalls: .card and .condensedCard modes (#2995) 2023-09-14 18:28:11 -07:00
NachoSoto 8ba761a23f Paywalls: send presented PaywallViewMode with purchases (#2859)
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.
2023-09-14 18:28:11 -07:00
NachoSoto 97dcce8248 Paywalls: fixed color in template 3 (#2980)
Thanks to @joshdholtz for finding this.
2023-09-14 18:28:11 -07:00
NachoSoto e25d31f7dc Paywalls: updated template names (#2971) 2023-09-14 18:28:11 -07:00
NachoSoto df7bd8b33f Paywalls: updated variable names (#2970)
These match the new agreed upon variables.

- Improved the localized unit abbreviations
- Refactored `VariableDataProvider` so all the logic is now in `Package`
- Added new tests for `Package` variables
2023-09-14 18:28:11 -07:00
NachoSoto 0903c1f5cc Paywalls: multi-package horizontal template (#2949)
![image](https://github.com/RevenueCat/purchases-ios/assets/685609/a5cc3f4b-99d0-40a2-8a85-82f243383978)
2023-09-14 18:28:11 -07:00
NachoSoto 534a556e62 Paywalls: initial iOS 15 support (#2933)
`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
2023-09-14 18:28:11 -07:00
NachoSoto 748878cf9c Paywalls: markdown support (#2961)
This relies on `SwiftUI`'s automatic rendering of markdown when using
`Text(LocalizedStringKey)`

![Screenshot 2023-08-03 at 11 52
55](https://github.com/RevenueCat/purchases-ios/assets/685609/0f19be26-aaa1-4bb2-ab0f-e0b3b1396f0b)
2023-09-14 18:28:11 -07:00
NachoSoto 78abf188e0 Paywalls: updated icon set to match frontend (#2962) 2023-09-14 18:28:11 -07:00
NachoSoto 18bb87ad27 Paywalls: added support for PackageType.custom (#2959)
Fixes [PWL-80].
2023-09-14 18:28:11 -07:00
NachoSoto e78c8782d0 Paywalls: added support for custom and lifetime products (#2941)
The main change is that `VariableHandler` no longer cashes when trying
to determine price per month for non-subscriptions. I added a test to
cover this behavior.
2023-09-14 18:28:11 -07:00
NachoSoto bf32e02fa6 Paywalls: new .onPurchaseCompleted modifier (#2930)
This allows users to present a `PaywallView` and be notified of
purchasing events. Example:
```swift
VStack {
    YourViews()

    if !self.didPurchase {
        PaywallView()
    }
}
    .onPurchaseCompleted { customerInfo in
        print("Purchase completed: \(customerInfo.entitlements)")
        self.didPurchase = true
    }
```

Additionally, an explicit optional closure is added to
`.presentPaywallIfNecessary`:
```swift
YourApp()
    .presentPaywallIfNecessary {
        !$0.entitlements.active.keys.contains("entitlement_identifier")
    } purchaseCompleted: { customerInfo in
        print("Customer info unlocked entitlement: \(customerInfo.entitlements)")
    }
```

These are now tested through new unit tests.
2023-09-14 18:28:11 -07:00
NachoSoto 82a96c1f82 Paywalls: improved default paywall configuration (#2926)
This could still use more polish, but some basic fixes:
- Fixed colors
- Added application name as a title
- Using `total_price_and_per_month` instead of `price_per_month` so it
also works with monthly subscriptions
- Added snapshot test for its dark mode version
2023-09-14 18:28:11 -07:00
NachoSoto a1b7ab8def Paywalls: some basic polish from design feedback (#2917)
PWL-28, PWL-29, PWL-30
2023-09-14 18:28:11 -07:00
NachoSoto f86c8bda4e Paywalls: new text1 and text2 colors (#2903)
`foreground` becomes `text1`, allowing us to keep growing that list just
like accents.
`accent1` is now also optional.
2023-09-14 18:28:11 -07:00
NachoSoto c56e1dcefc Paywalls: one package with features template (#2902)
Depends on #2882.

<img width="391" alt="Screenshot 2023-07-26 at 16 49 26"
src="https://github.com/RevenueCat/purchases-ios/assets/685609/4daf9dbf-0731-436c-a0b5-e9387f59f1e0">
2023-09-14 18:28:11 -07:00
NachoSoto 9d4974f5d8 Paywalls: added "features" to LocalizedConfiguration (#2899)
To be used by upcoming templates.
2023-09-14 18:28:11 -07:00
NachoSoto 458d5fdcdd Paywalls: updated template names (#2878)
These now match our initial 2 templates.

I've updated everything for consistency:
- `PaywallTemplate`
- `View`s
- Snapshot tests
- Test fixtures
2023-09-14 18:28:11 -07:00
NachoSoto 253a36756e Paywalls: added accent colors (#2883)
Also updated the second template with them:
<img width="435" alt="Screenshot 2023-07-25 at 23 18 31"
src="https://github.com/RevenueCat/purchases-ios/assets/685609/0ecb2406-0ef9-451d-a145-90820dd108b3">
2023-09-14 18:28:11 -07:00
NachoSoto a1a8b858c2 Paywalls: changed images representation to an object (#2875)
This is much better, no longer relying on array index.
2023-09-14 18:28:11 -07:00
NachoSoto 653d6ad9c3 Paywalls: added offerName parameter (#2877)
This is now used in `MultiPackageTemplate`, defaulting to the
`productName` if none is set.
2023-09-14 18:28:11 -07:00
NachoSoto b2897768f1 Paywalls: handle missing paywalls gracefully (#2855)
- Improved `PaywallView` API: now there's only 2 constructors (with
optional `Mode` parameters):
    - `PaywallView()`
    - `PaywallView(offering:)`
- New `PaywallData.default` as a fallback when trying to present a
paywall with missing data (either because it failed to decode, or it's
missing)
- Extracted error state handling to `ErrorDisplay` (used by
`PaywallView` and `AsyncButton` now). It can optionally dismiss the
presenting sheet.
- Handling offering loading errors in `PaywallView`
- Improved `DebugErrorView` to allow displaying a fallback view:
```swift
DebugErrorView(
    "Offering '\(offering.identifier)' has no configured paywall.\n" +
    "The displayed paywall contains default configuration.\n" +
    "This error will be hidden in production.",
    releaseBehavior: .replacement(
        AnyView(
            LoadedOfferingPaywallView(
                offering: offering,
                paywall: .default,
                mode: mode,
                introEligibility: checker,
                purchaseHandler: purchaseHandler
            )
        )
    )
)
```
- Added `LoadingPaywallView` as a placeholder view during loading
- Improved `MultiPackageTemplate` and `RemoteImage` to fix some layout
issues during transitions
- Added transition animations between loading state and loaded paywall
2023-09-14 18:28:11 -07:00
NachoSoto c57b8d0f3d Paywalls: added new blurredBackgroundImage configuration (#2852)
<img width="387" alt="Screenshot 2023-07-20 at 18 21 42"
src="https://github.com/RevenueCat/purchases-ios/assets/685609/b8cb4109-fdc7-4c6a-8014-b2f778b03bcd">
2023-09-14 18:28:11 -07:00
NachoSoto b09c617a31 Paywalls: added FooterView (#2850)
This adds 3 new features: restore purchases, ToS, and privacy policy.
All configurable.

![image](https://github.com/RevenueCat/purchases-ios/assets/685609/b38dadec-9fa1-4d48-876d-b53d0dda93d9)
2023-09-14 18:28:11 -07:00
NachoSoto ef8877032c Paywalls: multi-package template (#2840)
- 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">
2023-09-14 18:28:11 -07:00
NachoSoto c8b87b0d87 Paywalls: TrialOrIntroEligibilityChecker.eligibility(for packages:) (#2846)
This will be used for the multi-package template.

Includes #2858.
2023-09-14 18:28:11 -07:00