mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Attempt backing up a subset of messages if you hit the limit.
This commit is contained in:
@@ -96,6 +96,9 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
|
||||
private const val KEY_RESTORING_VIA_QR = "backup.restore_via_qr"
|
||||
|
||||
private const val KEY_MESSAGE_CUTOFF_DURATION = "backup.message_cutoff_duration"
|
||||
private const val KEY_LAST_USED_MESSAGE_CUTOFF_TIME = "backup.last_used_message_cutoff_time"
|
||||
|
||||
private val cachedCdnCredentialsExpiresIn: Duration = 12.hours
|
||||
|
||||
private val lock = ReentrantLock()
|
||||
@@ -259,8 +262,8 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
|
||||
if (storedValue != value) {
|
||||
clearNotEnoughRemoteStorageSpace()
|
||||
clearBackupCreationFailed()
|
||||
clearMessageBackupFailureSheetWatermark()
|
||||
backupCreationError = null
|
||||
}
|
||||
|
||||
deletionState = DeletionState.NONE
|
||||
@@ -303,7 +306,7 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
var hasBackupBeenUploaded: Boolean by booleanValue(KEY_BACKUP_UPLOADED, false)
|
||||
|
||||
val hasBackupCreationError: Boolean get() = backupCreationError != null
|
||||
val backupCreationError: BackupCreationError? by enumValue(KEY_BACKUP_CREATION_ERROR, null, BackupCreationError.serializer)
|
||||
var backupCreationError: BackupCreationError? by enumValue(KEY_BACKUP_CREATION_ERROR, null, BackupCreationError.serializer)
|
||||
val nextBackupFailureSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_ACKNOWLEDGED_SNOOZE_TIME, 0L).milliseconds
|
||||
val nextBackupFailureSheetSnoozeTime: Duration get() = getLong(KEY_BACKUP_FAIL_SHEET_SNOOZE_TIME, getNextBackupFailureSheetSnoozeTime(lastBackupTime.milliseconds).inWholeMilliseconds).milliseconds
|
||||
|
||||
@@ -419,6 +422,20 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) {
|
||||
.apply()
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, this represents how far back we should backup messages. For instance, if the returned value is 1 year in milliseconds, you should back up
|
||||
* every message within the last year. If unset, back up all messages. We only cutoff old messages for users whose backup is over the
|
||||
* size limit, which is *extraordinarily* rare, so this value is almost always null.
|
||||
*/
|
||||
var messageCuttoffDuration: Duration? by durationValue(KEY_MESSAGE_CUTOFF_DURATION, null)
|
||||
|
||||
/**
|
||||
* The last threshold we used for backing up messages. Messages sent before this time were not included in the backup.
|
||||
* A value of 0 indicates that we included all messages. We only cutoff old messages for users whose backup is over the
|
||||
* size limit, which is *extraordinarily* rare, so this value is almost always 0.
|
||||
*/
|
||||
var lastUsedMessageCutoffTime: Long by longValue(KEY_LAST_USED_MESSAGE_CUTOFF_TIME, 0)
|
||||
|
||||
/**
|
||||
* When we are told by the server that we are out of storage space, we should show
|
||||
* UX treatment to make the user aware of this.
|
||||
|
||||
@@ -5,6 +5,8 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.signal.core.util.LongSerializer
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.nanoseconds
|
||||
|
||||
internal fun SignalStoreValues.longValue(key: String, default: Long): SignalStoreValueDelegate<Long> {
|
||||
return LongValue(key, default, this.store)
|
||||
@@ -46,6 +48,10 @@ internal fun <M> SignalStoreValues.protoValue(key: String, default: M, adapter:
|
||||
return KeyValueProtoWithDefaultValue(key, default, adapter, this.store, onSet)
|
||||
}
|
||||
|
||||
internal fun SignalStoreValues.durationValue(key: String, default: Duration?): SignalStoreValueDelegate<Duration?> {
|
||||
return DurationValue(key, default, this.store)
|
||||
}
|
||||
|
||||
internal fun <T> SignalStoreValueDelegate<T>.withPrecondition(precondition: () -> Boolean): SignalStoreValueDelegate<T> {
|
||||
return PreconditionDelegate(
|
||||
delegate = this,
|
||||
@@ -159,6 +165,20 @@ private class NullableBlobValue(private val key: String, default: ByteArray?, st
|
||||
}
|
||||
}
|
||||
|
||||
private class DurationValue(private val key: String, default: Duration?, store: KeyValueStore) : SignalStoreValueDelegate<Duration?>(store, default) {
|
||||
companion object {
|
||||
private const val UNSET: Long = -1
|
||||
}
|
||||
|
||||
override fun getValue(values: KeyValueStore): Duration? {
|
||||
return values.getLong(key, default?.inWholeNanoseconds ?: UNSET).takeUnless { it == UNSET }?.nanoseconds
|
||||
}
|
||||
|
||||
override fun setValue(values: KeyValueStore, value: Duration?) {
|
||||
values.beginWrite().putLong(key, value?.inWholeNanoseconds ?: UNSET).apply()
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyValueProtoWithDefaultValue<M>(
|
||||
private val key: String,
|
||||
default: M,
|
||||
|
||||
Reference in New Issue
Block a user