mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-08 23:14:17 +01:00
Trigger backup-id upload before allowing user to pay.
This commit is contained in:
committed by
Greyson Parrelli
parent
862628fc28
commit
5ec3371b9a
-4
@@ -4,7 +4,6 @@ import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotDisplayed
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.junit4.createEmptyComposeRule
|
||||
@@ -103,9 +102,6 @@ class MessageBackupsCheckoutActivityTest {
|
||||
state = InAppPaymentTable.State.END
|
||||
)
|
||||
)
|
||||
|
||||
composeTestRule.waitForIdle()
|
||||
composeTestRule.onNodeWithTag("dialog-circular-progress-indicator").assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,6 +19,7 @@ class InAppPaymentsRule : ExternalResource() {
|
||||
override fun before() {
|
||||
initialiseConfigurationResponse()
|
||||
initialisePutSubscription()
|
||||
initialiseSetArchiveBackupId()
|
||||
}
|
||||
|
||||
private fun initialiseConfigurationResponse() {
|
||||
@@ -39,4 +40,12 @@ class InAppPaymentsRule : ExternalResource() {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun initialiseSetArchiveBackupId() {
|
||||
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
|
||||
Put("/v1/archives/backupid") {
|
||||
MockResponse().success()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,16 @@ object BackupRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers backup id reservation. As documented, this is safe to perform multiple times.
|
||||
*/
|
||||
@WorkerThread
|
||||
fun triggerBackupIdReservation(): NetworkResult<Unit> {
|
||||
val messageBackupKey = SignalStore.backup.messageBackupKey
|
||||
val mediaRootBackupKey = SignalStore.backup.mediaRootBackupKey
|
||||
return SignalNetwork.archive.triggerBackupIdReservation(messageBackupKey, mediaRootBackupKey, SignalStore.account.requireAci())
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes backup via server
|
||||
*/
|
||||
|
||||
+11
@@ -14,12 +14,14 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import kotlinx.coroutines.rx3.asFlowable
|
||||
import org.signal.core.ui.Dialogs
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
@@ -121,6 +123,7 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega
|
||||
composable(route = MessageBackupsStage.Route.TYPE_SELECTION.name) {
|
||||
MessageBackupsTypeSelectionScreen(
|
||||
stage = state.stage,
|
||||
paymentReadyState = state.paymentReadyState,
|
||||
currentBackupTier = state.currentMessageBackupTier,
|
||||
selectedBackupTier = state.selectedMessageBackupTier,
|
||||
availableBackupTypes = state.availableBackupTypes,
|
||||
@@ -152,6 +155,14 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega
|
||||
requireActivity().finishAfterTransition()
|
||||
}
|
||||
}
|
||||
|
||||
if (state.paymentReadyState == MessageBackupsFlowState.PaymentReadyState.FAILED) {
|
||||
Dialogs.SimpleMessageDialog(
|
||||
message = stringResource(R.string.MessageBackupsFlowFragment__a_network_failure_occurred),
|
||||
dismiss = stringResource(android.R.string.ok),
|
||||
onDismiss = { requireActivity().finishAfterTransition() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUserLaunchedAnExternalApplication() = error("Not supported by this fragment.")
|
||||
|
||||
+9
-2
@@ -18,5 +18,12 @@ data class MessageBackupsFlowState(
|
||||
val startScreen: MessageBackupsStage,
|
||||
val stage: MessageBackupsStage = startScreen,
|
||||
val accountEntropyPool: AccountEntropyPool = SignalStore.account.accountEntropyPool,
|
||||
val failure: Throwable? = null
|
||||
)
|
||||
val failure: Throwable? = null,
|
||||
val paymentReadyState: PaymentReadyState = PaymentReadyState.NOT_READY
|
||||
) {
|
||||
enum class PaymentReadyState {
|
||||
NOT_READY,
|
||||
READY,
|
||||
FAILED
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -69,6 +69,22 @@ class MessageBackupsFlowViewModel(
|
||||
init {
|
||||
check(SignalStore.backup.backupTier != MessageBackupTier.PAID) { "This screen does not support cancellation or downgrades." }
|
||||
|
||||
viewModelScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
BackupRepository.triggerBackupIdReservation()
|
||||
}
|
||||
|
||||
result.runIfSuccessful {
|
||||
Log.d(TAG, "Successfully triggered backup id reservation.")
|
||||
internalStateFlow.update { it.copy(paymentReadyState = MessageBackupsFlowState.PaymentReadyState.READY) }
|
||||
}
|
||||
|
||||
result.runOnStatusCodeError {
|
||||
Log.d(TAG, "Failed to trigger backup id reservation. ($it)")
|
||||
internalStateFlow.update { it.copy(paymentReadyState = MessageBackupsFlowState.PaymentReadyState.FAILED) }
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
internalStateFlow.update {
|
||||
it.copy(
|
||||
|
||||
+6
-3
@@ -70,6 +70,7 @@ import org.signal.core.ui.R as CoreUiR
|
||||
@Composable
|
||||
fun MessageBackupsTypeSelectionScreen(
|
||||
stage: MessageBackupsStage,
|
||||
paymentReadyState: MessageBackupsFlowState.PaymentReadyState,
|
||||
currentBackupTier: MessageBackupTier?,
|
||||
selectedBackupTier: MessageBackupTier?,
|
||||
availableBackupTypes: List<MessageBackupsType>,
|
||||
@@ -160,7 +161,7 @@ fun MessageBackupsTypeSelectionScreen(
|
||||
|
||||
Buttons.LargePrimary(
|
||||
onClick = onNextClicked,
|
||||
enabled = selectedBackupTier != currentBackupTier && selectedBackupTier != null,
|
||||
enabled = selectedBackupTier != currentBackupTier && selectedBackupTier != null && paymentReadyState == MessageBackupsFlowState.PaymentReadyState.READY,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = if (hasCurrentBackupTier) 10.dp else 16.dp)
|
||||
@@ -200,7 +201,8 @@ private fun MessageBackupsTypeSelectionScreenPreview() {
|
||||
onNavigationClick = {},
|
||||
onReadMoreClicked = {},
|
||||
onNextClicked = {},
|
||||
currentBackupTier = null
|
||||
currentBackupTier = null,
|
||||
paymentReadyState = MessageBackupsFlowState.PaymentReadyState.READY
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -219,7 +221,8 @@ private fun MessageBackupsTypeSelectionScreenWithCurrentTierPreview() {
|
||||
onNavigationClick = {},
|
||||
onReadMoreClicked = {},
|
||||
onNextClicked = {},
|
||||
currentBackupTier = MessageBackupTier.PAID
|
||||
currentBackupTier = MessageBackupTier.PAID,
|
||||
paymentReadyState = MessageBackupsFlowState.PaymentReadyState.READY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8047,6 +8047,10 @@
|
||||
<!-- Action button label to contact support -->
|
||||
<string name="SubscriptionNotFoundBottomSheet__contact_support">Contact support</string>
|
||||
|
||||
<!-- MessageBackupsFlowFragment -->
|
||||
<!-- Body for network failure dialog in message backups checkout flow -->
|
||||
<string name="MessageBackupsFlowFragment__a_network_failure_occurred">A network failure occurred. Please try again later.</string>
|
||||
|
||||
<!-- MessageBackupsEducationScreen -->
|
||||
<!-- Screen subtitle underneath large headline title -->
|
||||
<string name="MessageBackupsEducationScreen__backup_your_messages_and_media">Back up your messages and media and using Signal\'s secure, end-to-end encrypted storage service. Never lose a message when you get a new phone or reinstall Signal.</string>
|
||||
|
||||
Reference in New Issue
Block a user