mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-25 12:17:22 +00:00
Implement stop/resume media restore and update restore over cellular.
This commit is contained in:
committed by
Michelle Tang
parent
9867fa3f50
commit
93403a0d2c
@@ -69,8 +69,10 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobs.AvatarGroupsV2DownloadJob
|
||||
import org.thoughtcrime.securesms.jobs.CheckRestoreMediaLeftJob
|
||||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob
|
||||
import org.thoughtcrime.securesms.jobs.RestoreAttachmentJob
|
||||
import org.thoughtcrime.securesms.jobs.RestoreOptimizedMediaJob
|
||||
import org.thoughtcrime.securesms.keyvalue.BackupValues.ArchiveServiceCredentials
|
||||
import org.thoughtcrime.securesms.keyvalue.KeyValueStore
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
@@ -196,6 +198,12 @@ object BackupRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun resumeMediaRestore() {
|
||||
SignalStore.backup.userManuallySkippedMediaRestore = false
|
||||
RestoreOptimizedMediaJob.enqueue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels any relevant jobs for media restore
|
||||
*/
|
||||
@@ -206,6 +214,10 @@ object BackupRepository {
|
||||
AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.RESTORE_OFFLOADED))
|
||||
AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.INITIAL_RESTORE))
|
||||
AppDependencies.jobManager.cancelAllInQueue(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.MANUAL))
|
||||
|
||||
AppDependencies.jobManager.add(CheckRestoreMediaLeftJob(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.RESTORE_OFFLOADED)))
|
||||
AppDependencies.jobManager.add(CheckRestoreMediaLeftJob(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.INITIAL_RESTORE)))
|
||||
AppDependencies.jobManager.add(CheckRestoreMediaLeftJob(RestoreAttachmentJob.constructQueueString(RestoreAttachmentJob.RestoreOperation.MANUAL)))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,9 +55,7 @@ import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.billing.launchManageBackupsSubscription
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobs.BackupMessagesJob
|
||||
import org.thoughtcrime.securesms.jobs.BackupRestoreMediaJob
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.PlayStoreUtil
|
||||
import org.signal.core.ui.R as CoreUiR
|
||||
@@ -185,8 +183,7 @@ class BackupAlertBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
}
|
||||
|
||||
private fun performFullMediaDownload() {
|
||||
// TODO [backups] -- We need to force this to download everything
|
||||
AppDependencies.jobManager.add(BackupRestoreMediaJob())
|
||||
BackupRepository.resumeMediaRestore()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,8 +283,18 @@ sealed interface BackupStatusData {
|
||||
val restoreStatus: RestoreStatus = RestoreStatus.NORMAL
|
||||
) : BackupStatusData {
|
||||
override val iconRes: Int = if (restoreStatus == RestoreStatus.FINISHED) R.drawable.symbol_check_circle_24 else R.drawable.symbol_backup_light
|
||||
override val iconColors: BackupsIconColors = if (restoreStatus == RestoreStatus.FINISHED) BackupsIconColors.Success else BackupsIconColors.Normal
|
||||
override val iconColors: BackupsIconColors = when (restoreStatus) {
|
||||
RestoreStatus.FINISHED -> BackupsIconColors.Success
|
||||
RestoreStatus.NORMAL -> BackupsIconColors.Normal
|
||||
RestoreStatus.LOW_BATTERY,
|
||||
RestoreStatus.WAITING_FOR_INTERNET,
|
||||
RestoreStatus.WAITING_FOR_WIFI -> BackupsIconColors.Warning
|
||||
}
|
||||
override val showDismissAction: Boolean = restoreStatus == RestoreStatus.FINISHED
|
||||
override val actionRes: Int = when (restoreStatus) {
|
||||
RestoreStatus.WAITING_FOR_WIFI -> R.string.BackupStatus__resume
|
||||
else -> NONE
|
||||
}
|
||||
|
||||
override val title: String
|
||||
@Composable get() = stringResource(
|
||||
@@ -311,7 +321,7 @@ sealed interface BackupStatusData {
|
||||
RestoreStatus.FINISHED -> bytesTotal.toUnitString()
|
||||
}
|
||||
|
||||
override val progress: Float = if (bytesTotal.bytes > 0 && restoreStatus != RestoreStatus.FINISHED) {
|
||||
override val progress: Float = if (bytesTotal.bytes > 0 && restoreStatus == RestoreStatus.NORMAL) {
|
||||
min(1f, max(0f, bytesDownloaded.bytes.toFloat() / bytesTotal.bytes.toFloat()))
|
||||
} else {
|
||||
NONE.toFloat()
|
||||
|
||||
@@ -184,9 +184,10 @@ private fun getRestoringMediaString(backupStatusData: BackupStatusData.Restoring
|
||||
|
||||
@Composable
|
||||
private fun progressColor(backupStatusData: BackupStatusData): Color {
|
||||
return when (backupStatusData) {
|
||||
is BackupStatusData.RestoringMedia -> MaterialTheme.colorScheme.primary
|
||||
else -> backupStatusData.iconColors.foreground
|
||||
return if (backupStatusData is BackupStatusData.RestoringMedia && backupStatusData.restoreStatus == BackupStatusData.RestoreStatus.NORMAL) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
backupStatusData.iconColors.foreground
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList
|
||||
totalRestoredSize > 0 -> {
|
||||
flowOf(
|
||||
BackupStatusData.RestoringMedia(
|
||||
bytesTotal = totalRestoredSize.bytes.also { totalRestoredSize = 0 },
|
||||
bytesTotal = totalRestoredSize.bytes,
|
||||
restoreStatus = BackupStatusData.RestoreStatus.FINISHED
|
||||
)
|
||||
)
|
||||
@@ -75,7 +75,10 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList
|
||||
data = model,
|
||||
onBannerClick = listener::onBannerClick,
|
||||
onActionClick = listener::onActionClick,
|
||||
onDismissClick = listener::onDismissComplete
|
||||
onDismissClick = {
|
||||
totalRestoredSize = 0
|
||||
listener.onDismissComplete()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
||||
}
|
||||
|
||||
override fun onCancelMediaRestore() {
|
||||
viewModel.cancelMediaRestore()
|
||||
viewModel.requestDialog(RemoteBackupsSettingsState.Dialog.CANCEL_MEDIA_RESTORE_PROTECTION)
|
||||
}
|
||||
|
||||
override fun onDisplaySkipMediaRestoreProtectionDialog() {
|
||||
@@ -245,8 +245,12 @@ class RemoteBackupsSettingsFragment : ComposeFragment() {
|
||||
BackupAlertBottomSheet.create(BackupAlert.BackupFailed).show(parentFragmentManager, null)
|
||||
}
|
||||
|
||||
override fun onRestoreUsingCellularClick(canUseCellular: Boolean) {
|
||||
viewModel.setCanRestoreUsingCellular(canUseCellular)
|
||||
override fun onRestoreUsingCellularConfirm() {
|
||||
viewModel.requestDialog(RemoteBackupsSettingsState.Dialog.RESTORE_OVER_CELLULAR_PROTECTION)
|
||||
}
|
||||
|
||||
override fun onRestoreUsingCellularClick() {
|
||||
viewModel.setCanRestoreUsingCellular()
|
||||
}
|
||||
|
||||
override fun onRedemptionErrorDetailsClick() {
|
||||
@@ -334,7 +338,8 @@ private interface ContentCallbacks {
|
||||
fun onLearnMoreAboutLostSubscription() = Unit
|
||||
fun onContactSupport() = Unit
|
||||
fun onLearnMoreAboutBackupFailure() = Unit
|
||||
fun onRestoreUsingCellularClick(canUseCellular: Boolean) = Unit
|
||||
fun onRestoreUsingCellularConfirm() = Unit
|
||||
fun onRestoreUsingCellularClick() = Unit
|
||||
fun onRedemptionErrorDetailsClick() = Unit
|
||||
}
|
||||
|
||||
@@ -425,18 +430,20 @@ private fun RemoteBackupsSettingsContent(
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Rows.ToggleRow(
|
||||
checked = canRestoreUsingCellular,
|
||||
text = stringResource(id = R.string.RemoteBackupsSettingsFragment__restore_using_cellular),
|
||||
onCheckChanged = contentCallbacks::onRestoreUsingCellularClick
|
||||
)
|
||||
if (!canRestoreUsingCellular) {
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__resume_download),
|
||||
icon = painterResource(R.drawable.symbol_arrow_circle_down_24),
|
||||
onClick = contentCallbacks::onRestoreUsingCellularConfirm
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (backupRestoreState is BackupRestoreState.Ready && backupState is RemoteBackupsSettingsState.BackupState.Canceled) {
|
||||
} else if (backupRestoreState is BackupRestoreState.Ready) {
|
||||
item {
|
||||
BackupReadyToDownloadRow(
|
||||
ready = backupRestoreState,
|
||||
endOfSubscription = backupState.renewalTime,
|
||||
backupState = backupState,
|
||||
onDownloadClick = contentCallbacks::onStartMediaRestore
|
||||
)
|
||||
}
|
||||
@@ -536,6 +543,20 @@ private fun RemoteBackupsSettingsContent(
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore
|
||||
)
|
||||
}
|
||||
|
||||
RemoteBackupsSettingsState.Dialog.CANCEL_MEDIA_RESTORE_PROTECTION -> {
|
||||
CancelInitialRestoreDialog(
|
||||
onDismiss = contentCallbacks::onDialogDismissed,
|
||||
onSkipClick = contentCallbacks::onSkipMediaRestore
|
||||
)
|
||||
}
|
||||
|
||||
RemoteBackupsSettingsState.Dialog.RESTORE_OVER_CELLULAR_PROTECTION -> {
|
||||
ResumeRestoreOverCellularDialog(
|
||||
onDismiss = contentCallbacks::onDialogDismissed,
|
||||
onResumeOverCellularClick = contentCallbacks::onRestoreUsingCellularClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val snackbarMessageId = remember(requestedSnackbar) {
|
||||
@@ -1164,6 +1185,37 @@ private fun SkipDownloadDialog(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CancelInitialRestoreDialog(
|
||||
onSkipClick: () -> Unit = {},
|
||||
onDismiss: () -> Unit = {}
|
||||
) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(R.string.RemoteBackupsSettingsFragment__skip_restore_question),
|
||||
body = stringResource(R.string.RemoteBackupsSettingsFragment__skip_restore_message),
|
||||
confirm = stringResource(R.string.RemoteBackupsSettingsFragment__skip),
|
||||
dismiss = stringResource(android.R.string.cancel),
|
||||
confirmColor = MaterialTheme.colorScheme.error,
|
||||
onConfirm = onSkipClick,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ResumeRestoreOverCellularDialog(
|
||||
onResumeOverCellularClick: () -> Unit = {},
|
||||
onDismiss: () -> Unit = {}
|
||||
) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(R.string.ResumeRestoreCellular_resume_using_cellular_title),
|
||||
body = stringResource(R.string.ResumeRestoreCellular_resume_using_cellular_message),
|
||||
confirm = stringResource(R.string.BackupStatus__resume),
|
||||
dismiss = stringResource(android.R.string.cancel),
|
||||
onConfirm = onResumeOverCellularClick,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun CircularProgressDialog(
|
||||
@@ -1254,11 +1306,16 @@ private fun BackupFrequencyDialog(
|
||||
@Composable
|
||||
private fun BackupReadyToDownloadRow(
|
||||
ready: BackupRestoreState.Ready,
|
||||
endOfSubscription: Duration,
|
||||
backupState: RemoteBackupsSettingsState.BackupState,
|
||||
onDownloadClick: () -> Unit = {}
|
||||
) {
|
||||
val days = (endOfSubscription - System.currentTimeMillis().milliseconds).inWholeDays.toInt()
|
||||
val string = pluralStringResource(R.plurals.RemoteBackupsSettingsFragment__you_have_s_of_backup_data, days, ready.bytes, days)
|
||||
val string = if (backupState is RemoteBackupsSettingsState.BackupState.Canceled) {
|
||||
val days = (backupState.renewalTime - System.currentTimeMillis().milliseconds).inWholeDays.toInt()
|
||||
pluralStringResource(R.plurals.RemoteBackupsSettingsFragment__you_have_s_of_backup_data, days, ready.bytes, days)
|
||||
} else {
|
||||
stringResource(R.string.RemoteBackupsSettingsFragment__you_have_s_of_backup_data_not_on_device, ready.bytes)
|
||||
}
|
||||
|
||||
val annotated = buildAnnotatedString {
|
||||
append(string)
|
||||
val startIndex = string.indexOf(ready.bytes)
|
||||
@@ -1436,7 +1493,7 @@ private fun BackupReadyToDownloadPreview() {
|
||||
Previews.Preview {
|
||||
BackupReadyToDownloadRow(
|
||||
ready = BackupRestoreState.Ready("12GB"),
|
||||
endOfSubscription = System.currentTimeMillis().milliseconds + 30.days
|
||||
backupState = RemoteBackupsSettingsState.BackupState.None
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,9 @@ data class RemoteBackupsSettingsState(
|
||||
DOWNLOADING_YOUR_BACKUP,
|
||||
TURN_OFF_FAILED,
|
||||
SUBSCRIPTION_NOT_FOUND,
|
||||
SKIP_MEDIA_RESTORE_PROTECTION
|
||||
SKIP_MEDIA_RESTORE_PROTECTION,
|
||||
CANCEL_MEDIA_RESTORE_PROTECTION,
|
||||
RESTORE_OVER_CELLULAR_PROTECTION
|
||||
}
|
||||
|
||||
enum class Snackbar {
|
||||
|
||||
@@ -15,6 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -83,15 +84,25 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val restoreProgress = MediaRestoreProgressBanner()
|
||||
|
||||
var optimizedRemainingBytes = 0L
|
||||
while (isActive) {
|
||||
if (restoreProgress.enabled) {
|
||||
Log.d(TAG, "Backup is being restored. Collecting updates.")
|
||||
restoreProgress.dataFlow.collectLatest { latest ->
|
||||
_restoreState.update { BackupRestoreState.FromBackupStatusData(latest) }
|
||||
}
|
||||
restoreProgress
|
||||
.dataFlow
|
||||
.takeWhile { it !is BackupStatusData.RestoringMedia || it.restoreStatus != BackupStatusData.RestoreStatus.FINISHED }
|
||||
.collectLatest { latest ->
|
||||
_restoreState.update { BackupRestoreState.FromBackupStatusData(latest) }
|
||||
}
|
||||
} else if (
|
||||
!SignalStore.backup.optimizeStorage &&
|
||||
SignalStore.backup.userManuallySkippedMediaRestore &&
|
||||
SignalDatabase.attachments.getOptimizedMediaAttachmentSize().also { optimizedRemainingBytes = it } > 0
|
||||
) {
|
||||
_restoreState.update { BackupRestoreState.Ready(optimizedRemainingBytes.bytes.toUnitString()) }
|
||||
} else if (SignalStore.backup.totalRestorableAttachmentSize > 0L) {
|
||||
_restoreState.update { BackupRestoreState.Ready(SignalStore.backup.totalRestorableAttachmentSize.bytes.toUnitString()) }
|
||||
} else if (BackupRepository.shouldDisplayBackupFailedSettingsRow()) {
|
||||
@@ -126,9 +137,9 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
_state.update { it.copy(canBackUpUsingCellular = canBackUpUsingCellular) }
|
||||
}
|
||||
|
||||
fun setCanRestoreUsingCellular(canRestoreUsingCellular: Boolean) {
|
||||
SignalStore.backup.restoreWithCellular = canRestoreUsingCellular
|
||||
_state.update { it.copy(canRestoreUsingCellular = canRestoreUsingCellular) }
|
||||
fun setCanRestoreUsingCellular() {
|
||||
SignalStore.backup.restoreWithCellular = true
|
||||
_state.update { it.copy(canRestoreUsingCellular = true) }
|
||||
}
|
||||
|
||||
fun setBackupsFrequency(backupsFrequency: BackupFrequency) {
|
||||
@@ -139,17 +150,13 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
fun beginMediaRestore() {
|
||||
// TODO - [backups] Begin media restore.
|
||||
BackupRepository.resumeMediaRestore()
|
||||
}
|
||||
|
||||
fun skipMediaRestore() {
|
||||
BackupRepository.skipMediaRestore()
|
||||
}
|
||||
|
||||
fun cancelMediaRestore() {
|
||||
// TODO - [backups] Cancel in-progress media restoration
|
||||
}
|
||||
|
||||
fun requestDialog(dialog: RemoteBackupsSettingsState.Dialog) {
|
||||
_state.update { it.copy(dialog = dialog) }
|
||||
}
|
||||
@@ -269,14 +276,17 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
hasActiveSignalSubscription && hasActiveGooglePlayBillingSubscription -> {
|
||||
Log.d(TAG, "Found active signal subscription and active google play subscription. Clearing mismatch.")
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
}
|
||||
|
||||
!hasActiveSignalSubscription && !hasActiveGooglePlayBillingSubscription -> {
|
||||
Log.d(TAG, "Found inactive signal subscription and inactive google play subscription. Clearing mismatch.")
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
}
|
||||
|
||||
else -> {
|
||||
Log.w(TAG, "Hit unexpected subscription mismatch state: signal:false, google:true")
|
||||
return
|
||||
|
||||
@@ -294,6 +294,7 @@ class InternalBackupPlaygroundViewModel : ViewModel() {
|
||||
|
||||
fun wipeAllDataAndRestoreFromRemote() {
|
||||
SignalExecutors.BOUNDED_IO.execute {
|
||||
SignalStore.backup.restoreWithCellular = false
|
||||
restoreFromRemote()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,6 +759,13 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
||||
if (backupStatusData instanceof BackupStatusData.NotEnoughFreeSpace) {
|
||||
BackupAlertBottomSheet.create(new BackupAlert.DiskFull(((BackupStatusData.NotEnoughFreeSpace) backupStatusData).getRequiredSpace()))
|
||||
.show(getParentFragmentManager(), null);
|
||||
} else if (backupStatusData instanceof BackupStatusData.RestoringMedia && ((BackupStatusData.RestoringMedia) backupStatusData).getRestoreStatus() == BackupStatusData.RestoreStatus.WAITING_FOR_WIFI) {
|
||||
new MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.ResumeRestoreCellular_resume_using_cellular_title)
|
||||
.setMessage(R.string.ResumeRestoreCellular_resume_using_cellular_message)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.BackupStatus__resume, (d, w) -> SignalStore.backup().setRestoreWithCellular(true))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -555,6 +555,15 @@ class AttachmentTable(
|
||||
.readToSingleLong()
|
||||
}
|
||||
|
||||
fun getOptimizedMediaAttachmentSize(): Long {
|
||||
return readableDatabase
|
||||
.select("SUM($DATA_SIZE)")
|
||||
.from(TABLE_NAME)
|
||||
.where("$TRANSFER_STATE = ?", TRANSFER_RESTORE_OFFLOADED)
|
||||
.run()
|
||||
.readToSingleLong()
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all of the attachmentIds of attachments that need to be uploaded to the archive cdn.
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,7 @@ class AttachmentDownloadJob private constructor(
|
||||
return when (val transferState = databaseAttachment.transferState) {
|
||||
AttachmentTable.TRANSFER_PROGRESS_DONE -> null
|
||||
|
||||
AttachmentTable.TRANSFER_RESTORE_IN_PROGRESS,
|
||||
AttachmentTable.TRANSFER_RESTORE_OFFLOADED,
|
||||
AttachmentTable.TRANSFER_NEEDS_RESTORE -> RestoreAttachmentJob.restoreAttachment(databaseAttachment)
|
||||
|
||||
@@ -112,7 +113,6 @@ class AttachmentDownloadJob private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
AttachmentTable.TRANSFER_RESTORE_IN_PROGRESS,
|
||||
AttachmentTable.TRANSFER_PROGRESS_STARTED,
|
||||
AttachmentTable.TRANSFER_PROGRESS_PERMANENT_FAILURE -> {
|
||||
Log.d(TAG, "${databaseAttachment.attachmentId} is downloading or permanently failed, transferState: $transferState")
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.events.PartProgressEvent
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.JobLogger.format
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.BatteryNotLowConstraint
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.RestoreAttachmentConstraint
|
||||
import org.thoughtcrime.securesms.jobs.protos.RestoreAttachmentJobData
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
@@ -117,8 +118,14 @@ class RestoreAttachmentJob private constructor(
|
||||
private constructor(messageId: Long, attachmentId: AttachmentId, manual: Boolean, queue: String) : this(
|
||||
Parameters.Builder()
|
||||
.setQueue(queue)
|
||||
.addConstraint(RestoreAttachmentConstraint.KEY)
|
||||
.addConstraint(BatteryNotLowConstraint.KEY)
|
||||
.apply {
|
||||
if (manual) {
|
||||
addConstraint(NetworkConstraint.KEY)
|
||||
} else {
|
||||
addConstraint(RestoreAttachmentConstraint.KEY)
|
||||
addConstraint(BatteryNotLowConstraint.KEY)
|
||||
}
|
||||
}
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(30))
|
||||
.build(),
|
||||
messageId,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.thoughtcrime.securesms.jobs
|
||||
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
@@ -17,6 +18,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
class RestoreOptimizedMediaJob private constructor(parameters: Parameters) : Job(parameters) {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(RestoreOptimizedMediaJob::class)
|
||||
const val KEY = "RestoreOptimizeMediaJob"
|
||||
|
||||
fun enqueue() {
|
||||
@@ -42,6 +44,12 @@ class RestoreOptimizedMediaJob private constructor(parameters: Parameters) : Job
|
||||
|
||||
override fun run(): Result {
|
||||
if (SignalStore.backup.optimizeStorage && !SignalStore.backup.userManuallySkippedMediaRestore) {
|
||||
Log.i(TAG, "User is optimizing media and has not skipped restore, skipping.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
if (!SignalStore.backup.optimizeStorage && SignalStore.backup.userManuallySkippedMediaRestore) {
|
||||
Log.i(TAG, "User is not optimizing media but elected to skip media restore, skipping.")
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user