feat(workflows): Enable workflow resolution for PaywallView#6887
Merged
Conversation
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 6f7a8f6. Configure here.
It's only used by tvOS-excluded tests, so defining it outside the guard left it unused on tvOS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vegaro
reviewed
Jun 3, 2026
- Clarify UIKit prefetchExitOffer comment: under workflows the exit offer is emitted by WorkflowPaywallView and consumed by the SwiftUI presentation layer; the UIKit controller doesn't bridge it yet (follow-up for swipe-to-dismiss). - Reuse the offerings snapshot in the .defaultOffering path instead of fetching offerings() twice; thread it through resolveWorkflowContext. - Drop the always-true workflowsEndpointEnabled param from resolveWorkflowPaywallViewData/resolveWorkflowContext and remove the dead guard; callers already gate on the flag. - Document why cachedInitialOffering returns nil under workflows. - Remove ProcessInfo-dependent cachedInitialOffering tests, now covered deterministically by the explicit-flag matrix tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
Author
|
I think we can move forward with this one @vegaro, and discuss and tackle #6887 (comment) in the follow-up |
vegaro
approved these changes
Jun 4, 2026
vegaro
left a comment
Member
There was a problem hiding this comment.
one comment about some cleanup, otherwise it looks good
Collapse the duplicated content switch into a single injectable overload. The public cachedInitialOffering(for:) now just resolves the workflow flag (reading ProcessInfo on non-tvOS, false on tvOS where the endpoint isn't available) and delegates, so the switch lives in one place. Keeps the workflowsEndpointEnabled overload so tests can cover both flag states deterministically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Summary
PaywallView.offering and .defaultOffering content when workflowsEndpointEnabled is on.Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-06-02.at.16.33.26.mov
Note
Medium Risk
Changes paywall offering resolution and initial render behavior behind a feature flag; UIKit exit offers on dismiss are intentionally not wired for workflows yet.
Overview
When workflows are enabled,
PaywallViewnow resolves workflow-backed paywall data for.offeringand.defaultOffering(not only offering identifiers), including mapped paywall components and aWorkflowContext. Synchronous cached offering is alwaysnilin that mode so the UI does not flash the wrong paywall before async resolution.resolveWorkflowContextno longer gates on the flag internally (callers decide) and can reuse an already-fetchedOfferingssnapshot. UIKit skips legacy exit-offer prefetch while workflows own that path (noted as a follow-up for swipe-to-dismiss). Tests cover both flag states; PaywallsTester drops separate workflow demo modes because normal presentation now uses workflows.Reviewed by Cursor Bugbot for commit b728b63. Bugbot is set up for automated code reviews on this repo. Configure here.
AI session context
AI Context
Metadata
codex/codex-20260602-155608Not capturedGoal
Enable workflow resolution for
PaywallView: whenworkflowsEndpointEnabledis on, resolve workflow paywall data for.offeringand.defaultOfferingcontent (not just offering identifiers), keep the legacy cached/offering-only path gated behind the flag being off, and skip the UIKit legacy exit-offer prefetch while workflow context owns exit-offer resolution. Presentation now works on tap (no long press).Agent Contribution
r3355069412and confirmed the twoswitch contentblocks incachedInitialOfferingwere byte-for-byte duplicates.b728b635e): collapsed the duplicated switch into a single injectable overloadcachedInitialOffering(for:workflowsEndpointEnabled:); made the publiccachedInitialOffering(for:)a thin wrapper that resolves the flag (ProcessInfoon non-tvOS,falseon tvOS) and delegates. Net+24 / -35in that file.#if !os(tvOS)guard.Human Decisions
ProcessInfoinline in a single function) so tests cover both flag states deterministically; agreed to a follow-up (feat(workflows): synchronously seed workflow paywall from warm cache #6905) for synchronous seeding from the warm cache.Key Implementation Decisions
cachedInitialOffering(for:workflowsEndpointEnabled:)overload as the single home of the switch; public overload delegates.ProcessInfo.workflowsEndpointEnabledis defined only inside#if !os(tvOS)(extension inWorkflowContext.swift), so tvOS cannot read it; and two tests inject the flag to cover both states without depending on the-EnableWorkflowsEndpointlaunch arg.ProcessInfoinline in one function (the literal review suggestion) would not compile on tvOS and would break deterministic test coverage.resolveWorkflowPaywallViewDataintentionally re-resolves the workflow screen's base offering rather than reusing the passed offering.Files / Symbols Touched
RevenueCatUI/Purchasing/PurchaseHandler.swiftcachedInitialOffering(for:),cachedInitialOffering(for:workflowsEndpointEnabled:),resolvePaywallViewData(for:workflowsEndpointEnabled:),resolveWorkflowPaywallViewData,resolveWorkflowContextRevenueCatUI/UIKit/PaywallViewController.swiftTests/RevenueCatUITests/Data/PaywallViewConfigurationTests.swifttestCachedInitialOfferingReturnsNilForAllContentWhenWorkflowsEndpointEnabled,testCachedInitialOfferingUsesCachedOfferingsWhenWorkflowsEndpointDisabledTests/RevenueCatUITests/Purchasing/WorkflowContextTests.swiftresolveWorkflowContextTests/TestingApps/PaywallsTester/.../PaywallViewMode+Extensions.swiftDependencies / Config / Migrations
-EnableWorkflowsEndpointlaunch argument (ProcessInfo.workflowsEndpointEnabled,#if !os(tvOS)only). Temporary rollout gate.Validation
swift build --target RevenueCatUI: success (12.66s) after the refactor.b728b635eNot capturedat time of writing.Validation Gaps
swift build+ unchanged test target behavior.swift build(host is macOS); reasoned via#if/flag analysis.Review Focus
cachedInitialOffering(for:)produce identical results to the previous split implementation for all threeContentcases on both tvOS and non-tvOS?ProcessInfo) acceptable given the tvOS availability + test-determinism constraints?Risks / Reviewer Notes
PaywallViewConfigurationTests.Non-goals / Out of Scope
Omitted Context