mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-17 23:43:34 +01:00
Make regV5 resumable if the app closes.
This commit is contained in:
committed by
Michelle Tang
parent
c7ec3ab837
commit
f09bf5b14c
@@ -69,7 +69,7 @@ fun NetworkDebugOverlay(
|
||||
onClick = { showDialog = true },
|
||||
dragOffset = dragOffset,
|
||||
onDrag = { delta -> dragOffset += delta },
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
modifier = Modifier.align(Alignment.TopEnd)
|
||||
)
|
||||
|
||||
if (showDialog) {
|
||||
|
||||
@@ -14,7 +14,9 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
@@ -74,6 +76,7 @@ fun MainScreen(
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
@@ -95,6 +98,30 @@ fun MainScreen(
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
|
||||
if (state.pendingFlowState != null) {
|
||||
PendingFlowStateCard(state.pendingFlowState)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Button(
|
||||
onClick = { onEvent(MainScreenEvents.LaunchRegistration) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text("Resume Registration")
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = { showClearDataDialog = true },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colorScheme.error
|
||||
)
|
||||
) {
|
||||
Text("Clear Pending Data")
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
if (state.existingRegistrationState != null) {
|
||||
if (state.registrationExpired) {
|
||||
Row(
|
||||
@@ -150,7 +177,7 @@ fun MainScreen(
|
||||
) {
|
||||
Text("Clear All Data")
|
||||
}
|
||||
} else {
|
||||
} else if (state.pendingFlowState == null) {
|
||||
Button(
|
||||
onClick = { onEvent(MainScreenEvents.LaunchRegistration) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
@@ -213,6 +240,55 @@ private fun RegistrationField(label: String, value: String) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PendingFlowStateCard(pending: MainScreenState.PendingFlowState) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer
|
||||
)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "In-Progress Registration",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onTertiaryContainer
|
||||
)
|
||||
|
||||
HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp))
|
||||
|
||||
RegistrationField(label = "Current Screen", value = pending.currentScreen)
|
||||
RegistrationField(label = "Backstack Depth", value = pending.backstackSize.toString())
|
||||
if (pending.e164 != null) {
|
||||
RegistrationField(label = "Phone Number", value = pending.e164)
|
||||
}
|
||||
RegistrationField(label = "Has Session", value = if (pending.hasSession) "Yes" else "No")
|
||||
RegistrationField(label = "Has AEP", value = if (pending.hasAccountEntropyPool) "Yes" else "No")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun MainScreenWithPendingFlowStatePreview() {
|
||||
Previews.Preview {
|
||||
MainScreen(
|
||||
state = MainScreenState(
|
||||
pendingFlowState = MainScreenState.PendingFlowState(
|
||||
e164 = "+15551234567",
|
||||
backstackSize = 4,
|
||||
currentScreen = "VerificationCodeEntry",
|
||||
hasSession = true,
|
||||
hasAccountEntropyPool = false
|
||||
)
|
||||
),
|
||||
onEvent = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun MainScreenPreview() {
|
||||
|
||||
@@ -7,8 +7,17 @@ package org.signal.registration.sample.screens.main
|
||||
|
||||
data class MainScreenState(
|
||||
val existingRegistrationState: ExistingRegistrationState? = null,
|
||||
val registrationExpired: Boolean = false
|
||||
val registrationExpired: Boolean = false,
|
||||
val pendingFlowState: PendingFlowState? = null
|
||||
) {
|
||||
data class PendingFlowState(
|
||||
val e164: String?,
|
||||
val backstackSize: Int,
|
||||
val currentScreen: String,
|
||||
val hasSession: Boolean,
|
||||
val hasAccountEntropyPool: Boolean
|
||||
)
|
||||
|
||||
data class ExistingRegistrationState(
|
||||
val phoneNumber: String,
|
||||
val aci: String,
|
||||
|
||||
@@ -12,9 +12,11 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.registration.NetworkController
|
||||
import org.signal.registration.PersistedFlowState
|
||||
import org.signal.registration.StorageController
|
||||
import org.signal.registration.sample.storage.RegistrationPreferences
|
||||
|
||||
@@ -75,6 +77,7 @@ class MainScreenViewModel(
|
||||
} else {
|
||||
null
|
||||
},
|
||||
pendingFlowState = loadPendingFlowState(),
|
||||
registrationExpired = false
|
||||
)
|
||||
|
||||
@@ -84,6 +87,27 @@ class MainScreenViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadPendingFlowState(): MainScreenState.PendingFlowState? {
|
||||
return try {
|
||||
val data = storageController.readInProgressRegistrationData()
|
||||
if (data.flowStateJson.isEmpty()) return null
|
||||
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
val persisted = json.decodeFromString(PersistedFlowState.serializer(), data.flowStateJson)
|
||||
|
||||
MainScreenState.PendingFlowState(
|
||||
e164 = persisted.sessionE164,
|
||||
backstackSize = persisted.backStack.size,
|
||||
currentScreen = persisted.backStack.lastOrNull()?.let { it::class.simpleName } ?: "Unknown",
|
||||
hasSession = persisted.sessionMetadata != null,
|
||||
hasAccountEntropyPool = data.accountEntropyPool.isNotEmpty()
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to load pending flow state", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkRegistrationStatus() {
|
||||
when (val result = networkController.getSvrCredentials()) {
|
||||
is NetworkController.RegistrationNetworkResult.Success -> {
|
||||
|
||||
Reference in New Issue
Block a user