Skip to content

[Rules] Render default paywall instead of fallback for unsupported conditions#3175

Merged
vegaro merged 9 commits into
cesar/conditional-configurabilityfrom
cesar/default-paywall-unsupported-rules
Mar 5, 2026
Merged

[Rules] Render default paywall instead of fallback for unsupported conditions#3175
vegaro merged 9 commits into
cesar/conditional-configurabilityfrom
cesar/default-paywall-unsupported-rules

Conversation

@vegaro

@vegaro vegaro commented Mar 5, 2026

Copy link
Copy Markdown
Member

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.


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.

Written by Cursor Bugbot for commit ba8a4cb. This will update automatically on new commits. Configure here.

@vegaro vegaro requested a review from a team as a code owner March 5, 2026 10:13
…ed rules

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.
@vegaro vegaro force-pushed the cesar/default-paywall-unsupported-rules branch from c5d8028 to 8ca3d9b Compare March 5, 2026 10:13
@vegaro vegaro requested a review from facumenzella March 5, 2026 10:14
@RevenueCat-Danger-Bot

RevenueCat-Danger-Bot commented Mar 5, 2026

Copy link
Copy Markdown
1 Warning
⚠️ This PR increases the size of the repo by more than 100.00 KB (increased by 210.17 KB).

Generated by 🚫 Danger

facumenzella

This comment was marked as spam.

@facumenzella

Copy link
Copy Markdown
Member

As discussed in private, we need to handle this globally (not per component)

vegaro and others added 3 commits March 5, 2026 14:00
…component

The unsupported condition check now scans the entire component tree before
building styles. If any component has an unsupported condition, all rule-based
overrides are stripped across the entire paywall via a stripRules flag passed
through StyleFactory to toPresentedOverrides.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +96 to +98
public data class Unsupported(
val originalType: String,
) : Condition { override val isRule: Boolean get() = true }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have this one as false 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

good, will change, I had some doubts as well

@vegaro vegaro requested a review from facumenzella March 5, 2026 13:21

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Unsupported.isRule is false, bypassing stripRules filtering
    • ComponentOverride.Condition.Unsupported now overrides isRule to true so stripRules correctly removes unsupported-condition overrides.

Create PR

Or push these changes by commenting:

@cursor push 50ed4e7368
Preview (50ed4e7368)
diff --git a/purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/common/ComponentOverride.kt b/purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/common/ComponentOverride.kt
--- a/purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/common/ComponentOverride.kt
+++ b/purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/common/ComponentOverride.kt
@@ -95,7 +95,7 @@
         @Serializable
         public data class Unsupported(
             val originalType: String,
-        ) : Condition
+        ) : Condition { override val isRule: Boolean get() = true }
     }
 }
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.


@Test
fun `Should fall back to legacy paywall if override contains unsupported condition`() {
fun `Should render default paywall with legacy overrides when unsupported condition is present`() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we add an integration test here to verify the global strip behavior, not just that we stay on PaywallValidationResult.Components?

@facumenzella facumenzella left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just a few nits, looks great

@vegaro vegaro added the pr:fix A bug fix label Mar 5, 2026
@vegaro vegaro merged this pull request into cesar/conditional-configurability Mar 5, 2026
7 of 25 checks passed
@vegaro vegaro deleted the cesar/default-paywall-unsupported-rules branch March 5, 2026 14:44
vegaro added a commit that referenced this pull request Mar 5, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:fix A bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants