mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-17 23:43:34 +01:00
Improve welcome bottom sheet UI in regV5.
This commit is contained in:
committed by
jeffrey-signal
parent
5d92fb1cc4
commit
cd24691130
@@ -86,6 +86,7 @@ private val lightColorScheme = lightColorScheme(
|
|||||||
secondary = Color(0xFF586071),
|
secondary = Color(0xFF586071),
|
||||||
secondaryContainer = Color(0xFFDCE5F9),
|
secondaryContainer = Color(0xFFDCE5F9),
|
||||||
surface = Color(0xFFFBFCFF),
|
surface = Color(0xFFFBFCFF),
|
||||||
|
surfaceContainerLow = Color(0xFFF2F5F9),
|
||||||
surfaceVariant = Color(0xFFE7EBF3),
|
surfaceVariant = Color(0xFFE7EBF3),
|
||||||
background = Color(0xFFFBFCFF),
|
background = Color(0xFFFBFCFF),
|
||||||
error = Color(0xFFBA1B1B),
|
error = Color(0xFFBA1B1B),
|
||||||
@@ -156,6 +157,7 @@ private val darkColorScheme = darkColorScheme(
|
|||||||
secondary = Color(0xFFC1C6DD),
|
secondary = Color(0xFFC1C6DD),
|
||||||
secondaryContainer = Color(0xFF414659),
|
secondaryContainer = Color(0xFF414659),
|
||||||
surface = Color(0xFF1B1C1F),
|
surface = Color(0xFF1B1C1F),
|
||||||
|
surfaceContainerLow = Color(0xFF23242A),
|
||||||
surfaceVariant = Color(0xFF303133),
|
surfaceVariant = Color(0xFF303133),
|
||||||
background = Color(0xFF1B1C1F),
|
background = Color(0xFF1B1C1F),
|
||||||
error = Color(0xFFFFB4A9),
|
error = Color(0xFFFFB4A9),
|
||||||
|
|||||||
@@ -179,21 +179,6 @@ interface NetworkController {
|
|||||||
*/
|
*/
|
||||||
suspend fun setAccountAttributes(attributes: AccountAttributes): RegistrationNetworkResult<Unit, SetAccountAttributesError>
|
suspend fun setAccountAttributes(attributes: AccountAttributes): RegistrationNetworkResult<Unit, SetAccountAttributesError>
|
||||||
|
|
||||||
// TODO
|
|
||||||
// /**
|
|
||||||
// * Validates the provided SVR2 auth credentials, returning information on their usability.
|
|
||||||
// *
|
|
||||||
// * `POST /v2/svr/auth/check`
|
|
||||||
// */
|
|
||||||
// suspend fun validateSvr2AuthCredential(e164: String, usernamePasswords: List<String>)
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Validates the provided SVR3 auth credentials, returning information on their usability.
|
|
||||||
// *
|
|
||||||
// * `POST /v3/backup/auth/check`
|
|
||||||
// */
|
|
||||||
// suspend fun validateSvr3AuthCredential(e164: String, usernamePasswords: List<String>)
|
|
||||||
//
|
|
||||||
// /**
|
// /**
|
||||||
// * Set [RestoreMethod] enum on the server for use by the old device to update UX.
|
// * Set [RestoreMethod] enum on the server for use by the old device to update UX.
|
||||||
// */
|
// */
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ sealed interface RegistrationRoute : NavKey, Parcelable {
|
|||||||
data object Welcome : RegistrationRoute
|
data object Welcome : RegistrationRoute
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Permissions(val forRestore: Boolean = false) : RegistrationRoute
|
data class Permissions(val nextRoute: RegistrationRoute) : RegistrationRoute
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object PhoneNumberEntry : RegistrationRoute
|
data object PhoneNumberEntry : RegistrationRoute
|
||||||
@@ -100,10 +100,13 @@ sealed interface RegistrationRoute : NavKey, Parcelable {
|
|||||||
data object PinCreate : RegistrationRoute
|
data object PinCreate : RegistrationRoute
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object Restore : RegistrationRoute
|
data object ChooseRestoreOptionBeforeRegistration : RegistrationRoute
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object RestoreViaQr : RegistrationRoute
|
data object ChooseRestoreOptionAfterRegistration : RegistrationRoute
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data object QuickRestoreQrScan : RegistrationRoute
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object Transfer : RegistrationRoute
|
data object Transfer : RegistrationRoute
|
||||||
@@ -203,9 +206,9 @@ private fun EntryProviderScope<NavKey>.navigationEntries(
|
|||||||
WelcomeScreen(
|
WelcomeScreen(
|
||||||
onEvent = { event ->
|
onEvent = { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
WelcomeScreenEvents.Continue -> parentEventEmitter.navigateTo(RegistrationRoute.Permissions(forRestore = false))
|
WelcomeScreenEvents.Continue -> parentEventEmitter.navigateTo(RegistrationRoute.Permissions(nextRoute = RegistrationRoute.PhoneNumberEntry))
|
||||||
WelcomeScreenEvents.DoesNotHaveOldPhone -> parentEventEmitter.navigateTo(RegistrationRoute.Restore)
|
WelcomeScreenEvents.HasOldPhone -> parentEventEmitter.navigateTo(RegistrationRoute.Permissions(nextRoute = RegistrationRoute.QuickRestoreQrScan))
|
||||||
WelcomeScreenEvents.HasOldPhone -> parentEventEmitter.navigateTo(RegistrationRoute.Permissions(forRestore = true))
|
WelcomeScreenEvents.DoesNotHaveOldPhone -> parentEventEmitter.navigateTo(RegistrationRoute.Permissions(nextRoute = RegistrationRoute.ChooseRestoreOptionBeforeRegistration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -216,11 +219,7 @@ private fun EntryProviderScope<NavKey>.navigationEntries(
|
|||||||
PermissionsScreen(
|
PermissionsScreen(
|
||||||
permissionsState = permissionsState,
|
permissionsState = permissionsState,
|
||||||
onProceed = {
|
onProceed = {
|
||||||
if (key.forRestore) {
|
parentEventEmitter.navigateTo(key.nextRoute)
|
||||||
parentEventEmitter.navigateTo(RegistrationRoute.RestoreViaQr)
|
|
||||||
} else {
|
|
||||||
parentEventEmitter.navigateTo(RegistrationRoute.PhoneNumberEntry)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -399,11 +398,11 @@ private fun EntryProviderScope<NavKey>.navigationEntries(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
entry<RegistrationRoute.Restore> {
|
entry<RegistrationRoute.ChooseRestoreOptionAfterRegistration> {
|
||||||
// TODO: Implement RestoreScreen
|
// TODO: Implement RestoreScreen
|
||||||
}
|
}
|
||||||
|
|
||||||
entry<RegistrationRoute.RestoreViaQr> {
|
entry<RegistrationRoute.QuickRestoreQrScan> {
|
||||||
RestoreViaQrScreen(
|
RestoreViaQrScreen(
|
||||||
state = RestoreViaQrState(),
|
state = RestoreViaQrState(),
|
||||||
onEvent = { event ->
|
onEvent = { event ->
|
||||||
|
|||||||
@@ -8,14 +8,20 @@
|
|||||||
package org.signal.registration.screens.welcome
|
package org.signal.registration.screens.welcome
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SheetState
|
import androidx.compose.material3.SheetState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -29,6 +35,8 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@@ -40,7 +48,9 @@ import org.signal.core.ui.compose.BottomSheets
|
|||||||
import org.signal.core.ui.compose.Buttons
|
import org.signal.core.ui.compose.Buttons
|
||||||
import org.signal.core.ui.compose.DayNightPreviews
|
import org.signal.core.ui.compose.DayNightPreviews
|
||||||
import org.signal.core.ui.compose.Previews
|
import org.signal.core.ui.compose.Previews
|
||||||
|
import org.signal.core.ui.compose.SignalIcons
|
||||||
import org.signal.core.ui.compose.dismissWithAnimation
|
import org.signal.core.ui.compose.dismissWithAnimation
|
||||||
|
import org.signal.core.ui.compose.horizontalGutters
|
||||||
import org.signal.core.ui.compose.theme.SignalTheme
|
import org.signal.core.ui.compose.theme.SignalTheme
|
||||||
import org.signal.registration.R
|
import org.signal.registration.R
|
||||||
import org.signal.registration.test.TestTags
|
import org.signal.registration.test.TestTags
|
||||||
@@ -169,40 +179,79 @@ private fun RestoreOrTransferBottomSheetContent(
|
|||||||
onEvent: (WelcomeScreenEvents) -> Unit
|
onEvent: (WelcomeScreenEvents) -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 24.dp, vertical = 16.dp),
|
.padding(bottom = 54.dp)
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
) {
|
||||||
Buttons.LargeTonal(
|
Spacer(modifier = Modifier.size(26.dp))
|
||||||
onClick = {
|
|
||||||
|
RestoreActionRow(
|
||||||
|
icon = SignalIcons.QrCode.painter,
|
||||||
|
title = stringResource(R.string.WelcomeFragment_restore_action_i_have_my_old_phone),
|
||||||
|
subtitle = stringResource(R.string.WelcomeFragment_restore_action_scan_qr),
|
||||||
|
modifier = Modifier.testTag(TestTags.WELCOME_RESTORE_HAS_OLD_PHONE_BUTTON),
|
||||||
|
onRowClick = {
|
||||||
sheetState.dismissWithAnimation(scope) {
|
sheetState.dismissWithAnimation(scope) {
|
||||||
onEvent(WelcomeScreenEvents.HasOldPhone)
|
onEvent(WelcomeScreenEvents.HasOldPhone)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
modifier = Modifier
|
)
|
||||||
.fillMaxWidth()
|
|
||||||
.testTag(TestTags.WELCOME_RESTORE_HAS_OLD_PHONE_BUTTON)
|
|
||||||
) {
|
|
||||||
Text("I have my old phone")
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
RestoreActionRow(
|
||||||
|
icon = painterResource(R.drawable.symbol_no_phone_44),
|
||||||
Buttons.LargeTonal(
|
title = stringResource(R.string.WelcomeFragment_restore_action_i_dont_have_my_old_phone),
|
||||||
onClick = {
|
subtitle = stringResource(R.string.WelcomeFragment_restore_action_reinstalling),
|
||||||
|
modifier = Modifier.testTag(TestTags.WELCOME_RESTORE_NO_OLD_PHONE_BUTTON),
|
||||||
|
onRowClick = {
|
||||||
sheetState.dismissWithAnimation(scope) {
|
sheetState.dismissWithAnimation(scope) {
|
||||||
onEvent(WelcomeScreenEvents.DoesNotHaveOldPhone)
|
onEvent(WelcomeScreenEvents.DoesNotHaveOldPhone)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
modifier = Modifier
|
)
|
||||||
.fillMaxWidth()
|
}
|
||||||
.testTag(TestTags.WELCOME_RESTORE_NO_OLD_PHONE_BUTTON)
|
}
|
||||||
) {
|
|
||||||
Text("I don't have my old phone")
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
@Composable
|
||||||
|
private fun RestoreActionRow(
|
||||||
|
icon: Painter,
|
||||||
|
title: String,
|
||||||
|
subtitle: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onRowClick: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = modifier
|
||||||
|
.horizontalGutters()
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(18.dp))
|
||||||
|
.background(MaterialTheme.colorScheme.background)
|
||||||
|
.clickable(enabled = true, onClick = onRowClick)
|
||||||
|
.padding(horizontal = 24.dp, vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = icon,
|
||||||
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(44.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(start = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.bodyLarge
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = subtitle,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +266,7 @@ private fun WelcomeScreenPreview() {
|
|||||||
@DayNightPreviews
|
@DayNightPreviews
|
||||||
@Composable
|
@Composable
|
||||||
private fun RestoreOrTransferBottomSheetPreview() {
|
private fun RestoreOrTransferBottomSheetPreview() {
|
||||||
Previews.BottomSheetPreview(forceRtl = true) {
|
Previews.BottomSheetPreview {
|
||||||
RestoreOrTransferBottomSheetContent(
|
RestoreOrTransferBottomSheetContent(
|
||||||
sheetState = rememberModalBottomSheetState(),
|
sheetState = rememberModalBottomSheetState(),
|
||||||
scope = rememberCoroutineScope(),
|
scope = rememberCoroutineScope(),
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="44dp"
|
||||||
|
android:height="44dp"
|
||||||
|
android:viewportWidth="44"
|
||||||
|
android:viewportHeight="44">
|
||||||
|
<path
|
||||||
|
android:pathData="M31.22,26.773V7.624C31.22,5.783 30.252,4.853 28.354,4.853H26.02C25.754,4.853 25.602,5.005 25.602,5.271V5.612C25.602,6.315 25.147,6.808 24.426,6.808H19.605C18.884,6.808 18.429,6.315 18.429,5.612V5.271C18.429,5.005 18.277,4.853 17.992,4.853H15.658C13.76,4.853 12.792,5.764 12.792,7.605V8.326L10.743,6.277L10.837,5.897C11.255,3.677 12.887,2.5 15.373,2.5H28.639C31.694,2.5 33.573,4.341 33.573,7.301V29.126L31.22,26.773ZM36.571,38.273L5.827,7.548C5.391,7.112 5.391,6.371 5.827,5.954C6.283,5.48 7.004,5.517 7.44,5.954L38.166,36.679C38.602,37.115 38.621,37.837 38.166,38.273C37.729,38.71 37.008,38.729 36.571,38.273ZM15.373,41.575C12.337,41.575 10.458,39.753 10.458,36.793V15.101L12.792,17.455V36.451C12.792,38.311 13.76,39.241 15.658,39.241H28.354C30.214,39.241 31.163,38.349 31.22,36.565V35.844L33.212,37.894C33.193,38.007 33.155,38.14 33.136,38.273C32.662,40.418 31.087,41.575 28.639,41.575H15.373ZM18.087,37.894C17.65,37.894 17.328,37.59 17.328,37.153C17.328,36.698 17.65,36.394 18.087,36.394H25.944C26.38,36.394 26.703,36.698 26.703,37.153C26.703,37.59 26.38,37.894 25.944,37.894H18.087Z"
|
||||||
|
android:strokeWidth="0.4"
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:strokeColor="#000000"/>
|
||||||
|
</vector>
|
||||||
@@ -84,4 +84,14 @@
|
|||||||
<string name="VerificationCodeScreen__registration_error">Registration failed. Please try again.</string>
|
<string name="VerificationCodeScreen__registration_error">Registration failed. Please try again.</string>
|
||||||
<!-- Button text for having trouble with verification -->
|
<!-- Button text for having trouble with verification -->
|
||||||
<string name="VerificationCodeScreen__having_trouble">Having trouble?</string>
|
<string name="VerificationCodeScreen__having_trouble">Having trouble?</string>
|
||||||
|
|
||||||
|
<!-- RestoreWelcomeBottomSheet -->
|
||||||
|
<!-- Row title for restore/transfer using a previous registered phone/device -->
|
||||||
|
<string name="WelcomeFragment_restore_action_i_have_my_old_phone">I have my old phone</string>
|
||||||
|
<!-- Row subtitle for restore/transfer using a previous registered phone/device -->
|
||||||
|
<string name="WelcomeFragment_restore_action_scan_qr">Scan a QR code from your current Signal account to get started quickly</string>
|
||||||
|
<!-- Row title for restore/transfer without using a previous device -->
|
||||||
|
<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>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user