Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link Wallet menu #9872

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ internal sealed class LinkScreen(val route: String) {
data object Verification : LinkScreen("verification")
data object Wallet : LinkScreen("wallet")
data object PaymentMethod : LinkScreen("paymentMethod")
data object CardEdit : LinkScreen("cardEdit")
data class CardEdit(val paymentDetailsId: String) : LinkScreen(ROUTE) {
companion object {
const val ROUTE = "cardEdit/{paymentDetailsId}"
}
}
data object SignUp : LinkScreen("signUp")
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ internal fun LinkContent(
Screens(
navController = navController,
goBack = viewModel::goBack,
navigate = { screen ->
viewModel.navigate(screen, clearStack = false)
},
navigateAndClearStack = { screen ->
viewModel.navigate(screen, clearStack = true)
},
Expand All @@ -102,7 +105,8 @@ internal fun LinkContent(
},
getLinkAccount = {
viewModel.linkAccount
}
},
showBottomSheetContent = onUpdateSheetContent
)
}
}
Expand All @@ -114,21 +118,17 @@ private fun Screens(
navController: NavHostController,
getLinkAccount: () -> LinkAccount?,
goBack: () -> Unit,
navigate: (route: LinkScreen) -> Unit,
navigateAndClearStack: (route: LinkScreen) -> Unit,
dismissWithResult: (LinkActivityResult) -> Unit
dismissWithResult: (LinkActivityResult) -> Unit,
showBottomSheetContent: (BottomSheetContent?) -> Unit
) {
NavHost(
navController = navController,
startDestination = LinkScreen.Loading.route
) {
composable(LinkScreen.Loading.route) {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
Loader()
}

composable(LinkScreen.SignUp.route) {
Expand Down Expand Up @@ -162,14 +162,18 @@ private fun Screens(
WalletViewModel.factory(
parentComponent = parentComponent,
linkAccount = linkAccount,
navigate = navigate,
navigateAndClearStack = navigateAndClearStack,
dismissWithResult = dismissWithResult
)
}
WalletScreen(viewModel)
WalletScreen(
viewModel = viewModel,
showBottomSheetContent = showBottomSheetContent
)
}

composable(LinkScreen.CardEdit.route) {
composable(LinkScreen.CardEdit.ROUTE) {
CardEditScreen()
Comment on lines +176 to 177
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CardEdit route needs to extract the paymentDetailsId parameter from the NavBackStackEntry and pass it to CardEditScreen. The current implementation drops this required parameter. Consider updating to:

composable(
    route = LinkScreen.CardEdit.ROUTE,
    arguments = listOf(navArgument("paymentDetailsId") { type = NavType.StringType })
) { backStackEntry ->
    val paymentDetailsId = backStackEntry.arguments?.getString("paymentDetailsId")
    CardEditScreen(paymentDetailsId = paymentDetailsId)
}

Spotted by Graphite Reviewer

Is this helpful? React 👍 or 👎 to let us know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

Expand All @@ -178,3 +182,14 @@ private fun Screens(
}
}
}

@Composable
private fun Loader() {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import com.stripe.android.link.theme.HorizontalPadding
import com.stripe.android.link.theme.MinimumTouchTargetSize
Expand All @@ -38,9 +39,11 @@ internal fun LinkMenu(
for (item in items) {
LinkBottomSheetRow(
item = item,
modifier = Modifier.clickable {
onItemPress(item)
}
modifier = Modifier
.testTag(item.tag)
.clickable {
onItemPress(item)
}
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import com.stripe.android.core.strings.ResolvableString
*/
internal interface LinkMenuItem {
val text: ResolvableString
val tag: String
val isDestructive: Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ private fun MenuAndLoader(
)
} else {
IconButton(
modifier = Modifier
.testTag(WALLET_PAYMENT_DETAIL_ITEM_MENU_BUTTON),
onClick = onMenuButtonClick,
enabled = enabled
) {
Expand Down Expand Up @@ -259,3 +261,4 @@ private fun RowScope.BankAccountInfo(
}

internal const val WALLET_PAYMENT_DETAIL_ITEM_RADIO_BUTTON = "wallet_payment_detail_item_radio_button"
internal const val WALLET_PAYMENT_DETAIL_ITEM_MENU_BUTTON = "wallet_payment_detail_item_menu_button"
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,34 @@ import com.stripe.android.R as StripeR

internal sealed class WalletPaymentMethodMenuItem(
override val text: ResolvableString,
override val isDestructive: Boolean = false
override val tag: String,
override val isDestructive: Boolean = false,
) : LinkMenuItem {
data class RemoveItem(
override val text: ResolvableString
) : WalletPaymentMethodMenuItem(text, true)
) : WalletPaymentMethodMenuItem(
text = text,
tag = WALLET_MENU_REMOVE_ITEM_TAG,
isDestructive = true
)

data object EditCard : WalletPaymentMethodMenuItem(
text = R.string.stripe_wallet_update_card.resolvableString
text = R.string.stripe_wallet_update_card.resolvableString,
tag = WALLET_MENU_EDIT_CARD_TAG,
)

data object SetAsDefault : WalletPaymentMethodMenuItem(
text = R.string.stripe_wallet_set_as_default.resolvableString
text = R.string.stripe_wallet_set_as_default.resolvableString,
tag = WALLET_MENU_SET_AS_DEFAULT_TAG,
)

data object Cancel : WalletPaymentMethodMenuItem(
text = StripeR.string.stripe_cancel.resolvableString
text = StripeR.string.stripe_cancel.resolvableString,
tag = WALLET_MENU_CANCEL_TAG,
)
}

internal const val WALLET_MENU_REMOVE_ITEM_TAG = "WALLET_MENU_REMOVE_ITEM_TAG"
internal const val WALLET_MENU_EDIT_CARD_TAG = "WALLET_MENU_EDIT_CARD_TAG"
internal const val WALLET_MENU_SET_AS_DEFAULT_TAG = "WALLET_MENU_SET_AS_DEFAULT_TAG"
internal const val WALLET_MENU_CANCEL_TAG = "WALLET_MENU_CANCEL_TAG"
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.ui.unit.dp
import com.stripe.android.link.theme.HorizontalPadding
import com.stripe.android.link.theme.linkColors
import com.stripe.android.link.theme.linkShapes
import com.stripe.android.link.ui.BottomSheetContent
import com.stripe.android.link.ui.PrimaryButton
import com.stripe.android.link.ui.SecondaryButton
import com.stripe.android.model.ConsumerPaymentDetails
Expand All @@ -50,6 +51,7 @@ import com.stripe.android.uicore.utils.collectAsState
@Composable
internal fun WalletScreen(
viewModel: WalletViewModel,
showBottomSheetContent: (BottomSheetContent?) -> Unit
) {
val state by viewModel.uiState.collectAsState()
var isExpanded by rememberSaveable { mutableStateOf(false) }
Expand All @@ -62,7 +64,12 @@ internal fun WalletScreen(
isExpanded = expanded
},
onPrimaryButtonClick = viewModel::onPrimaryButtonClicked,
onPayAnotherWayClick = viewModel::onPayAnotherWayClicked,
onPayAnotherWayClicked = viewModel::onPayAnotherWayClicked,
onRemoveClicked = {},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onRemoveClicked handler is currently empty, preventing payment methods from being removed. This should be wired up to viewModel.onRemovePaymentMethodClicked() to enable payment method removal functionality.

Spotted by Graphite Reviewer

Is this helpful? React 👍 or 👎 to let us know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onEditPaymentMethodClicked = viewModel::onEditPaymentMethodClicked,
onSetDefaultClicked = {},
showBottomSheetContent = showBottomSheetContent,
onAddNewPaymentMethodClicked = viewModel::onAddNewPaymentMethodClicked
)
}

Expand All @@ -72,8 +79,13 @@ internal fun WalletBody(
isExpanded: Boolean,
onItemSelected: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onExpandedChanged: (Boolean) -> Unit,
onAddNewPaymentMethodClicked: () -> Unit,
onPrimaryButtonClick: () -> Unit,
onPayAnotherWayClick: () -> Unit,
onPayAnotherWayClicked: () -> Unit,
onEditPaymentMethodClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onSetDefaultClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onRemoveClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
showBottomSheetContent: (BottomSheetContent?) -> Unit
) {
if (state.paymentDetailsList.isEmpty()) {
Box(
Expand Down Expand Up @@ -105,7 +117,12 @@ internal fun WalletBody(
state = state,
isExpanded = isExpanded,
onItemSelected = onItemSelected,
onExpandedChanged = onExpandedChanged
onExpandedChanged = onExpandedChanged,
showBottomSheetContent = showBottomSheetContent,
onRemoveClicked = onRemoveClicked,
onSetDefaultClicked = onSetDefaultClicked,
onEditPaymentMethodClicked = onEditPaymentMethodClicked,
onAddNewPaymentMethodClicked = onAddNewPaymentMethodClicked,
)

AnimatedVisibility(state.showBankAccountTerms) {
Expand All @@ -128,7 +145,7 @@ internal fun WalletBody(
.testTag(WALLET_SCREEN_PAY_ANOTHER_WAY_BUTTON),
enabled = !state.primaryButtonState.isBlocking,
label = stringResource(id = R.string.stripe_wallet_pay_another_way),
onClick = onPayAnotherWayClick
onClick = onPayAnotherWayClicked
)
}
}
Expand All @@ -139,6 +156,11 @@ private fun PaymentMethodSection(
isExpanded: Boolean,
onItemSelected: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onExpandedChanged: (Boolean) -> Unit,
onAddNewPaymentMethodClicked: () -> Unit,
onEditPaymentMethodClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onSetDefaultClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
onRemoveClicked: (ConsumerPaymentDetails.PaymentDetails) -> Unit,
showBottomSheetContent: (BottomSheetContent?) -> Unit
) {
Box(
modifier = Modifier
Expand All @@ -149,8 +171,31 @@ private fun PaymentMethodSection(
ExpandedPaymentDetails(
uiState = state,
onItemSelected = onItemSelected,
onMenuButtonClick = {},
onAddNewPaymentMethodClick = {},
onMenuButtonClick = {
showBottomSheetContent {
WalletPaymentMethodMenu(
modifier = Modifier
.testTag(WALLET_SCREEN_MENU_SHEET_TAG),
paymentDetails = it,
onEditClick = {
showBottomSheetContent(null)
onEditPaymentMethodClicked(it)
},
onSetDefaultClick = {
showBottomSheetContent(null)
onSetDefaultClicked(it)
},
onRemoveClick = {
showBottomSheetContent(null)
onRemoveClicked(it)
},
onCancelClick = {
showBottomSheetContent(null)
}
)
}
},
onAddNewPaymentMethodClick = onAddNewPaymentMethodClicked,
onCollapse = {
onExpandedChanged(false)
}
Expand Down Expand Up @@ -378,3 +423,4 @@ internal const val WALLET_SCREEN_PAYMENT_METHODS_LIST = "wallet_screen_payment_m
internal const val WALLET_SCREEN_PAY_BUTTON = "wallet_screen_pay_button"
internal const val WALLET_SCREEN_PAY_ANOTHER_WAY_BUTTON = "wallet_screen_pay_another_way_button"
internal const val WALLET_SCREEN_BOX = "wallet_screen_box"
internal const val WALLET_SCREEN_MENU_SHEET_TAG = "wallet_screen_menu_sheet_tag"
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal class WalletViewModel @Inject constructor(
private val linkAccount: LinkAccount,
private val linkAccountManager: LinkAccountManager,
private val logger: Logger,
private val navigate: (route: LinkScreen) -> Unit,
private val navigateAndClearStack: (route: LinkScreen) -> Unit,
private val dismissWithResult: (LinkActivityResult) -> Unit
) : ViewModel() {
Expand Down Expand Up @@ -95,6 +96,14 @@ internal class WalletViewModel @Inject constructor(
dismissWithResult(LinkActivityResult.Canceled(LinkActivityResult.Canceled.Reason.PayAnotherWay))
}

fun onAddNewPaymentMethodClicked() {
navigate(LinkScreen.PaymentMethod)
}

fun onEditPaymentMethodClicked(item: ConsumerPaymentDetails.PaymentDetails) {
navigate(LinkScreen.CardEdit(item.id))
}

private fun completePaymentButtonLabel(
stripeIntent: StripeIntent,
) = when (stripeIntent) {
Expand All @@ -111,6 +120,7 @@ internal class WalletViewModel @Inject constructor(
fun factory(
parentComponent: NativeLinkComponent,
linkAccount: LinkAccount,
navigate: (route: LinkScreen) -> Unit,
navigateAndClearStack: (route: LinkScreen) -> Unit,
dismissWithResult: (LinkActivityResult) -> Unit
): ViewModelProvider.Factory {
Expand All @@ -121,6 +131,7 @@ internal class WalletViewModel @Inject constructor(
linkAccountManager = parentComponent.linkAccountManager,
logger = parentComponent.logger,
linkAccount = linkAccount,
navigate = navigate,
navigateAndClearStack = navigateAndClearStack,
dismissWithResult = dismissWithResult
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ internal class WalletScreenScreenshotTest {
onItemSelected = {},
onExpandedChanged = {},
onPrimaryButtonClick = {},
onPayAnotherWayClick = {}
onPayAnotherWayClicked = {},
onRemoveClicked = {},
onSetDefaultClicked = {},
onEditPaymentMethodClicked = {},
showBottomSheetContent = {},
onAddNewPaymentMethodClicked = {}
)
}
}
Expand Down
Loading
Loading