Wire custom callbacks through getPaywall#464
Merged
Conversation
Adds an optional `onCustomCallback` parameter to `getPaywall(...)` so paywalls embedded by the developer can handle custom webview callbacks. Previously this was only wired up through `register()`, which presents in its own UIWindow. The handler is stored on `PaywallViewControllerDelegateAdapter` and registered with `CustomCallbackRegistry` from `PaywallViewController` on init / when the delegate is reassigned, and unregistered on deinit. Bumps version to 4.15.1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Only unregister the custom callback handler when this PVC was the one that registered it. Prevents a getPaywall-flow VC from clearing a register-flow handler that happens to share the same paywall identifier. Co-Authored-By: Claude Opus 4.7 (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.
Changes in this pull request
onCustomCallbackparameter toSuperwall.getPaywall(forPlacement:params:paywallOverrides:delegate:onCustomCallback:)so paywalls retrieved for embedding can handle custom webview callbacks. Previously this was only wired up throughregister(), which presents the paywall in its ownUIWindow— embedding code (e.g. SwiftUI onboarding flows that need to layer their own UI over the paywall) had no way to receive callbacks and the webview always got a failure result.PaywallViewControllerDelegateAdapterwith anonCustomCallbackclosure and registers/unregisters it with the existingCustomCallbackRegistryfromPaywallViewController(init,delegate.didSet, deinit). Reuses the same registry as theregister()path, so the underlying message-handler dispatch inPaywallMessageHandler.handleRequestCallbackis unchanged.Tests
Adds
CustomCallbackGetPaywallTestswith 4 tests covering: handler registered when adapter has one; no registration when handler isnil; reassigning the delegate updates registration (anddelegate = nilclears it); deinit unregisters. Updates existing test mocks (SurveyManagerTests,PresentPaywallOperatorTests,WebEntitlementRedeemerTests,TrackingLogicTests) to pass the newcustomCallbackRegistry:init parameter.Checklist
CHANGELOG.mdfor any breaking changes, enhancements, or bug fixes.swiftlintin the main directory and fixed any issues.🤖 Generated with Claude Code
Greptile Summary
This PR wires
onCustomCallbackthroughgetPaywall()so embedded paywalls can receive custom webview callback results instead of always getting a failure. It extendsPaywallViewControllerDelegateAdapterwith the closure and manages registration/unregistration with the sharedCustomCallbackRegistryvia a newsyncCustomCallbackRegistration()helper called frominit,delegate.didSet, anddeinit.Confidence Score: 5/5
Safe to merge; the one concern is a low-probability cross-path interference scenario that is a P2 design suggestion, not a blocking defect.
All findings are P2. The unconditional
unregisterindeinit/syncCustomCallbackRegistration()only becomes a problem when bothregister()andgetPaywall()are used simultaneously with the same paywall identifier, which is an unusual usage pattern. Core logic, threading, and test coverage are all solid.PaywallViewController.swift— thesyncCustomCallbackRegistration/deinitunregister interaction warrants a second look if the two presentation paths are ever exercised concurrently on the same paywall identifier.Important Files Changed
customCallbackRegistrydependency andsyncCustomCallbackRegistration(); the unconditionalunregisterindeinitand theelsebranch can silently evict a handler registered by theregister()path.onCustomCallbackclosure to the adapter with a default-nil init parameter; clean, minimal change.onCustomCallbackparameter through both the completion-block and asyncgetPaywalloverloads; properly defaults tonilfor backwards compatibility.customCallbackRegistrytoPaywallViewControllerinit; mechanical, correct change.Sequence Diagram
sequenceDiagram participant Caller participant Superwall participant PaywallViewControllerDelegateAdapter participant PaywallViewController participant CustomCallbackRegistry participant WebView Caller->>Superwall: getPaywall(forPlacement:onCustomCallback:) Superwall->>PaywallViewControllerDelegateAdapter: init(swiftDelegate:objcDelegate:onCustomCallback:) Superwall->>PaywallViewController: init(...customCallbackRegistry:) PaywallViewController->>PaywallViewController: syncCustomCallbackRegistration() PaywallViewController->>CustomCallbackRegistry: register(paywallIdentifier:handler:) Caller->>Caller: embed / present PaywallViewController WebView->>PaywallMessageHandler: handleRequestCallback PaywallMessageHandler->>CustomCallbackRegistry: getHandler(paywallIdentifier:) CustomCallbackRegistry-->>PaywallMessageHandler: handler closure PaywallMessageHandler->>PaywallViewControllerDelegateAdapter: onCustomCallback(callback) PaywallViewControllerDelegateAdapter-->>PaywallMessageHandler: CustomCallbackResult Caller->>PaywallViewController: delegate = nil / deinit PaywallViewController->>CustomCallbackRegistry: unregister(paywallIdentifier:)Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "Wire custom callbacks through getPaywall" | Re-trigger Greptile