diff --git a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletScreen.kt b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletScreen.kt index bde5e4d8426..fee5b11cf99 100644 --- a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletScreen.kt +++ b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletScreen.kt @@ -111,7 +111,6 @@ internal fun WalletBody( showBottomSheetContent: (BottomSheetContent) -> Unit, hideBottomSheetContent: () -> Unit ) { - val context = LocalContext.current if (state.paymentDetailsList.isEmpty()) { Loader() return @@ -382,7 +381,7 @@ private fun ExpandedPaymentDetails( paymentDetails = item, enabled = isEnabled, isSelected = uiState.selectedItem?.id == item.id, - isUpdating = false, + isUpdating = uiState.cardBeingUpdated == item.id, onClick = { onItemSelected(item) }, diff --git a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletUiState.kt b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletUiState.kt index 53e3330ac89..366de160bd1 100644 --- a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletUiState.kt +++ b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletUiState.kt @@ -14,6 +14,7 @@ internal data class WalletUiState( val isProcessing: Boolean, val primaryButtonLabel: ResolvableString, val hasCompleted: Boolean, + val cardBeingUpdated: String? = null, val errorMessage: ResolvableString? = null, val expiryDateInput: FormFieldEntry = FormFieldEntry(null), val cvcInput: FormFieldEntry = FormFieldEntry(null), @@ -34,16 +35,21 @@ internal data class WalletUiState( val isMissingCvcInput = cvcInput.isComplete.not() val disableButton = (isExpired && isMissingExpiryDateInput) || - (requiresCvcRecollection && isMissingCvcInput) + (requiresCvcRecollection && isMissingCvcInput) || (cardBeingUpdated != null) - return if (hasCompleted) { - PrimaryButtonState.Completed - } else if (isProcessing) { - PrimaryButtonState.Processing - } else if (disableButton) { - PrimaryButtonState.Disabled - } else { - PrimaryButtonState.Enabled + return when { + hasCompleted -> { + PrimaryButtonState.Completed + } + isProcessing -> { + PrimaryButtonState.Processing + } + disableButton -> { + PrimaryButtonState.Disabled + } + else -> { + PrimaryButtonState.Enabled + } } } @@ -65,7 +71,8 @@ internal data class WalletUiState( return copy( paymentDetailsList = response.paymentDetails, selectedItem = selectedItem, - isProcessing = false + isProcessing = false, + cardBeingUpdated = null ) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletViewModel.kt index f5c0dc2d5ba..a8d27e8015a 100644 --- a/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/link/ui/wallet/WalletViewModel.kt @@ -96,30 +96,34 @@ internal class WalletViewModel @Inject constructor( } } - private fun loadPaymentDetails(selectedItemId: String? = null) { + private fun loadPaymentDetails() { _uiState.update { it.setProcessing() } viewModelScope.launch { - linkAccountManager.listPaymentDetails( - paymentMethodTypes = stripeIntent.supportedPaymentMethodTypes(linkAccount) - ).fold( - onSuccess = { response -> - _uiState.update { - it.updateWithResponse(response, selectedItemId = selectedItemId) - } - - if (response.paymentDetails.isEmpty()) { - navigateAndClearStack(LinkScreen.PaymentMethod) - } - }, - // If we can't load the payment details there's nothing to see here - onFailure = ::onFatal - ) + loadPaymentDetailsHelper(selectedItemId = null) } } + private suspend fun loadPaymentDetailsHelper(selectedItemId: String?) { + linkAccountManager.listPaymentDetails( + paymentMethodTypes = stripeIntent.supportedPaymentMethodTypes(linkAccount) + ).fold( + onSuccess = { response -> + _uiState.update { + it.updateWithResponse(response, selectedItemId = selectedItemId) + } + + if (response.paymentDetails.isEmpty()) { + navigateAndClearStack(LinkScreen.PaymentMethod) + } + }, + // If we can't load the payment details there's nothing to see here + onFailure = ::onFatal + ) + } + private fun onFatal(fatalError: Throwable) { logger.error("WalletViewModel Fatal error: ", fatalError) dismissWithResult( @@ -244,7 +248,7 @@ internal class WalletViewModel @Inject constructor( linkAccountManager.deletePaymentDetails(item.id) .fold( onSuccess = { - loadPaymentDetails(selectedItemId = uiState.value.selectedItem?.id) + loadPaymentDetailsHelper(selectedItemId = uiState.value.selectedItem?.id) }, onFailure = { error -> updateErrorMessageAndStopProcessing( @@ -258,7 +262,10 @@ internal class WalletViewModel @Inject constructor( fun onSetDefaultClicked(item: ConsumerPaymentDetails.PaymentDetails) { _uiState.update { - it.setProcessing() + it.copy( + cardBeingUpdated = item.id, + selectedItem = null + ) } viewModelScope.launch { val updateParams = ConsumerPaymentDetailsUpdateParams( @@ -269,7 +276,9 @@ internal class WalletViewModel @Inject constructor( linkAccountManager.updatePaymentDetails(updateParams) .fold( onSuccess = { - loadPaymentDetails() + loadPaymentDetailsHelper( + selectedItemId = item.id + ) }, onFailure = { error -> updateErrorMessageAndStopProcessing( @@ -307,7 +316,8 @@ internal class WalletViewModel @Inject constructor( _uiState.update { it.copy( alertMessage = error.stripeErrorMessage(), - isProcessing = false + isProcessing = false, + cardBeingUpdated = null ) } }