From 992c5cc6c938667f52d6ff6ff589987119ffe161 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 19 Oct 2026 19:37:32 +0200 Subject: [PATCH 1/6] fix: slide between usdt receive pages --- .../wallets/receive/ReceiveQrScreen.kt | 2 +- .../wallets/usdt/UsdtDepositReceiveScreen.kt | 160 ++++++++++-------- .../java/to/bitkit/ui/utils/Transitions.kt | 59 ++++--- changelog.d/next/1586.fixed.md | 1 + 4 files changed, 124 insertions(+), 98 deletions(-) create mode 100644 changelog.d/next/1586.fixed.md diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt index 0f5c88f04d..db445b1ee3 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt @@ -315,7 +315,7 @@ fun ReceiveQrScreen( Column( modifier = modifier.fillMaxSize().background( Colors.Gray7 - ).navigationBarsPadding().padding(horizontal = 16.dp) + ).navigationBarsPadding() ) { UsdtDepositReceiveScreen( viewModel = hiltViewModel(), diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt index 7e631ec31b..c6b422607c 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt @@ -1,6 +1,10 @@ package to.bitkit.ui.screens.wallets.usdt import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.ContentTransform +import androidx.compose.animation.togetherWith +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -56,6 +60,7 @@ import to.bitkit.ui.screens.wallets.activity.components.CustomTabRowWithSpacing import to.bitkit.ui.screens.wallets.receive.ReceiveTab import to.bitkit.ui.theme.AppTextStyles import to.bitkit.ui.theme.Colors +import to.bitkit.ui.utils.Transitions import java.text.DecimalFormatSymbols import java.text.NumberFormat import java.util.Locale @@ -101,80 +106,95 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( LaunchedEffect(state.address) { if (state.address != null) page = ReceivePage.FEES } UsdtRefreshEffect(viewModel, receiving = true, onReceived = { !state.busy }) BackHandler(onBack = back) - SheetTopBar( - titleText = stringResource( - when (page) { - ReceivePage.ADDRESS -> R.string.usdt__receive_title - ReceivePage.NETWORKS -> R.string.usdt__receive_network_title - ReceivePage.AMOUNT -> R.string.usdt__receive_amount_title - ReceivePage.FEES -> R.string.usdt__receive_fees_title - } - ), - onBack = back.takeIf { page != ReceivePage.ADDRESS }, - action = if (page == ReceivePage.ADDRESS && onContacts != null) { - { - IconButton(onClick = onContacts) { - Icon( - painterResource(R.drawable.ic_users), - stringResource(R.string.wallet__payment_request_choose_recipient) - ) - } - } - } else { - null - }, - ) - VerticalSpacer( - if (page == ReceivePage.NETWORKS || page == ReceivePage.AMOUNT) 8.dp else 16.dp - ) - if (page == ReceivePage.ADDRESS) { - CustomTabRowWithSpacing( - tabs = tabs, - currentTabIndex = tabs.indexOf(ReceiveTab.USDT), - labelOverrides = tabLabels, - onTabChange = onSelectTab - ) - VerticalSpacer(16.dp) - } - walletUi.error?.let { BodyS(stringResource(it), color = Colors.Brand) } - UsdtDepositReceiveContent( - page = page, - onPage = { page = it }, - wallet = wallet, - receiveError = walletUi.refreshError, - state = state, - amount = if (page == ReceivePage.AMOUNT) draftAmount else amount, - onNetwork = { - if (state.network != it) { - amount = "" - draftAmount = "" - deposits.selectNetwork(it) - } - page = if (it == null || state.address != null && state.network == it) { - ReceivePage.ADDRESS + AnimatedContent( + targetState = page, + transitionSpec = { + if (targetState > initialState) { + Transitions.defaultEnter togetherWith Transitions.defaultExit } else { - ReceivePage.AMOUNT + ContentTransform(Transitions.defaultPopEnter, Transitions.defaultPopExit, targetContentZIndex = -1f) } }, - onAmount = { - if (draftAmount != it) deposits.clearAmountError() - draftAmount = it - }, - onCreate = { - if (state.network == null) { - amount = draftAmount - page = ReceivePage.ADDRESS - } else { - deposits.prepare(draftAmount) + label = "UsdtReceivePage", + modifier = Modifier.weight(1f) + ) { target -> + Column(modifier = Modifier.fillMaxSize().background(Colors.Gray7).padding(horizontal = 16.dp)) { + SheetTopBar( + titleText = stringResource( + when (target) { + ReceivePage.ADDRESS -> R.string.usdt__receive_title + ReceivePage.NETWORKS -> R.string.usdt__receive_network_title + ReceivePage.AMOUNT -> R.string.usdt__receive_amount_title + ReceivePage.FEES -> R.string.usdt__receive_fees_title + } + ), + onBack = back.takeIf { target != ReceivePage.ADDRESS }, + action = if (target == ReceivePage.ADDRESS && onContacts != null) { + { + IconButton(onClick = onContacts) { + Icon( + painterResource(R.drawable.ic_users), + stringResource(R.string.wallet__payment_request_choose_recipient) + ) + } + } + } else { + null + }, + ) + VerticalSpacer( + if (target == ReceivePage.NETWORKS || target == ReceivePage.AMOUNT) 8.dp else 16.dp + ) + if (target == ReceivePage.ADDRESS) { + CustomTabRowWithSpacing( + tabs = tabs, + currentTabIndex = tabs.indexOf(ReceiveTab.USDT), + labelOverrides = tabLabels, + onTabChange = onSelectTab + ) + VerticalSpacer(16.dp) } - }, - onHistory = { app?.navigateToUsdtDeposits() }, - onRefresh = { - draftAmount = if (state.network == null) amount else draftAmount - deposits.selectNetwork(state.network) - page = ReceivePage.AMOUNT - }, - ) + walletUi.error?.let { BodyS(stringResource(it), color = Colors.Brand) } + UsdtDepositReceiveContent( + page = target, + onPage = { page = it }, + wallet = wallet, + receiveError = walletUi.refreshError, + state = state, + amount = if (target == ReceivePage.AMOUNT) draftAmount else amount, + onNetwork = { + if (state.network != it) { + amount = "" + draftAmount = "" + deposits.selectNetwork(it) + } + page = if (it == null || state.address != null && state.network == it) { + ReceivePage.ADDRESS + } else { + ReceivePage.AMOUNT + } + }, + onAmount = { + if (draftAmount != it) deposits.clearAmountError() + draftAmount = it + }, + onCreate = { + if (state.network == null) { + amount = draftAmount + page = ReceivePage.ADDRESS + } else { + deposits.prepare(draftAmount) + } + }, + onHistory = { app?.navigateToUsdtDeposits() }, + onRefresh = { + draftAmount = if (state.network == null) amount else draftAmount + deposits.selectNetwork(state.network) + page = ReceivePage.AMOUNT + }, + ) + } + } } @Composable diff --git a/app/src/main/java/to/bitkit/ui/utils/Transitions.kt b/app/src/main/java/to/bitkit/ui/utils/Transitions.kt index 303e6d9ce7..1d9d1647aa 100644 --- a/app/src/main/java/to/bitkit/ui/utils/Transitions.kt +++ b/app/src/main/java/to/bitkit/ui/utils/Transitions.kt @@ -34,38 +34,43 @@ object Transitions { val slideInVertically = slideInVertically(animationSpec = tween(), initialOffsetY = { it }) val slideOutVertically = slideOutVertically(animationSpec = tween(), targetOffsetY = { it }) - val defaultEnterTrans: (AnimatedContentTransitionScope.() -> EnterTransition?) = { - slideInHorizontally( - initialOffsetX = { fullWidth -> fullWidth }, - animationSpec = tween(300, easing = FastOutSlowInEasing) - ) - } + /** Slide in from the right when a screen is pushed. */ + val defaultEnter: EnterTransition = slideInHorizontally( + initialOffsetX = { fullWidth -> fullWidth }, + animationSpec = tween(300, easing = FastOutSlowInEasing) + ) - val defaultExitTrans: (AnimatedContentTransitionScope.() -> ExitTransition?) = { - slideOutHorizontally( - targetOffsetX = { fullWidth -> -fullWidth / 3 }, - animationSpec = tween(300, easing = FastOutSlowInEasing) - ) + fadeOut( - animationSpec = tween(300, easing = FastOutSlowInEasing), - targetAlpha = 0.8f - ) - } + /** Slide partly out to the left and dim when a screen is covered. */ + val defaultExit: ExitTransition = slideOutHorizontally( + targetOffsetX = { fullWidth -> -fullWidth / 3 }, + animationSpec = tween(300, easing = FastOutSlowInEasing) + ) + fadeOut( + animationSpec = tween(300, easing = FastOutSlowInEasing), + targetAlpha = 0.8f + ) + /** Slide back in from the left when the screen above is popped. */ + val defaultPopEnter: EnterTransition = slideInHorizontally( + initialOffsetX = { fullWidth -> -fullWidth / 3 }, + animationSpec = tween(300, easing = FastOutSlowInEasing) + ) + fadeIn( + animationSpec = tween(300, easing = FastOutSlowInEasing), + initialAlpha = 0.8f + ) + + /** Slide out to the right when a screen is popped. */ + val defaultPopExit: ExitTransition = slideOutHorizontally( + targetOffsetX = { fullWidth -> fullWidth }, + animationSpec = tween(300, easing = FastOutSlowInEasing) + ) + + val defaultEnterTrans: (AnimatedContentTransitionScope.() -> EnterTransition?) = { defaultEnter } + val defaultExitTrans: (AnimatedContentTransitionScope.() -> ExitTransition?) = { defaultExit } val defaultPopEnterTrans: (AnimatedContentTransitionScope.() -> EnterTransition?) = { - slideInHorizontally( - initialOffsetX = { fullWidth -> -fullWidth / 3 }, - animationSpec = tween(300, easing = FastOutSlowInEasing) - ) + fadeIn( - animationSpec = tween(300, easing = FastOutSlowInEasing), - initialAlpha = 0.8f - ) + defaultPopEnter } - val defaultPopExitTrans: (AnimatedContentTransitionScope.() -> ExitTransition?) = { - slideOutHorizontally( - targetOffsetX = { fullWidth -> fullWidth }, - animationSpec = tween(300, easing = FastOutSlowInEasing) - ) + defaultPopExit } } diff --git a/changelog.d/next/1586.fixed.md b/changelog.d/next/1586.fixed.md new file mode 100644 index 0000000000..9c8b5dccf4 --- /dev/null +++ b/changelog.d/next/1586.fixed.md @@ -0,0 +1 @@ +Receiving USDT now slides between the address, network, amount and fee screens, like the Bitcoin receive flow. From 042f3a25147890d19d78835824ede2fcda89f8a2 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 19 Oct 2026 19:37:47 +0200 Subject: [PATCH 2/6] test: check usdt receive edit slides in journey --- journeys/usdt-receive-amount-and-units.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/journeys/usdt-receive-amount-and-units.xml b/journeys/usdt-receive-amount-and-units.xml index 92900afd2b..d2508c40b0 100644 --- a/journeys/usdt-receive-amount-and-units.xml +++ b/journeys/usdt-receive-amount-and-units.xml @@ -4,6 +4,7 @@ Enable USDT in the introductory sheet or Settings, General, Payments before starting this flow. Open USDT from Home. Verify the USDT balance, teal Tether icon and existing activity rows. Open Receive. Verify Receive Dollars, the USDT tab and Network: Arbitrum One on the QR screen. + Tap Edit. Verify the Amount screen slides in from the right, as Edit Invoice does on the Savings tab. Tap Back and verify it slides out to the right over the QR. Tap Edit, enter 5 and tap Back. Verify the QR has no uint256 amount. Tap Edit. Enter 3.50. Verify the dollar amount and BTC equivalent are displayed, there is no input-unit toggle, the keypad follows the divider, and Continue stays at the bottom without overlap. Continue to the QR. Verify it requests the Arbitrum USDT token, the wallet address and uint256=3500000, never Bitcoin. From 7ea16b22d63e3acd55e7fd5af94acc0aa93ea2e0 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 19 Oct 2026 20:02:26 +0200 Subject: [PATCH 3/6] fix: keep usdt fees visible while sliding back --- .../wallets/usdt/UsdtDepositReceiveScreen.kt | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt index c6b422607c..a7170f8fe7 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.synonym.bitkitcore.UsdtDepositAddress import com.synonym.bitkitcore.UsdtDepositDetail import com.synonym.bitkitcore.UsdtDepositNetwork import com.synonym.bitkitcore.usdtFormatAmount @@ -222,24 +223,9 @@ internal fun ColumnScope.UsdtDepositReceiveContent( onAmount, onCreate ) - ReceivePage.FEES -> state.address?.let { address -> - UsdtAmountHeader(usdtFormatAmount(address.amount), displayAmount = usdtOverviewAmount(address.amount)) - VerticalSpacer(24.dp) - BodyM(stringResource(R.string.usdt__deposit_fee_note), color = Colors.White64, letterSpacing = 0.sp) - VerticalSpacer(24.dp) - EstimateRow( - stringResource(R.string.usdt__receive_fee), - if (address.amount >= address.estimatedReceived) { - usdtOverviewAmount(address.amount - address.estimatedReceived) - } else { - "—" - } - ) - EstimateRow(stringResource(R.string.usdt__receive_estimate), usdtOverviewAmount(address.estimatedReceived)) - FillHeight() - PrimaryButton(stringResource(R.string.common__continue), onClick = { - onPage(ReceivePage.ADDRESS) - }, textStyle = UsdtDetailStyles.Body, modifier = Modifier.testTag("UsdtReceiveFeesContinue")) + ReceivePage.FEES -> { + val shownAddress = remember { state.address } + FeeEstimate(state.address ?: shownAddress, onContinue = { onPage(ReceivePage.ADDRESS) }) } ReceivePage.ADDRESS -> { val atomic = runCatching { PaykitAmount.parseInput(PaykitAsset.USDT, amount).atomic }.getOrNull() @@ -258,6 +244,31 @@ internal fun ColumnScope.UsdtDepositReceiveContent( } } +@Composable +private fun ColumnScope.FeeEstimate(address: UsdtDepositAddress?, onContinue: () -> Unit) { + if (address == null) return + UsdtAmountHeader(usdtFormatAmount(address.amount), displayAmount = usdtOverviewAmount(address.amount)) + VerticalSpacer(24.dp) + BodyM(stringResource(R.string.usdt__deposit_fee_note), color = Colors.White64, letterSpacing = 0.sp) + VerticalSpacer(24.dp) + EstimateRow( + stringResource(R.string.usdt__receive_fee), + if (address.amount >= address.estimatedReceived) { + usdtOverviewAmount(address.amount - address.estimatedReceived) + } else { + "—" + } + ) + EstimateRow(stringResource(R.string.usdt__receive_estimate), usdtOverviewAmount(address.estimatedReceived)) + FillHeight() + PrimaryButton( + stringResource(R.string.common__continue), + onClick = onContinue, + textStyle = UsdtDetailStyles.Body, + modifier = Modifier.testTag("UsdtReceiveFeesContinue") + ) +} + internal enum class ReceivePage { ADDRESS, NETWORKS, AMOUNT, FEES } @Composable From c176c06fc97f3cd39e4c966bba14c610d80e8d54 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 19 Oct 2026 20:47:31 +0200 Subject: [PATCH 4/6] docs: note usdt receive slide step waits on ios --- journeys/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/journeys/README.md b/journeys/README.md index 78347624e5..f00b19c4c6 100644 --- a/journeys/README.md +++ b/journeys/README.md @@ -159,6 +159,7 @@ Known differences in the corpus, as of the iOS port (synonymdev/bitkit-ios#691): | `coin-selection/manual-wallet-switch.xml` | same file, journey name and actions; iOS can open the picker on the wallet switch, Android on the next swipe. The iOS picker has no accessibility identifiers, so assert its visible "Coin Selection" title. | | `payment-requests/requested-resolution-failure.xml` | same file and journey name; both platforms keep the preparing confirmation open across retries and stop automatic retries when it closes. Native progress and request-row identifiers differ. Android's subscription-reminder preparation has no intermediate Send sheet; see `paykit-clock-changes.md`. | | `payment-requests/request-summary.xml` | same file and journey name; Android additionally checks the open Sent receipt's live lifecycle subtitle after payment. iOS keeps a static note/date receipt without that subtitle, so those checks are not ported. | +| `usdt-receive-amount-and-units.xml` | same file and journey name; the Edit slide step (Amount slides in from the right, Back slides it out over the QR) waits on synonymdev/bitkit-ios#1018, since iOS still swaps the USDT receive pages without a transition. Port the step with that fix. | | `usdt-payment-restoration.xml` | same file, journey name and actions; Android restores an unpaid amount draft after process death, while iOS may return to the wallet. A submitted payment must return to the wallet without reopening the paid draft on either platform. | | `payment-requests/success-dismissal.xml` | same file, journey name and actions; both platforms dismiss successful and unpaid requests without a send error or duplicate payment. | | `payment-requests/minimum-onchain-amount.xml` | shared — minimum amount feedback, preparation cleanup, and manual retry use the same journey and `PaymentRequestAmountTooLowToast` identifier on both platforms. | From 4844170a3f35d06edb44181ab6923b0f8295ff49 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 21 Oct 2026 13:47:13 +0200 Subject: [PATCH 5/6] fix: freeze each usdt receive page while it slides out --- .../wallets/usdt/UsdtDepositReceiveScreen.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt index ee042d58da..f0001994e6 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt @@ -109,9 +109,10 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( UsdtRefreshEffect(viewModel, receiving = true, onReceived = { !state.busy }) BackHandler(onBack = back) AnimatedContent( - targetState = page, + targetState = ShownPage(page, state, if (page == ReceivePage.AMOUNT) draftAmount else amount), + contentKey = { it.page }, transitionSpec = { - if (targetState > initialState) { + if (targetState.page > initialState.page) { Transitions.defaultEnter togetherWith Transitions.defaultExit } else { ContentTransform(Transitions.defaultPopEnter, Transitions.defaultPopExit, targetContentZIndex = -1f) @@ -119,7 +120,8 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( }, label = "UsdtReceivePage", modifier = Modifier.weight(1f) - ) { target -> + ) { shown -> + val target = shown.page Column(modifier = Modifier.fillMaxSize().background(Colors.Gray7).padding(horizontal = 16.dp)) { SheetTopBar( titleText = stringResource( @@ -175,8 +177,8 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( onPage = { page = it }, wallet = wallet, receiveError = walletUi.refreshError, - state = state, - amount = if (target == ReceivePage.AMOUNT) draftAmount else amount, + state = shown.state, + amount = shown.amount, onNetwork = { if (state.network != it) { amount = "" @@ -239,8 +241,7 @@ internal fun ColumnScope.UsdtDepositReceiveContent( onCreate ) ReceivePage.FEES -> { - val shownAddress = remember { state.address } - FeeEstimate(state.address ?: shownAddress, onContinue = { onPage(ReceivePage.ADDRESS) }) + FeeEstimate(state.address, onContinue = { onPage(ReceivePage.ADDRESS) }) } ReceivePage.ADDRESS -> { val atomic = runCatching { PaykitAmount.parseInput(PaykitAsset.USDT, amount).atomic }.getOrNull() @@ -286,6 +287,8 @@ private fun ColumnScope.FeeEstimate(address: UsdtDepositAddress?, onContinue: () internal enum class ReceivePage { ADDRESS, NETWORKS, AMOUNT, FEES } +private data class ShownPage(val page: ReceivePage, val state: DepositUiState, val amount: String) + @Composable private fun ColumnScope.NetworkSelector( state: DepositUiState, From e10ba24288774b423de4a334cc5f5a61de69988c Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 22 Oct 2026 22:57:34 +0200 Subject: [PATCH 6/6] fix: ignore taps on usdt receive pages sliding out --- .../wallets/usdt/UsdtDepositReceiveScreen.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt index f0001994e6..bc7f8df7eb 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt @@ -122,6 +122,7 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( modifier = Modifier.weight(1f) ) { shown -> val target = shown.page + val isCurrent = { target == page } Column(modifier = Modifier.fillMaxSize().background(Colors.Gray7).padding(horizontal = 16.dp)) { SheetTopBar( titleText = stringResource( @@ -132,7 +133,7 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( ReceivePage.FEES -> R.string.usdt__receive_fees_title } ), - onBack = back.takeIf { target != ReceivePage.ADDRESS }, + onBack = whenCurrent(isCurrent, back).takeIf { target != ReceivePage.ADDRESS }, action = if (target == ReceivePage.ADDRESS && onContacts != null) { { IconButton(onClick = onContacts) { @@ -174,12 +175,12 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( ) { UsdtDepositReceiveContent( page = target, - onPage = { page = it }, + onPage = whenCurrentOf(isCurrent) { page = it }, wallet = wallet, receiveError = walletUi.refreshError, state = shown.state, amount = shown.amount, - onNetwork = { + onNetwork = whenCurrentOf(isCurrent) { if (state.network != it) { amount = "" draftAmount = "" @@ -191,11 +192,11 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( ReceivePage.AMOUNT } }, - onAmount = { + onAmount = whenCurrentOf(isCurrent) { if (draftAmount != it) deposits.clearError() draftAmount = it }, - onCreate = { + onCreate = whenCurrent(isCurrent) { if (state.network == null) { amount = draftAmount page = ReceivePage.ADDRESS @@ -204,7 +205,7 @@ internal fun ColumnScope.UsdtDepositReceiveScreen( } }, onHistory = { app?.navigateToUsdtDeposits() }, - onRefresh = { + onRefresh = whenCurrent(isCurrent) { draftAmount = if (state.network == null) amount else draftAmount deposits.selectNetwork(state.network) page = ReceivePage.AMOUNT @@ -287,6 +288,12 @@ private fun ColumnScope.FeeEstimate(address: UsdtDepositAddress?, onContinue: () internal enum class ReceivePage { ADDRESS, NETWORKS, AMOUNT, FEES } +private fun whenCurrent(isCurrent: () -> Boolean, block: () -> Unit): () -> Unit = { if (isCurrent()) block() } + +private fun whenCurrentOf(isCurrent: () -> Boolean, block: (T) -> Unit): (T) -> Unit = { + if (isCurrent()) block(it) +} + private data class ShownPage(val page: ReceivePage, val state: DepositUiState, val amount: String) @Composable