Skip to content

Commit

Permalink
Hide billing started dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawa committed Nov 27, 2023
1 parent 18a9b19 commit 4fbd1de
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,116 +31,109 @@ import org.koin.androidx.compose.koinViewModel
@Preview
@Composable
private fun PreviewPaymentDialogPurchaseCompleted() {
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_completed_dialog_title,
message = R.string.payment_completed_dialog_message,
icon = PaymentDialogIcon.SUCCESS,
confirmAction = PaymentDialogAction.Close,
successfulPayment = true
),
retryPurchase = {},
onCloseDialog = {}
)
}
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_completed_dialog_title,
message = R.string.payment_completed_dialog_message,
icon = PaymentDialogIcon.SUCCESS,
confirmAction = PaymentDialogAction.Close,
successfulPayment = true),
retryPurchase = {},
onCloseDialog = {})
}
}

@Preview
@Composable
private fun PreviewPaymentDialogPurchasePending() {
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_pending_dialog_title,
message = R.string.payment_pending_dialog_message,
confirmAction = PaymentDialogAction.Close,
closeOnDismiss = true
),
retryPurchase = {},
onCloseDialog = {}
)
}
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_pending_dialog_title,
message = R.string.payment_pending_dialog_message,
confirmAction = PaymentDialogAction.Close,
closeOnDismiss = true),
retryPurchase = {},
onCloseDialog = {})
}
}

@Preview
@Composable
private fun PreviewPaymentDialogGenericError() {
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.error_occurred,
message = R.string.try_again,
icon = PaymentDialogIcon.FAIL,
confirmAction = PaymentDialogAction.Close
),
retryPurchase = {},
onCloseDialog = {}
)
}
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.error_occurred,
message = R.string.try_again,
icon = PaymentDialogIcon.FAIL,
confirmAction = PaymentDialogAction.Close),
retryPurchase = {},
onCloseDialog = {})
}
}

@Preview
@Composable
private fun PreviewPaymentDialogLoading() {
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.loading_connecting,
icon = PaymentDialogIcon.LOADING,
closeOnDismiss = false
),
retryPurchase = {},
onCloseDialog = {}
)
}
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.loading_connecting,
icon = PaymentDialogIcon.LOADING,
closeOnDismiss = false),
retryPurchase = {},
onCloseDialog = {})
}
}

@Preview
@Composable
private fun PreviewPaymentDialogPaymentAvailabilityError() {
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_billing_error_dialog_title,
message = R.string.payment_billing_error_dialog_message,
icon = PaymentDialogIcon.FAIL,
confirmAction = PaymentDialogAction.Close,
dismissAction = PaymentDialogAction.RetryPurchase(productId = ProductId("test"))
),
retryPurchase = {},
onCloseDialog = {}
)
}
AppTheme {
PaymentDialog(
paymentDialogData =
PaymentDialogData(
title = R.string.payment_billing_error_dialog_title,
message = R.string.payment_billing_error_dialog_message,
icon = PaymentDialogIcon.FAIL,
confirmAction = PaymentDialogAction.Close,
dismissAction = PaymentDialogAction.RetryPurchase(productId = ProductId("test"))),
retryPurchase = {},
onCloseDialog = {})
}
}

@Destination(style = DestinationStyle.Dialog::class)
@Composable
fun Payment(productId: ProductId, resultBackNavigator: ResultBackNavigator<Boolean>) {
val vm = koinViewModel<PaymentViewModel>()
val uiState by vm.uiState.collectAsState()
val vm = koinViewModel<PaymentViewModel>()
val uiState = vm.uiState.collectAsState().value

LaunchedEffect(Unit) {
vm.uiSideEffect.collect {
when (it) {
is PaymentUiSideEffect.PaymentCancelled ->
resultBackNavigator.navigateBack(result = false)
}
}
LaunchedEffect(Unit) {
vm.uiSideEffect.collect {
when (it) {
is PaymentUiSideEffect.PaymentCancelled -> resultBackNavigator.navigateBack(result = false)
}
}
}

val context = LocalContext.current
LaunchedEffect(Unit) { vm.startBillingPayment(productId) { context.getActivity()!! } }
PaymentDialog(
paymentDialogData = uiState.paymentDialogData,
retryPurchase = { vm.startBillingPayment(it) { context.getActivity()!! } },
onCloseDialog = { resultBackNavigator.navigateBack(result = it) }
)
val context = LocalContext.current
LaunchedEffect(Unit) { vm.startBillingPayment(productId) { context.getActivity()!! } }

if (uiState.paymentDialogData == null) {
return
}

PaymentDialog(
paymentDialogData = uiState.paymentDialogData,
retryPurchase = { vm.startBillingPayment(it) { context.getActivity()!! } },
onCloseDialog = { resultBackNavigator.navigateBack(result = it) })
}

@Composable
Expand All @@ -149,73 +142,60 @@ fun PaymentDialog(
retryPurchase: (ProductId) -> Unit = {},
onCloseDialog: (isPaymentSuccessful: Boolean) -> Unit = {}
) {
val clickResolver: (action: PaymentDialogAction) -> Unit = {
when (it) {
is PaymentDialogAction.RetryPurchase -> retryPurchase(it.productId)
is PaymentDialogAction.Close -> onCloseDialog(paymentDialogData.successfulPayment)
}
val clickResolver: (action: PaymentDialogAction) -> Unit = {
when (it) {
is PaymentDialogAction.RetryPurchase -> retryPurchase(it.productId)
is PaymentDialogAction.Close -> onCloseDialog(paymentDialogData.successfulPayment)
}
AlertDialog(
icon = {
when (paymentDialogData.icon) {
PaymentDialogIcon.SUCCESS ->
Icon(
painter = painterResource(id = R.drawable.icon_success),
contentDescription = null
)
PaymentDialogIcon.FAIL ->
Icon(
painter = painterResource(id = R.drawable.icon_fail),
contentDescription = null
)
PaymentDialogIcon.LOADING -> MullvadCircularProgressIndicatorMedium()
else -> {}
}
},
title = {
paymentDialogData.title?.let {
Text(
text = stringResource(id = paymentDialogData.title),
style = MaterialTheme.typography.headlineSmall
)
}
},
text =
paymentDialogData.message?.let {
{
Text(
text = stringResource(id = paymentDialogData.message),
style = MaterialTheme.typography.bodySmall
)
}
},
containerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.onBackground,
iconContentColor = Color.Unspecified,
textContentColor =
MaterialTheme.colorScheme.onBackground
.copy(alpha = AlphaDescription)
.compositeOver(MaterialTheme.colorScheme.background),
onDismissRequest = {
if (paymentDialogData.closeOnDismiss) {
onCloseDialog(paymentDialogData.successfulPayment)
}
},
dismissButton = {
paymentDialogData.dismissAction?.let {
PrimaryButton(
text = stringResource(id = it.message),
onClick = { clickResolver(it) }
)
}
},
confirmButton = {
paymentDialogData.confirmAction?.let {
PrimaryButton(
text = stringResource(id = it.message),
onClick = { clickResolver(it) }
)
}
AlertDialog(
icon = {
when (paymentDialogData.icon) {
PaymentDialogIcon.SUCCESS ->
Icon(
painter = painterResource(id = R.drawable.icon_success),
contentDescription = null)
PaymentDialogIcon.FAIL ->
Icon(painter = painterResource(id = R.drawable.icon_fail), contentDescription = null)
PaymentDialogIcon.LOADING -> MullvadCircularProgressIndicatorMedium()
else -> {}
}
},
title = {
paymentDialogData.title?.let {
Text(
text = stringResource(id = paymentDialogData.title),
style = MaterialTheme.typography.headlineSmall)
}
},
text =
paymentDialogData.message?.let {
{
Text(
text = stringResource(id = paymentDialogData.message),
style = MaterialTheme.typography.bodySmall)
}
},
containerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.onBackground,
iconContentColor = Color.Unspecified,
textContentColor =
MaterialTheme.colorScheme.onBackground
.copy(alpha = AlphaDescription)
.compositeOver(MaterialTheme.colorScheme.background),
onDismissRequest = {
if (paymentDialogData.closeOnDismiss) {
onCloseDialog(paymentDialogData.successfulPayment)
}
},
dismissButton = {
paymentDialogData.dismissAction?.let {
PrimaryButton(text = stringResource(id = it.message), onClick = { clickResolver(it) })
}
},
confirmButton = {
paymentDialogData.confirmAction?.let {
PrimaryButton(text = stringResource(id = it.message), onClick = { clickResolver(it) })
}
)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.compose.dialog.payment.PaymentDialogData
Expand All @@ -19,26 +19,28 @@ import net.mullvad.mullvadvpn.util.toPaymentDialogData
class PaymentViewModel(
private val paymentUseCase: PaymentUseCase,
) : ViewModel() {
val uiState: StateFlow<PaymentUiState> =
paymentUseCase.purchaseResult
.mapNotNull { it?.toPaymentDialogData() }
.map { PaymentUiState(it) }
.stateIn(viewModelScope, SharingStarted.Lazily, PaymentUiState(PaymentDialogData()))
val uiState: StateFlow<PaymentUiState> =
paymentUseCase.purchaseResult
.filterNot {
it is PurchaseResult.Completed.Cancelled || it is PurchaseResult.Error.BillingError
}
.map { PaymentUiState(it?.toPaymentDialogData()) }
.stateIn(viewModelScope, SharingStarted.Lazily, PaymentUiState(PaymentDialogData()))

val uiSideEffect =
paymentUseCase.purchaseResult
.filter {
it is PurchaseResult.Completed.Cancelled || it is PurchaseResult.Error.BillingError
}
.map { PaymentUiSideEffect.PaymentCancelled }
val uiSideEffect =
paymentUseCase.purchaseResult
.filter {
it is PurchaseResult.Completed.Cancelled || it is PurchaseResult.Error.BillingError
}
.map { PaymentUiSideEffect.PaymentCancelled }

fun startBillingPayment(productId: ProductId, activityProvider: () -> Activity) {
viewModelScope.launch { paymentUseCase.purchaseProduct(productId, activityProvider) }
}
fun startBillingPayment(productId: ProductId, activityProvider: () -> Activity) {
viewModelScope.launch { paymentUseCase.purchaseProduct(productId, activityProvider) }
}
}

data class PaymentUiState(val paymentDialogData: PaymentDialogData)
data class PaymentUiState(val paymentDialogData: PaymentDialogData?)

sealed interface PaymentUiSideEffect {
data object PaymentCancelled : PaymentUiSideEffect
data object PaymentCancelled : PaymentUiSideEffect
}

0 comments on commit 4fbd1de

Please sign in to comment.