From 89bfba3ee9ab58b13e06f664a950cfcb5257cd64 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Tue, 16 Jul 2024 09:13:45 -0300 Subject: [PATCH] Backups subscription flow odds and ends. --- .../MessageBackupsFlowFragment.kt | 12 +++++++--- .../subscription/MessageBackupsFlowState.kt | 1 - .../MessageBackupsFlowViewModel.kt | 24 ++++++++++++------- .../MessageBackupsPinConfirmationScreen.kt | 4 +++- .../securesms/keyvalue/InAppPaymentValues.kt | 8 +++++++ 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt index ea07db4c00..b431c05409 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt @@ -5,6 +5,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription +import androidx.activity.OnBackPressedCallback import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -38,6 +39,7 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega @Composable override fun FragmentContent() { val state by viewModel.stateFlow.collectAsState() + val pin by viewModel.pinState val navController = rememberNavController() val checkoutDelegate = remember { @@ -57,8 +59,12 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega LaunchedEffect(Unit) { navController.setLifecycleOwner(this@MessageBackupsFlowFragment) - navController.setOnBackPressedDispatcher(requireActivity().onBackPressedDispatcher) - navController.enableOnBackPressed(true) + + requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + viewModel.goToPreviousScreen() + } + }) } Nav.Host( @@ -84,7 +90,7 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega composable(route = MessageBackupsScreen.PIN_CONFIRMATION.name) { MessageBackupsPinConfirmationScreen( - pin = state.pin, + pin = pin, onPinChanged = viewModel::onPinEntryUpdated, pinKeyboardType = state.pinKeyboardType, onPinKeyboardTypeSelected = viewModel::onPinKeyboardTypeUpdated, diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt index 9608c57d40..b4390acb7c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt @@ -17,7 +17,6 @@ data class MessageBackupsFlowState( val availableBackupTypes: List = emptyList(), val selectedPaymentMethod: InAppPaymentData.PaymentMethodType? = null, val availablePaymentMethods: List = emptyList(), - val pin: String = "", val pinKeyboardType: PinKeyboardType = SignalStore.pin.keyboardType, val inAppPayment: InAppPaymentTable.InAppPayment? = null, val startScreen: MessageBackupsScreen, diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowViewModel.kt index 74d6e7db4f..549fad5c4e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowViewModel.kt @@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription import android.text.TextUtils import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers @@ -43,7 +44,10 @@ class MessageBackupsFlowViewModel : ViewModel() { ) ) + private val internalPinState = mutableStateOf("") + val stateFlow: StateFlow = internalStateFlow + val pinState: State = internalPinState init { viewModelScope.launch { @@ -58,11 +62,14 @@ class MessageBackupsFlowViewModel : ViewModel() { } fun goToNextScreen() { + val pinSnapshot = pinState.value + internalPinState.value = "" + internalStateFlow.update { val nextScreen = when (it.screen) { MessageBackupsScreen.EDUCATION -> MessageBackupsScreen.PIN_EDUCATION MessageBackupsScreen.PIN_EDUCATION -> MessageBackupsScreen.PIN_CONFIRMATION - MessageBackupsScreen.PIN_CONFIRMATION -> validatePinAndUpdateState(it.pin) + MessageBackupsScreen.PIN_CONFIRMATION -> validatePinAndUpdateState(pinSnapshot) MessageBackupsScreen.TYPE_SELECTION -> validateTypeAndUpdateState(it.selectedMessageBackupTier!!) MessageBackupsScreen.CHECKOUT_SHEET -> validateGatewayAndUpdateState(it) MessageBackupsScreen.CREATING_IN_APP_PAYMENT -> error("This is driven by an async coroutine.") @@ -107,10 +114,7 @@ class MessageBackupsFlowViewModel : ViewModel() { } fun onPinEntryUpdated(pin: String) { - // TODO [alex] -- shouldn't store this in a flow - internalStateFlow.update { - it.copy(pin = pin) - } + internalPinState.value = pin } fun onPinKeyboardTypeUpdated(pinKeyboardType: PinKeyboardType) { @@ -137,13 +141,15 @@ class MessageBackupsFlowViewModel : ViewModel() { } private fun validateTypeAndUpdateState(tier: MessageBackupTier): MessageBackupsScreen { - SignalStore.backup.areBackupsEnabled = true - SignalStore.backup.backupTier = tier - // TODO [message-backups] - Does anything need to be kicked off? return when (tier) { - MessageBackupTier.FREE -> MessageBackupsScreen.COMPLETED + MessageBackupTier.FREE -> { + SignalStore.backup.areBackupsEnabled = true + SignalStore.backup.backupTier = MessageBackupTier.FREE + + MessageBackupsScreen.COMPLETED + } MessageBackupTier.PAID -> MessageBackupsScreen.CHECKOUT_SHEET } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsPinConfirmationScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsPinConfirmationScreen.kt index f15719a82e..7605da8685 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsPinConfirmationScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsPinConfirmationScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.style.TextAlign @@ -99,7 +100,8 @@ fun MessageBackupsPinConfirmationScreen( onDone = { onNextClick() } ), keyboardOptions = KeyboardOptions( - keyboardType = keyboardType + keyboardType = keyboardType, + imeAction = ImeAction.Done ), modifier = Modifier .padding(top = 72.dp) diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InAppPaymentValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InAppPaymentValues.kt index 892dc3ffae..6af1db320a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InAppPaymentValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InAppPaymentValues.kt @@ -10,6 +10,7 @@ import org.signal.donations.PaymentSourceType import org.signal.donations.StripeApi import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequestContext +import org.thoughtcrime.securesms.backup.v2.MessageBackupTier import org.thoughtcrime.securesms.badges.Badges import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository @@ -464,6 +465,10 @@ class InAppPaymentValues internal constructor(store: KeyValueStore) : SignalStor markDonationManuallyCancelled() } else { markBackupSubscriptionpManuallyCancelled() + + // TODO [message-backups] -- Handle downgrades? + SignalStore.backup.areBackupsEnabled = false + SignalStore.backup.backupTier = null } val subscriber = InAppPaymentsRepository.getSubscriber(subscriberType) @@ -504,6 +509,9 @@ class InAppPaymentValues internal constructor(store: KeyValueStore) : SignalStor } } else { clearBackupSubscriptionManuallyCancelled() + + SignalStore.backup.areBackupsEnabled = true + SignalStore.backup.backupTier = MessageBackupTier.PAID } val subscriber = InAppPaymentsRepository.requireSubscriber(subscriberType)