Load last backup times in PreferencesViewModel

pull/1136/head
Alex Baker 5 years ago
parent dd715c2b23
commit 5e472aabbe

@ -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<Long>? = 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()
}
}

@ -2,6 +2,8 @@ package org.tasks.preferences
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R 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.preferences.fragments.REQUEST_GOOGLE_TASKS
import org.tasks.sync.SyncAdapters import org.tasks.sync.SyncAdapters
import org.tasks.ui.Toaster import org.tasks.ui.Toaster
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -22,10 +25,18 @@ class MainPreferences : BasePreferences() {
@Inject lateinit var workManager: WorkManager @Inject lateinit var workManager: WorkManager
@Inject lateinit var toaster: Toaster @Inject lateinit var toaster: Toaster
private val viewModel: PreferencesViewModel by viewModels()
override fun getRootTitle() = R.string.TLA_menu_settings override fun getRootTitle() = R.string.TLA_menu_settings
override fun getRootPreference() = MainSettingsFragment() 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?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CALDAV_SETTINGS) { if (requestCode == REQUEST_CALDAV_SETTINGS) {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {

@ -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<Long?>()
val lastDriveBackup = MutableLiveData<Long?>()
val lastAndroidBackup = MutableLiveData<Long>()
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<Long>? = 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()
}
}

@ -3,30 +3,23 @@ package org.tasks.preferences.fragments
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.lifecycleScope import androidx.fragment.app.activityViewModels
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.SwitchPreferenceCompat 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.andlib.utility.DateUtilities
import com.todoroo.astrid.backup.BackupConstants
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.PermissionUtil import org.tasks.PermissionUtil
import org.tasks.R import org.tasks.R
import org.tasks.backup.BackupHelper
import org.tasks.dialogs.ExportTasksDialog import org.tasks.dialogs.ExportTasksDialog
import org.tasks.dialogs.ImportTasksDialog import org.tasks.dialogs.ImportTasksDialog
import org.tasks.drive.DriveInvoker
import org.tasks.drive.DriveLoginActivity import org.tasks.drive.DriveLoginActivity
import org.tasks.files.FileHelper import org.tasks.files.FileHelper
import org.tasks.gtasks.GoogleAccountManager
import org.tasks.injection.InjectingPreferenceFragment import org.tasks.injection.InjectingPreferenceFragment
import org.tasks.preferences.FragmentPermissionRequestor import org.tasks.preferences.FragmentPermissionRequestor
import org.tasks.preferences.PermissionRequestor import org.tasks.preferences.PermissionRequestor
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.preferences.PreferencesViewModel
import org.tasks.ui.Toaster import org.tasks.ui.Toaster
import timber.log.Timber
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@ -42,10 +35,9 @@ class Backups : InjectingPreferenceFragment() {
@Inject lateinit var preferences: Preferences @Inject lateinit var preferences: Preferences
@Inject lateinit var permissionRequestor: FragmentPermissionRequestor @Inject lateinit var permissionRequestor: FragmentPermissionRequestor
@Inject lateinit var toaster: Toaster @Inject lateinit var toaster: Toaster
@Inject lateinit var googleAccountManager: GoogleAccountManager
@Inject lateinit var locale: Locale @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 override fun getPreferenceXml() = R.xml.preferences_backups
@ -75,64 +67,52 @@ class Backups : InjectingPreferenceFragment() {
requestGoogleDriveLogin() requestGoogleDriveLogin()
false false
} }
}
override fun onResume() {
super.onResume()
updateDriveAccount() viewModel.lastBackup.observe(this, this::updateLastBackup)
viewModel.lastDriveBackup.observe(this, this::updateDriveBackup)
val driveBackup = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat viewModel.lastAndroidBackup.observe(this, this::updateAndroidBackup)
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, R.string.last_backup,
if (files.isEmpty()) { timestamp
getString(R.string.last_backup_never) ?.let { DateUtilities.getLongDateStringWithTime(it, locale) }
} else { ?: getString(R.string.last_backup_never)
DateUtilities.getLongDateStringWithTime(
BackupConstants.getTimestamp(files[0]),
locale
) )
})
}
} }
lifecycleScope.launch { private fun updateDriveBackup(timestamp: Long?) {
findPreference(R.string.backup_BAc_export).summary = findPreference(R.string.google_drive_backup).summary =
getString( getString(
R.string.last_backup, R.string.last_backup,
backupHelper.getLastBackup() timestamp
?.takeIf { it > 0 }
?.let { DateUtilities.getLongDateStringWithTime(it, locale) } ?.let { DateUtilities.getLongDateStringWithTime(it, locale) }
?: getString(R.string.last_backup_never) ?: 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 = findPreference(R.string.p_backups_android_backup_enabled).summary =
getString( getString(
R.string.last_backup, R.string.last_backup,
if (lastAndroidBackup == 0L) { timestamp
getString(R.string.last_backup_never) ?.let { DateUtilities.getLongDateStringWithTime(it, locale) }
} else { ?: getString(R.string.last_backup_never)
DateUtilities.getLongDateStringWithTime(lastAndroidBackup, locale)
}
) )
} }
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( override fun onRequestPermissionsResult(
requestCode: Int, requestCode: Int,
permissions: Array<out String>, permissions: Array<out String>,
@ -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 { private fun onGoogleDriveCheckChanged(preference: Preference, newValue: Any?) = when {
newValue as Boolean -> { newValue as Boolean -> {
requestGoogleDriveLogin() requestGoogleDriveLogin()
@ -203,7 +173,7 @@ class Backups : InjectingPreferenceFragment() {
} }
private fun updateDriveAccount() { private fun updateDriveAccount() {
val account = driveAccount val account = viewModel.driveAccount
val pref = findPreference(R.string.p_google_drive_backup_account) val pref = findPreference(R.string.p_google_drive_backup_account)
pref.isEnabled = account != null pref.isEnabled = account != null
pref.summary = pref.summary =

Loading…
Cancel
Save