Handle nonretryable errors during link + sync.

This commit is contained in:
Michelle Tang 2025-01-14 10:42:01 -05:00 committed by Cody Henthorne
parent 148b40e4ff
commit f4ed8e29f4
4 changed files with 43 additions and 4 deletions

View file

@ -71,6 +71,7 @@ import org.thoughtcrime.securesms.BiometricDeviceLockContract
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.linkdevice.LinkDeviceSettingsState.DialogState
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.navigation.safeNavigate
import java.util.Locale
@ -202,6 +203,10 @@ class LinkDeviceFragment : ComposeFragment() {
onDeviceRemovalConfirmed = { device -> viewModel.removeDevice(device) },
onSyncFailureRetryRequested = { viewModel.onSyncErrorRetryRequested() },
onSyncFailureIgnored = { viewModel.onSyncErrorIgnored() },
onSyncFailureLearnMore = {
viewModel.onSyncErrorIgnored()
CommunicationActions.openBrowserLink(requireContext(), requireContext().getString(R.string.LinkDeviceFragment__learn_more_url))
},
onSyncCancelled = { viewModel.onSyncCancelled() },
onEditDevice = { device ->
viewModel.setDeviceToEdit(device)
@ -257,6 +262,7 @@ fun DeviceListScreen(
onDeviceRemovalConfirmed: (Device) -> Unit = {},
onSyncFailureRetryRequested: () -> Unit = {},
onSyncFailureIgnored: () -> Unit = {},
onSyncFailureLearnMore: () -> Unit = {},
onSyncCancelled: () -> Unit = {},
onEditDevice: (Device) -> Unit = {},
onDialogDismissed: () -> Unit = {}
@ -281,7 +287,29 @@ fun DeviceListScreen(
onDismiss = onSyncCancelled
)
}
is DialogState.SyncingFailed,
is DialogState.SyncingFailed -> {
if (state.dialogState.canRetry) {
Dialogs.SimpleAlertDialog(
title = stringResource(R.string.LinkDeviceFragment__sync_failure_title),
body = stringResource(R.string.LinkDeviceFragment__sync_failure_body),
confirm = stringResource(R.string.LinkDeviceFragment__sync_failure_retry_button),
onConfirm = onSyncFailureRetryRequested,
dismiss = stringResource(R.string.LinkDeviceFragment__sync_failure_dismiss_button),
onDismissRequest = onSyncFailureIgnored,
onDeny = onSyncFailureIgnored
)
} else {
Dialogs.SimpleAlertDialog(
title = stringResource(R.string.LinkDeviceFragment__sync_failure_title),
body = stringResource(R.string.LinkDeviceFragment__sync_failure_body_unretryable),
confirm = stringResource(R.string.LinkDeviceFragment__continue),
onConfirm = onSyncFailureIgnored,
dismiss = stringResource(R.string.LinkDeviceFragment__learn_more),
onDismissRequest = onSyncFailureIgnored,
onDeny = onSyncFailureLearnMore
)
}
}
DialogState.SyncingTimedOut -> {
Dialogs.SimpleAlertDialog(
title = stringResource(R.string.LinkDeviceFragment__sync_failure_title),

View file

@ -30,7 +30,7 @@ data class LinkDeviceSettingsState(
data object Unlinking : DialogState
data class SyncingMessages(val deviceId: Int, val deviceCreatedAt: Long) : DialogState
data object SyncingTimedOut : DialogState
data class SyncingFailed(val deviceId: Int, val deviceCreatedAt: Long) : DialogState
data class SyncingFailed(val deviceId: Int, val deviceCreatedAt: Long, val canRetry: Boolean) : DialogState
data class DeviceUnlinked(val deviceCreatedAt: Long) : DialogState
}

View file

@ -313,9 +313,14 @@ class LinkDeviceViewModel : ViewModel() {
is LinkDeviceRepository.LinkUploadArchiveResult.BadRequest,
is LinkDeviceRepository.LinkUploadArchiveResult.NetworkError -> {
Log.w(TAG, "[addDeviceWithSync] Failed to upload the archive! Result: $uploadResult")
val canRetry = uploadResult !is LinkDeviceRepository.LinkUploadArchiveResult.BackupCreationFailure
_state.update {
it.copy(
dialogState = DialogState.SyncingFailed(waitResult.id, waitResult.created)
dialogState = DialogState.SyncingFailed(
deviceId = waitResult.id,
deviceCreatedAt = waitResult.created,
canRetry = canRetry
)
)
}
}
@ -385,6 +390,7 @@ class LinkDeviceViewModel : ViewModel() {
Log.i(TAG, "Alerting linked device of sync failure - will not retry")
LinkDeviceRepository.sendTransferArchiveError(dialogState.deviceId, dialogState.deviceCreatedAt, TransferArchiveError.CONTINUE_WITHOUT_UPLOAD)
}
loadDevices()
_state.update {
it.copy(

View file

@ -1010,8 +1010,13 @@
<string name="LinkDeviceFragment__sync_failure_title">Message sync failed</string>
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
<string name="LinkDeviceFragment__sync_failure_body">Your messages couldn\'t be transferred to your linked device. You can try re-linking and transferring again, or continue without transferring your message history.</string>
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed but the device was still able to be linked -->
<string name="LinkDeviceFragment__sync_failure_body_unretryable">Your device was successfully linked, but your messages could not be transferred.</string>
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
<string name="LinkDeviceFragment__learn_more">Learn more</string>
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
<string name="LinkDeviceFragment__sync_failure_retry_button">Try linking again</string>
<string name="LinkDeviceFragment__sync_failure_retry_button">Retry</string>
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
<string name="LinkDeviceFragment__sync_failure_dismiss_button">Continue without transferring</string>
<!-- Option in context menu to edit the name of a linked device -->