diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index aab652a4f2..8cb7dfdd23 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1536,7 +1536,7 @@
LinkAndSyncProgress.Downloading(event.count, event.estimatedTotalCount)
- RestoreV2Event.Type.PROGRESS_RESTORE -> LinkAndSyncProgress.Restoring
- RestoreV2Event.Type.PROGRESS_FINALIZING -> LinkAndSyncProgress.Restoring
+ RestoreV2Event.Type.PROGRESS_RESTORE -> LinkAndSyncProgress.Restoring(event.count, event.estimatedTotalCount)
+ RestoreV2Event.Type.PROGRESS_FINALIZING -> LinkAndSyncProgress.Finalizing
}
trySend(progress)
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/AttachmentProgressService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/AttachmentProgressService.kt
index 35a823d5f0..e455fe7453 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/AttachmentProgressService.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/AttachmentProgressService.kt
@@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.signal.core.util.PendingIntentFlags
+import org.signal.core.util.SafeForegroundService
import org.signal.core.util.logging.Log
import org.signal.core.util.throttleLatest
import org.thoughtcrime.securesms.MainActivity
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/BackupMediaRestoreService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/BackupMediaRestoreService.kt
index a11d864e03..7e15f72b28 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/BackupMediaRestoreService.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/BackupMediaRestoreService.kt
@@ -8,6 +8,7 @@ import android.os.Build
import androidx.core.app.NotificationCompat
import org.signal.core.util.ByteSize
import org.signal.core.util.PendingIntentFlags
+import org.signal.core.util.SafeForegroundService
import org.signal.core.util.bytes
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.MainActivity
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/BackupProgressService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/BackupProgressService.kt
index 637288e52d..9732277ea6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/BackupProgressService.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/BackupProgressService.kt
@@ -12,18 +12,21 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.PowerManager
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import org.signal.core.util.PendingIntentFlags
+import org.signal.core.util.SafeForegroundService
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.MainActivity
-import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.notifications.NotificationIds
import java.util.concurrent.locks.ReentrantLock
import javax.annotation.CheckReturnValue
import kotlin.concurrent.withLock
+import kotlin.time.Duration.Companion.hours
+import org.signal.core.ui.R as CoreUiR
/**
* Foreground service to provide "long" run support to backup jobs.
@@ -44,6 +47,9 @@ class BackupProgressService : SafeForegroundService() {
private var progress: Float = 0f
private var indeterminate: Boolean = true
+ private const val WAKE_LOCK_TAG = "signal:backupProgress"
+ private val WAKE_LOCK_TIMEOUT = 2.hours.inWholeMilliseconds
+
@CheckReturnValue
fun start(context: Context, startingTitle: String): Controller {
controllerLock.withLock {
@@ -72,7 +78,7 @@ class BackupProgressService : SafeForegroundService() {
private fun getForegroundNotification(context: Context): Notification {
return NotificationCompat.Builder(context, NotificationChannels.getInstance().OTHER)
- .setSmallIcon(R.drawable.ic_notification)
+ .setSmallIcon(CoreUiR.drawable.ic_signal_backup)
.setContentTitle(title)
.setProgress(100, (progress * 100).toInt(), indeterminate)
.setContentIntent(PendingIntent.getActivity(context, 0, MainActivity.clearTop(context), PendingIntentFlags.mutable()))
@@ -81,6 +87,8 @@ class BackupProgressService : SafeForegroundService() {
}
}
+ private var wakeLock: PowerManager.WakeLock? = null
+
override val tag: String = TAG
override val notificationId: Int = NotificationIds.BACKUP_PROGRESS
@@ -88,11 +96,47 @@ class BackupProgressService : SafeForegroundService() {
return getForegroundNotification(this)
}
+ override fun onServiceStartCommandReceived(intent: Intent) {
+ acquireWakeLock()
+ }
+
+ override fun onServiceStopCommandReceived(intent: Intent) {
+ releaseWakeLock()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ releaseWakeLock()
+ }
+
override fun onTimeout(startId: Int, fgsType: Int) {
Log.w(TAG, "BackupProgressService has timed out. startId: $startId, foregroundServiceType: $fgsType")
stop(context = this, fromTimeout = true)
}
+ private fun acquireWakeLock() {
+ try {
+ if (wakeLock?.isHeld != true) {
+ wakeLock = ContextCompat.getSystemService(this, PowerManager::class.java)
+ ?.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG)
+ ?.apply { acquire(WAKE_LOCK_TIMEOUT) }
+ }
+ } catch (e: Exception) {
+ Log.w(TAG, "Failed to acquire wake lock.", e)
+ }
+ }
+
+ private fun releaseWakeLock() {
+ try {
+ if (wakeLock?.isHeld == true) {
+ wakeLock?.release()
+ }
+ } catch (e: Exception) {
+ Log.w(TAG, "Failed to release wake lock.", e)
+ }
+ wakeLock = null
+ }
+
/**
* Use to update notification progress/state.
*/
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/GenericForegroundService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/GenericForegroundService.kt
index d4b94bfc7c..59e32c0541 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/GenericForegroundService.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/GenericForegroundService.kt
@@ -12,13 +12,13 @@ import androidx.annotation.DrawableRes
import androidx.core.app.NotificationCompat
import androidx.core.app.ServiceCompat
import androidx.core.content.IntentCompat
+import org.signal.core.util.ForegroundServiceUtil
import org.signal.core.util.PendingIntentFlags.mutable
+import org.signal.core.util.UnableToStartException
import org.signal.core.util.logging.Log
import org.signal.network.util.Preconditions
import org.thoughtcrime.securesms.MainActivity
import org.thoughtcrime.securesms.R
-import org.thoughtcrime.securesms.jobs.ForegroundServiceUtil
-import org.thoughtcrime.securesms.jobs.UnableToStartException
import org.thoughtcrime.securesms.notifications.NotificationChannels
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.ReentrantLock
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/NotificationController.kt b/app/src/main/java/org/thoughtcrime/securesms/service/NotificationController.kt
index ea88811baa..07ed0153b6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/NotificationController.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/NotificationController.kt
@@ -5,8 +5,8 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
+import org.signal.core.util.UnableToStartException
import org.signal.core.util.logging.Log
-import org.thoughtcrime.securesms.jobs.UnableToStartException
import org.thoughtcrime.securesms.service.GenericForegroundService.Companion.stopForegroundTask
import org.thoughtcrime.securesms.service.GenericForegroundService.LocalBinder
import java.util.concurrent.atomic.AtomicReference
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallManager.kt
index 2fac15deb8..79edfc5567 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallManager.kt
@@ -29,12 +29,12 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
import io.reactivex.rxjava3.schedulers.Schedulers
import org.signal.core.ui.permissions.Permissions
import org.signal.core.util.PendingIntentFlags
+import org.signal.core.util.SafeForegroundService
+import org.signal.core.util.UnableToStartException
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.dependencies.AppDependencies
-import org.thoughtcrime.securesms.jobs.UnableToStartException
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
-import org.thoughtcrime.securesms.service.SafeForegroundService
import org.thoughtcrime.securesms.util.DeviceProperties
import org.thoughtcrime.securesms.util.TelephonyUtil
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder
diff --git a/core/ui/src/main/java/org/signal/core/ui/compose/KeepScreenOnEffect.kt b/core/ui/src/main/java/org/signal/core/ui/compose/KeepScreenOnEffect.kt
new file mode 100644
index 0000000000..de910100ba
--- /dev/null
+++ b/core/ui/src/main/java/org/signal/core/ui/compose/KeepScreenOnEffect.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2026 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.signal.core.ui.compose
+
+import android.app.Activity
+import android.view.WindowManager
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.platform.LocalContext
+
+/**
+ * Keeps the screen on while this composable is in the composition by toggling
+ * [WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON] on the host activity window.
+ */
+@Composable
+fun KeepScreenOnEffect() {
+ val context = LocalContext.current
+
+ DisposableEffect(Unit) {
+ val window = (context as? Activity)?.window
+ window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+
+ onDispose {
+ window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
+ }
+ }
+}
diff --git a/app/src/main/res/drawable-hdpi/ic_signal_backup.png b/core/ui/src/main/res/drawable-hdpi/ic_signal_backup.png
similarity index 100%
rename from app/src/main/res/drawable-hdpi/ic_signal_backup.png
rename to core/ui/src/main/res/drawable-hdpi/ic_signal_backup.png
diff --git a/app/src/main/res/drawable-mdpi/ic_signal_backup.png b/core/ui/src/main/res/drawable-mdpi/ic_signal_backup.png
similarity index 100%
rename from app/src/main/res/drawable-mdpi/ic_signal_backup.png
rename to core/ui/src/main/res/drawable-mdpi/ic_signal_backup.png
diff --git a/app/src/main/res/drawable-xhdpi/ic_signal_backup.png b/core/ui/src/main/res/drawable-xhdpi/ic_signal_backup.png
similarity index 100%
rename from app/src/main/res/drawable-xhdpi/ic_signal_backup.png
rename to core/ui/src/main/res/drawable-xhdpi/ic_signal_backup.png
diff --git a/app/src/main/res/drawable-xxhdpi/ic_signal_backup.png b/core/ui/src/main/res/drawable-xxhdpi/ic_signal_backup.png
similarity index 100%
rename from app/src/main/res/drawable-xxhdpi/ic_signal_backup.png
rename to core/ui/src/main/res/drawable-xxhdpi/ic_signal_backup.png
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_signal_backup.png b/core/ui/src/main/res/drawable-xxxhdpi/ic_signal_backup.png
similarity index 100%
rename from app/src/main/res/drawable-xxxhdpi/ic_signal_backup.png
rename to core/ui/src/main/res/drawable-xxxhdpi/ic_signal_backup.png
diff --git a/core/util/build.gradle.kts b/core/util/build.gradle.kts
index 177f511f2c..cf3a1c7f76 100644
--- a/core/util/build.gradle.kts
+++ b/core/util/build.gradle.kts
@@ -14,6 +14,7 @@ dependencies {
implementation(libs.androidx.sqlite)
implementation(libs.androidx.documentfile)
+ implementation(libs.google.jsr305)
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.exifinterface)
implementation(libs.kotlinx.serialization.json)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ForegroundServiceUtil.kt b/core/util/src/main/java/org/signal/core/util/ForegroundServiceUtil.kt
similarity index 87%
rename from app/src/main/java/org/thoughtcrime/securesms/jobs/ForegroundServiceUtil.kt
rename to core/util/src/main/java/org/signal/core/util/ForegroundServiceUtil.kt
index 7abc2323d4..6c10731f11 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ForegroundServiceUtil.kt
+++ b/core/util/src/main/java/org/signal/core/util/ForegroundServiceUtil.kt
@@ -1,4 +1,4 @@
-package org.thoughtcrime.securesms.jobs
+package org.signal.core.util
import android.app.AlarmManager
import android.app.ForegroundServiceStartNotAllowedException
@@ -10,12 +10,7 @@ import android.os.Build
import android.os.SystemClock
import androidx.annotation.WorkerThread
import androidx.core.content.ContextCompat
-import org.signal.core.util.AppForegroundObserver
-import org.signal.core.util.PendingIntentFlags
-import org.signal.core.util.ServiceUtil
import org.signal.core.util.logging.Log
-import org.thoughtcrime.securesms.service.GenericForegroundService
-import org.thoughtcrime.securesms.service.NotificationController
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock
@@ -118,17 +113,6 @@ object ForegroundServiceUtil {
}
}
- /**
- * Does its best to start a foreground service with your task name, including possibly blocking and waiting until we are able to.
- * However, it is always possible that the attempt will fail, so always handle the [UnableToStartException].
- */
- @Throws(UnableToStartException::class)
- @JvmStatic
- fun startGenericTaskWhenCapable(context: Context, task: String): NotificationController {
- blockUntilCapable(context)
- return GenericForegroundService.startForegroundTask(context, task)
- }
-
/**
* Waits until we're capable of starting a foreground service.
* @return True if you should expect to be able to start a foreground service, otherwise false. Please note that this isn't *guaranteed*, just what we believe
diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/SafeForegroundService.kt b/core/util/src/main/java/org/signal/core/util/SafeForegroundService.kt
similarity index 96%
rename from app/src/main/java/org/thoughtcrime/securesms/service/SafeForegroundService.kt
rename to core/util/src/main/java/org/signal/core/util/SafeForegroundService.kt
index 3a0486d770..d46ee471fe 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/service/SafeForegroundService.kt
+++ b/core/util/src/main/java/org/signal/core/util/SafeForegroundService.kt
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-package org.thoughtcrime.securesms.service
+package org.signal.core.util
import android.annotation.SuppressLint
import android.app.Notification
@@ -16,8 +16,6 @@ import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.ServiceCompat
import org.signal.core.util.logging.Log
-import org.thoughtcrime.securesms.jobs.ForegroundServiceUtil
-import org.thoughtcrime.securesms.jobs.UnableToStartException
import java.util.concurrent.locks.ReentrantLock
import javax.annotation.CheckReturnValue
import kotlin.concurrent.withLock
@@ -38,6 +36,7 @@ abstract class SafeForegroundService : Service() {
private const val ACTION_TIMEOUT = "timeout"
private var states: MutableMap, State> = mutableMapOf()
+ private val restartExtras: MutableMap, Bundle> = mutableMapOf()
private val stateLock = ReentrantLock()
/**
@@ -78,6 +77,7 @@ abstract class SafeForegroundService : Service() {
State.STOPPING -> {
Log.d(TAG, "[start] Attempted to start while the service is stopping. Enqueueing a restart.")
states[serviceClass] = State.NEEDS_RESTART
+ restartExtras[serviceClass] = Bundle(extras)
true
}
}
@@ -124,6 +124,7 @@ abstract class SafeForegroundService : Service() {
State.NEEDS_RESTART -> {
Log.i(TAG, "[stop] Clearing pending restart.")
states[serviceClass] = State.STOPPING
+ restartExtras.remove(serviceClass)
false
}
}
@@ -232,7 +233,8 @@ abstract class SafeForegroundService : Service() {
State.NEEDS_RESTART -> {
Log.i(TAG, "[onDestroy] Restarting service!")
states[javaClass] = State.STOPPED
- if (!start(this, javaClass)) {
+ val extras = restartExtras.remove(javaClass) ?: Bundle.EMPTY
+ if (!start(this, javaClass, extras)) {
Log.w(TAG, "[onDestroy] Failed to restart service.")
}
}
diff --git a/demo/registration/src/main/java/org/signal/registration/sample/dependencies/DemoStorageController.kt b/demo/registration/src/main/java/org/signal/registration/sample/dependencies/DemoStorageController.kt
index 36aa4419be..ac89d3e973 100644
--- a/demo/registration/src/main/java/org/signal/registration/sample/dependencies/DemoStorageController.kt
+++ b/demo/registration/src/main/java/org/signal/registration/sample/dependencies/DemoStorageController.kt
@@ -406,7 +406,7 @@ class DemoStorageController(private val context: Context) : StorageController {
// Decrypt + parse the backup proto to prove the round-trip worked. We intentionally do NOT
// import the frames into a database -- that is the app's full backup-restore pipeline.
- trySend(LinkAndSyncProgress.Restoring)
+ trySend(LinkAndSyncProgress.Finalizing)
val downloadedBytes = tempFile.length()
var frameCount = 0
EncryptedBackupReader.createForLocalOrLinking(
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/localbackuprestore/LocalBackupRestoreScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/localbackuprestore/LocalBackupRestoreScreen.kt
index 5db73548ba..5640eff85e 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/localbackuprestore/LocalBackupRestoreScreen.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/localbackuprestore/LocalBackupRestoreScreen.kt
@@ -51,6 +51,7 @@ import kotlinx.coroutines.launch
import org.signal.core.ui.compose.AllDevicePreviews
import org.signal.core.ui.compose.BottomSheets
import org.signal.core.ui.compose.Buttons
+import org.signal.core.ui.compose.KeepScreenOnEffect
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.SignalIcons
import org.signal.core.util.mebiBytes
@@ -83,6 +84,10 @@ fun LocalBackupRestoreScreen(
}
}
+ if (state.restorePhase == LocalBackupRestoreState.RestorePhase.Preparing || state.restorePhase == LocalBackupRestoreState.RestorePhase.InProgress) {
+ KeepScreenOnEffect()
+ }
+
when (state.restorePhase) {
LocalBackupRestoreState.RestorePhase.SelectFolder -> {
SelectFolderContent(onEvent = onEvent, modifier = modifier)
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/LinkAndSyncProgress.kt b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/LinkAndSyncProgress.kt
index 387a088f21..df0951939b 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/LinkAndSyncProgress.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/LinkAndSyncProgress.kt
@@ -18,8 +18,11 @@ sealed interface LinkAndSyncProgress {
/** Downloading the backup from the primary/CDN. */
data class Downloading(val bytesDownloaded: ByteSize, val totalBytes: ByteSize) : LinkAndSyncProgress
- /** Importing/restoring messages from the downloaded backup. */
- data object Restoring : LinkAndSyncProgress
+ /** Importing/restoring messages from the downloaded backup, with determinate progress. */
+ data class Restoring(val bytesRestored: ByteSize, val totalBytes: ByteSize) : LinkAndSyncProgress
+
+ /** Post-restore finalization work that does not report granular progress. */
+ data object Finalizing : LinkAndSyncProgress
/** The link-and-sync restore completed (or there was nothing to restore). */
data object Complete : LinkAndSyncProgress
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreen.kt
index 7bdc113e13..efdd229730 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreen.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreen.kt
@@ -44,6 +44,7 @@ import org.signal.core.ui.assumedFormFactor
import org.signal.core.ui.compose.AllDevicePreviews
import org.signal.core.ui.compose.Buttons
import org.signal.core.ui.compose.Dialogs
+import org.signal.core.ui.compose.KeepScreenOnEffect
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.SignalIcons
import org.signal.core.ui.rememberWindowBreakpoint
@@ -54,6 +55,7 @@ import org.signal.registration.screens.OnePaneRegistrationScaffold
import org.signal.registration.screens.RegistrationScaffold
import org.signal.registration.screens.TwoPaneRegistrationScaffold
import org.signal.registration.screens.attachDebugLogHelper
+import org.signal.registration.screens.messagesync.MessageSyncScreenState.Stage
import org.signal.registration.test.TestTags
/**
@@ -67,6 +69,10 @@ fun MessageSyncScreen(
) {
val layoutParams = RegistrationScaffold.rememberLayoutParams()
+ if (!state.showSyncFailedDialog) {
+ KeepScreenOnEffect()
+ }
+
Surface(modifier = modifier.testTag(TestTags.MESSAGE_SYNC_SCREEN)) {
when (layoutParams) {
is RegistrationScaffold.Params.OnePane -> OnePane(layoutParams, state, onEvent)
@@ -175,32 +181,37 @@ private fun FirstPaneContent(
modifier = Modifier.padding(top = 16.dp)
)
- val showDownloadProgress = state.totalBytes.bytes > 0 && !state.isFinishing
val progressModifier = Modifier
.padding(top = 48.dp, bottom = 16.dp)
.widthIn(max = 415.dp)
.fillMaxWidth()
- if (showDownloadProgress) {
- LinearProgressIndicator(
- progress = { state.downloadedBytes.percentageOf(state.totalBytes) },
+ when (val stage = state.stage) {
+ is Stage.Downloading -> LinearProgressIndicator(
+ progress = { stage.downloaded.percentageOf(stage.total) },
drawStopIndicator = {},
gapSize = 0.dp,
modifier = progressModifier
)
- } else {
- LinearProgressIndicator(modifier = progressModifier)
+ is Stage.Restoring -> LinearProgressIndicator(
+ progress = { stage.restored.percentageOf(stage.total) },
+ drawStopIndicator = {},
+ gapSize = 0.dp,
+ modifier = progressModifier
+ )
+ Stage.Preparing, Stage.Finishing -> LinearProgressIndicator(modifier = progressModifier)
}
Text(
- text = when {
- state.isFinishing -> stringResource(R.string.MessageSyncScreen__finishing)
- showDownloadProgress -> stringResource(
+ text = when (val stage = state.stage) {
+ Stage.Preparing -> stringResource(R.string.MessageSyncScreen__preparing)
+ is Stage.Downloading -> stringResource(
R.string.MessageSyncScreen__downloading_s_of_s,
- state.downloadedBytes.toUnitString(),
- state.totalBytes.toUnitString()
+ stage.downloaded.toUnitString(),
+ stage.total.toUnitString()
)
- else -> stringResource(R.string.MessageSyncScreen__preparing)
+ is Stage.Restoring -> stringResource(R.string.MessageSyncScreen__restoring)
+ Stage.Finishing -> stringResource(R.string.MessageSyncScreen__finishing)
},
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
@@ -369,8 +380,7 @@ private fun MessageSyncScreenPreview() {
Previews.Preview {
MessageSyncScreen(
state = MessageSyncScreenState(
- downloadedBytes = 1.mebiBytes,
- totalBytes = 3300.kibiBytes
+ stage = Stage.Downloading(downloaded = 1.mebiBytes, total = 3300.kibiBytes)
),
onEvent = {}
)
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreenState.kt b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreenState.kt
index 97bfceff21..6df711081d 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreenState.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncScreenState.kt
@@ -6,11 +6,34 @@
package org.signal.registration.screens.messagesync
import org.signal.core.util.ByteSize
-import org.signal.core.util.bytes
+/**
+ * UI state for the message-sync screen.
+ *
+ * [stage] is the single source of truth for which phase of the link-and-sync restore we're showing.
+ * [showSyncFailedDialog] is an independent overlay shown when the restore fails.
+ */
data class MessageSyncScreenState(
- val downloadedBytes: ByteSize = 0.bytes,
- val totalBytes: ByteSize = 0.bytes,
- val isFinishing: Boolean = false,
+ val stage: Stage = Stage.Preparing,
val showSyncFailedDialog: Boolean = false
-)
+) {
+
+ /** Whether we've moved past cancelable progress into non-cancelable finalization. */
+ val isFinishing: Boolean
+ get() = stage is Stage.Finishing
+
+ /** The phase of the restore currently surfaced to the user. */
+ sealed interface Stage {
+ /** Waiting for the first progress event; shown as an indeterminate bar. */
+ data object Preparing : Stage
+
+ /** Downloading the backup from the primary/CDN; shown as determinate progress. */
+ data class Downloading(val downloaded: ByteSize, val total: ByteSize) : Stage
+
+ /** Importing messages from the downloaded backup; shown as determinate progress. */
+ data class Restoring(val restored: ByteSize, val total: ByteSize) : Stage
+
+ /** Post-restore finalization that doesn't report granular progress; shown as an indeterminate bar. */
+ data object Finishing : Stage
+ }
+}
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncViewModel.kt b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncViewModel.kt
index 61024d2047..33542b1d6f 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncViewModel.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/messagesync/MessageSyncViewModel.kt
@@ -19,12 +19,12 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.signal.core.ui.compose.EventDrivenViewModel
-import org.signal.core.util.bytes
import org.signal.core.util.logging.Log
import org.signal.registration.RegistrationFlowEvent
import org.signal.registration.RegistrationFlowState
import org.signal.registration.RegistrationRepository
import org.signal.registration.RegistrationRoute
+import org.signal.registration.screens.messagesync.MessageSyncScreenState.Stage
import org.signal.registration.screens.util.navigateTo
/**
@@ -62,16 +62,21 @@ class MessageSyncViewModel(
when (progress) {
is LinkAndSyncProgress.Waiting -> Unit
is LinkAndSyncProgress.Downloading -> _state.update {
- it.copy(downloadedBytes = progress.bytesDownloaded, totalBytes = progress.totalBytes)
+ it.copy(stage = Stage.Downloading(downloaded = progress.bytesDownloaded, total = progress.totalBytes))
+ }
+ is LinkAndSyncProgress.Restoring -> _state.update {
+ it.copy(stage = Stage.Restoring(restored = progress.bytesRestored, total = progress.totalBytes))
+ }
+ is LinkAndSyncProgress.Finalizing -> _state.update {
+ it.copy(stage = Stage.Finishing)
}
- is LinkAndSyncProgress.Restoring -> _state.update { it.copy(isFinishing = true) }
is LinkAndSyncProgress.Complete -> {
Log.i(TAG, "[MessageSync] Link-and-sync complete; restoring from storage service then completing.")
finish()
}
is LinkAndSyncProgress.Failed -> {
Log.w(TAG, "[MessageSync] Link-and-sync failed; prompting the user to retry or continue without messages.", progress.cause)
- _state.update { it.copy(isFinishing = false, showSyncFailedDialog = true) }
+ _state.update { it.copy(showSyncFailedDialog = true) }
}
is LinkAndSyncProgress.RelinkRequired -> {
Log.w(TAG, "[MessageSync] Primary requested re-link; wiping local data and restarting.")
@@ -88,7 +93,7 @@ class MessageSyncViewModel(
}
finishJob = viewModelScope.launch {
- _state.update { it.copy(isFinishing = true) }
+ _state.update { it.copy(stage = Stage.Finishing) }
if (cancelDownload) {
restoreJob?.cancelAndJoin()
}
@@ -107,19 +112,19 @@ class MessageSyncViewModel(
MessageSyncScreenEvent.LearnMoreClick -> error("This event is handled in the nav-entry.")
MessageSyncScreenEvent.CancelClick -> {
Log.i(TAG, "[MessageSync] User cancelled message sync; awaiting restore cancellation, then restoring from storage service and completing.")
- stateEmitter(state.copy(isFinishing = true))
+ stateEmitter(state.copy(stage = Stage.Finishing))
finish(cancelDownload = true)
- state.copy(isFinishing = true)
+ state.copy(stage = Stage.Finishing)
}
MessageSyncScreenEvent.RetryClick -> {
Log.i(TAG, "[MessageSync] User retrying link-and-sync after a failure.")
startRestore()
- state.copy(showSyncFailedDialog = false, isFinishing = false, downloadedBytes = 0.bytes, totalBytes = 0.bytes)
+ state.copy(showSyncFailedDialog = false, stage = Stage.Preparing)
}
MessageSyncScreenEvent.ContinueWithoutMessagesClick -> {
Log.i(TAG, "[MessageSync] User continuing without message history after a failed link-and-sync.")
finish()
- state.copy(showSyncFailedDialog = false, isFinishing = true)
+ state.copy(showSyncFailedDialog = false, stage = Stage.Finishing)
}
}
stateEmitter(result)
diff --git a/feature/registration/src/main/java/org/signal/registration/screens/remotebackuprestore/RemoteBackupRestoreScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/remotebackuprestore/RemoteBackupRestoreScreen.kt
index 9bc1b1ad9e..5e2920dc8e 100644
--- a/feature/registration/src/main/java/org/signal/registration/screens/remotebackuprestore/RemoteBackupRestoreScreen.kt
+++ b/feature/registration/src/main/java/org/signal/registration/screens/remotebackuprestore/RemoteBackupRestoreScreen.kt
@@ -38,6 +38,7 @@ import org.signal.core.models.AccountEntropyPool
import org.signal.core.ui.compose.AllDevicePreviews
import org.signal.core.ui.compose.Buttons
import org.signal.core.ui.compose.Dialogs
+import org.signal.core.ui.compose.KeepScreenOnEffect
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.SignalIcons
import org.signal.core.ui.compose.theme.SignalTheme
@@ -57,6 +58,10 @@ fun RemoteRestoreScreen(
onEvent: (RemoteBackupRestoreScreenEvents) -> Unit,
modifier: Modifier = Modifier
) {
+ if (state.restoreState == RemoteBackupRestoreState.RestoreState.InProgress) {
+ KeepScreenOnEffect()
+ }
+
when (state.loadState) {
RemoteBackupRestoreState.LoadState.Loading -> {
Dialogs.IndeterminateProgressDialog(
diff --git a/feature/registration/src/main/res/values/strings.xml b/feature/registration/src/main/res/values/strings.xml
index 76cd8ec543..ebcde549d5 100644
--- a/feature/registration/src/main/res/values/strings.xml
+++ b/feature/registration/src/main/res/values/strings.xml
@@ -443,6 +443,8 @@
Preparing…
Finishing…
+
+ Restoring…
Messages and chat info are protected by end-to-end encryption, including the syncing process.
diff --git a/feature/registration/src/screenshotTest/kotlin/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests.kt b/feature/registration/src/screenshotTest/kotlin/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests.kt
index e8057b66e6..4887bcd485 100644
--- a/feature/registration/src/screenshotTest/kotlin/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests.kt
+++ b/feature/registration/src/screenshotTest/kotlin/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests.kt
@@ -12,6 +12,7 @@ import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.RtlPreview
import org.signal.core.util.kibiBytes
import org.signal.core.util.mebiBytes
+import org.signal.registration.screens.messagesync.MessageSyncScreenState.Stage
class MessageSyncScreenScreenshotTests {
@PreviewTest
@@ -22,11 +23,51 @@ class MessageSyncScreenScreenshotTests {
Previews.Preview {
MessageSyncScreen(
state = MessageSyncScreenState(
- downloadedBytes = 1.mebiBytes,
- totalBytes = 3300.kibiBytes
+ stage = Stage.Downloading(downloaded = 1.mebiBytes, total = 3300.kibiBytes)
),
onEvent = {}
)
}
}
+
+ @PreviewTest
+ @AllDevicePreviews
+ @RtlPreview
+ @Composable
+ fun MessageSyncScreenPreparingPreview() {
+ Previews.Preview {
+ MessageSyncScreen(
+ state = MessageSyncScreenState(stage = Stage.Preparing),
+ onEvent = {}
+ )
+ }
+ }
+
+ @PreviewTest
+ @AllDevicePreviews
+ @RtlPreview
+ @Composable
+ fun MessageSyncScreenRestoringPreview() {
+ Previews.Preview {
+ MessageSyncScreen(
+ state = MessageSyncScreenState(
+ stage = Stage.Restoring(restored = 2.mebiBytes, total = 3300.kibiBytes)
+ ),
+ onEvent = {}
+ )
+ }
+ }
+
+ @PreviewTest
+ @AllDevicePreviews
+ @RtlPreview
+ @Composable
+ fun MessageSyncScreenFinishingPreview() {
+ Previews.Preview {
+ MessageSyncScreen(
+ state = MessageSyncScreenState(stage = Stage.Finishing),
+ onEvent = {}
+ )
+ }
+ }
}
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (day)_41c0d57c_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (day)_41c0d57c_0.png
new file mode 100644
index 0000000000..08d2001244
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (day)_41c0d57c_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f278203913e71bdf003996c021290c9c5fd2f5b4d171fc03559530f780cc1353
+size 131987
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (night)_9dae7e43_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (night)_9dae7e43_0.png
new file mode 100644
index 0000000000..06e7deca6e
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable landscape (night)_9dae7e43_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c4843e9203cdc31b21fffaa97abcdaef2771db26946898142d62e2adaa03fe1c
+size 128373
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable portrait (day)_bf09cc79_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable portrait (day)_bf09cc79_0.png
new file mode 100644
index 0000000000..dc140fd900
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_foldable portrait (day)_bf09cc79_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:52d7ad7b4fdcf39a2ae0ede7c1841e0977e8f52505ce9b3652601a65308b0586
+size 132584
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (day)_38357cfa_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (day)_38357cfa_0.png
new file mode 100644
index 0000000000..4bb64dbbef
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (day)_38357cfa_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:01eab7a28187e31052fffb823c0927056a364919cd687befb627c8438fa2b5a6
+size 49229
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (night)_2eebbf71_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (night)_2eebbf71_0.png
new file mode 100644
index 0000000000..d75b41f0b0
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone landscape (night)_2eebbf71_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4463d008a1c661567ed9072200225299be5651186055505d0361fc6679d4c618
+size 49224
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone portrait (day)_1526b652_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone portrait (day)_1526b652_0.png
new file mode 100644
index 0000000000..d282ed23a4
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_phone portrait (day)_1526b652_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:65327400793ee00bafcf3083de0f35944347434621c144178824741de3860c51
+size 58385
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_rtl_5cbb5cfd_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_rtl_5cbb5cfd_0.png
new file mode 100644
index 0000000000..273f0dd5be
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_rtl_5cbb5cfd_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bc0dcd4e4fe04d78b96f49b42c04803b6a240d2646496d6f40dbcc878bae6e4e
+size 68648
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (day)_de1bb092_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (day)_de1bb092_0.png
new file mode 100644
index 0000000000..ebd64a83b6
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (day)_de1bb092_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e5645d7f8e80adfc70b87f8089e72bb5d433928d206786659a8ac125b6750619
+size 113827
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (night)_fe962c61_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (night)_fe962c61_0.png
new file mode 100644
index 0000000000..89fdd1924d
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable landscape (night)_fe962c61_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e8755ec06c301ba7f2ec55e0393fcfcb61fd04515181837a88e9feb6183bea81
+size 112957
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable portrait (day)_e269713d_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable portrait (day)_e269713d_0.png
new file mode 100644
index 0000000000..1c8421e6e1
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_small foldable portrait (day)_e269713d_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bfd2484d3140e836609f6471d99ce6458a83d08217248e09ae21cd956dd57779
+size 104939
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (day)_308754cb_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (day)_308754cb_0.png
new file mode 100644
index 0000000000..3d5e4c7a4e
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (day)_308754cb_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ff47e333b71686dcd97f5c8dd710dd21d4ecdc232949ed51defae2d691c4392
+size 114956
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (night)_d25401fe_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (night)_d25401fe_0.png
new file mode 100644
index 0000000000..2258aa4d53
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet landscape (night)_d25401fe_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c7241546eeb98ffa220afb2f57914ca5d36b7ea0760e0623c40321777664a68e
+size 95954
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet portrait (day)_ae17fb11_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet portrait (day)_ae17fb11_0.png
new file mode 100644
index 0000000000..07f2393e07
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenFinishingPreview_tablet portrait (day)_ae17fb11_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b66f017a10e2cab1d676e2d3cb0eccabaf489078b8a4f1733c0a828d6ff7eec3
+size 121562
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (day)_41c0d57c_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (day)_41c0d57c_0.png
new file mode 100644
index 0000000000..8cd9122fd4
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (day)_41c0d57c_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:566aef6885cf79f4778d198d1a58da70339d19f4975432d649df3b6cfff43ab3
+size 133355
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (night)_9dae7e43_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (night)_9dae7e43_0.png
new file mode 100644
index 0000000000..57f6072073
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable landscape (night)_9dae7e43_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3a7d00202dedccf68454d48bba04c87d64951496c85db3e07d4fba337f0ea53a
+size 129920
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable portrait (day)_bf09cc79_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable portrait (day)_bf09cc79_0.png
new file mode 100644
index 0000000000..b498d442d5
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_foldable portrait (day)_bf09cc79_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:453536e56d62df9da83e9992def0e2e418765b6bab8008f25d74cb33be0c399e
+size 133954
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (day)_38357cfa_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (day)_38357cfa_0.png
new file mode 100644
index 0000000000..ddf9694ab6
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (day)_38357cfa_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4aa109cdb3d90928af7e6658eb9d5ba62e05140054746e348d8bf831d8baee1b
+size 50506
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (night)_2eebbf71_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (night)_2eebbf71_0.png
new file mode 100644
index 0000000000..15e984a4fb
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone landscape (night)_2eebbf71_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5b1a3ec2f034cbb91e51841a55a444f24afb1b44c0fe767c47fa0f8152dbfe6a
+size 50731
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone portrait (day)_1526b652_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone portrait (day)_1526b652_0.png
new file mode 100644
index 0000000000..eb9b8302a0
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_phone portrait (day)_1526b652_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6c25d96c4f3aac30c4a71583862e3788a9d6df857499ebb6c89d847a4e033a03
+size 59528
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_rtl_5cbb5cfd_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_rtl_5cbb5cfd_0.png
new file mode 100644
index 0000000000..e77915bf94
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_rtl_5cbb5cfd_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:156d77b033986b5a459684fc56b363629d55251b8c51f35c52e4a550061d7928
+size 67437
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (day)_de1bb092_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (day)_de1bb092_0.png
new file mode 100644
index 0000000000..8566649935
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (day)_de1bb092_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0c75df96242b6753c01ac0d71c1f158758cc5fcd60e8efb932273da5e2bbcece
+size 115207
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (night)_fe962c61_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (night)_fe962c61_0.png
new file mode 100644
index 0000000000..7089e77474
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable landscape (night)_fe962c61_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8328095d98186d69cb549de2c9c813334e3cd3daf499e63685184ff9cae28ffd
+size 114495
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable portrait (day)_e269713d_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable portrait (day)_e269713d_0.png
new file mode 100644
index 0000000000..d3e8313019
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_small foldable portrait (day)_e269713d_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:94103353e323be41177b5d323f2aeb7ef349fcb1e177063f62eda053b59bdd7d
+size 106317
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (day)_308754cb_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (day)_308754cb_0.png
new file mode 100644
index 0000000000..f8e6842f69
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (day)_308754cb_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1ff00796f1e8f3617c9bb50461f6a6ba5a3064e54335b2bf93507745f53559a9
+size 116472
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (night)_d25401fe_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (night)_d25401fe_0.png
new file mode 100644
index 0000000000..28eba0d26c
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet landscape (night)_d25401fe_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:252a603ca156958850b13c39a87c31fc0fb0df01e33b3598c9dc8ee2d896089a
+size 97583
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet portrait (day)_ae17fb11_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet portrait (day)_ae17fb11_0.png
new file mode 100644
index 0000000000..3cdb1edfab
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenPreparingPreview_tablet portrait (day)_ae17fb11_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c7fa06a697f18d8a1ae6c9e9a151098cf1b7208d85587c87b603d84c6ea64140
+size 123110
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (day)_41c0d57c_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (day)_41c0d57c_0.png
new file mode 100644
index 0000000000..23bdb12e82
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (day)_41c0d57c_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:21fe9a94ad9b7f7e3a4daa834eed440be6967896db1e8c4691bc578417f10188
+size 134027
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (night)_9dae7e43_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (night)_9dae7e43_0.png
new file mode 100644
index 0000000000..4fae68d96b
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable landscape (night)_9dae7e43_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b5f2e83f2f47c21e356ebb22e408764f9c1c31e8ce1da89981a981131e5e56fe
+size 130546
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable portrait (day)_bf09cc79_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable portrait (day)_bf09cc79_0.png
new file mode 100644
index 0000000000..f647197def
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_foldable portrait (day)_bf09cc79_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d6df760824910a93714d5159f02540582e33f024d53ab4be682e95ae4dc8740c
+size 134610
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (day)_38357cfa_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (day)_38357cfa_0.png
new file mode 100644
index 0000000000..6301c6e563
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (day)_38357cfa_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8c7ee3d2ab87950f5ba97b9dfcee32cbc314975f67cf14731fca2197550fb1f2
+size 51094
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (night)_2eebbf71_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (night)_2eebbf71_0.png
new file mode 100644
index 0000000000..586b7b1126
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone landscape (night)_2eebbf71_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:143279658bf04623eed661cd2b1dd3b4f58fc83b791a227272a5a4dd1b251b85
+size 51297
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone portrait (day)_1526b652_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone portrait (day)_1526b652_0.png
new file mode 100644
index 0000000000..9a62a85655
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_phone portrait (day)_1526b652_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:540c5e3ddf9c0e4d7abd00928498f71f893e05e6bda6bcd6594631b95176a517
+size 59993
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_rtl_5cbb5cfd_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_rtl_5cbb5cfd_0.png
new file mode 100644
index 0000000000..422c557aee
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_rtl_5cbb5cfd_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fa8378f9482503c5cd38d8d981cf2b737616eee64412b10b011fd336bcfec71b
+size 67623
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (day)_de1bb092_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (day)_de1bb092_0.png
new file mode 100644
index 0000000000..71db57b887
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (day)_de1bb092_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:42c642fc44f38da4bed19c25d40f9c1c21da375be70ffff6aa0d3f2fb4830efc
+size 115856
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (night)_fe962c61_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (night)_fe962c61_0.png
new file mode 100644
index 0000000000..e1a8e81413
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable landscape (night)_fe962c61_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6dc72a139219c38bec594ae0404ceadd5bcbebbcf105df42d89468a873bfa5ad
+size 115092
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable portrait (day)_e269713d_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable portrait (day)_e269713d_0.png
new file mode 100644
index 0000000000..905bf81eba
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_small foldable portrait (day)_e269713d_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e263b66becb610374fde851fe639eb9a167138b18717bf53806fe32dadb975d8
+size 106913
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (day)_308754cb_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (day)_308754cb_0.png
new file mode 100644
index 0000000000..c63352ceb9
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (day)_308754cb_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3d84aae5f7ba7500fb84ba6c0fc2d3a6090b83bda65135ea1e40627c39700a9c
+size 117184
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (night)_d25401fe_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (night)_d25401fe_0.png
new file mode 100644
index 0000000000..d534e3b779
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet landscape (night)_d25401fe_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9a54b6bcf3fdf67312813e45d386301c21077b34b3af80bb28459bbccf91ee96
+size 98198
diff --git a/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet portrait (day)_ae17fb11_0.png b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet portrait (day)_ae17fb11_0.png
new file mode 100644
index 0000000000..774e725e08
--- /dev/null
+++ b/feature/registration/src/screenshotTestDebug/reference/org/signal/registration/screens/messagesync/MessageSyncScreenScreenshotTests/MessageSyncScreenRestoringPreview_tablet portrait (day)_ae17fb11_0.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:82cb6e56c2f9efd858c5ea2704dc82207cefe112de1d3c072d8e92726386d9fa
+size 123724
diff --git a/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncScreenTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncScreenTest.kt
index 5369348fa1..4c93b1923b 100644
--- a/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncScreenTest.kt
+++ b/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncScreenTest.kt
@@ -42,7 +42,7 @@ class MessageSyncScreenTest {
composeTestRule.setContent {
SignalTheme {
MessageSyncScreen(
- state = MessageSyncScreenState(downloadedBytes = 1.mebiBytes, totalBytes = 3300.kibiBytes),
+ state = MessageSyncScreenState(stage = MessageSyncScreenState.Stage.Downloading(downloaded = 1.mebiBytes, total = 3300.kibiBytes)),
onEvent = {}
)
}
@@ -59,7 +59,7 @@ class MessageSyncScreenTest {
composeTestRule.setContent {
SignalTheme {
MessageSyncScreen(
- state = MessageSyncScreenState(downloadedBytes = 1.mebiBytes, totalBytes = 3300.kibiBytes),
+ state = MessageSyncScreenState(stage = MessageSyncScreenState.Stage.Downloading(downloaded = 1.mebiBytes, total = 3300.kibiBytes)),
onEvent = { event -> emittedEvent = event }
)
}
@@ -75,7 +75,7 @@ class MessageSyncScreenTest {
composeTestRule.setContent {
SignalTheme {
MessageSyncScreen(
- state = MessageSyncScreenState(downloadedBytes = 1.mebiBytes, totalBytes = 3300.kibiBytes),
+ state = MessageSyncScreenState(stage = MessageSyncScreenState.Stage.Downloading(downloaded = 1.mebiBytes, total = 3300.kibiBytes)),
onEvent = {}
)
}
@@ -89,7 +89,7 @@ class MessageSyncScreenTest {
composeTestRule.setContent {
SignalTheme {
MessageSyncScreen(
- state = MessageSyncScreenState(isFinishing = true),
+ state = MessageSyncScreenState(stage = MessageSyncScreenState.Stage.Finishing),
onEvent = {}
)
}
diff --git a/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncViewModelTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncViewModelTest.kt
index 5b8c1eb7d0..d0705b7e6c 100644
--- a/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncViewModelTest.kt
+++ b/feature/registration/src/test/java/org/signal/registration/screens/messagesync/MessageSyncViewModelTest.kt
@@ -8,6 +8,7 @@ package org.signal.registration.screens.messagesync
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.doesNotContain
+import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import io.mockk.coVerify
@@ -136,10 +137,10 @@ class MessageSyncViewModelTest {
}
@Test
- fun `restore Restoring switches to indeterminate finishing state`() = runTest(testDispatcher) {
+ fun `restore Finalizing switches to indeterminate finishing state`() = runTest(testDispatcher) {
every { mockRepository.restoreLinkAndSyncBackup() } returns flowOf(
LinkAndSyncProgress.Downloading(bytesDownloaded = 5.bytes, totalBytes = 10.bytes),
- LinkAndSyncProgress.Restoring
+ LinkAndSyncProgress.Finalizing
)
val viewModel = createViewModel()
@@ -147,6 +148,18 @@ class MessageSyncViewModelTest {
assertThat(viewModel.state.value.isFinishing).isTrue()
}
+ @Test
+ fun `restore Restoring surfaces determinate restore progress without finishing`() = runTest(testDispatcher) {
+ every { mockRepository.restoreLinkAndSyncBackup() } returns flowOf(
+ LinkAndSyncProgress.Restoring(bytesRestored = 3.bytes, totalBytes = 10.bytes)
+ )
+
+ val viewModel = createViewModel()
+
+ assertThat(viewModel.state.value.stage).isEqualTo(MessageSyncScreenState.Stage.Restoring(restored = 3.bytes, total = 10.bytes))
+ assertThat(viewModel.state.value.isFinishing).isFalse()
+ }
+
private fun TestScope.createViewModel(): MessageSyncViewModel {
val viewModel = MessageSyncViewModel(
repository = mockRepository,