Skip to content

Add close_workflow button action#6753

Merged
facumenzella merged 14 commits into
mainfrom
facu/close-workflow-button-action
May 13, 2026
Merged

Add close_workflow button action#6753
facumenzella merged 14 commits into
mainfrom
facu/close-workflow-button-action

Conversation

@facumenzella
Copy link
Copy Markdown
Member

@facumenzella facumenzella commented May 8, 2026

Summary

Ports purchases-android#3453 to iOS.

Supports the backend `close_workflow` button action for Paywalls V2 so it dismisses the entire paywall/workflow, including from nested contexts such as sheets, without introducing a source-breaking public API change.

Changes

  • Keeps `PaywallComponent.ButtonComponent.Action` unchanged as a public enum
  • Preserves backend `"close_workflow"` via an internal SPI marker (`isCloseWorkflowAction`) on `ButtonComponent`
  • Maps that marker to the internal `ButtonComponentViewModel.Action.closeWorkflow`
  • Threads a dedicated top-level `closeWorkflowAction` separately from contextual `onDismiss`, so `close_workflow` never reuses workflow back-navigation behavior
  • Uses that dedicated close action from nested contexts, including sheets
  • Logs a warning if `close_workflow` is triggered without a handler
  • Unit tests:
    • Decode/encode round-trip and isCloseWorkflowAction flag (testCloseWorkflowDecoding, testCloseWorkflowRoundTripsThroughEncoding)
    • Equality/hash regression: close_workflow and navigate_back buttons with the same .action value are distinct via isCloseWorkflowAction (testCloseWorkflowAndNavigateBackButtonsAreNotEqual)
    • ViewModel mapping: decoded close_workflow component maps to .closeWorkflow action with correct interaction value (ButtonComponentViewModelMappingTests)

Verification

  • `swift build`
  • `swift test`
  • `bundle exec fastlane run_api_tests`

Note

Medium Risk
Adds a new workflow dismissal path and custom decoding/encoding to preserve a backend-only action; mistakes could cause buttons to dismiss the wrong layer (step vs whole workflow) or regress component equality/telemetry.

Overview
Adds support for the backend close_workflow button action in Paywalls V2 so a button can dismiss the entire workflow/paywall (even from nested contexts like sheets) rather than performing step back-navigation.

This preserves API compatibility by decoding "close_workflow" as public .navigateBack while storing an internal isCloseWorkflowAction flag, mapping it to a new internal view-model action (.closeWorkflow), and threading a top-level closeWorkflowAction through the SwiftUI environment (with warning logs when unhandled). Tests cover decoding/round-tripping, equality/hash behavior, interaction value mapping, and project integration.

Reviewed by Cursor Bugbot for commit 467c8af. Bugbot is set up for automated code reviews on this repo. Configure here.

Ports RevenueCat/purchases-android#3453 to iOS. Adds a new
`close_workflow` button action that always dismisses the entire paywall,
regardless of workflow step or whether triggered from inside a sheet.

The action flows through the existing pipeline:
- `PaywallComponent.ButtonComponent.Action.closeWorkflow` (serialization)
- `ButtonComponentViewModel.Action.closeWorkflow` (view model)
- `closeWorkflowAction` environment key (set at RootView, propagates
  through sheets where local onDismiss only closes the sheet)
- `ButtonComponentView` reads the env key and calls it on tap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella marked this pull request as ready for review May 8, 2026 14:13
@facumenzella facumenzella requested review from a team as code owners May 8, 2026 14:13
Comment thread RevenueCatUI/Templates/V2/Components/Root/RootView.swift Outdated
Comment thread Sources/Paywalls/Components/PaywallButtonComponent.swift
@facumenzella facumenzella changed the title Add close_workflow button action Preserve close_workflow behavior without public API change May 11, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

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.

Fix All in Cursor

❌ 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 e15b057. Configure here.

Comment thread Sources/Paywalls/Components/PaywallButtonComponent.swift
@facumenzella facumenzella changed the title Preserve close_workflow behavior without public API change Add close_workflow button action (API-safe) May 11, 2026
@facumenzella facumenzella changed the title Add close_workflow button action (API-safe) Add close_workflow button action (API-safe) May 11, 2026
@facumenzella facumenzella changed the title Add close_workflow button action (API-safe) Add close_workflow button action May 11, 2026
@vegaro vegaro changed the title Add close_workflow button action Add close_workflow button action May 11, 2026
Comment thread RevenueCatUI/Templates/V2/Components/Root/RootView.swift Outdated
The environment modifier must be outer to bottomSheet — views created
inside BottomSheetOverlayModifier.body are siblings of content and only
inherit from the modifier's outer context, not from inner modifiers on
the content itself.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella requested a review from vegaro May 12, 2026 10:08
- ButtonComponentCodableTests: assert that close_workflow and navigate_back
  buttons with identical .action values are nonetheless unequal via
  isCloseWorkflowAction (Equatable and Hashable both verified)
- ButtonComponentViewModelMappingTests (new file): assert that a decoded
  close_workflow button maps to .closeWorkflow in the view model (interaction
  value "close_workflow"), and navigate_back maps to .navigateBack

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella requested a review from a team as a code owner May 12, 2026 11:34
facumenzella and others added 4 commits May 12, 2026 05:46
…deproj

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolve xcodeproj conflict: ffa6c18 removed the RevenueCatUITests
Sources build phase from RevenueCat.xcodeproj (target migrated to
Tuist), so drop the ButtonComponentViewModelMappingTests.swift addition
from that file — tests are picked up by the Tuist glob.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… xcodeproj

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread RevenueCatUI/Templates/V2/Components/Root/RootView.swift Outdated
…flow, drop fragile hash assertion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
facumenzella and others added 2 commits May 12, 2026 12:52
…aram from ComponentsView and RootView

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella requested a review from vegaro May 12, 2026 20:00
@facumenzella facumenzella merged commit c31d3b7 into main May 13, 2026
17 of 19 checks passed
@facumenzella facumenzella deleted the facu/close-workflow-button-action branch May 13, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants