Fix workflow exit offer presentation across sheet boundaries#6804
Conversation
Uses an environment Binding<Offering?> injected by PresentingPaywallModifier so WorkflowPaywallView can write the resolved exit offer directly, bypassing the preference-key path which does not propagate reliably across sheet presentation boundaries. Also adds "Workflow - Sheet" and "Workflow - Full" tester modes that present workflows through the full modifier stack (including exit offer handling). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4 builds increased size
RevenueCat 1.0 (1)
|
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 87.7 kB |
| Code Signature | ⬆️ 4.2 kB |
| DYLD.Exports | ⬆️ 1.1 kB |
| Other | ⬆️ 60.3 kB |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.local-source
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 12.6 kB (0.1%)
Total download size change: ⬆️ 3.8 kB (0.09%)
Largest size changes
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 5.4 kB |
| SwiftUI.ModifiedContent | ⬆️ 1.0 kB |
| SwiftUI.View.View | ⬆️ 960 B |
| RevenueCatUI.View.onChangeOf(perform) | ⬆️ 660 B |
| Code Signature | ⬆️ 624 B |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.cocoapods
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 49.8 kB (0.18%)
Total download size change: ⬆️ 6.5 kB (0.11%)
Largest size changes
| Item | Install Size Change |
|---|---|
| DYLD.String Table | ⬆️ 36.3 kB |
| SwiftUI.ModifiedContent | ⬆️ 1.1 kB |
| Code Signature | ⬆️ 1.0 kB |
| SwiftUI.View.View | ⬆️ 960 B |
| RevenueCatUI.View.onChangeOf(perform) | ⬆️ 660 B |
BinarySizeTest 1.0 (1)
com.revenuecat.binary-size-test.spm
⚖️ Compare build
📦 Install build
⏱️ Analyze build performance
Total install size change: ⬆️ 8.4 kB (0.08%)
Total download size change: ⬆️ 3.7 kB (0.09%)
Largest size changes
| Item | Install Size Change |
|---|---|
| SwiftUI.ModifiedContent | ⬆️ 1.0 kB |
| SwiftUI.View.View | ⬆️ 960 B |
| RevenueCatUI.View.onChangeOf(perform) | ⬆️ 660 B |
| SwiftUI.Environment | ⬆️ 528 B |
| Other | ⬆️ 5.2 kB |
🛸 Powered by Emerge Tools
Comment trigger: Size diff threshold of 100.00kB exceeded
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, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1960a71. Configure here.
Use exitOfferContext(for:currentStepId:) instead of context.exitOfferOffering when syncing the binding, and update on every step change via onChange so the binding is nil when the user is not on the triggering step — matching Android's shouldTriggerExitOfferForCurrentStep guard. Adds testExitOfferOfferingIsNotStepAware as a regression guard documenting that context.exitOfferOffering is not step-aware and must not be used here. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ailure Replace onChange(of:perform:) (deprecated in visionOS 1.0) with the project's onChangeOf backport extension. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>





Summary
Test plan
🤖 Generated with Claude Code
Note
Medium Risk
Changes how workflow exit-offer offerings are propagated during paywall presentation, which can affect when/if exit offers appear on dismissal across sheets/full-screen covers. Logic is localized but touches core paywall presentation flow and adds new environment plumbing that could regress exit-offer triggering if miswired.
Overview
Fixes workflow exit-offer presentation when a workflow paywall is hosted inside a
.sheet/.fullScreenCoverby adding an environment-injectedBinding<Offering?>(workflowExitOfferOfferingBinding) and havingWorkflowPaywallViewwrite the step-resolved exit offer directly to it on appear and on step changes.PresentingPaywallModifiernow injects itsexitOfferOfferingstate into the environment, bypassing unreliable SwiftUI preference propagation across presentation boundaries while keeping exit-offer resolution step-aware viaexitOfferContext(for:currentStepId:).Adds a regression test documenting that
context.exitOfferOfferingis not step-aware, and updates the PaywallsTester app to split workflow presentation into “Workflow - Sheet” and “Workflow - Full” paths that exercise the full modifier stack and manual exit-offer presentation.Reviewed by Cursor Bugbot for commit 0211a88. Bugbot is set up for automated code reviews on this repo. Configure here.