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()
}