diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusBanner.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusBanner.kt index b69594ff8e..2f4a89f42c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusBanner.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/status/BackupStatusBanner.kt @@ -57,6 +57,7 @@ private const val NONE = -1 @Composable fun BackupStatusBanner( data: BackupStatusData, + onBannerClick: () -> Unit = {}, onActionClick: (BackupStatusData) -> Unit = {}, onDismissClick: () -> Unit = {}, contentPadding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp) @@ -68,6 +69,7 @@ fun BackupStatusBanner( .border(1.dp, color = MaterialTheme.colorScheme.outline.copy(alpha = 0.38f), shape = RoundedCornerShape(12.dp)) .fillMaxWidth() .defaultMinSize(minHeight = 48.dp) + .clickable(onClick = onBannerClick) .padding(12.dp) ) { Icon( @@ -309,7 +311,7 @@ sealed interface BackupStatusData { RestoreStatus.FINISHED -> bytesTotal.toUnitString() } - override val progress: Float = if (bytesTotal.bytes > 0 && restoreStatus == RestoreStatus.NORMAL) { + override val progress: Float = if (bytesTotal.bytes > 0) { min(1f, max(0f, bytesDownloaded.bytes.toFloat() / bytesTotal.bytes.toFloat())) } else { NONE.toFloat() diff --git a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/MediaRestoreProgressBanner.kt b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/MediaRestoreProgressBanner.kt index 86d486475e..db1c78d0e1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/banner/banners/MediaRestoreProgressBanner.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/banner/banners/MediaRestoreProgressBanner.kt @@ -73,6 +73,7 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList override fun DisplayBanner(model: BackupStatusData, contentPadding: PaddingValues) { BackupStatusBanner( data = model, + onBannerClick = listener::onBannerClick, onActionClick = listener::onActionClick, onDismissClick = listener::onDismissComplete ) @@ -107,14 +108,15 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList return flow .throttleLatest(1.seconds) .map { + val totalRestoreSize = SignalStore.backup.totalRestorableAttachmentSize + val remainingAttachmentSize = SignalDatabase.attachments.getRemainingRestorableAttachmentSize() + val completedBytes = totalRestoreSize - remainingAttachmentSize + when { - !WifiConstraint.isMet(AppDependencies.application) && !SignalStore.backup.restoreWithCellular -> BackupStatusData.RestoringMedia(restoreStatus = BackupStatusData.RestoreStatus.WAITING_FOR_WIFI) - !NetworkConstraint.isMet(AppDependencies.application) -> BackupStatusData.RestoringMedia(restoreStatus = BackupStatusData.RestoreStatus.WAITING_FOR_INTERNET) - !BatteryNotLowConstraint.isMet() -> BackupStatusData.RestoringMedia(restoreStatus = BackupStatusData.RestoreStatus.LOW_BATTERY) + !WifiConstraint.isMet(AppDependencies.application) && !SignalStore.backup.restoreWithCellular -> BackupStatusData.RestoringMedia(completedBytes.bytes, totalRestoreSize.bytes, BackupStatusData.RestoreStatus.WAITING_FOR_WIFI) + !NetworkConstraint.isMet(AppDependencies.application) -> BackupStatusData.RestoringMedia(completedBytes.bytes, totalRestoreSize.bytes, BackupStatusData.RestoreStatus.WAITING_FOR_INTERNET) + !BatteryNotLowConstraint.isMet() -> BackupStatusData.RestoringMedia(completedBytes.bytes, totalRestoreSize.bytes, BackupStatusData.RestoreStatus.LOW_BATTERY) else -> { - val totalRestoreSize = SignalStore.backup.totalRestorableAttachmentSize - val remainingAttachmentSize = SignalDatabase.attachments.getRemainingRestorableAttachmentSize() - val completedBytes = totalRestoreSize - remainingAttachmentSize val availableBytes = SignalStore.backup.spaceAvailableOnDiskBytes if (availableBytes > -1L && remainingAttachmentSize > availableBytes) { @@ -129,11 +131,13 @@ class MediaRestoreProgressBanner(private val listener: RestoreProgressBannerList } interface RestoreProgressBannerListener { + fun onBannerClick() fun onActionClick(data: BackupStatusData) fun onDismissComplete() } private object EmptyListener : RestoreProgressBannerListener { + override fun onBannerClick() = Unit override fun onActionClick(data: BackupStatusData) = Unit override fun onDismissComplete() = Unit } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt index 59c6c5dd24..615d8cdc63 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/AppSettingsActivity.kt @@ -74,6 +74,7 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent { CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).folderId, CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).threadId ) + StartLocation.BACKUPS_SETTINGS -> AppSettingsFragmentDirections.actionDirectToBackupsSettingsFragment() } } @@ -216,6 +217,9 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent { return getIntentForStartLocation(context, StartLocation.CREATE_CHAT_FOLDER).putExtra(START_ARGUMENTS, arguments) } + @JvmStatic + fun backupsSettings(context: Context): Intent = getIntentForStartLocation(context, StartLocation.BACKUPS_SETTINGS) + private fun getIntentForStartLocation(context: Context, startLocation: StartLocation): Intent { return Intent(context, AppSettingsActivity::class.java) .putExtra(ARG_NAV_GRAPH, R.navigation.app_settings_with_change_number) @@ -242,7 +246,8 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent { RECOVER_USERNAME(15), REMOTE_BACKUPS(16), CHAT_FOLDERS(17), - CREATE_CHAT_FOLDER(18); + CREATE_CHAT_FOLDER(18), + BACKUPS_SETTINGS(19); companion object { fun fromCode(code: Int?): StartLocation { 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 a157b2f534..8e38476aa0 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 @@ -81,7 +81,7 @@ class BackupsSettingsFragment : ComposeFragment() { BackupsSettingsContent( backupsSettingsState = state, - onNavigationClick = { findNavController().popBackStack() }, + onNavigationClick = { requireActivity().onNavigateUp() }, onBackupsRowClick = { when (state.enabledState) { is BackupsSettingsState.EnabledState.Active, BackupsSettingsState.EnabledState.Inactive -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsViewModel.kt index 937e186578..b4fd782fc6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsViewModel.kt @@ -164,7 +164,8 @@ class RemoteBackupsSettingsViewModel : ViewModel() { lastBackupTimestamp = SignalStore.backup.lastBackupTime, backupSize = SignalStore.backup.totalBackupSize, backupsFrequency = SignalStore.backup.backupFrequency, - canBackUpUsingCellular = SignalStore.backup.backupWithCellular + canBackUpUsingCellular = SignalStore.backup.backupWithCellular, + canRestoreUsingCellular = SignalStore.backup.restoreWithCellular ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 654739628f..c69cfba80d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -914,6 +914,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode return Unit.INSTANCE; }), new MediaRestoreProgressBanner(new MediaRestoreProgressBanner.RestoreProgressBannerListener() { + @Override + public void onBannerClick() { + startActivity(AppSettingsActivity.backupsSettings(requireContext())); + } + @Override public void onActionClick(@NonNull BackupStatusData backupStatusData) { if (backupStatusData instanceof BackupStatusData.NotEnoughFreeSpace) { diff --git a/app/src/main/res/navigation/app_settings_with_change_number.xml b/app/src/main/res/navigation/app_settings_with_change_number.xml index 53480bf079..239b7c6951 100644 --- a/app/src/main/res/navigation/app_settings_with_change_number.xml +++ b/app/src/main/res/navigation/app_settings_with_change_number.xml @@ -705,7 +705,9 @@ app:enterAnim="@anim/fragment_open_enter" app:exitAnim="@anim/fragment_open_exit" app:popEnterAnim="@anim/fragment_close_enter" - app:popExitAnim="@anim/fragment_close_exit" /> + app:popExitAnim="@anim/fragment_close_exit" + app:popUpTo="@id/app_settings" + app:popUpToInclusive="true" /> + +