Skip to content

Add guard to prevent pw from dismissing on deep link#390

Merged
ianrumac merged 2 commits intodevelopfrom
ir/fix/deep-link-dismiss
Apr 1, 2026
Merged

Add guard to prevent pw from dismissing on deep link#390
ianrumac merged 2 commits intodevelopfrom
ir/fix/deep-link-dismiss

Conversation

@ianrumac
Copy link
Copy Markdown
Collaborator

@ianrumac ianrumac commented Apr 1, 2026

Changes in this pull request

  • Add guard to prevent dismissing paywall on deep link
  • Fixes issue with isPaywallPresented being stuck in true

Checklist

  • All unit tests pass.
  • All UI tests pass.
  • Demo project builds and runs.
  • I added/updated tests or detailed why my change isn't tested.
  • I added an entry to the CHANGELOG.md for any breaking changes, enhancements, or bug fixes.
  • I have run ktlint in the main directory and fixed any issues.
  • I have updated the SDK documentation as well as the online docs.
  • I have reviewed the contributing guide

Greptile Summary

This PR fixes a bug where isPaywallPresented would remain stuck at true indefinitely when a deep link (or any other trigger) caused the SuperwallPaywallActivity to finish while an in-app browser overlay was open (isBrowserViewPresented = true). The root cause was that both beforeOnDestroy and destroyed had an early-return guard that skipped all dismiss-lifecycle callbacks whenever the browser was presented — even when the activity was actually being destroyed.

Key changes:

  • beforeOnDestroy and destroyed in PaywallView now accept an isActivityFinishing: Boolean = false parameter.
  • When isActivityFinishing = true, the browser-presented guard is bypassed so willDismissPaywall / didDismissPaywall and state cleanup always execute on a real finish.
  • SuperwallPaywallActivity.onPause and onStop pass isFinishing (Android's Activity.isFinishing()) to these methods, correctly distinguishing a transient lifecycle pause from an actual finish.
  • The default parameter value (false) preserves the existing behaviour for all other call sites (Compose, internal PaywallView calls) with no regressions.

Minor notes:

  • The Compose path (PaywallComposable.kt) still calls both methods without arguments, so the same isPaywallPresented stuck-at-true scenario can theoretically occur for Compose-embedded paywalls when the browser is open at release time.
  • No new unit or UI tests were added for the isActivityFinishing = true branch.
  • CHANGELOG.md was not updated (checklist item unchecked).

Confidence Score: 5/5

Safe to merge — the fix is well-scoped, backward-compatible, and correctly targets the stated bug; remaining finding is a pre-existing limitation in the Compose path that is out of scope for this PR.

All changed logic is guarded by a default-false parameter, so existing callers are completely unaffected. The Activity path correctly uses Android's isFinishing() API. The only open finding (Compose path not benefiting from the fix) is a pre-existing limitation rather than a regression introduced here, warranting P2 at most.

No files require special attention; the Compose composable (PaywallComposable.kt, unchanged in this PR) is the only place the same latent bug could surface.

Important Files Changed

Filename Overview
superwall/src/main/java/com/superwall/sdk/paywall/view/PaywallView.kt Added isActivityFinishing parameter to beforeOnDestroy and destroyed, allowing dismiss lifecycle to run even when isBrowserViewPresented=true if the activity is actually finishing; Compose callers still use the default (false) so the same bug remains for Compose-embedded paywalls.
superwall/src/main/java/com/superwall/sdk/paywall/view/SuperwallPaywallActivity.kt Passes Activity.isFinishing() to beforeOnDestroy and destroyed in onPause/onStop; correctly distinguishes a real finish from a transient lifecycle pause caused by a deep link or another activity coming to the foreground.

Sequence Diagram

sequenceDiagram
    participant DL as Deep Link / Finish trigger
    participant SPA as SuperwallPaywallActivity
    participant PV as PaywallView
    participant SW as Superwall SDK

    Note over SPA,PV: isBrowserViewPresented = true (browser overlay open)

    DL->>SPA: finish() called (or back stack removed)
    SPA->>SPA: onPause() — isFinishing = true
    SPA->>PV: beforeOnDestroy(isActivityFinishing = true)
    Note over PV: Guard: isBrowserViewPresented && !true → false → proceeds
    PV->>SW: willDismissPaywall(info)

    SPA->>SPA: onStop() — isFinishing = true
    SPA->>PV: destroyed(isActivityFinishing = true)
    Note over PV: Guard: isBrowserViewPresented && !true → false → proceeds
    PV->>SW: didDismissPaywall(info)
    PV->>SW: isPaywallPresented = false ✅

    Note over SPA,SW: Before fix: both calls would early-return,\nleaving isPaywallPresented stuck at true ❌
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: superwall/src/main/java/com/superwall/sdk/paywall/view/PaywallView.kt
Line: 401-414

Comment:
**Compose callers bypass the new guard**

The Compose integration in `PaywallComposable.kt` (lines 110 and 114) calls both `beforeOnDestroy()` and `destroyed()` without arguments, so `isActivityFinishing` defaults to `false`. This means if a browser overlay is active (`isBrowserViewPresented = true`) when a Compose-embedded paywall is released, the dismiss lifecycle is still skipped and `isPaywallPresented` will remain stuck at `true` — the same bug this PR fixes for the Activity path.

Since Compose uses a View-lifecycle signal (AndroidView's `onRelease`) rather than `Activity.isFinishing()`, passing a `Boolean` isn't directly applicable. Consider adding an explicit override or a separate parameter (e.g., `forceCleanup: Boolean = false`) that the Compose caller can set to `true` on `onRelease`, mirroring what the Activity now does for `isFinishing`.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Add guard to prevent pw from dismissing ..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@ianrumac ianrumac merged commit 43009a4 into develop Apr 1, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant