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 V2] Adds a StyleFactory #1965

Merged
merged 19 commits into from
Dec 10, 2024
Merged

[Paywalls V2] Adds a StyleFactory #1965

merged 19 commits into from
Dec 10, 2024

Conversation

JayShortway
Copy link
Member

Description

This PR includes all the scaffolding needed to recursively build the tree of ComponentStyles, and to validate that all components are correctly configured (e.g. all localizations are available). Any errors encountered are accumulated, so they can all be reported at once. (As opposed to failing fast, in which case only the first error would be reported.)

Apologies for the size of this PR, but I think separating some of these changes would make it hard to see how they're used. So, take this 👇 map and let me guide you.

🗺️ Guide

purchases

In support of the main change

  • Some classes are further opened up, i.e. made fake-public, because they are needed by revenuecatui. Data classes are made @Pokos if they're public.
  • Documentation is added to Result to explain the fact that it is duplicated in revenuecatui.

revenuecatui

In support of the main change

  • As discussed, the Result class from purchases is copied. A few extensions, mostly inspired by Arrow, are added. Most importantly:
    • zipOrAccumulate: takes multiple Results and either combines their successful values, or accumulates the errors.
    • mapOrAccumulate: takes a List<Result> and turns it into a Result<List> by mapping either its successful values, or accumulating the errors.
  • A new NonEmptyList class is added, also inspired by Arrow. This is useful for error accumulation. If we used a normal List type for this, we could still end up in the invalid state of receiving an Error result with an empty list of errors. Using a NonEmptyList, it is guaranteed we have at least 1 error in this case.
  • Tests are adjusted for the new Result type.
  • Tests are added for the new extensions.

The main change

  • There's a new StyleFactory that can create ComponentStyles recursively to build a tree. It uses the new Result class, the extensions, and the NonEmptyList to accumulate any errors found. Its logic is loosely based on the ViewModelFactory and individual *ComponentViewModels in iOS.
  • Adds PackageContext, based on the class of the same name in iOS.
  • Some transformation methods are added, such as toShape(), to be able to build the StackComponentStyle.
  • StyleFactoryTests are added.
  • VariableContextTests are added. This is an inner class to PackageContext containing the most logic.

fun create(component: PaywallComponent): Result<ComponentStyle, NonEmptyList<PaywallValidationError>> =
when (component) {
is ButtonComponent -> TODO("ButtonComponentStyle is not yet implemented.")
is ImageComponent -> TODO("ImageComponentStyle is not yet implemented.")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not entirely true anymore, but I'd like to verify that this approach works before we add support for all the other ComponentStyles.

@@ -15,6 +15,7 @@ import com.revenuecat.purchases.ui.revenuecatui.errors.PaywallValidationError
import com.revenuecat.purchases.ui.revenuecatui.extensions.createDefault
import com.revenuecat.purchases.ui.revenuecatui.extensions.createDefaultForIdentifiers
import com.revenuecat.purchases.ui.revenuecatui.extensions.defaultTemplate
import kotlin.Result
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was needed because the OfferingToStateMapper is in the same package as the new Result class, but it is using kotlin.Result.

@@ -86,6 +86,7 @@ dependencies {
testImplementation libs.coroutines.test
testImplementation libs.kotlinx.serialization.json
testImplementation libs.androidx.test.compose
testImplementation libs.androidx.test.compose.manifest
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests failed on CI due to a manifest merger issue.

This was already added as debugImplementation, but we run tests for the release variant (as well), e.g. testDefaultsReleaseUnitTest, so this makes sure we have it in any test variant, whether debug or release.

Copy link

codecov bot commented Dec 6, 2024

Codecov Report

Attention: Patch coverage is 37.50000% with 5 lines in your changes missing coverage. Please review.

Project coverage is 81.87%. Comparing base (f8155ad) to head (e633fa3).

Files with missing lines Patch % Lines
...at/purchases/paywalls/components/ImageComponent.kt 50.00% 0 Missing and 2 partials ⚠️
...at/purchases/paywalls/components/StackComponent.kt 0.00% 0 Missing and 2 partials ⚠️
...chases/paywalls/components/properties/MaskShape.kt 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1965   +/-   ##
=======================================
  Coverage   81.87%   81.87%           
=======================================
  Files         260      260           
  Lines        8493     8493           
  Branches     1226     1226           
=======================================
  Hits         6954     6954           
  Misses       1041     1041           
  Partials      498      498           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@tonidero tonidero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this all makes sense! Just a couple questions

@JayShortway JayShortway merged commit 43cbbf1 into main Dec 10, 2024
10 checks passed
@JayShortway JayShortway deleted the pw2-stylefactory branch December 10, 2024 13:03
tonidero pushed a commit that referenced this pull request Dec 12, 2024
**This is an automatic release.**

## RevenueCatUI SDK
### 🐞 Bugfixes
* Fix multi-tier template to allow optional header image (#1971) via
Josh Holtz (@joshdholtz)

### 🔄 Other Changes
* [Paywalls V2] Adds first version of `LoadedPaywallComponents` (#1970)
via JayShortway (@JayShortway)
* [Paywalls V2] Add `ButtonComponentView` (#1963) via Toni Rico
(@tonidero)
* [Paywalls V2] Adds `PaywallState.Loaded.Components` (#1969) via
JayShortway (@JayShortway)
* [Paywalls V2] Adds image background tests (#1967) via JayShortway
(@JayShortway)
* [Paywalls V2] `TextComponentView` updates when the theme changes
(#1966) via JayShortway (@JayShortway)
* [Paywalls V2] Adds a `StyleFactory` (#1965) via JayShortway
(@JayShortway)
* [EXTERNAL] fix: update polish translations (#1919) via @radko93
(#1964) via JayShortway (@JayShortway)
* [Paywalls V2] Adds `ImageComponentView` (#1959) via Toni Rico
(@tonidero)
* WebPurchaseRedemption: Rename `AlreadyRedeemed` result to
`PurchaseBelongsToOtherUser` (#1962) via Toni Rico (@tonidero)
* [Paywalls V2] Extends support for blurred shadows to all Android
versions (#1957) via JayShortway (@JayShortway)

Co-authored-by: revenuecat-ops <ops@revenuecat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants