Fix selected_package condition inside package components#6412
Conversation
…e package components 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>
Generated by 🚫 Danger |
4 builds increased size
RevenueCat 1.0 (1)
|
| 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 |
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.6 kB (1.08%)
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 |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 185.3 kB (0.74%)
Total download size change: ⬆️ 52.7 kB (0.92%)
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 |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 8.1 kB (0.07%)
Total download size change: ⬆️ 2.9 kB (0.07%)
Largest size changes
| Item | Install Size Change |
|---|---|
| 📝 RevenueCat.SubscriberAttributesManager.setAppstackCampaignAttribu... | ⬆️ 2.2 kB |
| 📝 RevenueCat.Attribution.setAppstackAttributionParams(completion) | ⬆️ 1.3 kB |
| 📝 RevenueCat.SubscriberAttributesManager.stringValueForAppstackData... | ⬆️ 568 B |
| Other | ⬆️ 4.0 kB |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
📸 Snapshot Test1 modified, 9 added, 251 unchanged
🛸 Powered by Emerge Tools |
|
@vegaro just tested it with icons and works like a charm |
* [Conditional Configurability][1] Add new condition types for conditional 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> * Fix CI: Add @_spi(Internal) import to PresentedPartialsTests 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> * Add missing deserialization error handling tests 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> * Fix ExtendedCondition decoder to handle missing type field gracefully 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> * same line * Add clarifying comment about Condition's unused Codable implementation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add ConditionDeserializationTests.swift to Xcode project Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Simplify ExtendedCondition by removing redundant legacy cases 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> * Remove redundant Condition suffix from ExtendedCondition cases 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> * [Conditional Configurability][2] Implement `selected_package` condition 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> * [Conditional Configurability][3] Implement variable and extended intro/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> * [Conditional Configurability][4] Validate unsupported conditions in toPresentedOverrides (#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> * [bug-bash] Fix selectedPackage conditional visibility not working The selectedPackage condition was never evaluated correctly because components were calling buildPartial without passing ConditionContext. This meant selectedPackageId was always nil during condition evaluation. Updated all component ViewModels to: - Accept selectedPackageId parameter in their styles() method - Create ConditionContext with the selected package ID - Pass conditionContext to buildPartial() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [bug-bash] Add warning log for unrecognized paywall condition types Developers will now see a warning when the SDK encounters a condition type it doesn't recognize, helping them identify when they need to update the SDK. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [bug-bash] Add support for multiple_intro_offers condition type This condition is supported in Android. On iOS, it always evaluates to false since iOS does not support multiple intro offers. Adding this prevents the paywall from falling back to the default when this condition is present. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [bug-bash] Pass custom variables to ConditionContext for variable conditions Custom variable conditions were always evaluating to false because the customVariables dictionary was empty. Components now get the customPaywallVariables from the SwiftUI environment and pass them to their ViewModel's styles() method, which forwards them to ConditionContext for proper condition evaluation. Updated components: Stack, Image, Icon, Video, Timeline, Carousel. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [bug-bash] Make number() and bool() public for CustomVariableValue Developers need to be able to create numeric and boolean custom variable values, not just strings. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix tabs override condition conversion to preserve extended conditions (#6361) * Add missing condition evaluation unit tests for PresentedPartials Closes test coverage gap identified from Android PR #3156. Adds 15 new test cases covering intro/promo offer negative cases, type safety, override precedence, and cross-offer independence. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add multiple_intro_offers compatibility guardrail tests for iOS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * add bool and number support in paywalls tester (#6394) * Split intro/promo offer condition JSON keys for backward compatibility with older SDKs (#6397) Splits legacy boolean conditions (introOffer/promoOffer) from operator-based ones (introOfferCondition/promoOfferCondition) and updates JSON keys so old SDKs safely ignore new condition types. Also renames variable → variable_condition and selected_package → selected_package_condition. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * Review fixes: remove multipleIntroOffers from public API, restore private storage, epsilon double comparison - Remove `multipleIntroOffers` from public `Condition` enum to avoid source-breaking change on @Frozen enum. It remains in `ExtendedCondition` and maps to `.unsupported`. - Restore `Storage` and `storage` to `private` on `CustomVariableValue` — condition evaluation uses the existing `isString`/`isNumber`/`isBool` helpers instead. - Replace exact `==` double comparison with epsilon-based `doublesMatch` to handle floating point representation differences from JSON round-trips. - Add tests for epsilon comparison edge cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Remove unused legacy buildPartial and shouldApply overloads All callers use the new buildPartial with conditionContext parameter. Remove the legacy overload (without conditionContext) and its shouldApply wrapper that had an unnecessary #available gate returning false on pre-iOS 15. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix condition evaluation not using dashboard default custom variables ConditionContext was only receiving developer-provided custom variables from the SwiftUI environment, but not the dashboard-configured defaults. This caused variable-based conditions (e.g. "something == false") to always fail when the developer didn't explicitly provide the variable, even if a default was set in the dashboard. The fix merges defaultCustomVariables into ConditionContext at init time (developer values take priority), and passes them from all 8 view model sites that create ConditionContext. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Wire up conditional configurability for TabsComponent TabsComponentViewModel had presentedOverrides stored but never evaluated. Added a styles() method that creates a ConditionContext, calls buildPartial, and returns a TabsComponentStyle with overrides applied. The view now evaluates conditions and checks visibility before rendering. Also updated TabsComponentStyle.init to accept Background? instead of ColorScheme? to match the actual data model, and added a clarifying comment to CountdownComponentViewModel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add tests for intro/promo offer conditions with wrong value types 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> * Disable autocapitalization on custom variables value TextField Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add bug bash unit tests for conditional configurability (#6398) 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 (#6400) * 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> * Show default paywall instead of fallback for unsupported conditions (#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> * Add malformed condition logging and fix missing test file in Xcode project 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> * Fix selected_package condition evaluating against wrong package inside 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> * Rename condOp to conditionOperator in PresentedPartials Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add SelectedPackageId.swift to RevenueCat.xcodeproj Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add .number() and .bool() to CustomVariableValue API tester (#6415) These were promoted from internal to public in #6285. Co-authored-by: Claude Opus 4.6 <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>







Summary
selected_packageconditions inside package components were always evaluating against the package component's own ID instead of the globally selected packagePackageComponentViewoverridesPackageContextfor variable processing ({{ price }}), which also overrode the package ID used for condition evaluation@Environment(\.selectedPackageId)set at the root, which is NOT overridden byPackageComponentView. All component views now read from this environment key for condition evaluationTest plan
selected_packagecondition match/no-match/nil inside package component scopeswift build)🤖 Generated with Claude Code
Note
Medium Risk
Touches condition evaluation wiring across multiple Paywalls V2 components, which can affect visibility/styling for paywall layouts depending on selected package. Changes are mostly plumbing with good unit test coverage, but mistakes could cause incorrect paywall rendering.
Overview
Fixes
selected_packageconditions inside package-scoped components by introducing a new SwiftUI environment valueselectedPackageId(set at thePaywallsV2Viewroot and in previews) and updating component views to use it when computing styles/visibility.TextComponentViewModel.stylesnow takesselectedPackageIdseparately frompackageContext, ensuring condition evaluation uses the global selection while variable substitution still uses the component’s own package. Adds unit tests covering selected-package match/not-match/nil behavior and a non-regression test confirming text variable processing continues to use the localPackageContextpackage.Written by Cursor Bugbot for commit 8b05dd7. This will update automatically on new commits. Configure here.