diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsFragment.kt index 93f8f9102c..426711a8c0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsFragment.kt @@ -5,6 +5,7 @@ package org.thoughtcrime.securesms.components.settings.app.backups +import android.content.Context import android.os.Bundle import android.view.View import androidx.activity.result.ActivityResultLauncher @@ -23,8 +24,11 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector @@ -37,6 +41,7 @@ import androidx.compose.ui.unit.dp import androidx.fragment.app.viewModels import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.fragment.findNavController +import kotlinx.coroutines.delay import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.Dividers import org.signal.core.ui.compose.Previews @@ -61,6 +66,7 @@ import java.util.Currency import java.util.Locale import kotlin.time.Duration import kotlin.time.Duration.Companion.days +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds import org.signal.core.ui.R as CoreUiR @@ -537,14 +543,15 @@ private fun ActiveBackupsRow( @Composable private fun LastBackedUpText(lastBackupAt: Duration) { - val lastBackupString = if (lastBackupAt.inWholeMilliseconds > 0) { - DateUtils.getDatelessRelativeTimeSpanFormattedDate( - LocalContext.current, - Locale.getDefault(), - lastBackupAt.inWholeMilliseconds - ).value - } else { - stringResource(R.string.RemoteBackupsSettingsFragment__never) + val context = LocalContext.current + + var lastBackupString by remember { mutableStateOf(calculateLastBackupTimeString(context, lastBackupAt)) } + + LaunchedEffect(Unit) { + while (true) { + delay(1.minutes) + lastBackupString = calculateLastBackupTimeString(context, lastBackupAt) + } } Text( @@ -557,6 +564,18 @@ private fun LastBackedUpText(lastBackupAt: Duration) { ) } +private fun calculateLastBackupTimeString(context: Context, lastBackupAt: Duration): String { + return if (lastBackupAt.inWholeMilliseconds > 0) { + DateUtils.getDatelessRelativeTimeSpanFormattedDate( + context, + Locale.getDefault(), + lastBackupAt.inWholeMilliseconds + ).value + } else { + context.getString(R.string.RemoteBackupsSettingsFragment__never) + } +} + @Composable private fun InternalBackupOverrideRow( backupsSettingsState: BackupsSettingsState, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsViewModel.kt index 86b4363fc3..18d8404231 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/BackupsSettingsViewModel.kt @@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.components.settings.app.backups import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -49,6 +50,15 @@ class BackupsSettingsViewModel : ViewModel() { } } } + + viewModelScope.launch(Dispatchers.IO) { + SignalStore.backup.lastBackupTimeFlow + .collect { lastBackupTime -> + internalStateFlow.update { + it.copy(lastBackupAt = lastBackupTime.milliseconds) + } + } + } } fun onBackupTierInternalOverrideChanged(tier: MessageBackupTier?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt index d368b54fb8..5cf321d73f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/BackupValues.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.keyvalue import com.fasterxml.jackson.annotation.JsonProperty import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow import okio.withLock import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.backup.DeletionState @@ -140,8 +141,14 @@ class BackupValues(store: KeyValueStore) : SignalStoreValues(store) { set(value) { putLong(KEY_LAST_BACKUP_TIME, value) clearMessageBackupFailureSheetWatermark() + if (_lastBackupTimeFlow.isInitialized()) { + _lastBackupTimeFlow.value.tryEmit(value) + } } + private val _lastBackupTimeFlow: Lazy> = lazy { MutableStateFlow(lastBackupTime) } + val lastBackupTimeFlow by lazy { _lastBackupTimeFlow.value } + /** The version of the backup file we last successfully made. */ var lastBackupProtoVersion: Long by longValue(KEY_LAST_BACKUP_PROTO_VERSION, -1)