Skip to content

[Rules] Introduce rule system#6285

Merged
facumenzella merged 41 commits into
mainfrom
facundo/coco
Mar 6, 2026
Merged

[Rules] Introduce rule system#6285
facumenzella merged 41 commits into
mainfrom
facundo/coco

Conversation

@facumenzella

@facumenzella facumenzella commented Feb 18, 2026

Copy link
Copy Markdown
Member

Summary

Adds support for new condition types in paywall component overrides for conditional configurability V0:

  • variableCondition: Compare custom variables with equality operators (=, !=)
  • selectedPackageCondition: Check if selected package is in a list (in, not in)
  • Extended introOfferCondition and promoOfferCondition with operator/value fields

https://github.com/RevenueCat/sdk-specs/tree/main/openspec/changes/add-conditional-configurability-v0

Also adds:

  • ConditionValue enum for string/int/double/bool comparison values
  • EqualityOperator enum for =, != operators
  • ArrayOperator enum for in, not in operators
  • Backwards compatibility with legacy intro_offer/promo_offer format
  • Fallback to .unsupported for unknown condition types
  • Comprehensive unit tests for deserialization and edge cases

Android equivalent: RevenueCat/purchases-android#3110

Test plan

  • Unit tests for JSON deserialization of all new condition types
  • Unit tests for backwards compatibility with legacy conditions
  • Unit tests for unknown/malformed conditions falling back to unsupported

🤖 Generated with Claude Code


Note

Medium Risk
Updates paywall override decoding and evaluation across many V2 components, so mis-parsed conditions or missing context (selected package/custom variables) could change paywall visibility/styling at runtime. Risk is mitigated by a global fallback that discards rule-based overrides when unsupported conditions are detected.

Overview
Adds conditional configurability v0 to paywall component overrides by introducing ExtendedCondition decoding (with ConditionValue, equality/array operators) and evaluating overrides against a new ConditionContext (selected package + custom variables).

Threads this context through V2 component view models (Text, Image, Icon, Video, Stack, Carousel, Timeline, Tabs) and adds an environment key for selectedPackageId; if any unsupported condition is found anywhere in a paywall, the factory now globally discards rule-based overrides and logs Strings.paywall_contains_unsupported_condition.

Also makes CustomVariableValue.number/.bool public, adds previews covering conditional behavior, and adds unit tests for condition deserialization plus new logging for malformed/unrecognized condition types.

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

…nal configurability

Add ExtendedCondition enum as @_spi(Internal) to support new condition types
while keeping the public Condition API stable. This includes:

- ExtendedCondition enum with associated values for variableCondition,
  selectedPackageCondition, extended introOffer/promoOffer conditions
- EqualityOperator and ArrayOperator enums for condition evaluation
- ConditionValue enum for type-safe variable values
- ComponentOverride now stores ExtendedCondition internally, exposes
  public Condition via computed property
- Updated PresentedPartials to use ExtendedCondition
- Comprehensive deserialization tests

The public Condition enum remains unchanged as String raw-value to
maintain API stability. New condition types map to .unsupported in
the public API.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The existing test file needs SPI access to use ExtendedCondition
cases after the restructuring for conditional configurability.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
facumenzella and others added 2 commits February 18, 2026 13:36
Match Android test coverage for edge cases:
- Unknown operator falls back to unsupported
- Wrong field types fall back to unsupported
- Empty JSON object falls back to unsupported
- JSON without type field falls back to unsupported

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The decoder now wraps the entire decoding logic in a do-catch block,
so that empty JSON objects or JSON without a "type" field fall back
to `.unsupported` instead of throwing a keyNotFound error.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@emerge-tools

emerge-tools Bot commented Feb 18, 2026

Copy link
Copy Markdown

3 builds increased size, 1 build had no size change

Name Version Download Change Install Change Approval
RevenueCat
com.revenuecat.PaywallsTester
1.0 (1) 17.7 MB ⬆️ 112.6 kB (0.64%) 63.5 MB ⬆️ 410.8 kB (0.65%) N/A
BinarySizeTest
com.revenuecat.binary-size-test.local-source
1.0 (1) 3.8 MB ⬆️ 40.2 kB (1.07%) 11.5 MB ⬆️ 118.6 kB (1.05%) ⏳ Needs approval
BinarySizeTest
com.revenuecat.binary-size-test.cocoapods
1.0 (1) 5.8 MB ⬆️ 53.9 kB (0.94%) 25.5 MB ⬆️ 189.3 kB (0.75%) ⏳ Needs approval
BinarySizeTest
com.revenuecat.binary-size-test.spm
1.0 (1) 4.0 MB ⬆️ 9 B 12.1 MB - N/A

RevenueCat 1.0 (1)
com.revenuecat.PaywallsTester

⚖️ Compare build
⏱️ Analyze build performance

Total install size change: ⬆️ 410.8 kB (0.65%)
Total download size change: ⬆️ 112.6 kB (0.64%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 149.4 kB
RevenueCatUI.TabsComponentViewModel.TabsComponentViewModel ⬆️ 26.3 kB
RevenueCatUI.StackComponentViewModel.StackComponentViewModel ⬇️ -16.0 kB
RevenueCatUI.VideoComponentViewModel.VideoComponentViewModel ⬆️ 11.8 kB
Code Signature ⬆️ 9.8 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 118.6 kB (1.05%)
Total download size change: ⬆️ 40.2 kB (1.07%)

Largest size changes

Item Install Size Change
📝 RevenueCatUI.VideoComponentViewModel.styles(state,condition,isEli... ⬆️ 13.3 kB
🗑 RevenueCatUI.VideoComponentViewModel.styles(state,condition,isEli... ⬇️ -9.6 kB
📝 RevenueCatUI.TabsComponentStyle.value witness ⬆️ 7.9 kB
📝 RevenueCatUI.CarouselComponentViewModel.styles(state,condition,is... ⬆️ 6.6 kB
📝 RevenueCatUI.ImageComponentViewModel.styles(state,condition,isEli... ⬆️ 6.0 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 189.3 kB (0.75%)
Total download size change: ⬆️ 53.9 kB (0.94%)

Largest size changes

Item Install Size Change
DYLD.String Table ⬆️ 32.5 kB
DYLD.String Table ⬆️ 15.9 kB
📝 RevenueCatUI.VideoComponentViewModel.styles(state,condition,isEli... ⬆️ 11.7 kB
🗑 RevenueCatUI.VideoComponentViewModel.styles(state,condition,isEli... ⬇️ -9.6 kB
RevenueCatUI.Template2View.iconImage ⬆️ 9.5 kB
View Treemap

Image of diff

BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm

No changes to report


🛸 Powered by Emerge Tools

Comment trigger: Size diff threshold of 100.00kB exceeded

facumenzella and others added 2 commits February 18, 2026 15:17
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@facumenzella

Copy link
Copy Markdown
Member Author

Note! The danger check about is a false positive because the extension has spi but not the type inside (I think)

facumenzella and others added 2 commits February 20, 2026 11:06
Normalize legacy intro_offer/promo_offer conditions to their extended form
(operator: .equals, value: true) during deserialization instead of having
separate cases for legacy and extended forms.

This simplifies the enum and evaluation logic while maintaining full
backwards compatibility with legacy JSON.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rename for consistency with other cases (.compact, .medium, etc.):
- introOfferCondition → introOffer
- promoOfferCondition → promoOffer
- variableCondition → variable
- selectedPackageCondition → selectedPackage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment thread Package.resolved
facumenzella and others added 3 commits February 20, 2026 13:14
…on evaluation (#6286)

* [Conditional Configurability][2] Add ConditionContext and evaluation logic

- Add ConditionContext struct for passing evaluation context
- Add buildPartial overload that accepts ConditionContext
- Add shouldApply overload with full condition evaluation
- Add evaluateCondition for all condition types
- Add helper methods for variable, package, and boolean condition evaluation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix availability annotations and CustomVariableValue usage

- Add @available(iOS 15.0, ...) to ConditionContext and related methods
- Fix matchesValue to use CustomVariableValue getters (.stringValue,
  .boolValue, .doubleValue) instead of pattern matching on private enum

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Simplify shouldApply by delegating to iOS 15+ version

The else branch is dead code since Paywalls is iOS 15+ anyway.
This consolidates the condition evaluation logic in one function.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…o/promo condition evaluation (#6287)

* [Conditional Configurability][3] Add condition evaluation tests

Add comprehensive tests for the condition evaluation logic:
- Selected package condition tests (in/not in operators)
- Variable condition tests (string, int, not found)
- Extended intro offer condition tests (equals/not equals)
- Multiple conditions (AND logic) tests
- Unsupported condition tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add missing condition evaluation tests and fix availability

- Add promo offer condition tests with operators
- Add variable boolean, double, and type mismatch tests
- Add intro offer negative test case
- Fix @available annotations for ConditionContext and related methods
- Fix matchesValue to use CustomVariableValue getters

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix type-strict variable condition evaluation and remove unrelated files

- Add isString, isNumber, isBool type checking methods to CustomVariableValue
- Update matchesValue to perform type-strict comparison (string != int, etc.)
- Remove accidentally committed PR_6285_review.md and package-lock.json
- Revert unrelated Package.resolved changes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…oPresentedOverrides (#6288)

* [Conditional Configurability][3] Add condition evaluation tests

Add comprehensive tests for the condition evaluation logic:
- Selected package condition tests (in/not in operators)
- Variable condition tests (string, int, not found)
- Extended intro offer condition tests (equals/not equals)
- Multiple conditions (AND logic) tests
- Unsupported condition tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add missing condition evaluation tests and fix availability

- Add promo offer condition tests with operators
- Add variable boolean, double, and type mismatch tests
- Add intro offer negative test case
- Fix @available annotations for ConditionContext and related methods
- Fix matchesValue to use CustomVariableValue getters

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix type-strict variable condition evaluation and remove unrelated files

- Add isString, isNumber, isBool type checking methods to CustomVariableValue
- Update matchesValue to perform type-strict comparison (string != int, etc.)
- Remove accidentally committed PR_6285_review.md and package-lock.json
- Revert unrelated Package.resolved changes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* [Conditional Configurability][4] Add unsupported condition detection

- Add `PaywallError.unsupportedCondition` case for future fallback support
- Add `containsUnsupportedConditions()` method to detect unsupported conditions
- Add logging string for unsupported condition warning
- Add comprehensive tests for unsupported condition detection

Note: The actual fallback mechanism (throwing and catching at paywall level)
will be implemented in a follow-up PR to avoid cascading changes to all
component ViewModels.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Make CustomVariableValue.number and .bool public

Allow developers to pass numeric and boolean custom variables to paywalls,
enabling condition evaluation based on these types.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Update API tester to use public .number() and .bool() methods

The CustomVariableValue factory methods .number() and .bool() are now
public. Update the API tester to use these methods directly instead of
using .string() for all values.

Existing test coverage in VariableHandlerV2Tests.swift already covers
these factory methods comprehensively.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Integrate unsupported condition validation into toPresentedOverrides

This matches Android's approach where toPresentedOverrides checks for
unsupported conditions and throws PaywallError.unsupportedCondition,
triggering fallback to the default paywall.

Changes:
- toPresentedOverrides now throws when unsupported conditions are found
- Updated all view model initializers to be throwing
- Updated ViewModelFactory to use try when instantiating view models
- Used try? with fallback for video backgrounds in SwiftUI contexts
- Updated preview code with try!/force_try

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add tests for toPresentedOverrides throwing on unsupported conditions

Add test coverage verifying that toPresentedOverrides throws
PaywallError.unsupportedCondition when any override contains an
unsupported condition type.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* [Conditional Configurability][5] PR comments and fallback paywall (#6319)

* Integrate unsupported condition validation into toPresentedOverrides

This matches Android's approach where toPresentedOverrides checks for
unsupported conditions and throws PaywallError.unsupportedCondition,
triggering fallback to the default paywall.

Changes:
- toPresentedOverrides now throws when unsupported conditions are found
- Updated all view model initializers to be throwing
- Updated ViewModelFactory to use try when instantiating view models
- Used try? with fallback for video backgrounds in SwiftUI contexts
- Updated preview code with try!/force_try

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* suggestions

^ Conflicts:
^	RevenueCatUI/Data/CustomPaywallVariables.swift
^	RevenueCatUI/Templates/V2/ViewModelHelpers/PresentedPartials.swift

* internal bool and number

* fallback paywall

* Fix compilation error and SwiftLint violations

- Fix call to renamed method: containsUnsupportedConditions -> hasUnsupportedCondition
- Rename variable 'c' to 'component' to satisfy identifier_name rule
- Add swiftlint:disable for cyclomatic_complexity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove accidental .package.resolved file

* Remove extra blank lines

---------

Co-authored-by: Facundo Menzella <facumenzella@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Add non-throwing factory for video backgrounds

- Add VideoComponentViewModel.forBackground() for video backgrounds
- Video backgrounds don't have overrides, so no validation needed
- Remove try? fallback pattern in DisplayableColor.swift
- Consistent with other components: early validation, non-throwing where safe

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com>
Comment thread RevenueCat.xcodeproj/project.pbxproj
Comment thread RevenueCatUI/Templates/V2/ViewModelHelpers/PresentedPartials.swift
facumenzella and others added 5 commits March 4, 2026 16:36
Verify that conditions with non-boolean values (e.g., string instead of
bool) gracefully fall back to .unsupported, triggering the fallback paywall.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add unit tests derived from the bug bash test plan to cover:
- Override precedence with visibility (two/three overrides, last-matching wins)
- Same condition evaluated independently on multiple components
- Condition + selected state interaction
- Variable match/mismatch for text replacement scenarios
- Intro offer with different eligibility states
- Different condition types on sibling components
- containsUnsupportedConditions for carousel, tabs, button, package, deep nesting

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add Emerge snapshot previews for conditional configurability

Add SwiftUI previews that test basic show/hide behavior using
variable conditions on Text and Stack components. These will be
automatically picked up by Emerge's SnapshotPreviews for visual
regression testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Improve snapshot preview names for easier debugging

Make display names include the condition, operator, value, and expected
outcome so broken snapshots can be diagnosed at a glance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add ConditionalConfigurabilityPreview.swift to xcodeproj

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix notEquals preview: use matching variable value so condition triggers

The preview set tier="free" with a notEquals "free" condition, which
evaluates to false — the override never applied. Changed to tier="premium"
so the condition matches and the text is correctly hidden.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…6406)

* Show default paywall instead of fallback when unsupported conditions found

Per the spec, when the SDK encounters condition types it doesn't
recognize, it should render the same V2 paywall with only legacy
overrides applied — not fall back to a completely different V1 paywall.

When any unsupported condition is found, all rule-based overrides
(variable, selected_package, intro_offer_condition,
promo_offer_condition, and unsupported) are discarded. Only legacy
overrides (compact, medium, expanded, selected, introOffer,
promoOffer, multipleIntroOffers) are kept. This aligns with Android
PR #3175.

Changes:
- Add `isRule` property to ExtendedCondition to distinguish
  conditional configurability rules from legacy base conditions
- Update toPresentedOverrides to filter out all rule-based overrides
  when any unsupported condition is present
- Remove throw from PaywallsV2View (keep warning log)
- Remove PaywallError.unsupportedCondition (no longer thrown)
- Update log message to explain overrides will be ignored

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Propagate discardRules globally when any component has unsupported conditions

When any component in the paywall tree contains unsupported conditions,
all rule-based overrides are now discarded globally across every component,
not just per-component. This matches the spec requirement for rendering the
"default paywall" with only legacy overrides applied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Classify .unsupported as non-rule since it pre-dates conditional configurability

Only the extended conditions introduced by conditional configurability
(variable, selectedPackage, introOfferCondition, promoOfferCondition) are
classified as rules. .unsupported existed before coco as a fallback for
unrecognized condition types and always evaluates to false at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix button sheet detection, add cross-subtree tests, align log wording

- Fix containsUnsupportedConditions() to check button sheet destination
  stacks, not just the button's own stack
- Add cross-subtree integration tests: unsupported in button sheet and
  nested tabs triggers global discard on sibling components
- Update warning log to match Android: "Unsupported paywall rule
  encountered. Rendering paywall without conditional configurability rules."

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Remove redundant local hasUnsupportedCondition check from toPresentedOverrides

The global discardRules flag already walks the entire component tree,
so the per-component hasUnsupportedCondition() fallback in
toPresentedOverrides was redundant. Simplify to only check discardRules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Recurse into timeline item sub-components for unsupported condition detection

TimelineComponent.containsUnsupportedConditions() was only checking
the timeline's own overrides and each item's direct overrides, but not
recursing into item.title, item.description, or item.icon. This meant
unsupported conditions in those sub-components wouldn't set the global
discardRules flag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review feedback: drop unsupported overrides, deduplicate tree walk, add @_spi

- Filter also drops .unsupported overrides when discardRules is true
- Move warning log after factory call, read factory.discardRules
  instead of traversing the component tree twice
- Mark isRule as @_spi(Internal)
- Add tests: discardRules drops .unsupported and mixed legacy+rule overrides

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread Sources/Paywalls/Components/Common/ComponentOverrides.swift Outdated
facumenzella and others added 2 commits March 5, 2026 17:24
…oject

Log a warning when a known condition type fails to decode instead of
silently falling back to .unsupported. Also add ToPresentedOverridesTests.swift
to the Xcode project to fix the Danger bot missing-file warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread RevenueCatUI/Templates/V2/ViewModelHelpers/PresentedPartials.swift Outdated
@JZDesign JZDesign requested a review from a team March 5, 2026 17:41
…e package components (#6412)

PackageComponentView overrides PackageContext for its children (for variable
processing), which caused selected_package conditions to always evaluate against
the package component's own ID instead of the globally selected package.

Fix: introduce a separate @Environment(\.selectedPackageId) key set at the root
that is NOT overridden by PackageComponentView. All component views now read
selectedPackageId from this environment key for condition evaluation.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread RevenueCatUI/Templates/V2/Components/Tabs/TabsComponentView.swift
@facumenzella facumenzella requested a review from JZDesign March 6, 2026 12:27
@RevenueCat-Danger-Bot

RevenueCat-Danger-Bot commented Mar 6, 2026

Copy link
Copy Markdown
2 Warnings
⚠️ This PR increases the size of the repo by more than 100.00 KB (increased by 161.23 KB).
⚠️ Public enums should not be added. Consider using a struct with static properties or an @objc enum instead.

The following files contain new public enums:
• Sources/Paywalls/Components/Common/ComponentOverrides.swift

Generated by 🚫 Danger

facumenzella and others added 2 commits March 6, 2026 13:32
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +100 to +117
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

// Try bool first (could be decoded as number), then int, double, string
if let boolValue = try? container.decode(Bool.self) {
self = .bool(boolValue)
} else if let intValue = try? container.decode(Int.self) {
self = .int(intValue)
} else if let doubleValue = try? container.decode(Double.self) {
self = .double(doubleValue)
} else if let stringValue = try? container.decode(String.self) {
self = .string(stringValue)
} else {
throw DecodingError.typeMismatch(
ConditionValue.self,
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Expected string, number, or boolean value"

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.

Do we not have a condition type flag? This could get really heavy with a lot of conditions. Especially considering that we have a customer thinking about using them all for bringing their own localization (all strings, all 4 coding attempts per variable, and it will be every string on the paywall)

Right now we have 4n worst case and n best case. But I think we ought to have a flag of type, so we can serialize the type, inspect it, and then decode the exact value type that we want to, that would change it to 2n

Big bonus: it's capped at 2n if we add more types (I can't imagine what they are)

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.

Yea, I think we have a miss here. We can ship this way and fix it later. But we should add a type discriminator to be safe.

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.

not a bad idea yeah. I agree it's not blocking but a nice improvement

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.

Nice, I like this.

facumenzella added a commit that referenced this pull request Mar 6, 2026
These were promoted from internal to public in #6285.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These were promoted from internal to public in #6285.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread RevenueCatUI/Templates/V2/ViewModelHelpers/PresentedPartials.swift
@facumenzella facumenzella merged commit 9c0ce52 into main Mar 6, 2026
13 of 17 checks passed
@facumenzella facumenzella deleted the facundo/coco branch March 6, 2026 15:57
facumenzella added a commit that referenced this pull request Mar 6, 2026
The function was changed from `rethrows` to `throws` in #6285, but the
new filtering logic (`filter`, `allSatisfy`) doesn't throw independently
of the `convert` closure. Using `rethrows` avoids forcing unnecessary
`try` at call sites that pass non-throwing closures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
facumenzella added a commit that referenced this pull request Mar 9, 2026
* Restore `rethrows` on `toPresentedOverrides`

The function was changed from `rethrows` to `throws` in #6285, but the
new filtering logic (`filter`, `allSatisfy`) doesn't throw independently
of the `convert` closure. Using `rethrows` avoids forcing unnecessary
`try` at call sites that pass non-throwing closures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Remove unnecessary `try` at call sites with non-throwing closures

Since `toPresentedOverrides` is now `rethrows`, call sites passing
non-throwing closures no longer need `try`. Fixes pod lib lint warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix Video init: use non-throwing LocalizedVideoPartial(partial:) initializer

The `LocalizedVideoPartial.create(from:using:)` method was removed on
main. Use the direct initializer instead, which doesn't throw, allowing
the Video init and its call site to drop `throws`/`try`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants