mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 00:29:11 +01:00
Add infra for regV5 restore flows.
This commit is contained in:
committed by
Michelle Tang
parent
39de824bf0
commit
6c1897d8d5
@@ -30,9 +30,6 @@ import org.signal.core.ui.navigation.TransitionSpecs
|
||||
import org.signal.registration.screens.accountlocked.AccountLockedScreen
|
||||
import org.signal.registration.screens.accountlocked.AccountLockedScreenEvents
|
||||
import org.signal.registration.screens.accountlocked.AccountLockedState
|
||||
// TODO [regV5] Uncomment when restore selection flow is ready
|
||||
// import org.signal.registration.screens.restoreselection.ArchiveRestoreSelectionScreen
|
||||
// import org.signal.registration.screens.restoreselection.ArchiveRestoreSelectionViewModel
|
||||
import org.signal.registration.screens.captcha.CaptchaScreen
|
||||
import org.signal.registration.screens.captcha.CaptchaScreenEvents
|
||||
import org.signal.registration.screens.captcha.CaptchaState
|
||||
@@ -52,6 +49,8 @@ import org.signal.registration.screens.pinentry.PinEntryForSvrRestoreViewModel
|
||||
import org.signal.registration.screens.pinentry.PinEntryScreen
|
||||
import org.signal.registration.screens.quickrestore.QuickRestoreQrScreen
|
||||
import org.signal.registration.screens.quickrestore.QuickRestoreQrViewModel
|
||||
import org.signal.registration.screens.restoreselection.ArchiveRestoreSelectionScreen
|
||||
import org.signal.registration.screens.restoreselection.ArchiveRestoreSelectionViewModel
|
||||
import org.signal.registration.screens.util.navigateBack
|
||||
import org.signal.registration.screens.util.navigateTo
|
||||
import org.signal.registration.screens.verificationcode.VerificationCodeScreen
|
||||
@@ -101,9 +100,8 @@ sealed interface RegistrationRoute : NavKey, Parcelable {
|
||||
@Serializable
|
||||
data object PinCreate : RegistrationRoute
|
||||
|
||||
// TODO [regV5] Uncomment when restore selection flow is ready
|
||||
// @Serializable
|
||||
// data object ArchiveRestoreSelection : RegistrationRoute
|
||||
@Serializable
|
||||
data object ArchiveRestoreSelection : RegistrationRoute
|
||||
|
||||
@Serializable
|
||||
data object ChooseRestoreOptionBeforeRegistration : RegistrationRoute
|
||||
@@ -404,22 +402,22 @@ private fun EntryProviderScope<NavKey>.navigationEntries(
|
||||
)
|
||||
}
|
||||
|
||||
// TODO [regV5] Uncomment when restore selection flow is ready
|
||||
// entry<RegistrationRoute.ArchiveRestoreSelection> {
|
||||
// val viewModel: ArchiveRestoreSelectionViewModel = viewModel(
|
||||
// factory = ArchiveRestoreSelectionViewModel.Factory(
|
||||
// repository = registrationRepository,
|
||||
// parentState = registrationViewModel.state,
|
||||
// parentEventEmitter = registrationViewModel::onEvent
|
||||
// )
|
||||
// )
|
||||
// val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
//
|
||||
// ArchiveRestoreSelectionScreen(
|
||||
// state = state,
|
||||
// onEvent = { viewModel.onEvent(it) }
|
||||
// )
|
||||
// }
|
||||
// -- Archive Restore Selection Screen
|
||||
entry<RegistrationRoute.ArchiveRestoreSelection> {
|
||||
val viewModel: ArchiveRestoreSelectionViewModel = viewModel(
|
||||
factory = ArchiveRestoreSelectionViewModel.Factory(
|
||||
repository = registrationRepository,
|
||||
parentState = registrationViewModel.state,
|
||||
parentEventEmitter = registrationViewModel::onEvent
|
||||
)
|
||||
)
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
ArchiveRestoreSelectionScreen(
|
||||
state = state,
|
||||
onEvent = { viewModel.onEvent(it) }
|
||||
)
|
||||
}
|
||||
|
||||
entry<RegistrationRoute.ChooseRestoreOptionAfterRegistration> {
|
||||
// TODO: Implement RestoreScreen
|
||||
|
||||
@@ -34,8 +34,8 @@ import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.MultiplePermissionsState
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.horizontalGutters
|
||||
import org.signal.registration.R
|
||||
|
||||
@@ -46,9 +46,9 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.CircularProgressWrapper
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Dialogs
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.registration.R
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
package org.signal.registration.screens.pincreation
|
||||
|
||||
import org.signal.core.models.AccountEntropyPool
|
||||
import org.signal.registration.BuildConfig
|
||||
import org.signal.registration.util.DebugLoggable
|
||||
import org.signal.registration.util.DebugLoggableModel
|
||||
|
||||
data class PinCreationState(
|
||||
@@ -15,4 +13,4 @@ data class PinCreationState(
|
||||
val inputLabel: String? = null,
|
||||
val isConfirmEnabled: Boolean = false,
|
||||
val accountEntropyPool: AccountEntropyPool? = null
|
||||
) : DebugLoggableModel()
|
||||
) : DebugLoggableModel()
|
||||
|
||||
@@ -25,4 +25,3 @@ sealed class QrState : DebugLoggableModel() {
|
||||
data object Scanned : QrState()
|
||||
data object Failed : QrState()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.registration.screens.restoreselection
|
||||
|
||||
/**
|
||||
* Restore options that may be presented on the archive restore selection screen.
|
||||
* The available options are determined by the [org.signal.registration.StorageController].
|
||||
*/
|
||||
enum class ArchiveRestoreOption {
|
||||
SignalSecureBackup,
|
||||
LocalBackup,
|
||||
DeviceTransfer,
|
||||
None
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.registration.screens.restoreselection
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
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.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
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.Dialogs
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.registration.R
|
||||
import org.signal.registration.test.TestTags
|
||||
|
||||
@Composable
|
||||
fun ArchiveRestoreSelectionScreen(
|
||||
state: ArchiveRestoreSelectionState,
|
||||
onEvent: (ArchiveRestoreSelectionScreenEvents) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
if (state.showSkipRestoreWarning) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(R.string.ArchiveRestoreSelectionScreen__skip_restore_dialog_title),
|
||||
body = stringResource(R.string.ArchiveRestoreSelectionScreen__skip_restore_dialog_warning),
|
||||
confirm = stringResource(R.string.ArchiveRestoreSelectionScreen__skip_restore_dialog_confirm_button),
|
||||
dismiss = stringResource(android.R.string.cancel),
|
||||
onConfirm = { onEvent(ArchiveRestoreSelectionScreenEvents.ConfirmSkip) },
|
||||
onDismiss = { onEvent(ArchiveRestoreSelectionScreenEvents.DismissSkipWarning) },
|
||||
confirmColor = MaterialTheme.colorScheme.error,
|
||||
properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)
|
||||
)
|
||||
}
|
||||
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState)
|
||||
.padding(horizontal = 24.dp)
|
||||
.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_SCREEN),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.ArchiveRestoreSelectionScreen__restore_or_transfer_account),
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.ArchiveRestoreSelectionScreen__subheading),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(28.dp))
|
||||
|
||||
state.restoreOptions.forEachIndexed { index, option ->
|
||||
if (index > 0) {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
RestoreOptionCard(
|
||||
option = option,
|
||||
onClick = { onEvent(ArchiveRestoreSelectionScreenEvents.RestoreOptionSelected(option)) }
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
TextButton(
|
||||
onClick = { onEvent(ArchiveRestoreSelectionScreenEvents.Skip) },
|
||||
modifier = Modifier
|
||||
.padding(bottom = 32.dp)
|
||||
.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_SKIP)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.ArchiveRestoreSelectionScreen__skip),
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RestoreOptionCard(
|
||||
option: ArchiveRestoreOption,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
when (option) {
|
||||
ArchiveRestoreOption.SignalSecureBackup -> {
|
||||
SelectionCard(
|
||||
icon = { Icon(painter = SignalIcons.Backup.painter, contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp)) },
|
||||
title = stringResource(R.string.ArchiveRestoreSelectionScreen__from_signal_backups),
|
||||
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__your_free_or_paid_signal_backup_plan),
|
||||
onClick = onClick,
|
||||
modifier = modifier.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_FROM_SIGNAL_BACKUPS)
|
||||
)
|
||||
}
|
||||
ArchiveRestoreOption.DeviceTransfer -> {
|
||||
SelectionCard(
|
||||
icon = { Icon(painter = painterResource(R.drawable.symbol_transfer_24), contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp)) },
|
||||
title = stringResource(R.string.ArchiveRestoreSelectionScreen__from_your_old_phone),
|
||||
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__transfer_directly_from_old),
|
||||
onClick = onClick,
|
||||
modifier = modifier.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_DEVICE_TRANSFER)
|
||||
)
|
||||
}
|
||||
ArchiveRestoreOption.LocalBackup -> {
|
||||
SelectionCard(
|
||||
icon = { Icon(painter = painterResource(R.drawable.symbol_folder_24), contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp)) },
|
||||
title = stringResource(R.string.ArchiveRestoreSelectionScreen__local_backup_card_title),
|
||||
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__local_backup_card_description),
|
||||
onClick = onClick,
|
||||
modifier = modifier.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_FROM_BACKUP_FOLDER)
|
||||
)
|
||||
}
|
||||
|
||||
ArchiveRestoreOption.None -> {
|
||||
SelectionCard(
|
||||
icon = { Icon(painter = painterResource(R.drawable.symbol_folder_24), contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp)) },
|
||||
title = stringResource(R.string.ArchiveRestoreSelectionScreen__skip_restore_title),
|
||||
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__skip_restore_description),
|
||||
onClick = onClick,
|
||||
modifier = modifier.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_FROM_BACKUP_FOLDER)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SelectionCard(
|
||||
icon: @Composable () -> Unit,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainerLow
|
||||
),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
icon()
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
Text(
|
||||
text = subtitle,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllDevicePreviews
|
||||
@Composable
|
||||
private fun ArchiveRestoreSelectionScreenPreview() {
|
||||
Previews.Preview {
|
||||
ArchiveRestoreSelectionScreen(
|
||||
state = ArchiveRestoreSelectionState(
|
||||
restoreOptions = listOf(ArchiveRestoreOption.SignalSecureBackup, ArchiveRestoreOption.LocalBackup, ArchiveRestoreOption.DeviceTransfer, ArchiveRestoreOption.None)
|
||||
),
|
||||
onEvent = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.registration.screens.restoreselection
|
||||
|
||||
import org.signal.registration.util.DebugLoggableModel
|
||||
|
||||
sealed class ArchiveRestoreSelectionScreenEvents : DebugLoggableModel() {
|
||||
data class RestoreOptionSelected(val option: ArchiveRestoreOption) : ArchiveRestoreSelectionScreenEvents()
|
||||
data object Skip : ArchiveRestoreSelectionScreenEvents()
|
||||
data object ConfirmSkip : ArchiveRestoreSelectionScreenEvents()
|
||||
data object DismissSkipWarning : ArchiveRestoreSelectionScreenEvents()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.registration.screens.restoreselection
|
||||
|
||||
import org.signal.registration.util.DebugLoggableModel
|
||||
|
||||
data class ArchiveRestoreSelectionState(
|
||||
val restoreOptions: List<ArchiveRestoreOption> = emptyList(),
|
||||
val showSkipButton: Boolean = false,
|
||||
val showSkipRestoreWarning: Boolean = false
|
||||
) : DebugLoggableModel()
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.registration.screens.restoreselection
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.registration.RegistrationFlowEvent
|
||||
import org.signal.registration.RegistrationFlowState
|
||||
import org.signal.registration.RegistrationRepository
|
||||
import org.signal.registration.RegistrationRoute
|
||||
import org.signal.registration.screens.util.navigateTo
|
||||
|
||||
class ArchiveRestoreSelectionViewModel(
|
||||
private val repository: RegistrationRepository,
|
||||
private val parentState: StateFlow<RegistrationFlowState>,
|
||||
private val parentEventEmitter: (RegistrationFlowEvent) -> Unit
|
||||
) : ViewModel() {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(ArchiveRestoreSelectionViewModel::class)
|
||||
}
|
||||
|
||||
private val _localState = MutableStateFlow(ArchiveRestoreSelectionState())
|
||||
val state = combine(_localState, parentState) { state, parentState -> applyParentState(state, parentState) }
|
||||
.onEach { Log.d(TAG, "[State] $it") }
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), ArchiveRestoreSelectionState())
|
||||
|
||||
init {
|
||||
// viewModelScope.launch {
|
||||
// val options = repository.isSignalSecureBackupAvailable()
|
||||
// _localState.value = _localState.value.copy(restoreOptions = options)
|
||||
// }
|
||||
}
|
||||
|
||||
fun onEvent(event: ArchiveRestoreSelectionScreenEvents) {
|
||||
Log.d(TAG, "[Event] $event")
|
||||
viewModelScope.launch {
|
||||
val stateEmitter: (ArchiveRestoreSelectionState) -> Unit = { newState ->
|
||||
_localState.value = newState
|
||||
}
|
||||
applyEvent(state.value, event, stateEmitter)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun applyEvent(state: ArchiveRestoreSelectionState, event: ArchiveRestoreSelectionScreenEvents, stateEmitter: (ArchiveRestoreSelectionState) -> Unit) {
|
||||
val result = when (event) {
|
||||
is ArchiveRestoreSelectionScreenEvents.RestoreOptionSelected -> {
|
||||
Log.w(TAG, "Restore option selected: ${event.option}, but flow not yet implemented") // TODO [registration] - Handle restore option selection
|
||||
state
|
||||
}
|
||||
is ArchiveRestoreSelectionScreenEvents.Skip -> {
|
||||
state.copy(showSkipRestoreWarning = true)
|
||||
}
|
||||
is ArchiveRestoreSelectionScreenEvents.ConfirmSkip -> {
|
||||
parentEventEmitter.navigateTo(RegistrationRoute.PinCreate)
|
||||
state.copy(showSkipRestoreWarning = false)
|
||||
}
|
||||
is ArchiveRestoreSelectionScreenEvents.DismissSkipWarning -> {
|
||||
state.copy(showSkipRestoreWarning = false)
|
||||
}
|
||||
}
|
||||
stateEmitter(result)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun applyParentState(state: ArchiveRestoreSelectionState, parentState: RegistrationFlowState): ArchiveRestoreSelectionState {
|
||||
return state
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val repository: RegistrationRepository,
|
||||
private val parentState: StateFlow<RegistrationFlowState>,
|
||||
private val parentEventEmitter: (RegistrationFlowEvent) -> Unit
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ArchiveRestoreSelectionViewModel(repository, parentState, parentEventEmitter) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,9 +44,9 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.BottomSheets
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.core.ui.compose.dismissWithAnimation
|
||||
|
||||
@@ -42,4 +42,12 @@ object TestTags {
|
||||
const val VERIFICATION_CODE_RESEND_SMS_BUTTON = "verification_code_resend_sms_button"
|
||||
const val VERIFICATION_CODE_CALL_ME_BUTTON = "verification_code_call_me_button"
|
||||
const val VERIFICATION_CODE_HAVING_TROUBLE_BUTTON = "verification_code_having_trouble_button"
|
||||
|
||||
// Archive Restore Selection Screen
|
||||
const val ARCHIVE_RESTORE_SELECTION_SCREEN = "archive_restore_selection_screen"
|
||||
const val ARCHIVE_RESTORE_SELECTION_FROM_SIGNAL_BACKUPS = "archive_restore_selection_from_signal_backups"
|
||||
const val ARCHIVE_RESTORE_SELECTION_FROM_BACKUP_FOLDER = "archive_restore_selection_from_backup_folder"
|
||||
const val ARCHIVE_RESTORE_SELECTION_FROM_BACKUP_FILE = "archive_restore_selection_from_backup_file"
|
||||
const val ARCHIVE_RESTORE_SELECTION_DEVICE_TRANSFER = "archive_restore_selection_device_transfer"
|
||||
const val ARCHIVE_RESTORE_SELECTION_SKIP = "archive_restore_selection_skip"
|
||||
}
|
||||
|
||||
@@ -15,4 +15,4 @@ open class DebugLoggableModel : DebugLoggable {
|
||||
toSafeString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.683,1.69c-0.276,-0.066 -0.56,-0.065 -0.86,-0.065h-2.56c-0.809,0 -1.469,0 -2.005,0.044 -0.554,0.045 -1.052,0.142 -1.517,0.378a3.875,3.875 0,0 0,-1.694 1.694c-0.236,0.465 -0.333,0.963 -0.378,1.517 -0.044,0.536 -0.044,1.196 -0.044,2.005v9.474c0,0.809 0,1.469 0.044,2.005 0.045,0.554 0.142,1.052 0.378,1.517 0.372,0.73 0.965,1.322 1.694,1.694 0.465,0.236 0.963,0.333 1.517,0.378 0.536,0.044 1.196,0.044 2.005,0.044h5.474c0.809,0 1.469,0 2.005,-0.044 0.554,-0.045 1.052,-0.142 1.517,-0.378a3.875,3.875 0,0 0,1.694 -1.694c0.236,-0.465 0.333,-0.963 0.378,-1.517 0.044,-0.536 0.044,-1.196 0.044,-2.005v-6.56c0,-0.3 0,-0.584 -0.066,-0.86a2.376,2.376 0,0 0,-0.284 -0.687c-0.148,-0.242 -0.35,-0.442 -0.562,-0.655l-5.438,-5.438c-0.213,-0.213 -0.413,-0.413 -0.655,-0.562a2.374,2.374 0,0 0,-0.687 -0.284ZM11.125,3.375L9.3,3.375c-0.855,0 -1.443,0 -1.9,0.038 -0.445,0.036 -0.688,0.103 -0.865,0.194 -0.4,0.203 -0.725,0.528 -0.928,0.928 -0.09,0.177 -0.158,0.42 -0.194,0.866 -0.037,0.456 -0.038,1.045 -0.038,1.899v9.4c0,0.855 0,1.443 0.038,1.9 0.036,0.445 0.103,0.688 0.194,0.865 0.203,0.4 0.528,0.725 0.928,0.928 0.177,0.09 0.42,0.158 0.866,0.194 0.456,0.037 1.044,0.038 1.899,0.038h5.4c0.855,0 1.443,0 1.9,-0.038 0.445,-0.036 0.688,-0.103 0.865,-0.194 0.4,-0.203 0.725,-0.528 0.928,-0.928 0.09,-0.177 0.158,-0.42 0.194,-0.866 0.037,-0.456 0.038,-1.044 0.038,-1.899v-5.825h-1.862c-0.809,0 -1.469,0 -2.005,-0.044 -0.554,-0.045 -1.052,-0.141 -1.517,-0.378a3.875,3.875 0,0 1,-1.694 -1.694c-0.237,-0.465 -0.333,-0.963 -0.378,-1.517 -0.044,-0.536 -0.044,-1.196 -0.044,-2.005L11.125,3.375ZM18.338,9.125L17.013,8l-2.988,-2.988 -1.15,-1.35L12.875,5.2c0,0.855 0,1.443 0.038,1.9 0.036,0.445 0.103,0.688 0.194,0.865 0.203,0.4 0.528,0.725 0.928,0.928 0.177,0.09 0.42,0.158 0.866,0.194 0.456,0.037 1.044,0.038 1.899,0.038h1.538Z"
|
||||
android:fillColor="#000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M1.63 6v7.2 0.06 1.98c0 0.8 0 1.47 0.04 2C1.7 17.8 1.8 18.3 2.05 18.76c0.37 0.73 0.96 1.32 1.7 1.7 0.46 0.23 0.95 0.33 1.5 0.37 0.54 0.05 1.2 0.05 2.01 0.05h9.48c0.8 0 1.47 0 2-0.05 0.56-0.04 1.05-0.14 1.52-0.38 0.73-0.37 1.32-0.96 1.7-1.7 0.23-0.46 0.33-0.95 0.37-1.5 0.05-0.54 0.05-1.2 0.05-2.01V9.76c0-0.8 0-1.47-0.05-2C22.3 7.2 22.2 6.7 21.95 6.24c-0.37-0.73-0.96-1.32-1.7-1.7-0.46-0.23-0.95-0.33-1.5-0.37-0.54-0.05-1.2-0.05-2.01-0.05h-5.75c-0.41 0-0.81-0.15-1.11-0.43L9.72 3.54c-0.63-0.59-1.45-0.92-2.3-0.92H5C3.14 2.63 1.62 4.14 1.62 6Zm18.96 5.4c0.03 0.46 0.04 1.05 0.04 1.9v1.9c0 0.85 0 1.44-0.04 1.9-0.04 0.45-0.1 0.69-0.2 0.86-0.2 0.4-0.53 0.73-0.93 0.93-0.17 0.1-0.41 0.16-0.86 0.2-0.46 0.03-1.05 0.04-1.9 0.04H7.3c-0.85 0-1.44 0-1.9-0.04-0.45-0.04-0.69-0.1-0.86-0.2-0.4-0.2-0.73-0.53-0.93-0.93-0.1-0.17-0.16-0.41-0.2-0.86-0.03-0.46-0.04-1.05-0.04-1.9v-1.9c0-0.85 0-1.44 0.04-1.9 0.04-0.45 0.1-0.69 0.2-0.86 0.2-0.4 0.53-0.73 0.93-0.93C4.7 9.5 4.95 9.45 5.4 9.4c0.46-0.03 1.05-0.04 1.9-0.04h9.4c0.85 0 1.44 0 1.9 0.04 0.45 0.04 0.69 0.1 0.86 0.2 0.4 0.2 0.73 0.53 0.93 0.93 0.1 0.17 0.16 0.41 0.2 0.86ZM3.38 6C3.38 5.1 4.1 4.37 5 4.37h2.41c0.41 0 0.81 0.16 1.11 0.44l0.16 0.15c0.63 0.59 1.45 0.92 2.3 0.92h5.72c0.85 0 1.44 0 1.9 0.03 0.45 0.04 0.69 0.1 0.86 0.2 0.4 0.2 0.73 0.53 0.93 0.93 0.06 0.11 0.12 0.25 0.15 0.46 0.05 0.36 0.13 0.5 0.57 0.93l-0.1 0.1c-0.23-0.2-0.5-0.35-0.75-0.48-0.47-0.24-0.96-0.34-1.52-0.38-0.53-0.05-1.2-0.05-2-0.04H7.26c-0.8 0-1.47 0-2 0.04C4.7 7.7 4.2 7.8 3.74 8.05c-0.29 0.14-0.56 0.33-0.8 0.54L2.86 8.52C3.28 8.09 3.38 7.9 3.38 7.54V6Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M8.12 5.13C7.95 4.97 7.73 4.88 7.5 4.88c-0.23 0-0.45 0.09-0.62 0.25l-3.5 3.5c-0.34 0.34-0.34 0.9 0 1.24 0.34 0.34 0.9 0.34 1.24 0l2.13-2.13L6.62 9.5v8.25c0 0.48 0.4 0.88 0.88 0.88s0.88-0.4 0.88-0.88V9.5L8.24 7.74l2.13 2.13c0.34 0.34 0.9 0.34 1.24 0 0.34-0.34 0.34-0.9 0-1.24l-3.5-3.5Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17.12 18.87c-0.17 0.16-0.39 0.25-0.62 0.25-0.23 0-0.45-0.09-0.62-0.25l-3.5-3.5c-0.34-0.34-0.34-0.9 0-1.24 0.34-0.34 0.9-0.34 1.24 0l2.13 2.13-0.13-1.76V6.25c0-0.48 0.4-0.88 0.88-0.88s0.88 0.4 0.88 0.88v8.25l-0.13 1.76 2.13-2.13c0.34-0.34 0.9-0.34 1.24 0 0.34 0.34 0.34 0.9 0 1.24l-3.5 3.5Z"/>
|
||||
</vector>
|
||||
@@ -94,4 +94,40 @@
|
||||
<string name="WelcomeFragment_restore_action_i_dont_have_my_old_phone">I don\'t have my old phone</string>
|
||||
<!-- Row subtitle for restore/transfer without using a previous device -->
|
||||
<string name="WelcomeFragment_restore_action_reinstalling">Or you\'re reinstalling Signal on the same device</string>
|
||||
|
||||
<!-- ArchiveRestoreSelectionScreen -->
|
||||
<!-- Title text for the archive restore selection screen -->
|
||||
<string name="ArchiveRestoreSelectionScreen__restore_or_transfer_account">Restore or transfer account</string>
|
||||
<!-- Subtitle text for the archive restore selection screen -->
|
||||
<string name="ArchiveRestoreSelectionScreen__subheading">Choose how you’d like to restore your message history and account data.</string>
|
||||
<!-- Title for the Signal Backups option card -->
|
||||
<string name="ArchiveRestoreSelectionScreen__from_signal_backups">From Signal Backups</string>
|
||||
<!-- Subtitle for the Signal Backups option card -->
|
||||
<string name="ArchiveRestoreSelectionScreen__your_free_or_paid_signal_backup_plan">Your free or paid Signal Backup plan</string>
|
||||
<!-- Title for an option that, when clicked, will take the user to a flow to restore form a local backup -->
|
||||
<string name="ArchiveRestoreSelectionScreen__local_backup_card_title">Restore on-device backup</string>
|
||||
<!-- Description for an option that, when clicked, will take the user to a flow to restore form a local backup -->
|
||||
<string name="ArchiveRestoreSelectionScreen__local_backup_card_description">Restore your messages from a backup you saved on your device.</string>
|
||||
<!-- Title for an option that, when clicked, will take the user to a flow to restore form a local backup -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip_restore_title">Continue without transferring</string>
|
||||
<!-- Description for an option that, when clicked, will take the user to a flow to restore form a local backup -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip_restore_description">Messages & media won’t be transferred</string>
|
||||
<!-- Title for the backup folder option card (V2 format) -->
|
||||
<string name="ArchiveRestoreSelectionScreen__from_a_backup_folder">From a backup folder</string>
|
||||
<!-- Title for the backup file option card (V1 legacy format) -->
|
||||
<string name="ArchiveRestoreSelectionScreen__from_a_backup_file">From a backup file</string>
|
||||
<!-- Subtitle for the backup folder/file option cards -->
|
||||
<string name="ArchiveRestoreSelectionScreen__choose_a_backup_youve_saved">Choose a backup you\'ve saved</string>
|
||||
<!-- Title for the device transfer option card -->
|
||||
<string name="ArchiveRestoreSelectionScreen__from_your_old_phone">From your old phone</string>
|
||||
<!-- Subtitle for the device transfer option card -->
|
||||
<string name="ArchiveRestoreSelectionScreen__transfer_directly_from_old">Transfer directly from your old Android</string>
|
||||
<!-- Skip button text -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip">Skip</string>
|
||||
<!-- Title for the skip restore confirmation dialog -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip_restore_dialog_title">Skip restore?</string>
|
||||
<!-- Warning body text for the skip restore confirmation dialog -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip_restore_dialog_warning">If you skip restore now you will not be able to restore later. If you re-enable backups after skipping restore, your current backup will be replaced with your new messaging history.</string>
|
||||
<!-- Confirm button text for the skip restore dialog -->
|
||||
<string name="ArchiveRestoreSelectionScreen__skip_restore_dialog_confirm_button">Skip restore</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user