mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-08-05 04:45:14 +01:00
Improve UX for missing SVR data in regV5.
This commit is contained in:
committed by
Michelle Tang
parent
bdb6b7d5f1
commit
55b5997a4e
@@ -289,6 +289,8 @@ class RegistrationRepository(val context: Context, val networkController: Networ
|
||||
backupSizeBytes = provisioningMessage.backupSizeBytes ?: 0,
|
||||
backupVersion = provisioningMessage.backupVersion
|
||||
)
|
||||
pin = provisioningMessage.pin ?: ""
|
||||
pinIsAlphanumeric = provisioningMessage.pin?.any { !it.isDigit() } == true
|
||||
}
|
||||
|
||||
val aep = AccountEntropyPool(provisioningMessage.accountEntropyPool)
|
||||
|
||||
+2
@@ -69,6 +69,8 @@ class PinEntryForRegistrationLockViewModel(
|
||||
is PinEntryScreenEvents.Skip -> {
|
||||
handleSkip()
|
||||
}
|
||||
is PinEntryScreenEvents.CreateNewPin,
|
||||
is PinEntryScreenEvents.ContactSupport -> Unit
|
||||
is PinEntryScreenEvents.ToggleKeyboard,
|
||||
is PinEntryScreenEvents.NeedHelp -> {
|
||||
stateEmitter(PinEntryScreenEventHandler.applyEvent(state, event))
|
||||
|
||||
+2
@@ -76,6 +76,8 @@ class PinEntryForSmsBypassViewModel(
|
||||
is PinEntryScreenEvents.Skip -> {
|
||||
handleSkip()
|
||||
}
|
||||
is PinEntryScreenEvents.CreateNewPin,
|
||||
is PinEntryScreenEvents.ContactSupport -> Unit
|
||||
is PinEntryScreenEvents.ToggleKeyboard,
|
||||
is PinEntryScreenEvents.NeedHelp -> {
|
||||
stateEmitter(PinEntryScreenEventHandler.applyEvent(state, event))
|
||||
|
||||
+11
-3
@@ -72,6 +72,15 @@ class PinEntryForSvrRestoreViewModel(
|
||||
is PinEntryScreenEvents.Skip -> {
|
||||
handleSkip()
|
||||
}
|
||||
is PinEntryScreenEvents.CreateNewPin -> {
|
||||
Log.i(TAG, "[CreateNewPin] User opted to create a new PIN after no data was found. Navigating to PIN creation.")
|
||||
stateEmitter(state.copy(showNoDataToRestoreDialog = false))
|
||||
parentEventEmitter.navigateTo(RegistrationRoute.PinCreate)
|
||||
}
|
||||
is PinEntryScreenEvents.ContactSupport -> {
|
||||
Log.i(TAG, "[ContactSupport] User opted to contact support after no data was found.")
|
||||
stateEmitter(state.copy(showNoDataToRestoreDialog = false))
|
||||
}
|
||||
is PinEntryScreenEvents.ToggleKeyboard,
|
||||
is PinEntryScreenEvents.NeedHelp -> {
|
||||
stateEmitter(PinEntryScreenEventHandler.applyEvent(state, event))
|
||||
@@ -128,9 +137,8 @@ class PinEntryForSvrRestoreViewModel(
|
||||
state.copy(triesRemaining = error.triesRemaining)
|
||||
}
|
||||
is NetworkController.RestoreMasterKeyError.NoDataFound -> {
|
||||
Log.w(TAG, "[PinEntered] No SVR data found. Need to create a PIN instead.")
|
||||
parentEventEmitter.navigateTo(RegistrationRoute.PinCreate)
|
||||
state
|
||||
Log.w(TAG, "[PinEntered] No SVR data found. Prompting user to create a new PIN.")
|
||||
state.copy(showNoDataToRestoreDialog = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -45,6 +45,7 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.Dialogs
|
||||
@@ -111,6 +112,22 @@ fun PinEntryScreen(
|
||||
)
|
||||
}
|
||||
|
||||
if (state.showNoDataToRestoreDialog) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = "",
|
||||
body = stringResource(R.string.PinEntryScreen__no_data_could_be_found),
|
||||
confirm = stringResource(R.string.PinEntryScreen__create_new_pin),
|
||||
dismiss = stringResource(R.string.PinEntryScreen__contact_support),
|
||||
onConfirm = { onEvent(PinEntryScreenEvents.CreateNewPin) },
|
||||
onDeny = { onEvent(PinEntryScreenEvents.ContactSupport) },
|
||||
onDismissRequest = { onEvent(PinEntryScreenEvents.ContactSupport) },
|
||||
properties = DialogProperties(
|
||||
dismissOnBackPress = false,
|
||||
dismissOnClickOutside = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// autofocus PIN field on initial composition
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
|
||||
+2
@@ -12,4 +12,6 @@ sealed class PinEntryScreenEvents {
|
||||
data object ToggleKeyboard : PinEntryScreenEvents()
|
||||
data object NeedHelp : PinEntryScreenEvents()
|
||||
data object Skip : PinEntryScreenEvents()
|
||||
data object CreateNewPin : PinEntryScreenEvents()
|
||||
data object ContactSupport : PinEntryScreenEvents()
|
||||
}
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ data class PinEntryState(
|
||||
val showNeedHelp: Boolean = false,
|
||||
val isAlphanumericKeyboard: Boolean = false,
|
||||
val loading: Boolean = false,
|
||||
val showNoDataToRestoreDialog: Boolean = false,
|
||||
val triesRemaining: Int? = null,
|
||||
val mode: Mode = Mode.SvrRestore,
|
||||
val oneTimeEvent: OneTimeEvent? = null,
|
||||
|
||||
@@ -373,6 +373,10 @@
|
||||
<string name="PinEntryScreen__create_new_pin">Create New PIN</string>
|
||||
<!-- Labels the button in the skip dialog that dismisses it. -->
|
||||
<string name="PinEntryScreen__cancel">Cancel</string>
|
||||
<!-- Body of the dialog shown when no data could be found to restore from the user's PIN, prompting them to create a new PIN. -->
|
||||
<string name="PinEntryScreen__no_data_could_be_found">No data could be found to restore your account. Please create a new PIN.</string>
|
||||
<!-- Labels the button in the no-data-to-restore dialog that lets the user contact support. -->
|
||||
<string name="PinEntryScreen__contact_support">Contact support</string>
|
||||
|
||||
<!-- Title for the screen asking the user to grant the notification permission -->
|
||||
<string name="AllowNotificationsScreen__allow_notifications">Allow Notifications</string>
|
||||
|
||||
+24
-1
@@ -163,7 +163,7 @@ class PinEntryForSvrRestoreViewModelTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `PinEntered with no SVR data navigates to PinCreate`() = runTest {
|
||||
fun `PinEntered with no SVR data shows the no-data-to-restore dialog without navigating`() = runTest {
|
||||
val svrCredentials = NetworkController.SvrCredentials(
|
||||
username = "test-username",
|
||||
password = "test-password"
|
||||
@@ -179,6 +179,19 @@ class PinEntryForSvrRestoreViewModelTest {
|
||||
|
||||
viewModel.applyEvent(initialState, PinEntryScreenEvents.PinEntered("123456"), parentEventEmitter, stateEmitter)
|
||||
|
||||
assertThat(emittedParentEvents).hasSize(0)
|
||||
assertThat(emittedStates.last().showNoDataToRestoreDialog).isEqualTo(true)
|
||||
}
|
||||
|
||||
// ==================== No Data To Restore Dialog Tests ====================
|
||||
|
||||
@Test
|
||||
fun `CreateNewPin dismisses the dialog and navigates to PinCreate`() = runTest {
|
||||
val initialState = PinEntryState(mode = PinEntryState.Mode.SvrRestore, showNoDataToRestoreDialog = true)
|
||||
|
||||
viewModel.applyEvent(initialState, PinEntryScreenEvents.CreateNewPin, parentEventEmitter, stateEmitter)
|
||||
|
||||
assertThat(emittedStates.last().showNoDataToRestoreDialog).isEqualTo(false)
|
||||
assertThat(emittedParentEvents).hasSize(1)
|
||||
assertThat(emittedParentEvents.first())
|
||||
.isInstanceOf<RegistrationFlowEvent.NavigateToScreen>()
|
||||
@@ -186,6 +199,16 @@ class PinEntryForSvrRestoreViewModelTest {
|
||||
.isInstanceOf<RegistrationRoute.PinCreate>()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ContactSupport dismisses the dialog without navigating`() = runTest {
|
||||
val initialState = PinEntryState(mode = PinEntryState.Mode.SvrRestore, showNoDataToRestoreDialog = true)
|
||||
|
||||
viewModel.applyEvent(initialState, PinEntryScreenEvents.ContactSupport, parentEventEmitter, stateEmitter)
|
||||
|
||||
assertThat(emittedStates.last().showNoDataToRestoreDialog).isEqualTo(false)
|
||||
assertThat(emittedParentEvents).hasSize(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `PinEntered with network error restoring master key returns NetworkError event`() = runTest {
|
||||
val svrCredentials = NetworkController.SvrCredentials(
|
||||
|
||||
Reference in New Issue
Block a user