From 5e472aabbe806acf3457a9716c847ae63c8b8b31 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Tue, 15 Sep 2020 15:22:44 -0500 Subject: [PATCH] Load last backup times in PreferencesViewModel --- .../java/org/tasks/backup/BackupHelper.kt | 39 ------- .../org/tasks/preferences/MainPreferences.kt | 11 ++ .../tasks/preferences/PreferencesViewModel.kt | 96 +++++++++++++++ .../tasks/preferences/fragments/Backups.kt | 110 +++++++----------- 4 files changed, 147 insertions(+), 109 deletions(-) delete mode 100644 app/src/main/java/org/tasks/backup/BackupHelper.kt create mode 100644 app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt diff --git a/app/src/main/java/org/tasks/backup/BackupHelper.kt b/app/src/main/java/org/tasks/backup/BackupHelper.kt deleted file mode 100644 index 56694a1a9..000000000 --- a/app/src/main/java/org/tasks/backup/BackupHelper.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.tasks.backup - -import android.content.ContentResolver -import android.content.Context -import androidx.documentfile.provider.DocumentFile -import com.todoroo.astrid.backup.BackupConstants -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.tasks.preferences.Preferences -import java.io.File -import javax.inject.Inject - -class BackupHelper @Inject constructor( - @param:ApplicationContext private val context: Context, - private val preferences: Preferences -) { - suspend fun getLastBackup(): Long? { - val uri = preferences.backupDirectory - val timestamps: List? = withContext(Dispatchers.IO) { - when (uri?.scheme) { - ContentResolver.SCHEME_CONTENT -> { - DocumentFile.fromTreeUri(context, uri) - ?.listFiles() - ?.filter { BackupConstants.isBackupFile(it.name!!) } - ?.map { BackupConstants.getTimestamp(it) } - } - ContentResolver.SCHEME_FILE -> { - File(uri.path!!) - .listFiles() - ?.filter { BackupConstants.isBackupFile(it.name) } - ?.map { BackupConstants.getTimestamp(it) } - } - else -> emptyList() - } - } - return timestamps?.maxOrNull() - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/MainPreferences.kt b/app/src/main/java/org/tasks/preferences/MainPreferences.kt index b24a44561..305655923 100644 --- a/app/src/main/java/org/tasks/preferences/MainPreferences.kt +++ b/app/src/main/java/org/tasks/preferences/MainPreferences.kt @@ -2,6 +2,8 @@ package org.tasks.preferences import android.app.Activity import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity import dagger.hilt.android.AndroidEntryPoint import org.tasks.R @@ -13,6 +15,7 @@ import org.tasks.preferences.fragments.REQUEST_DRIVE_BACKUP import org.tasks.preferences.fragments.REQUEST_GOOGLE_TASKS import org.tasks.sync.SyncAdapters import org.tasks.ui.Toaster +import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint @@ -22,10 +25,18 @@ class MainPreferences : BasePreferences() { @Inject lateinit var workManager: WorkManager @Inject lateinit var toaster: Toaster + private val viewModel: PreferencesViewModel by viewModels() + override fun getRootTitle() = R.string.TLA_menu_settings override fun getRootPreference() = MainSettingsFragment() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + Timber.d("viewModel=$viewModel") + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == REQUEST_CALDAV_SETTINGS) { if (resultCode == RESULT_OK) { diff --git a/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt b/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt new file mode 100644 index 000000000..97817343c --- /dev/null +++ b/app/src/main/java/org/tasks/preferences/PreferencesViewModel.kt @@ -0,0 +1,96 @@ +package org.tasks.preferences + +import android.content.ContentResolver +import android.content.Context +import androidx.documentfile.provider.DocumentFile +import androidx.hilt.lifecycle.ViewModelInject +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.api.client.googleapis.json.GoogleJsonResponseException +import com.google.api.services.drive.DriveScopes +import com.todoroo.astrid.backup.BackupConstants +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.tasks.R +import org.tasks.drive.DriveInvoker +import org.tasks.gtasks.GoogleAccountManager +import timber.log.Timber +import java.io.File + +class PreferencesViewModel @ViewModelInject constructor( + @ApplicationContext private val context: Context, + private val preferences: Preferences, + private val driveInvoker: DriveInvoker, + private val googleAccountManager: GoogleAccountManager, +) : ViewModel() { + val lastBackup = MutableLiveData() + val lastDriveBackup = MutableLiveData() + val lastAndroidBackup = MutableLiveData() + + val driveAccount: String? + get() { + val account = preferences.getStringValue(R.string.p_google_drive_backup_account) + val enabled = !account.isNullOrBlank() + && preferences.getBoolean(R.string.p_google_drive_backup, false) + && googleAccountManager.canAccessAccount(account) + && !preferences.alreadyNotified(account, DriveScopes.DRIVE_FILE) + return if (enabled) account else null + } + + + private fun updateDriveBackup() = viewModelScope.launch { + if (driveAccount.isNullOrBlank()) { + lastDriveBackup.value = null + return@launch + } + val files = preferences.getStringValue(R.string.p_google_drive_backup_folder) + ?.takeIf { it.isNotBlank() } + ?.let { + try { + driveInvoker.getFilesByPrefix(it, "auto.", "user.") + } catch (e: GoogleJsonResponseException) { + Timber.e(e) + null + } + } + ?: emptyList() + lastDriveBackup.value = files.firstOrNull()?.let { BackupConstants.getTimestamp(it) } + } + + private fun updateLocalBackup() = viewModelScope.launch { + val uri = preferences.backupDirectory + val timestamps: List? = withContext(Dispatchers.IO) { + when (uri?.scheme) { + ContentResolver.SCHEME_CONTENT -> { + DocumentFile.fromTreeUri(context, uri) + ?.listFiles() + ?.filter { BackupConstants.isBackupFile(it.name!!) } + ?.map { BackupConstants.getTimestamp(it) } + } + ContentResolver.SCHEME_FILE -> { + File(uri.path!!) + .listFiles() + ?.filter { BackupConstants.isBackupFile(it.name) } + ?.map { BackupConstants.getTimestamp(it) } + } + else -> emptyList() + } + } + lastBackup.value = timestamps?.maxOrNull() + } + + private fun updateAndroidBackup() { + lastAndroidBackup.value = preferences + .getLong(R.string.p_backups_android_backup_last, -1L) + .takeIf { it >= 0 } + } + + init { + updateLocalBackup() + updateDriveBackup() + updateAndroidBackup() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt index 189eb31e2..67e384aaf 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt @@ -3,30 +3,23 @@ package org.tasks.preferences.fragments import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle -import androidx.lifecycle.lifecycleScope +import androidx.fragment.app.activityViewModels import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat -import com.google.api.client.googleapis.json.GoogleJsonResponseException -import com.google.api.services.drive.DriveScopes import com.todoroo.andlib.utility.DateUtilities -import com.todoroo.astrid.backup.BackupConstants import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.launch import org.tasks.PermissionUtil import org.tasks.R -import org.tasks.backup.BackupHelper import org.tasks.dialogs.ExportTasksDialog import org.tasks.dialogs.ImportTasksDialog -import org.tasks.drive.DriveInvoker import org.tasks.drive.DriveLoginActivity import org.tasks.files.FileHelper -import org.tasks.gtasks.GoogleAccountManager import org.tasks.injection.InjectingPreferenceFragment import org.tasks.preferences.FragmentPermissionRequestor import org.tasks.preferences.PermissionRequestor import org.tasks.preferences.Preferences +import org.tasks.preferences.PreferencesViewModel import org.tasks.ui.Toaster -import timber.log.Timber import java.util.* import javax.inject.Inject @@ -42,10 +35,9 @@ class Backups : InjectingPreferenceFragment() { @Inject lateinit var preferences: Preferences @Inject lateinit var permissionRequestor: FragmentPermissionRequestor @Inject lateinit var toaster: Toaster - @Inject lateinit var googleAccountManager: GoogleAccountManager @Inject lateinit var locale: Locale - @Inject lateinit var driveInvoker: DriveInvoker - @Inject lateinit var backupHelper: BackupHelper + + private val viewModel: PreferencesViewModel by activityViewModels() override fun getPreferenceXml() = R.xml.preferences_backups @@ -75,64 +67,52 @@ class Backups : InjectingPreferenceFragment() { requestGoogleDriveLogin() false } - } - - override fun onResume() { - super.onResume() - updateDriveAccount() + viewModel.lastBackup.observe(this, this::updateLastBackup) + viewModel.lastDriveBackup.observe(this, this::updateDriveBackup) + viewModel.lastAndroidBackup.observe(this, this::updateAndroidBackup) + } - val driveBackup = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat - driveBackup.isChecked = driveAccount != null - if (driveAccount != null) { - lifecycleScope.launch { - val files = preferences.getStringValue(R.string.p_google_drive_backup_folder) - ?.takeIf { it.isNotBlank() } - ?.let { - try { - driveInvoker.getFilesByPrefix(it, "auto.", "user.") - } catch (e: GoogleJsonResponseException) { - Timber.e(e) - null - } - } - ?: emptyList() - driveBackup.summary = getString( + private fun updateLastBackup(timestamp: Long?) { + findPreference(R.string.backup_BAc_export).summary = + getString( R.string.last_backup, - if (files.isEmpty()) { - getString(R.string.last_backup_never) - } else { - DateUtilities.getLongDateStringWithTime( - BackupConstants.getTimestamp(files[0]), - locale - ) - }) - } - } + timestamp + ?.let { DateUtilities.getLongDateStringWithTime(it, locale) } + ?: getString(R.string.last_backup_never) + ) + } - lifecycleScope.launch { - findPreference(R.string.backup_BAc_export).summary = - getString( - R.string.last_backup, - backupHelper.getLastBackup() - ?.takeIf { it > 0 } - ?.let { DateUtilities.getLongDateStringWithTime(it, locale) } - ?: getString(R.string.last_backup_never) - ) - } + private fun updateDriveBackup(timestamp: Long?) { + findPreference(R.string.google_drive_backup).summary = + getString( + R.string.last_backup, + timestamp + ?.let { DateUtilities.getLongDateStringWithTime(it, locale) } + ?: getString(R.string.last_backup_never) + ) + } - val lastAndroidBackup = preferences.getLong(R.string.p_backups_android_backup_last, 0L) + private fun updateAndroidBackup(timestamp: Long?) { findPreference(R.string.p_backups_android_backup_enabled).summary = getString( R.string.last_backup, - if (lastAndroidBackup == 0L) { - getString(R.string.last_backup_never) - } else { - DateUtilities.getLongDateStringWithTime(lastAndroidBackup, locale) - } + timestamp + ?.let { DateUtilities.getLongDateStringWithTime(it, locale) } + ?: getString(R.string.last_backup_never) ) } + override fun onResume() { + super.onResume() + + updateDriveAccount() + + val driveBackup = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat + val driveAccount = viewModel.driveAccount + driveBackup.isChecked = driveAccount != null + } + override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, @@ -179,16 +159,6 @@ class Backups : InjectingPreferenceFragment() { } } - private val driveAccount: String? - get() { - val account = preferences.getStringValue(R.string.p_google_drive_backup_account) - val enabled = !account.isNullOrBlank() - && preferences.getBoolean(R.string.p_google_drive_backup, false) - && googleAccountManager.canAccessAccount(account) - && !preferences.alreadyNotified(account, DriveScopes.DRIVE_FILE) - return if (enabled) account else null - } - private fun onGoogleDriveCheckChanged(preference: Preference, newValue: Any?) = when { newValue as Boolean -> { requestGoogleDriveLogin() @@ -203,7 +173,7 @@ class Backups : InjectingPreferenceFragment() { } private fun updateDriveAccount() { - val account = driveAccount + val account = viewModel.driveAccount val pref = findPreference(R.string.p_google_drive_backup_account) pref.isEnabled = account != null pref.summary =