From 7b362460e70ffada8d97de04bd891a00eb06da76 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 12 Feb 2026 15:57:08 -0500 Subject: [PATCH] Spruce up the welcome and permission screens in regV5. --- app/build.gradle.kts | 1 + .../ui/permissions/GrantPermissionsScreen.kt | 2 +- app/src/main/res/values/strings.xml | 31 --- .../screens/permissions/PermissionsScreen.kt | 202 +++++++++--------- .../phonenumber/PhoneNumberEntryScreen.kt | 2 +- .../screens/shared/RegistrationScreen.kt | 110 ++++++++++ .../screens/welcome/WelcomeScreen.kt | 81 +++++-- .../org/signal/registration/test/TestTags.kt | 4 + .../src/main/res/drawable-hdpi/welcome.webp | Bin .../src/main/res/drawable-mdpi/welcome.webp | Bin .../src/main/res/drawable-xhdpi/welcome.webp | Bin .../src/main/res/drawable-xxhdpi/welcome.webp | Bin .../main/res/drawable-xxxhdpi/welcome.webp | Bin .../main/res/drawable/permission_contact.xml | 0 .../src/main/res/drawable/permission_file.xml | 0 .../res/drawable/permission_notification.xml | 0 .../main/res/drawable/permission_phone.xml | 0 .../src/main/res/values/strings.xml | 35 +++ .../RegistrationNavigationTest.kt | 11 +- .../screens/welcome/WelcomeScreenTest.kt | 3 +- 20 files changed, 322 insertions(+), 160 deletions(-) create mode 100644 feature/registration/src/main/java/org/signal/registration/screens/shared/RegistrationScreen.kt rename {app => feature/registration}/src/main/res/drawable-hdpi/welcome.webp (100%) rename {app => feature/registration}/src/main/res/drawable-mdpi/welcome.webp (100%) rename {app => feature/registration}/src/main/res/drawable-xhdpi/welcome.webp (100%) rename {app => feature/registration}/src/main/res/drawable-xxhdpi/welcome.webp (100%) rename {app => feature/registration}/src/main/res/drawable-xxxhdpi/welcome.webp (100%) rename {app => feature/registration}/src/main/res/drawable/permission_contact.xml (100%) rename {app => feature/registration}/src/main/res/drawable/permission_file.xml (100%) rename {app => feature/registration}/src/main/res/drawable/permission_notification.xml (100%) rename {app => feature/registration}/src/main/res/drawable/permission_phone.xml (100%) create mode 100644 feature/registration/src/main/res/values/strings.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7a7a2611ba..dfee7486fa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -578,6 +578,7 @@ dependencies { implementation(project(":core:models")) implementation(project(":core:models-jvm")) implementation(project(":feature:camera")) + implementation(project(":feature:registration")) implementation(libs.androidx.fragment.ktx) implementation(libs.androidx.appcompat) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/ui/permissions/GrantPermissionsScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/ui/permissions/GrantPermissionsScreen.kt index 7adb4af9a7..7852749290 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/ui/permissions/GrantPermissionsScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/ui/permissions/GrantPermissionsScreen.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.unit.dp import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.DayNightPreviews import org.signal.core.ui.compose.Previews -import org.thoughtcrime.securesms.R +import org.signal.registration.R import org.thoughtcrime.securesms.registration.ui.shared.RegistrationScreen /** diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e6ec47c90..2b0499f81e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2770,8 +2770,6 @@ I understand Play Services Error Google Play Services is updating or temporarily unavailable. Please try again. - - Signal is a 501c3 nonprofit\nTerms & Privacy Policy Signal needs the contacts and media permissions to help you connect with friends and send messages. Your contacts are uploaded using Signal\'s private contact discovery, which means they are end-to-end encrypted and never visible to the Signal service. Signal needs the contacts permission to help you connect with friends. Your contacts are uploaded using Signal\'s private contact discovery, which means they are end-to-end encrypted and never visible to the Signal service. You\'ve made too many attempts to register this number. Please try again later. @@ -2804,8 +2802,6 @@ Cancel Next - Continue - Take privacy with you.\nBe yourself in every message. Phone number @@ -4341,31 +4337,6 @@ Update now - - - Not now - - Next - - Allow permissions - - To help you message people you know, Signal will request these permissions. - - Notifications - - Get notified when new messages arrive. - - Contacts - - Find people you know. Your contacts are encrypted and not visible to the Signal service. - - Phone calls - - Make registering easier and enable additional calling features. - - Storage - - Send photos, videos and files from your device. @@ -4828,8 +4799,6 @@ I have written down this passphrase. Without it, I will be unable to restore a backup. Restore backup Transfer or restore account - - Restore or transfer Transfer account Skip diff --git a/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt index 4d85fe3c6c..da739dff0c 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt @@ -8,27 +8,31 @@ package org.signal.registration.screens.permissions import android.Manifest +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement 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.material3.Button +import androidx.compose.foundation.layout.size import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton 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.graphics.vector.ImageVector import androidx.compose.ui.platform.testTag -import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.res.stringResource +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.DayNightPreviews import org.signal.core.ui.compose.Previews +import org.signal.registration.R +import org.signal.registration.screens.shared.RegistrationScreen import org.signal.registration.screens.util.MockMultiplePermissionsState import org.signal.registration.screens.util.MockPermissionsState import org.signal.registration.test.TestTags @@ -38,7 +42,7 @@ import org.signal.registration.test.TestTags * Requests necessary runtime permissions before continuing. * * @param permissionsState The permissions state managed at the activity level. - * @param onEvent Callback for screen events. + * @param onProceed Callback invoked when the user proceeds (either granting or skipping). * @param modifier Modifier to be applied to the root container. */ @Composable @@ -47,102 +51,60 @@ fun PermissionsScreen( onProceed: () -> Unit = {}, modifier: Modifier = Modifier ) { - Column( - modifier = modifier - .fillMaxSize() - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + val permissions = permissionsState.permissions.map { it.permission } + + RegistrationScreen( + title = stringResource(id = R.string.GrantPermissionsFragment__allow_permissions), + subtitle = stringResource(id = R.string.GrantPermissionsFragment__to_help_you_message_people_you_know), + modifier = modifier.testTag(TestTags.PERMISSIONS_SCREEN), + bottomContent = { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + TextButton( + modifier = Modifier + .weight(weight = 1f, fill = false) + .testTag(TestTags.PERMISSIONS_NOT_NOW_BUTTON), + onClick = onProceed + ) { + Text( + text = stringResource(id = R.string.GrantPermissionsFragment__not_now) + ) + } + + Spacer(modifier = Modifier.size(24.dp)) + + Buttons.LargeTonal( + modifier = Modifier.testTag(TestTags.PERMISSIONS_NEXT_BUTTON), + onClick = { + permissionsState.launchMultiplePermissionRequest() + onProceed() + } + ) { + Text( + text = stringResource(id = R.string.GrantPermissionsFragment__next) + ) + } + } + } ) { - Text( - text = "Permissions", - style = MaterialTheme.typography.headlineLarge, - textAlign = TextAlign.Center - ) - - Spacer(modifier = Modifier.height(16.dp)) - - Text( - text = "Signal needs the following permissions to provide the best experience:", - style = MaterialTheme.typography.bodyLarge, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - - Spacer(modifier = Modifier.height(24.dp)) - - PermissionsList(permissions = permissionsState.permissions.map { it.permission }) - - Spacer(modifier = Modifier.height(48.dp)) - - Button( - onClick = { - permissionsState.launchMultiplePermissionRequest() - onProceed() - }, - modifier = Modifier - .fillMaxWidth() - .testTag(TestTags.PERMISSIONS_NEXT_BUTTON) - ) { - Text("Next") - } - - OutlinedButton( - onClick = { onProceed() }, - modifier = Modifier - .fillMaxWidth() - .testTag(TestTags.PERMISSIONS_NOT_NOW_BUTTON) - ) { - Text("Not now") - } - } -} - -/** - * Displays a list of permission explanations. - */ -@Composable -private fun PermissionsList( - permissions: List, - modifier: Modifier = Modifier -) { - Column( - modifier = modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - val permissionDescriptions = getPermissionDescriptions(permissions) - permissionDescriptions.forEach { description -> - PermissionItem(description = description) - } - } -} - -/** - * Individual permission item with description. - */ -@Composable -private fun PermissionItem( - description: String, - modifier: Modifier = Modifier -) { - Text( - text = "• $description", - style = MaterialTheme.typography.bodyMedium, - modifier = modifier.fillMaxWidth() - ) -} - -/** - * Converts permission names to user-friendly descriptions. - */ -private fun getPermissionDescriptions(permissions: List): List { - return buildList { if (permissions.any { it == Manifest.permission.POST_NOTIFICATIONS }) { - add("Notifications - Stay updated with new messages") + PermissionRow( + imageVector = ImageVector.vectorResource(id = R.drawable.permission_notification), + title = stringResource(id = R.string.GrantPermissionsFragment__notifications), + subtitle = stringResource(id = R.string.GrantPermissionsFragment__get_notified_when) + ) } + if (permissions.any { it == Manifest.permission.READ_CONTACTS || it == Manifest.permission.WRITE_CONTACTS }) { - add("Contacts - Find friends who use Signal") + PermissionRow( + imageVector = ImageVector.vectorResource(id = R.drawable.permission_contact), + title = stringResource(id = R.string.GrantPermissionsFragment__contacts), + subtitle = stringResource(id = R.string.GrantPermissionsFragment__find_people_you_know) + ) } + if (permissions.any { it == Manifest.permission.READ_EXTERNAL_STORAGE || it == Manifest.permission.WRITE_EXTERNAL_STORAGE || @@ -151,14 +113,54 @@ private fun getPermissionDescriptions(permissions: List): List { it == Manifest.permission.READ_MEDIA_AUDIO } ) { - add("Photos and media - Share images and videos") + PermissionRow( + imageVector = ImageVector.vectorResource(id = R.drawable.permission_file), + title = stringResource(id = R.string.GrantPermissionsFragment__storage), + subtitle = stringResource(id = R.string.GrantPermissionsFragment__send_photos_videos_and_files) + ) } + if (permissions.any { it == Manifest.permission.READ_PHONE_STATE || it == Manifest.permission.READ_PHONE_NUMBERS }) { - add("Phone - Verify your phone number") + PermissionRow( + imageVector = ImageVector.vectorResource(id = R.drawable.permission_phone), + title = stringResource(id = R.string.GrantPermissionsFragment__phone_calls), + subtitle = stringResource(id = R.string.GrantPermissionsFragment__make_registering_easier) + ) } } } +@Composable +private fun PermissionRow( + imageVector: ImageVector, + title: String, + subtitle: String +) { + Row(modifier = Modifier.padding(bottom = 32.dp)) { + Image( + imageVector = imageVector, + contentDescription = null, + modifier = Modifier.size(48.dp) + ) + + Spacer(modifier = Modifier.size(16.dp)) + + Column { + Text( + text = title, + style = MaterialTheme.typography.titleSmall + ) + + Text( + text = subtitle, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + Spacer(modifier = Modifier.size(32.dp)) + } +} + @DayNightPreviews @Composable private fun PermissionsScreenPreview() { diff --git a/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt index 2902f840be..ef04bb4af4 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt @@ -76,7 +76,7 @@ fun PhoneNumberScreen( ) } - Box(modifier = modifier.fillMaxSize()) { + Box(modifier = modifier.fillMaxSize().testTag(TestTags.PHONE_NUMBER_SCREEN)) { ScreenContent(state, onEvent) if (state.showFullScreenSpinner) { diff --git a/feature/registration/src/main/java/org/signal/registration/screens/shared/RegistrationScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/shared/RegistrationScreen.kt new file mode 100644 index 0000000000..502c4961ca --- /dev/null +++ b/feature/registration/src/main/java/org/signal/registration/screens/shared/RegistrationScreen.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2025 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.signal.registration.screens.shared + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +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.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.signal.core.ui.compose.DayNightPreviews +import org.signal.core.ui.compose.Previews +import org.signal.core.ui.compose.horizontalGutters + +/** + * A base framework for rendering the various registration screens. + */ +@Composable +fun RegistrationScreen( + title: String, + subtitle: String, + bottomContent: @Composable (BoxScope.() -> Unit), + modifier: Modifier = Modifier, + mainContent: @Composable ColumnScope.() -> Unit +) { + Surface(modifier = modifier) { + Column( + verticalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + ) { + val scrollState = rememberScrollState() + + Column( + modifier = Modifier + .verticalScroll(scrollState) + .weight(weight = 1f, fill = false) + .padding(bottom = 16.dp) + .horizontalGutters() + ) { + Spacer(Modifier.height(40.dp)) + + Text( + text = title, + style = MaterialTheme.typography.headlineMedium, + modifier = Modifier.fillMaxWidth() + ) + + Text( + text = subtitle, + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(top = 16.dp) + ) + + Spacer(modifier = Modifier.height(40.dp)) + + mainContent() + } + + Surface( + shadowElevation = if (scrollState.canScrollForward) 8.dp else 0.dp, + modifier = Modifier.fillMaxWidth() + ) { + Box( + modifier = Modifier + .padding(top = 8.dp, bottom = 24.dp) + .horizontalGutters() + ) { + bottomContent() + } + } + } + } +} + +@DayNightPreviews +@Composable +private fun RegistrationScreenPreview() { + Previews.Preview { + RegistrationScreen( + title = "Title", + subtitle = "Subtitle", + bottomContent = { + TextButton(onClick = {}) { + Text("Bottom Button") + } + } + ) { + Text("Main content") + } + } +} diff --git a/feature/registration/src/main/java/org/signal/registration/screens/welcome/WelcomeScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/welcome/WelcomeScreen.kt index 2fddf6623f..3b835ea2a5 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/welcome/WelcomeScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/welcome/WelcomeScreen.kt @@ -7,19 +7,19 @@ package org.signal.registration.screens.welcome -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column 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.material3.Button +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton import androidx.compose.material3.SheetState import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -29,14 +29,20 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource +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.BottomSheets +import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.DayNightPreviews import org.signal.core.ui.compose.Previews import org.signal.core.ui.compose.dismissWithAnimation +import org.signal.core.ui.compose.theme.SignalTheme +import org.signal.registration.R import org.signal.registration.test.TestTags /** @@ -53,34 +59,70 @@ fun WelcomeScreen( Column( modifier = modifier .fillMaxSize() - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + .testTag(TestTags.WELCOME_SCREEN), + horizontalAlignment = Alignment.CenterHorizontally ) { - Text( - text = "Welcome to Signal", - style = MaterialTheme.typography.headlineLarge, - textAlign = TextAlign.Center + Image( + painter = painterResource(R.drawable.welcome), + contentDescription = null, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .padding(16.dp), + contentScale = ContentScale.Fit ) - Spacer(modifier = Modifier.height(48.dp)) + Text( + text = stringResource(R.string.RegistrationActivity_take_privacy_with_you_be_yourself_in_every_message), + style = MaterialTheme.typography.headlineMedium, + textAlign = TextAlign.Center, + modifier = Modifier + .padding(horizontal = 32.dp) + .testTag(TestTags.WELCOME_HEADLINE) + ) - Button( + Spacer(modifier = Modifier.height(40.dp)) + + TextButton( + onClick = { /* Terms & Privacy link */ }, + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onSurfaceVariant + ) + ) { + Text( + text = stringResource(R.string.RegistrationActivity_terms_and_privacy), + textAlign = TextAlign.Center + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + + Buttons.LargeTonal( onClick = { onEvent(WelcomeScreenEvents.Continue) }, modifier = Modifier .fillMaxWidth() + .padding(horizontal = 32.dp) .testTag(TestTags.WELCOME_GET_STARTED_BUTTON) ) { - Text("Get Started") + Text(stringResource(R.string.RegistrationActivity_continue)) } - OutlinedButton( + + Spacer(modifier = Modifier.height(17.dp)) + + Buttons.LargeTonal( onClick = { showBottomSheet = true }, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = SignalTheme.colors.colorSurface2 + ), modifier = Modifier .fillMaxWidth() + .padding(horizontal = 32.dp) .testTag(TestTags.WELCOME_RESTORE_OR_TRANSFER_BUTTON) ) { - Text("Restore or transfer") + Text(stringResource(R.string.registration_activity__restore_or_transfer)) } + + Spacer(modifier = Modifier.height(48.dp)) } if (showBottomSheet) { @@ -130,9 +172,9 @@ private fun RestoreOrTransferBottomSheetContent( modifier = Modifier .fillMaxWidth() .padding(horizontal = 24.dp, vertical = 16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) + horizontalAlignment = Alignment.CenterHorizontally ) { - Button( + Buttons.LargeTonal( onClick = { sheetState.dismissWithAnimation(scope) { onEvent(WelcomeScreenEvents.HasOldPhone) @@ -145,9 +187,10 @@ private fun RestoreOrTransferBottomSheetContent( Text("I have my old phone") } - Button( + Spacer(modifier = Modifier.height(12.dp)) + + Buttons.LargeTonal( onClick = { - onEvent(WelcomeScreenEvents.DoesNotHaveOldPhone) sheetState.dismissWithAnimation(scope) { onEvent(WelcomeScreenEvents.DoesNotHaveOldPhone) } diff --git a/feature/registration/src/main/java/org/signal/registration/test/TestTags.kt b/feature/registration/src/main/java/org/signal/registration/test/TestTags.kt index 47a9030889..82f32a1b9b 100644 --- a/feature/registration/src/main/java/org/signal/registration/test/TestTags.kt +++ b/feature/registration/src/main/java/org/signal/registration/test/TestTags.kt @@ -11,16 +11,20 @@ package org.signal.registration.test object TestTags { // Welcome Screen + const val WELCOME_SCREEN = "welcome_screen" + const val WELCOME_HEADLINE = "welcome_headline" const val WELCOME_GET_STARTED_BUTTON = "welcome_get_started_button" const val WELCOME_RESTORE_OR_TRANSFER_BUTTON = "welcome_restore_or_transfer_button" const val WELCOME_RESTORE_HAS_OLD_PHONE_BUTTON = "welcome_restore_has_old_phone_button" const val WELCOME_RESTORE_NO_OLD_PHONE_BUTTON = "welcome_restore_no_old_phone_button" // Permissions Screen + const val PERMISSIONS_SCREEN = "permissions_screen" const val PERMISSIONS_NEXT_BUTTON = "permissions_next_button" const val PERMISSIONS_NOT_NOW_BUTTON = "permissions_not_now_button" // Phone Number Screen + const val PHONE_NUMBER_SCREEN = "phone_number_screen" const val PHONE_NUMBER_COUNTRY_PICKER = "phone_number_country_picker" const val PHONE_NUMBER_COUNTRY_CODE_FIELD = "phone_number_country_code_field" const val PHONE_NUMBER_PHONE_FIELD = "phone_number_phone_field" diff --git a/app/src/main/res/drawable-hdpi/welcome.webp b/feature/registration/src/main/res/drawable-hdpi/welcome.webp similarity index 100% rename from app/src/main/res/drawable-hdpi/welcome.webp rename to feature/registration/src/main/res/drawable-hdpi/welcome.webp diff --git a/app/src/main/res/drawable-mdpi/welcome.webp b/feature/registration/src/main/res/drawable-mdpi/welcome.webp similarity index 100% rename from app/src/main/res/drawable-mdpi/welcome.webp rename to feature/registration/src/main/res/drawable-mdpi/welcome.webp diff --git a/app/src/main/res/drawable-xhdpi/welcome.webp b/feature/registration/src/main/res/drawable-xhdpi/welcome.webp similarity index 100% rename from app/src/main/res/drawable-xhdpi/welcome.webp rename to feature/registration/src/main/res/drawable-xhdpi/welcome.webp diff --git a/app/src/main/res/drawable-xxhdpi/welcome.webp b/feature/registration/src/main/res/drawable-xxhdpi/welcome.webp similarity index 100% rename from app/src/main/res/drawable-xxhdpi/welcome.webp rename to feature/registration/src/main/res/drawable-xxhdpi/welcome.webp diff --git a/app/src/main/res/drawable-xxxhdpi/welcome.webp b/feature/registration/src/main/res/drawable-xxxhdpi/welcome.webp similarity index 100% rename from app/src/main/res/drawable-xxxhdpi/welcome.webp rename to feature/registration/src/main/res/drawable-xxxhdpi/welcome.webp diff --git a/app/src/main/res/drawable/permission_contact.xml b/feature/registration/src/main/res/drawable/permission_contact.xml similarity index 100% rename from app/src/main/res/drawable/permission_contact.xml rename to feature/registration/src/main/res/drawable/permission_contact.xml diff --git a/app/src/main/res/drawable/permission_file.xml b/feature/registration/src/main/res/drawable/permission_file.xml similarity index 100% rename from app/src/main/res/drawable/permission_file.xml rename to feature/registration/src/main/res/drawable/permission_file.xml diff --git a/app/src/main/res/drawable/permission_notification.xml b/feature/registration/src/main/res/drawable/permission_notification.xml similarity index 100% rename from app/src/main/res/drawable/permission_notification.xml rename to feature/registration/src/main/res/drawable/permission_notification.xml diff --git a/app/src/main/res/drawable/permission_phone.xml b/feature/registration/src/main/res/drawable/permission_phone.xml similarity index 100% rename from app/src/main/res/drawable/permission_phone.xml rename to feature/registration/src/main/res/drawable/permission_phone.xml diff --git a/feature/registration/src/main/res/values/strings.xml b/feature/registration/src/main/res/values/strings.xml new file mode 100644 index 0000000000..f392f2e25d --- /dev/null +++ b/feature/registration/src/main/res/values/strings.xml @@ -0,0 +1,35 @@ + + + Take privacy with you.\nBe yourself in every message. + + Signal is a 501c3 nonprofit\nTerms & Privacy Policy + Continue + + Restore or transfer + + + + Allow permissions + + To help you message people you know, Signal will request these permissions. + + Not now + + Next + + Notifications + + Get notified when new messages arrive. + + Contacts + + Find people you know. Your contacts are encrypted and not visible to the Signal service. + + Phone calls + + Make registering easier and enable additional calling features. + + Storage + + Send photos, videos and files from your device. + diff --git a/feature/registration/src/test/java/org/signal/registration/RegistrationNavigationTest.kt b/feature/registration/src/test/java/org/signal/registration/RegistrationNavigationTest.kt index bbe58304a1..3203db44b0 100644 --- a/feature/registration/src/test/java/org/signal/registration/RegistrationNavigationTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/RegistrationNavigationTest.kt @@ -10,7 +10,6 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.test.core.app.ApplicationProvider import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag -import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.lifecycle.SavedStateHandle import com.google.accompanist.permissions.ExperimentalPermissionsApi @@ -67,7 +66,7 @@ class RegistrationNavigationTest { } // Then - verify Welcome screen is displayed - composeTestRule.onNodeWithText("Welcome to Signal").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.WELCOME_SCREEN).assertIsDisplayed() } @Test @@ -89,7 +88,7 @@ class RegistrationNavigationTest { composeTestRule.onNodeWithTag(TestTags.WELCOME_GET_STARTED_BUTTON).performClick() // Then - verify Permissions screen is displayed - composeTestRule.onNodeWithText("Permissions").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.PERMISSIONS_SCREEN).assertIsDisplayed() } @Test @@ -114,7 +113,7 @@ class RegistrationNavigationTest { composeTestRule.onNodeWithTag(TestTags.PERMISSIONS_NEXT_BUTTON).performClick() // Then - verify PhoneNumber screen is displayed - composeTestRule.onNodeWithText("You will receive a verification code").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.PHONE_NUMBER_SCREEN).assertIsDisplayed() } @Test @@ -139,7 +138,7 @@ class RegistrationNavigationTest { composeTestRule.onNodeWithTag(TestTags.PERMISSIONS_NOT_NOW_BUTTON).performClick() // Then - verify PhoneNumber screen is displayed - composeTestRule.onNodeWithText("You will receive a verification code").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.PHONE_NUMBER_SCREEN).assertIsDisplayed() } // Note: Back navigation testing in Navigation 3 requires testing through @@ -168,7 +167,7 @@ class RegistrationNavigationTest { // Then - verify Permissions screen is displayed // (After permissions, user would go to RestoreViaQr screen) - composeTestRule.onNodeWithText("Permissions").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.PERMISSIONS_SCREEN).assertIsDisplayed() } @Test diff --git a/feature/registration/src/test/java/org/signal/registration/screens/welcome/WelcomeScreenTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/welcome/WelcomeScreenTest.kt index 00b0dc21db..f38d523455 100644 --- a/feature/registration/src/test/java/org/signal/registration/screens/welcome/WelcomeScreenTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/screens/welcome/WelcomeScreenTest.kt @@ -10,7 +10,6 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.test.core.app.ApplicationProvider import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag -import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import org.junit.Rule import org.junit.Test @@ -130,7 +129,7 @@ class WelcomeScreenTest { } // Then - composeTestRule.onNodeWithText("Welcome to Signal").assertIsDisplayed() + composeTestRule.onNodeWithTag(TestTags.WELCOME_HEADLINE).assertIsDisplayed() composeTestRule.onNodeWithTag(TestTags.WELCOME_GET_STARTED_BUTTON).assertIsDisplayed() composeTestRule.onNodeWithTag(TestTags.WELCOME_RESTORE_OR_TRANSFER_BUTTON).assertIsDisplayed() }