Fix icons and restore options in regV5.

This commit is contained in:
Greyson Parrelli
2026-07-02 15:12:42 -04:00
committed by Alex Hart
parent 512df1ec1b
commit 60192c4b46
18 changed files with 119 additions and 118 deletions
@@ -58,6 +58,8 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon {
FlashOff(icon(R.drawable.symbol_flash_slash_24)),
FlashOn(icon(R.drawable.symbol_flash_24)),
Flip(icon(R.drawable.symbol_flip_24)),
Folder(icon(R.drawable.symbol_folder_24)),
FolderDisplay(icon(R.drawable.symbol_folder_display_48)),
Forward(icon(R.drawable.symbol_forward_24)),
Info(icon(R.drawable.symbol_info_24)),
Keyboard(icon(R.drawable.ic_keyboard_24)),
@@ -65,6 +67,7 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon {
Lock(icon(R.drawable.symbol_lock_24)),
Maximize(icon(R.drawable.symbol_maximize_24)),
Mic(icon(R.drawable.symbol_mic_24)),
MobileNextDisplay(icon(R.drawable.symbol_mobile_next_display_48)),
MoreVertical(icon(R.drawable.symbol_more_vertical_24)),
PersonCircle(icon(R.drawable.symbol_person_circle_24)),
Phone(icon(R.drawable.symbol_phone_24)),
@@ -77,8 +80,11 @@ enum class SignalIcons(private val icon: SignalIcon) : SignalIcon by icon {
Search(icon(R.drawable.symbol_search_24)),
Settings(icon(R.drawable.symbol_settings_android_24)),
Share(icon(R.drawable.symbol_share_android_24)),
SignalBackupsDisplay(icon(R.drawable.symbol_signal_backups_display_48)),
Sticker(icon(R.drawable.symbol_sticker_24)),
Text(icon(R.drawable.symbol_text_24)),
Transfer(icon(R.drawable.symbol_transfer_24)),
TransferDisplay(icon(R.drawable.symbol_transfer_display_48)),
Trash(icon(R.drawable.symbol_trash_24)),
X(icon(R.drawable.symbol_x_24)),
XCircleFill(icon(R.drawable.symbol_x_circle_fill_24))
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M12.429,6H14.694C14.81,6 14.89,6 14.969,6.002C16.451,6.041 17.866,6.627 18.941,7.647C18.999,7.702 19.056,7.759 19.138,7.841L19.149,7.851C19.245,7.948 19.279,7.982 19.31,8.012C19.956,8.624 20.805,8.975 21.694,8.999C21.737,9 21.784,9 21.921,9L33.653,9C35.288,9 36.589,9 37.639,9.086C38.713,9.174 39.63,9.357 40.469,9.785C41.824,10.475 42.925,11.576 43.615,12.931C44.043,13.77 44.226,14.687 44.314,15.762C44.4,16.811 44.4,18.112 44.4,19.747V25.66V25.747V30.053C44.4,31.688 44.4,32.989 44.314,34.039C44.226,35.113 44.043,36.03 43.615,36.869C42.925,38.223 41.824,39.325 40.469,40.015C39.63,40.443 38.713,40.626 37.639,40.714C36.589,40.8 35.288,40.8 33.652,40.8H14.347C12.712,40.8 11.411,40.8 10.361,40.714C9.287,40.626 8.37,40.443 7.531,40.015C6.176,39.325 5.075,38.223 4.385,36.869C3.957,36.03 3.774,35.113 3.686,34.039C3.6,32.989 3.6,31.688 3.6,30.052V25.747V25.659V14.829C3.6,13.528 3.6,12.479 3.669,11.63C3.741,10.755 3.892,9.987 4.254,9.276C4.829,8.147 5.747,7.229 6.876,6.654C7.587,6.292 8.355,6.141 9.23,6.069C10.079,6 11.128,6 12.429,6ZM6,30V25.8C6,24.1 6.001,22.897 6.078,21.957C6.153,21.031 6.297,20.465 6.523,20.021C6.983,19.118 7.718,18.383 8.621,17.923C9.065,17.697 9.631,17.553 10.557,17.478C11.497,17.401 12.7,17.4 14.4,17.4H33.6C35.3,17.4 36.503,17.401 37.443,17.478C38.369,17.553 38.935,17.697 39.379,17.923C40.282,18.383 41.017,19.118 41.477,20.021C41.703,20.465 41.847,21.031 41.922,21.957C41.999,22.897 42,24.1 42,25.8V30C42,31.7 41.999,32.903 41.922,33.843C41.847,34.769 41.703,35.335 41.477,35.779C41.017,36.682 40.282,37.417 39.379,37.877C38.935,38.103 38.369,38.247 37.443,38.322C36.503,38.399 35.3,38.4 33.6,38.4H14.4C12.7,38.4 11.497,38.399 10.557,38.322C9.631,38.247 9.065,38.103 8.621,37.877C7.718,37.417 6.983,36.682 6.523,35.779C6.297,35.335 6.153,34.769 6.078,33.843C6.001,32.903 6,31.7 6,30ZM41.477,14.021C41.703,14.465 41.847,15.031 41.922,15.957C41.972,16.568 42.054,16.946 42.332,17.688L42.293,17.709C41.889,16.911 41.264,16.19 40.469,15.785C39.63,15.357 38.713,15.174 37.639,15.086C36.589,15 35.288,15 33.653,15H14.347C12.712,15 11.411,15 10.361,15.086C9.287,15.174 8.37,15.357 7.531,15.785C6.735,16.19 6.111,16.911 5.707,17.709L5.668,17.688C5.928,16.731 6,15.941 6,14.88C6,13.516 6.001,12.565 6.061,11.825C6.121,11.099 6.231,10.682 6.392,10.366C6.738,9.688 7.288,9.138 7.966,8.792C8.282,8.631 8.699,8.521 9.425,8.461C10.165,8.401 11.116,8.4 12.48,8.4H14.679C14.816,8.4 14.863,8.4 14.906,8.401C15.795,8.425 16.644,8.776 17.289,9.388C17.321,9.418 17.354,9.452 17.451,9.549L17.462,9.559C17.544,9.641 17.601,9.698 17.659,9.753C18.734,10.773 20.149,11.359 21.631,11.398C21.71,11.4 21.79,11.4 21.906,11.4L33.6,11.4C35.3,11.4 36.503,11.401 37.443,11.478C38.369,11.553 38.935,11.697 39.379,11.923C40.282,12.383 41.017,13.118 41.477,14.021Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>
@@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M20.347,1.8H27.652C29.288,1.8 30.589,1.8 31.638,1.886C32.713,1.973 33.629,2.157 34.468,2.585C35.823,3.275 36.925,4.376 37.615,5.731C38.042,6.57 38.226,7.487 38.314,8.561C38.4,9.611 38.4,10.912 38.4,12.547V35.452C38.4,37.088 38.4,38.389 38.314,39.438C38.226,40.513 38.042,41.429 37.615,42.269C36.925,43.623 35.823,44.725 34.468,45.415C33.629,45.843 32.713,46.026 31.638,46.114C30.589,46.2 29.288,46.2 27.652,46.2H20.347C18.711,46.2 17.411,46.2 16.361,46.114C15.286,46.026 14.37,45.843 13.531,45.415C12.176,44.725 11.075,43.623 10.384,42.269C9.957,41.429 9.773,40.513 9.685,39.438C9.6,38.389 9.6,37.088 9.6,35.452V12.547C9.6,10.912 9.6,9.611 9.685,8.561C9.773,7.487 9.957,6.57 10.384,5.731C11.075,4.376 12.176,3.275 13.531,2.585C14.37,2.157 15.286,1.973 16.361,1.886C17.411,1.8 18.711,1.8 20.347,1.8ZM16.556,4.278C15.63,4.353 15.065,4.497 14.62,4.723C13.717,5.183 12.983,5.917 12.523,6.821C12.296,7.265 12.153,7.83 12.077,8.757C12,9.697 12,10.9 12,12.6V35.4C12,37.1 12,38.303 12.077,39.243C12.153,40.169 12.296,40.735 12.523,41.179C12.983,42.082 13.717,42.816 14.62,43.277C15.065,43.503 15.63,43.646 16.556,43.722C17.497,43.799 18.7,43.8 20.4,43.8H27.6C29.3,43.8 30.502,43.799 31.443,43.722C32.369,43.646 32.934,43.503 33.379,43.277C34.282,42.816 35.016,42.082 35.476,41.179C35.703,40.735 35.846,40.169 35.922,39.243C35.999,38.303 36,37.1 36,35.4V12.6C36,10.9 35.999,9.697 35.922,8.757C35.846,7.83 35.703,7.265 35.476,6.821C35.016,5.917 34.282,5.183 33.379,4.723C32.934,4.497 32.369,4.353 31.443,4.278C30.502,4.201 29.3,4.2 27.6,4.2H20.4C18.7,4.2 17.497,4.201 16.556,4.278Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M30.248,23.152C30.717,23.62 30.717,24.38 30.248,24.848L25.448,29.649C24.979,30.117 24.22,30.117 23.751,29.649C23.282,29.18 23.282,28.42 23.751,27.951L26.697,25.006L23.4,25.2L23.4,22.8L26.697,22.994L23.751,20.049C23.282,19.58 23.282,18.82 23.751,18.351C24.22,17.883 24.979,17.883 25.448,18.351L30.248,23.152ZM23.4,22.8L23.4,25.2L17.4,25.2C16.737,25.2 16.2,24.663 16.2,24C16.2,23.337 16.737,22.8 17.4,22.8L23.4,22.8Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>
@@ -0,0 +1,26 @@
<!--
~ Copyright 2026 Signal Messenger, LLC
~ SPDX-License-Identifier: AGPL-3.0-only
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M11.089,36.154C11.774,35.012 13.497,35.264 13.828,36.554L15.014,41.19C15.295,42.293 14.293,43.296 13.189,43.014L8.554,41.828C7.263,41.498 7.012,39.775 8.154,39.089L9.988,37.988L11.089,36.154Z"
android:fillColor="#000000"/>
<path
android:pathData="M23,11C23.279,11 23.507,11.221 23.517,11.5L23.968,25.044L33.501,25.478C33.78,25.49 34,25.72 34,26C34,26.28 33.78,26.51 33.501,26.522L23,27C22.448,27 22,26.552 22,26L22.483,11.5C22.493,11.221 22.721,11 23,11Z"
android:fillColor="#000000"/>
<path
android:pathData="M23,11L23,10.25L23,11ZM23.517,11.5L24.266,11.475L24.266,11.475L23.517,11.5ZM23.968,25.044L23.218,25.069C23.231,25.46 23.543,25.775 23.934,25.793L23.968,25.044ZM33.501,25.478L33.536,24.728L33.535,24.728L33.501,25.478ZM34,26H34.75H34ZM33.501,26.522L33.535,27.272L33.536,27.272L33.501,26.522ZM23,27V27.75C23.011,27.75 23.023,27.75 23.034,27.749L23,27ZM22,26L21.25,25.975C21.25,25.983 21.25,25.992 21.25,26H22ZM22.483,11.5L23.233,11.525L23.233,11.525L22.483,11.5ZM23,11L23,11.75C22.874,11.75 22.771,11.65 22.767,11.525L23.517,11.5L24.266,11.475C24.243,10.793 23.684,10.25 23,10.25L23,11ZM23.517,11.5L22.767,11.525L23.218,25.069L23.968,25.044L24.717,25.019L24.266,11.475L23.517,11.5ZM23.968,25.044L23.934,25.793L33.467,26.227L33.501,25.478L33.535,24.728L24.002,24.295L23.968,25.044ZM33.501,25.478L33.466,26.227C33.346,26.221 33.25,26.122 33.25,26H34H34.75C34.75,25.319 34.215,24.76 33.536,24.728L33.501,25.478ZM34,26H33.25C33.25,25.878 33.346,25.779 33.466,25.773L33.501,26.522L33.536,27.272C34.215,27.24 34.75,26.681 34.75,26H34ZM33.501,26.522L33.467,25.773L22.966,26.251L23,27L23.034,27.749L33.535,27.272L33.501,26.522ZM23,27V26.25C22.862,26.25 22.75,26.138 22.75,26H22H21.25C21.25,26.966 22.034,27.75 23,27.75V27ZM22,26L22.75,26.025L23.233,11.525L22.483,11.5L21.734,11.475L21.25,25.975L22,26ZM22.483,11.5L23.233,11.525C23.229,11.65 23.126,11.75 23,11.75L23,11L23,10.25C22.316,10.25 21.757,10.793 21.734,11.475L22.483,11.5Z"
android:fillColor="#000000"/>
<path
android:pathData="M40.025,35.969C42.521,32.631 44,28.488 44,24C44,19.512 42.521,15.369 40.025,12.031M35.969,7.975C32.632,5.479 28.489,4 24,4C19.511,4 15.368,5.479 12.031,7.975M7.975,12.031C5.479,15.369 4,19.512 4,24C4,30.557 7.155,36.377 12.031,40.025M19.078,43.39C20.652,43.788 22.302,44 24,44C24.345,44 24.687,43.991 25.027,43.974M30.656,42.866C32.579,42.187 34.367,41.223 35.969,40.025"
android:strokeWidth="2.5"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</vector>
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M18.771,1.2H13.629C12.328,1.2 11.279,1.2 10.43,1.269C9.555,1.341 8.787,1.492 8.076,1.854C6.947,2.429 6.029,3.347 5.454,4.476C5.092,5.187 4.941,5.955 4.869,6.83C4.8,7.679 4.8,8.728 4.8,10.029V28.371C4.8,29.672 4.8,30.721 4.869,31.57C4.941,32.445 5.092,33.213 5.454,33.924C6.029,35.053 6.947,35.971 8.076,36.546C8.787,36.908 9.555,37.059 10.43,37.131C11.279,37.2 12.328,37.2 13.628,37.2H18.6L18.6,34.8H13.68C12.316,34.8 11.365,34.799 10.625,34.739C9.899,34.679 9.482,34.569 9.166,34.408C8.488,34.063 7.938,33.512 7.592,32.834C7.431,32.518 7.321,32.101 7.261,31.375C7.201,30.635 7.2,29.684 7.2,28.32V10.08C7.2,8.716 7.201,7.765 7.261,7.025C7.321,6.299 7.431,5.882 7.592,5.566C7.938,4.888 8.488,4.338 9.166,3.992C9.482,3.831 9.899,3.721 10.625,3.661C11.365,3.601 12.316,3.6 13.68,3.6H18.72C20.084,3.6 21.035,3.601 21.775,3.661C22.501,3.721 22.918,3.831 23.234,3.992C23.912,4.338 24.462,4.888 24.808,5.566C24.969,5.882 25.079,6.299 25.139,7.025C25.173,7.451 25.188,7.946 25.195,8.55C25.426,8.518 25.656,8.494 25.883,8.475C26.398,8.433 26.971,8.415 27.594,8.406C27.586,7.816 27.569,7.293 27.531,6.83C27.459,5.955 27.308,5.187 26.946,4.476C26.371,3.347 25.453,2.429 24.324,1.854C23.613,1.492 22.845,1.341 21.97,1.269C21.121,1.2 20.072,1.2 18.771,1.2Z"
android:fillColor="#000000"/>
<path
android:pathData="M34.371,10.2H29.229C27.928,10.2 26.879,10.2 26.03,10.269C25.155,10.341 24.387,10.492 23.676,10.854C22.547,11.429 21.629,12.347 21.054,13.476C20.692,14.187 20.541,14.955 20.469,15.83C20.4,16.679 20.4,17.728 20.4,19.029V25.144C20.806,25.184 21.466,25.198 22.8,25.2V19.08C22.8,17.716 22.801,16.765 22.861,16.025C22.921,15.299 23.031,14.882 23.192,14.566C23.538,13.888 24.088,13.337 24.766,12.992C25.082,12.831 25.499,12.721 26.225,12.661C26.965,12.601 27.916,12.6 29.28,12.6H34.32C35.684,12.6 36.635,12.601 37.375,12.661C38.101,12.721 38.518,12.831 38.834,12.992C39.512,13.337 40.063,13.888 40.408,14.566C40.569,14.882 40.679,15.299 40.739,16.025C40.799,16.765 40.8,17.716 40.8,19.08V37.32C40.8,38.684 40.799,39.635 40.739,40.375C40.679,41.101 40.569,41.518 40.408,41.834C40.063,42.512 39.512,43.063 38.834,43.408C38.518,43.569 38.101,43.679 37.375,43.739C36.635,43.799 35.684,43.8 34.32,43.8H29.28C27.916,43.8 26.965,43.799 26.225,43.739C25.499,43.679 25.082,43.569 24.766,43.408C24.088,43.063 23.538,42.512 23.192,41.834C23.031,41.518 22.921,41.101 22.861,40.375C22.801,39.635 22.8,38.684 22.8,37.32V31.2C21.919,31.201 21.126,31.2 20.4,31.157V37.371C20.4,38.672 20.4,39.721 20.469,40.57C20.541,41.445 20.692,42.213 21.054,42.924C21.629,44.053 22.547,44.971 23.676,45.546C24.387,45.908 25.155,46.059 26.03,46.131C26.879,46.2 27.928,46.2 29.229,46.2H34.371C35.672,46.2 36.721,46.2 37.57,46.131C38.445,46.059 39.213,45.908 39.924,45.546C41.053,44.971 41.971,44.053 42.546,42.924C42.908,42.213 43.059,41.445 43.131,40.57C43.2,39.721 43.2,38.672 43.2,37.372V19.029C43.2,17.728 43.2,16.679 43.131,15.83C43.059,14.955 42.908,14.187 42.546,13.476C41.971,12.347 41.053,11.429 39.924,10.854C39.213,10.492 38.445,10.341 37.57,10.269C36.721,10.2 35.672,10.2 34.371,10.2Z"
android:fillColor="#000000"/>
<path
android:pathData="M13.8,17.4C14.463,17.4 15,17.937 15,18.6V18.768C15,20.915 15.009,21.77 15.177,22.447C15.713,24.603 17.397,26.287 19.554,26.823C20.23,26.991 21.085,27 23.232,27H28.5V26.326C28.5,25.397 29.512,24.82 30.312,25.294L33.473,27.168C34.258,27.632 34.258,28.768 33.473,29.232L30.312,31.106C29.512,31.58 28.5,31.003 28.5,30.073V29.4L23.037,29.4C21.148,29.4 19.974,29.4 18.975,29.152C15.955,28.402 13.598,26.045 12.848,23.025C12.6,22.026 12.6,20.852 12.6,18.963L12.6,18.6C12.6,17.937 13.137,17.4 13.8,17.4Z"
android:fillColor="#000000"/>
</vector>
@@ -172,6 +172,7 @@ sealed interface RegistrationRoute : NavKey, Parcelable {
}
add(ArchiveRestoreOption.LocalBackup)
add(ArchiveRestoreOption.DeviceTransfer)
add(ArchiveRestoreOption.None)
},
isPreRegistration = true
)
@@ -182,6 +183,7 @@ sealed interface RegistrationRoute : NavKey, Parcelable {
restoreOptions = buildList {
add(ArchiveRestoreOption.SignalSecureBackup)
add(ArchiveRestoreOption.LocalBackup)
add(ArchiveRestoreOption.None)
},
isPreRegistration = true
)
@@ -21,13 +21,13 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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 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.SignalIcons
import org.signal.registration.R
import org.signal.registration.screens.RegistrationScaffold
@@ -51,7 +51,7 @@ fun DeviceTransferCompleteScreen(
Spacer(modifier = Modifier.height(64.dp))
Icon(
painter = painterResource(R.drawable.symbol_transfer_24),
painter = SignalIcons.Transfer.painter,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(64.dp)
@@ -20,13 +20,13 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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 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.SignalIcons
import org.signal.registration.R
import org.signal.registration.screens.RegistrationScaffold
@@ -48,7 +48,7 @@ fun DeviceTransferInstructionsScreen(
Spacer(modifier = Modifier.height(48.dp))
Icon(
painter = painterResource(R.drawable.symbol_transfer_24),
painter = SignalIcons.Transfer.painter,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(64.dp)
@@ -42,11 +42,9 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@@ -125,7 +123,7 @@ private fun SelectFolderContent(
BackupOptionCard(
icon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.symbol_folder_24),
imageVector = SignalIcons.Folder.imageVector,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(32.dp)
@@ -278,7 +276,7 @@ private fun BackupInfoCard(
val sizeIcon = if (backupInfo.type == LocalBackupInfo.BackupType.V1) {
SignalIcons.File.imageVector
} else {
ImageVector.vectorResource(R.drawable.symbol_folder_24)
SignalIcons.Folder.imageVector
}
Row(verticalAlignment = Alignment.CenterVertically) {
@@ -5,8 +5,6 @@
package org.signal.registration.screens.restoreselection
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -23,14 +21,12 @@ 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.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import org.signal.core.ui.compose.AllDevicePreviews
@@ -95,22 +91,6 @@ private fun OnePaneLayout(
RestoreOptions(state, onEvent)
}
},
footer = {
RegistrationScaffold.FooterSurface(
isElevated = scrollState.canScrollForward
) {
if (state.showSkipButton) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(params.footerPadding),
horizontalArrangement = Arrangement.Center
) {
SkipRestoreButton(onEvent)
}
}
}
}
)
}
@@ -149,22 +129,6 @@ private fun TwoPaneLayout(
) {
RestoreOptions(state, onEvent)
}
},
footer = {
RegistrationScaffold.FooterSurface(
isElevated = firstPaneScrollState.canScrollForward || secondPaneScrollState.canScrollForward
) {
if (state.showSkipButton) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(params.footerPadding),
horizontalArrangement = Arrangement.End
) {
SkipRestoreButton(onEvent)
}
}
}
}
)
}
@@ -200,20 +164,6 @@ private fun RestoreOptions(state: ArchiveRestoreSelectionState, onEvent: (Archiv
}
}
@Composable
private fun SkipRestoreButton(onEvent: (ArchiveRestoreSelectionScreenEvents) -> Unit) {
TextButton(
onClick = { onEvent(ArchiveRestoreSelectionScreenEvents.Skip) },
modifier = Modifier
.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_SKIP)
) {
Text(
text = stringResource(R.string.ArchiveRestoreSelectionScreen__skip),
color = MaterialTheme.colorScheme.primary
)
}
}
@Composable
private fun RestoreOptionCard(
option: ArchiveRestoreOption,
@@ -223,7 +173,7 @@ private fun RestoreOptionCard(
when (option) {
ArchiveRestoreOption.SignalSecureBackup -> {
SelectionCard(
imageVector = SignalIcons.Backup.imageVector,
imageVector = SignalIcons.SignalBackupsDisplay.imageVector,
title = stringResource(R.string.ArchiveRestoreSelectionScreen__from_signal_backups),
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__your_free_or_paid_signal_backup_plan),
onClick = onClick,
@@ -233,7 +183,7 @@ private fun RestoreOptionCard(
ArchiveRestoreOption.DeviceTransfer -> {
SelectionCard(
imageVector = ImageVector.vectorResource(R.drawable.symbol_transfer_24),
imageVector = SignalIcons.TransferDisplay.imageVector,
title = stringResource(R.string.ArchiveRestoreSelectionScreen__from_your_old_phone),
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__transfer_directly_from_old),
onClick = onClick,
@@ -243,7 +193,7 @@ private fun RestoreOptionCard(
ArchiveRestoreOption.LocalBackup -> {
SelectionCard(
imageVector = ImageVector.vectorResource(R.drawable.symbol_folder_24),
imageVector = SignalIcons.FolderDisplay.imageVector,
title = stringResource(R.string.ArchiveRestoreSelectionScreen__local_backup_card_title),
subtitle = stringResource(R.string.ArchiveRestoreSelectionScreen__local_backup_card_description),
onClick = onClick,
@@ -253,11 +203,11 @@ private fun RestoreOptionCard(
ArchiveRestoreOption.None -> {
SelectionCard(
imageVector = ImageVector.vectorResource(R.drawable.symbol_folder_24),
imageVector = SignalIcons.MobileNextDisplay.imageVector,
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)
modifier = modifier.testTag(TestTags.ARCHIVE_RESTORE_SELECTION_NONE)
)
}
}
@@ -272,18 +222,17 @@ private fun SelectionCard(
modifier: Modifier = Modifier
) {
Card(
onClick = onClick,
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainerLow
),
modifier = modifier
.fillMaxWidth()
.clickable(onClick = onClick)
modifier = modifier.fillMaxWidth()
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(16.dp)
) {
Icon(imageVector = imageVector, contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(32.dp))
Icon(imageVector = imageVector, contentDescription = null, tint = MaterialTheme.colorScheme.primary, modifier = Modifier.size(48.dp))
Spacer(modifier = Modifier.width(16.dp))
@@ -8,8 +8,6 @@ package org.signal.registration.screens.restoreselection
sealed class ArchiveRestoreSelectionScreenEvents {
data class RestoreOptionSelected(val option: ArchiveRestoreOption) : ArchiveRestoreSelectionScreenEvents()
data object Skip : ArchiveRestoreSelectionScreenEvents()
data object ConfirmSkip : ArchiveRestoreSelectionScreenEvents()
data object DismissSkipWarning : ArchiveRestoreSelectionScreenEvents()
@@ -16,6 +16,4 @@ data class ArchiveRestoreSelectionState(
val storageCapable: Boolean = false
) {
override fun toString(): String = "ArchiveRestoreSelectionState(restoreOptions=$restoreOptions, showSkipWarningDialog=$showSkipWarningDialog, restoreMethodToken=${restoreMethodToken?.censor()}, storageCapable=$storageCapable)"
val showSkipButton: Boolean get() = ArchiveRestoreOption.None !in restoreOptions
}
@@ -102,20 +102,22 @@ class ArchiveRestoreSelectionViewModel(
}
}
}
is ArchiveRestoreSelectionScreenEvents.Skip -> {
state.copy(showSkipWarningDialog = true)
}
is ArchiveRestoreSelectionScreenEvents.ConfirmSkip -> {
notifyOldDevice(state.restoreMethodToken, NetworkController.RestoreMethod.DECLINE)
repository.setRestoreDecision(RestoreDecision.SKIPPED)
if (state.storageCapable) {
Log.i(TAG, "[ConfirmSkip] Account is storage capable. Navigating to PIN entry to restore the existing PIN.")
parentEventEmitter.navigateTo(RegistrationRoute.PinEntryForSvrRestore)
if (isPreRegistration) {
parentEventEmitter.navigateTo(RegistrationRoute.PhoneNumberEntry)
state.copy(showSkipWarningDialog = false)
} else {
Log.i(TAG, "[ConfirmSkip] Account is not storage capable. Navigating to PIN creation.")
parentEventEmitter.navigateTo(RegistrationRoute.PinCreate)
notifyOldDevice(state.restoreMethodToken, NetworkController.RestoreMethod.DECLINE)
repository.setRestoreDecision(RestoreDecision.SKIPPED)
if (state.storageCapable) {
Log.i(TAG, "[ConfirmSkip] Account is storage capable. Navigating to PIN entry to restore the existing PIN.")
parentEventEmitter.navigateTo(RegistrationRoute.PinEntryForSvrRestore)
} else {
Log.i(TAG, "[ConfirmSkip] Account is not storage capable. Navigating to PIN creation.")
parentEventEmitter.navigateTo(RegistrationRoute.PinCreate)
}
state.copy(showSkipWarningDialog = false)
}
state.copy(showSkipWarningDialog = false)
}
is ArchiveRestoreSelectionScreenEvents.DismissSkipWarning -> {
state.copy(showSkipWarningDialog = false)
@@ -67,7 +67,7 @@ object TestTags {
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"
const val ARCHIVE_RESTORE_SELECTION_NONE = "archive_restore_selection_none"
// Local Backup Restore Screen
const val LOCAL_BACKUP_RESTORE_SCREEN = "local_backup_restore_screen"
@@ -139,8 +139,6 @@
<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 -->
@@ -174,23 +174,26 @@ class ArchiveRestoreSelectionViewModelTest {
assertThat(emittedStates.last().showSkipWarningDialog).isTrue()
}
// ==================== Skip Tests ====================
@Test
fun `Skip sets showSkipWarningDialog to true`() = runTest {
val viewModel = createViewModel(isPreRegistration = false)
val initialState = ArchiveRestoreSelectionState()
viewModel.applyEvent(initialState, ArchiveRestoreSelectionScreenEvents.Skip, stateEmitter)
assertThat(emittedStates).hasSize(1)
assertThat(emittedStates.last().showSkipWarningDialog).isTrue()
}
// ==================== ConfirmSkip Tests ====================
@Test
fun `ConfirmSkip when not storage capable navigates to PinCreate and clears dialog`() = runTest {
fun `ConfirmSkip pre-registration navigates to PhoneNumberEntry and clears dialog without recording a skip`() = runTest {
val viewModel = createViewModel(isPreRegistration = true)
val initialState = ArchiveRestoreSelectionState(showSkipWarningDialog = true)
viewModel.applyEvent(initialState, ArchiveRestoreSelectionScreenEvents.ConfirmSkip, stateEmitter)
coVerify(exactly = 0) { mockRepository.setRestoreDecision(any()) }
assertThat(emittedParentEvents).hasSize(1)
assertThat(emittedParentEvents.first())
.isInstanceOf<RegistrationFlowEvent.NavigateToScreen>()
.prop(RegistrationFlowEvent.NavigateToScreen::route)
.isEqualTo(RegistrationRoute.PhoneNumberEntry)
assertThat(emittedStates.last().showSkipWarningDialog).isFalse()
}
@Test
fun `ConfirmSkip post-registration when not storage capable navigates to PinCreate and clears dialog`() = runTest {
val viewModel = createViewModel(isPreRegistration = false)
val initialState = ArchiveRestoreSelectionState(showSkipWarningDialog = true, storageCapable = false)
@@ -206,7 +209,7 @@ class ArchiveRestoreSelectionViewModelTest {
}
@Test
fun `ConfirmSkip when storage capable navigates to PinEntryForSvrRestore and clears dialog`() = runTest {
fun `ConfirmSkip post-registration when storage capable navigates to PinEntryForSvrRestore and clears dialog`() = runTest {
val viewModel = createViewModel(isPreRegistration = false)
val initialState = ArchiveRestoreSelectionState(showSkipWarningDialog = true, storageCapable = true)
@@ -248,24 +251,6 @@ class ArchiveRestoreSelectionViewModelTest {
assertThat(viewModel.state.value.restoreOptions).isEqualTo(options)
}
@Test
fun `showSkipButton is false when None is in options`() = runTest {
val viewModel = createViewModel(
restoreOptions = listOf(ArchiveRestoreOption.SignalSecureBackup, ArchiveRestoreOption.None)
)
assertThat(viewModel.state.value.showSkipButton).isFalse()
}
@Test
fun `showSkipButton is true when None is not in options`() = runTest {
val viewModel = createViewModel(
restoreOptions = listOf(ArchiveRestoreOption.SignalSecureBackup, ArchiveRestoreOption.LocalBackup)
)
assertThat(viewModel.state.value.showSkipButton).isTrue()
}
@Test
fun `applyParentState copies storageCapable from parent`() = runTest {
val viewModel = createViewModel()