diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8784f83aa..d8d792439 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -136,6 +136,10 @@ android:label="@string/notification_checking_finished_title" android:launchMode="singleTask"/> + + diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt index 97362a902..eac8aee2c 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsViewModel.kt @@ -47,6 +47,7 @@ import com.stevesoltys.seedvault.worker.AppBackupWorker import com.stevesoltys.seedvault.worker.AppBackupWorker.Companion.UNIQUE_WORK_NAME import com.stevesoltys.seedvault.worker.AppCheckerWorker import com.stevesoltys.seedvault.worker.BackupRequester.Companion.requestFilesAndAppBackup +import com.stevesoltys.seedvault.worker.FileCheckerWorker import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -90,6 +91,8 @@ internal class SettingsViewModel( private val mBackupSize = MutableLiveData() val backupSize: LiveData = mBackupSize + private val mFilesBackupSize = MutableLiveData() + val filesBackupSize: LiveData = mFilesBackupSize internal val lastBackupTime = settingsManager.lastBackupTime internal val appBackupWorkInfo = @@ -329,10 +332,20 @@ internal class SettingsViewModel( } } + fun loadFileBackupSize() { + viewModelScope.launch(Dispatchers.IO) { + mFilesBackupSize.postValue(storageBackup.getBackupSize()) + } + } + fun checkAppBackups(percent: Int) { AppCheckerWorker.scheduleNow(app, percent) } + fun checkFileBackups(percent: Int) { + FileCheckerWorker.scheduleNow(app, percent) + } + fun onLogcatUriReceived(uri: Uri?) = viewModelScope.launch(Dispatchers.IO) { if (uri == null) { onLogcatError() diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/check/AppCheckFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/check/AppCheckFragment.kt index f6988b803..280a655f3 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/check/AppCheckFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/check/AppCheckFragment.kt @@ -20,8 +20,8 @@ import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.settings.SettingsViewModel import org.koin.androidx.viewmodel.ext.android.activityViewModel -private const val WARN_PERCENT = 25 -private const val WARN_BYTES = 1024 * 1024 * 1024 // 1 GB +internal const val WARN_PERCENT = 25 +internal const val WARN_BYTES = 1024 * 1024 * 1024 // 1 GB class AppCheckFragment : Fragment() { diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/check/FileCheckFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/check/FileCheckFragment.kt new file mode 100644 index 000000000..0882c082d --- /dev/null +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/check/FileCheckFragment.kt @@ -0,0 +1,89 @@ +/* + * SPDX-FileCopyrightText: 2024 The Calyx Institute + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.stevesoltys.seedvault.ui.check + +import android.os.Bundle +import android.text.format.Formatter +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.ScrollView +import android.widget.TextView +import androidx.fragment.app.Fragment +import com.google.android.material.slider.LabelFormatter +import com.google.android.material.slider.Slider +import com.stevesoltys.seedvault.R +import com.stevesoltys.seedvault.settings.SettingsViewModel +import org.koin.androidx.viewmodel.ext.android.activityViewModel + +class FileCheckFragment : Fragment() { + + private val viewModel: SettingsViewModel by activityViewModel() + private lateinit var sliderLabel: TextView + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { + val v = inflater.inflate(R.layout.fragment_app_check, container, false) as ScrollView + + v.requireViewById(R.id.titleView).setText(R.string.settings_file_check_title) + v.requireViewById(R.id.descriptionView).setText(R.string.settings_file_check_text) + v.requireViewById(R.id.introView).setText(R.string.settings_file_check_text2) + + val slider = v.requireViewById(R.id.slider) + sliderLabel = v.requireViewById(R.id.sliderLabel) + + // label not scrolling will be fixed in material-components 1.12.0 (next update) + slider.setLabelFormatter { value -> + viewModel.filesBackupSize.value?.let { + Formatter.formatShortFileSize(context, (it * value / 100).toLong()) + } ?: "${value.toInt()}%" + } + slider.addOnChangeListener { _, value, _ -> + onSliderChanged(value) + } + + viewModel.filesBackupSize.observe(viewLifecycleOwner) { + if (it != null) { + slider.labelBehavior = LabelFormatter.LABEL_VISIBLE + slider.invalidate() + onSliderChanged(slider.value) + } + // we can stop observing as the loaded size won't change again + viewModel.filesBackupSize.removeObservers(viewLifecycleOwner) + } + + v.requireViewById