Rules v0 Integration branch#3117
Merged
Merged
Conversation
This was referenced Feb 18, 2026
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3117 +/- ##
==========================================
- Coverage 79.30% 79.29% -0.01%
==========================================
Files 347 347
Lines 13992 14024 +32
Branches 1902 1907 +5
==========================================
+ Hits 11096 11121 +25
- Misses 2110 2115 +5
- Partials 786 788 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…nal configurability (#3110) ### Motivation The conditional configurability V0 feature requires new condition types in the data layer to support dynamic paywall component visibility based on variables, packages, and extended intro/promo offer conditions. ### Description - Adds `Variable`, `Package`, `SelectedPackage` data classes to `ComponentOverride.Condition` sealed interface - Extends `IntroOffer` and `PromoOffer` conditions from simple objects to data classes with `operator` and `value` fields (backwards compatible with legacy format) - Adds `EqualityOperator`, `ArrayOperator`, and `ConditionValue` types for condition evaluation - Updates `ConditionSerializer` to handle new types with fallback to `Unsupported` on parse errors - Comprehensive unit tests for deserialization, backwards compatibility, unknown types, and malformed data **Tasks:** PW-169 (1.1–1.13) Co-authored-by: Cursor <cursoragent@cursor.com>
…on evaluation (#3111) ### Motivation The `selected_package` condition allows paywall components to change their appearance based on which package the user has selected (e.g., show different text when annual vs monthly is selected). ### Description - Introduces `ConditionContext` to carry evaluation state (`selectedPackageId`, `currentPackageId`, `customVariables`) - Extends `buildPresentedPartial` to accept `ConditionContext` parameter - Implements `SelectedPackage` condition evaluation with `in` / `not in` operators - Threads selected package ID from all component state classes through to condition evaluation - Unit tests for `selected_package` condition evaluation (in, not in, no selection) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…, and extended intro/promo condition evaluation (#3112) ### Motivation Completes the V0 condition evaluation logic. - With variable conditions paywalls can adapt based on developer custom variables. - Selected package conditions let components change based on which package the user has selected. - Intro/promo conditions now support explicit operator (`=`/`!=`) and value fields for more precise control. ### Description - Implements `Variable` condition evaluation with equality comparison and type coercion (string, bool, int, double) - Implements `SelectedPackage` condition evaluation against the currently selected package ID - Implements extended `IntroOffer` and `PromoOffer` evaluation with `operator` (`=`/`!=`) and `value` fields - Removes `Package` condition (not used by backend or dashboard) - Threads `customVariables` through `ConditionContext` to all component state classes - Wires `customVariables` from `PaywallState.Loaded` into the evaluation pipeline Co-authored-by: Cursor <cursoragent@cursor.com>
114c8c1 to
b583bb3
Compare
… to trigger fallback paywall (#3113) ### Motivation When a paywall uses condition types that this SDK version doesn't understand (e.g., conditions added in a newer backend version), the SDK should gracefully fall back to the default paywall rather than rendering incorrectly. ### Description - Adds `UnsupportedCondition` validation in `toPresentedOverrides`. If any override contains an `Unsupported` condition, it produces a `PaywallValidationError` - Adds `PaywallValidationError.UnsupportedCondition` error type with descriptive error string --------- Co-authored-by: Cursor <cursoragent@cursor.com>
We were missing support for boolean and number custom variables <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Public API surface changes by making `CustomVariableValue.Number` and `CustomVariableValue.Boolean` publicly constructible and updating call sites to use typed values, which could affect downstream integrations and string formatting expectations. > > **Overview** > Adds first-class support for numeric and boolean custom paywall variables by making `CustomVariableValue.Number` and `CustomVariableValue.Boolean` public and exporting them in the public API (`api.txt`). > > Updates the tester apps and examples to construct and pass typed `Number`/`Boolean` values (instead of stringifying), including the custom variables editor dialog’s value creation logic and sample `CUSTOM_VARIABLES`/API tests. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 84aec0f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Now that we know the JSON is not changing, adjusted the logic to be simpler. Also found we can use `JSONPrimitive` and simplify things a lot. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes core JSON deserialization/fallback behavior for paywall components and override conditions; malformed payloads will now preserve the declared `type`, which could alter fallback outcomes in edge cases. > > **Overview** > Simplifies component override variable conditions by replacing the custom `ConditionValue` sealed type/serializer with a raw `JsonPrimitive`, and updates variable-matching logic in `PresentedPartial` to interpret strings/booleans/numbers directly. > > Hardens `SealedDeserializerWithDefault` to handle non-object JSON and to **preserve the discriminator `type`** when deserialization of a known type fails (instead of losing it), with expanded tests covering malformed known types, extra/unknown fields, and `null` variable values. Also promotes `kotlinx-serialization-json` to a runtime dependency in `revenuecatui` since `JsonPrimitive` parsing is now used in production code. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 92e8e9a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY --> > [!NOTE] > **Low Risk** > Test-only changes that broaden coverage for conditional override evaluation and compose visibility; minimal risk beyond potential CI/runtime cost from added UI tests. > > **Overview** > Expands `BuildPresentedPartialTests` to cover more edge cases in override selection/merging, including *last-match wins* behavior, `intro_offer`/`promo_offer` operator handling (`equals`/`not_equals`), and variable type-mismatch scenarios. > > Adds a large new `VisibilityConditionTests` suite exercising Compose rendering for conditional visibility/styling across components (carousel/timeline/video/text/stack/tabs), including interactions driven by `selected_package`, sibling independence, and footer/body cross-effects. > > Updates test helpers (`FakePaywallState`, test `toComponentsPaywallState`) to support injecting `customVariables` and a `stickyFooter` so the new UI tests can build realistic states. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c0c5ed6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Updates conditions to not reuse the old `intro_offer` and `promo_offer` ones. This way old SDKs behave as expected when a newer paywall with conditions sends some of the new ones. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it changes condition JSON deserialization keys and runtime evaluation for offer-based overrides, which could cause overrides to stop applying if payloads or clients are mismatched. Backward compatibility is partially maintained for legacy `intro_offer`/`promo_offer` objects, but new payloads must use the renamed `*_condition` types. > > **Overview** > **Updates the paywall override condition schema to avoid reusing legacy condition keys.** `intro_offer`/`promo_offer` are now plain boolean conditions (no operator/value), while new types `intro_offer_condition` and `promo_offer_condition` carry `operator` + `value`. > > **Renames the JSON `type` keys for parameterized conditions** from `selected_package` and `variable` to `selected_package_condition` and `variable_condition`, and updates `ConditionSerializer` mappings plus UI-side condition evaluation to match. Tests are adjusted to cover legacy payload tolerance (extra fields ignored for `intro_offer`/`promo_offer`) and the new `*_condition` types. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 918d463. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Facundo Menzella <facumenzella@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Generated by 🚫 Danger |
4aab30a to
d26ef51
Compare
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
8c423a1 to
07b8d82
Compare
…nditions (#3175) When an unsupported condition is encountered, instead of falling back to the generic fallback paywall, the SDK now renders the same components paywall with only base condition overrides applied, stripping all rule-based overrides. Also renames `IntroOfferCondition`/`PromoOfferCondition` to `IntroOfferRule`/`PromoOfferRule` and adds `Condition.isRule` to distinguish rule conditions from base conditions. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Alters runtime paywall rendering/override selection when unknown conditions are encountered, which may change UI behavior for some configurations. Logic is well-covered by new traversal and override-filtering tests, but impacts core presentation paths. > > **Overview** > **Unsupported condition handling is softened:** when any `ComponentOverride.Condition.Unsupported` is detected anywhere in the components tree, the SDK now renders the components paywall but *strips all overrides that use rule-based conditions* (plus the unsupported ones), leaving only base-condition overrides. > > This introduces `Condition.isRule` and renames `IntroOfferCondition`/`PromoOfferCondition` to `IntroOfferRule`/`PromoOfferRule`, updates condition evaluation/serialization accordingly, removes the `UnsupportedCondition` validation error pathway, and adds a recursive `containsUnsupportedCondition()` scan with expanded unit test coverage. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ba8a4cb. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
a209892 to
f14b962
Compare
This was referenced Mar 11, 2026
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Mar 12, 2026
**This is an automatic release.** ## RevenueCat SDK ### ✨ New Features * [EXPERIMENTAL]: Beta Galaxy Store Support (#2903) via Will Taylor (@fire-at-will) ### 🐞 Bugfixes * Skip installation on GCP CLI in run-firebase-test (#3218) via Will Taylor (@fire-at-will) * Fix reduced timeouts being used for HTTP requests when a proxy URL is configured (#3188) via Rick (@rickvdl) ## RevenueCatUI SDK ### 🐞 Bugfixes * Fix missing ripple effect in View-based paywall wrappers (#3206) via Toni Rico (@tonidero) ### Paywallv2 #### ✨ New Features * Rules v0 Integration branch (#3117) via Cesar de la Vega (@vegaro) ### 🔄 Other Changes * [Galaxy]: Add promotionEligibilities comment (#3214) via Will Taylor (@fire-at-will) * [EXTERNAL] Migrate deprecated buildDir to layout API (#3202) contributed by @AlexanderTalledo (#3212) via Toni Rico (@tonidero) * Remove automatic Claude code review workflow (#3211) via Cesar de la Vega (@vegaro) * Remove unused convention plugin (#3195) via Toni Rico (@tonidero) * [EXTERNAL] Integrate convention plugins into Version Catalogs (#3181) contributed by @AlexanderTalledo (#3194) via Toni Rico (@tonidero) * [EXTERNAL] Migrate androidx cardview dependency to version catalogs (#3192) contributed by @AlenxanderTalledo (#3193) via Toni Rico (@tonidero) * Improve AdMob adapter test coverage (#3204) via Pol Miro (@polmiro) * Bump fastlane-plugin-revenuecat_internal from `f5c099b` to `e146447` (#3197) via dependabot[bot] (@dependabot[bot]) * Fix integration tests (#3196) via Toni Rico (@tonidero) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk release bookkeeping: version strings and deployment paths are updated from `9.24.0-SNAPSHOT` to `9.24.0`, plus changelog/docs refresh. Main risk is accidental publishing/docs deployment to the wrong versioned location. > > **Overview** > Cuts the `9.24.0` release by updating all version references from `9.24.0-SNAPSHOT` to `9.24.0` (root `.version`, `gradle.properties`, and `Config.frameworkVersion`), and aligning sample/test app version catalogs to consume the released artifact. > > Updates documentation publishing to point at the `9.24.0` directory (CircleCI S3 sync and `docs/index.html` redirect) and refreshes `CHANGELOG.latest.md`/`CHANGELOG.md` with the `9.24.0` release notes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8e6d567. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

THIS IS A BASE BRANCH NO NEED TO REVIEW
Add support for Conditional Configurability in paywalls
Ability to set rules for:
And ability to configure component/Package visibility
Note
Medium Risk
Changes paywall component override deserialization and application logic (new condition types + rule stripping on unsupported conditions), which can affect which overrides render at runtime. Backward-compat fallbacks are added, but malformed/unknown config paths may still change paywall presentation.
Overview
Adds v0 conditional configurability for paywall component overrides by introducing new
ComponentOverride.Conditionrule types (selected package, custom variable, intro/promo offer with operators) and evaluating them via a newConditionContextthreaded through component state.Improves robustness and backwards-compat by making
SealedDeserializerWithDefaultfall back on unknown or malformed JSON, and by detecting anyUnsupportedcondition in the paywall tree to strip all rule-based overrides (and the unsupported ones) so the UI renders a “default paywall” using only base conditions.Exposes
CustomVariableValue.Number/Booleanpublicly and updates examples/testers to use typed values (including editor input), addskotlinx-serialization-jsonas a runtime dependency, and expands tests for the new condition parsing, evaluation, and stripping behavior.Written by Cursor Bugbot for commit 50c1246. This will update automatically on new commits. Configure here.