From 0e1e760eb9ea7c77a3c70e001c57d694ddec618c Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Wed, 20 May 2026 09:50:33 -0400 Subject: [PATCH] fix(onramp): dismiss Google Pay sheet on commit_error or cancel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a Coinbase commit_error arrives while the Google Pay GMS Activity is on top, nothing dismissed it — the user had to close it manually. Extract the CLEAR_TOP intent trick into dismissPaymentSheet() and call it from wrappedOnPaymentFailure and wrappedOnCancel whenever the payment sheet was presented. Signed-off-by: Brandon McAnsh --- .../app/onramp/CoinbaseOnRampWebview.kt | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampWebview.kt b/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampWebview.kt index 915992ab6..977c1de86 100644 --- a/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampWebview.kt +++ b/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampWebview.kt @@ -77,6 +77,7 @@ private fun WebView.configureForCoinbaseOnRamp( val autoClickTriggered = AtomicBoolean(false) val terminalEventReceived = AtomicBoolean(false) + val paymentSheetPresented = AtomicBoolean(false) var messageListenerInstalled = false var initialTimeoutRunnable: Runnable? = null @@ -89,6 +90,15 @@ private fun WebView.configureForCoinbaseOnRamp( paymentSheetTimeoutRunnable?.let { removeCallbacks(it) } } + fun dismissPaymentSheet() { + (context as? Activity)?.let { activity -> + val intent = Intent(activity, activity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) + } + activity.startActivity(intent) + } + } + val timeoutAction = Runnable { if (terminalEventReceived.compareAndSet(false, true)) { trace( @@ -118,6 +128,9 @@ private fun WebView.configureForCoinbaseOnRamp( val wrappedOnPaymentFailure: (CoinbaseOnRampWebError) -> Unit = { error -> terminalEventReceived.set(true) post { cancelAllTimeouts() } + if (paymentSheetPresented.get()) { + post { dismissPaymentSheet() } + } onPaymentFailure(error) } @@ -135,20 +148,13 @@ private fun WebView.configureForCoinbaseOnRamp( if (terminalEventReceived.compareAndSet(false, true)) { trace(tag = "CoinbaseOnRamp", message = "Payment sheet timeout fired (60s)") cancelAllTimeouts() - // The Google Pay sheet is a GMS Activity sitting on top of ours - // in the task stack. Relaunching our Activity with CLEAR_TOP - // finishes everything above it, dismissing the sheet. - (context as? Activity)?.let { activity -> - val intent = Intent(activity, activity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) - } - activity.startActivity(intent) - } + dismissPaymentSheet() onPaymentFailure(CoinbaseOnRampWebError.PaymentSheetTimeout()) } } val pauseWatchdog: () -> Unit = { + paymentSheetPresented.set(true) post { cancelAllTimeouts() val runnable = Runnable { paymentSheetTimeoutAction.run() }