Update Google Drive backup settings

Display timestamp of last backup
pull/1122/head
Alex Baker 5 years ago
parent 345346b1e9
commit 60e4ca2866

@ -47,9 +47,10 @@ class DriveInvoker @Inject constructor(
} }
@Throws(IOException::class) @Throws(IOException::class)
suspend fun getFilesByPrefix(folderId: String?, prefix: String?): List<File> { suspend fun getFilesByPrefix(folderId: String?, vararg prefix: String?): List<File> {
val namePredicate = prefix.joinToString(" or ") { "name contains '$it'" }
val query = String.format( val query = String.format(
"'%s' in parents and name contains '%s' and trashed = false and mimeType != '%s'", "'%s' in parents and ($namePredicate) and trashed = false and mimeType != '%s'",
folderId, prefix, MIME_FOLDER) folderId, prefix, MIME_FOLDER)
return execute( return execute(
service service
@ -59,6 +60,7 @@ class DriveInvoker @Inject constructor(
.setSpaces("drive") .setSpaces("drive")
.setFields("files(id, modifiedTime)")) .setFields("files(id, modifiedTime)"))
?.files ?.files
?.sortedWith(DRIVE_FILE_COMPARATOR)
?: emptyList() ?: emptyList()
} }
@ -139,5 +141,8 @@ class DriveInvoker @Inject constructor(
companion object { companion object {
private const val MIME_FOLDER = "application/vnd.google-apps.folder" private const val MIME_FOLDER = "application/vnd.google-apps.folder"
private val DRIVE_FILE_COMPARATOR = Comparator<File> { f1, f2 ->
f2.modifiedTime.value.compareTo(f1.modifiedTime.value)
}
} }
} }

@ -19,7 +19,6 @@ import java.io.IOException
import java.net.ConnectException import java.net.ConnectException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import java.net.UnknownHostException import java.net.UnknownHostException
import java.util.*
import javax.net.ssl.SSLException import javax.net.ssl.SSLException
class DriveUploader @WorkerInject constructor( class DriveUploader @WorkerInject constructor(
@ -37,18 +36,20 @@ class DriveUploader @WorkerInject constructor(
preferences.setString(R.string.p_google_drive_backup_folder, folder.id) preferences.setString(R.string.p_google_drive_backup_folder, folder.id)
drive.createFile(folder.id, uri) drive.createFile(folder.id, uri)
if (inputData.getBoolean(EXTRA_PURGE, false)) { if (inputData.getBoolean(EXTRA_PURGE, false)) {
val files = drive.getFilesByPrefix(folder.id, "auto.") drive
for (file in getDeleteList(files)) { .getFilesByPrefix(folder.id, "auto.")
try { .drop(BackupWork.DAYS_TO_KEEP_BACKUP)
drive.delete(file) .forEach {
} catch (e: GoogleJsonResponseException) { try {
if (e.statusCode == 404) { drive.delete(it)
Timber.e(e) } catch (e: GoogleJsonResponseException) {
} else { if (e.statusCode == 404) {
throw e Timber.e(e)
} else {
throw e
}
}
} }
}
}
} }
Result.success() Result.success()
} catch (e: SocketTimeoutException) { } catch (e: SocketTimeoutException) {
@ -89,17 +90,11 @@ class DriveUploader @WorkerInject constructor(
private const val FOLDER_NAME = "Tasks Backups" private const val FOLDER_NAME = "Tasks Backups"
private const val EXTRA_URI = "extra_uri" private const val EXTRA_URI = "extra_uri"
private const val EXTRA_PURGE = "extra_purge" private const val EXTRA_PURGE = "extra_purge"
private val DRIVE_FILE_COMPARATOR = Comparator<File> { f1, f2 ->
f2.modifiedTime.value.compareTo(f1.modifiedTime.value)
}
fun getInputData(uri: Uri, purge: Boolean) = fun getInputData(uri: Uri, purge: Boolean) =
Data.Builder() Data.Builder()
.putString(EXTRA_URI, uri.toString()) .putString(EXTRA_URI, uri.toString())
.putBoolean(EXTRA_PURGE, purge) .putBoolean(EXTRA_PURGE, purge)
.build() .build()
private fun getDeleteList(files: List<File>) =
files.sortedWith(DRIVE_FILE_COMPARATOR).drop(BackupWork.DAYS_TO_KEEP_BACKUP)
} }
} }

@ -3,15 +3,18 @@ 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.preference.Preference import androidx.preference.Preference
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import com.google.api.services.drive.DriveScopes import com.google.api.services.drive.DriveScopes
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
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.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.gtasks.GoogleAccountManager
@ -37,6 +40,7 @@ class Backups : InjectingPreferenceFragment() {
@Inject lateinit var toaster: Toaster @Inject lateinit var toaster: Toaster
@Inject lateinit var googleAccountManager: GoogleAccountManager @Inject lateinit var googleAccountManager: GoogleAccountManager
@Inject lateinit var locale: Locale @Inject lateinit var locale: Locale
@Inject lateinit var driveInvoker: DriveInvoker
override fun getPreferenceXml() = R.xml.preferences_backups override fun getPreferenceXml() = R.xml.preferences_backups
@ -58,12 +62,36 @@ class Backups : InjectingPreferenceFragment() {
.show(parentFragmentManager, FRAG_TAG_EXPORT_TASKS) .show(parentFragmentManager, FRAG_TAG_EXPORT_TASKS)
false false
} }
findPreference(R.string.google_drive_backup)
.setOnPreferenceChangeListener(this@Backups::onGoogleDriveCheckChanged)
findPreference(R.string.p_google_drive_backup_account)
.setOnPreferenceClickListener {
requestGoogleDriveLogin()
false
}
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
updateGoogleDriveCheckbox() updateDriveAccount()
val driveBackup = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat
driveBackup.isChecked = driveAccount != null
if (driveAccount != null) {
lifecycleScope.launch {
val folder = preferences.getStringValue(R.string.p_google_drive_backup_folder)
val files = driveInvoker.getFilesByPrefix(folder, "auto.", "user.")
driveBackup.summary = getString(
R.string.last_backup,
if (files.isEmpty()) {
getString(R.string.last_backup_never)
} else {
DateUtilities.getLongDateStringWithTime(files[0].modifiedTime.value, locale)
})
}
}
val lastBackup = preferences.getLong(R.string.p_backups_android_backup_last, 0L) val lastBackup = preferences.getLong(R.string.p_backups_android_backup_last, 0L)
findPreference(R.string.p_backups_android_backup_enabled).summary = findPreference(R.string.p_backups_android_backup_enabled).summary =
@ -123,35 +151,46 @@ class Backups : InjectingPreferenceFragment() {
} }
} }
private fun updateGoogleDriveCheckbox() { private val driveAccount: String?
val account = preferences.getStringValue(R.string.p_google_drive_backup_account) get() {
val pref = findPreference(R.string.google_drive_backup) as SwitchPreferenceCompat val account = preferences.getStringValue(R.string.p_google_drive_backup_account)
pref.isChecked = preferences.getBoolean(R.string.p_google_drive_backup, false) val enabled = !account.isNullOrBlank()
&& googleAccountManager.canAccessAccount(account) && preferences.getBoolean(R.string.p_google_drive_backup, false)
&& !preferences.alreadyNotified(account, DriveScopes.DRIVE_FILE) && googleAccountManager.canAccessAccount(account)
pref.summary = if (pref.isChecked) account else null && !preferences.alreadyNotified(account, DriveScopes.DRIVE_FILE)
findPreference(R.string.google_drive_backup) return if (enabled) account else null
.setOnPreferenceChangeListener(this@Backups::onGoogleDriveCheckChanged) }
}
private fun onGoogleDriveCheckChanged(preference: Preference, newValue: Any?) = when { private fun onGoogleDriveCheckChanged(preference: Preference, newValue: Any?) = when {
newValue as Boolean -> { newValue as Boolean -> {
if (permissionRequestor.requestAccountPermissions()) { requestGoogleDriveLogin()
requestGoogleDriveLogin()
}
false false
} }
else -> { else -> {
preference.summary = null preference.summary = null
preferences.setString(R.string.p_google_drive_backup_account, null)
updateDriveAccount()
true true
} }
} }
private fun updateDriveAccount() {
val account = driveAccount
val pref = findPreference(R.string.p_google_drive_backup_account)
pref.isEnabled = account != null
pref.summary =
account
?.takeIf { it.isNotBlank() }
?: getString(R.string.none)
}
private fun requestGoogleDriveLogin() { private fun requestGoogleDriveLogin() {
startActivityForResult( if (permissionRequestor.requestAccountPermissions()) {
Intent(context, DriveLoginActivity::class.java), startActivityForResult(
REQUEST_DRIVE_BACKUP Intent(context, DriveLoginActivity::class.java),
) REQUEST_DRIVE_BACKUP
)
}
} }
private fun initializeBackupDirectory() { private fun initializeBackupDirectory() {

@ -642,4 +642,5 @@ File %1$s contained %2$s.\n\n
<string name="last_backup">Last backup: %s</string> <string name="last_backup">Last backup: %s</string>
<string name="last_backup_never">never</string> <string name="last_backup_never">never</string>
<string name="device_settings">Device settings</string> <string name="device_settings">Device settings</string>
<string name="account">Account</string>
</resources> </resources>

@ -6,10 +6,6 @@
android:key="@string/p_backup_dir" android:key="@string/p_backup_dir"
android:title="@string/backup_directory" /> android:title="@string/backup_directory" />
<SwitchPreferenceCompat
android:key="@string/google_drive_backup"
android:title="@string/google_drive_backup" />
<Preference <Preference
android:key="@string/backup_BAc_import" android:key="@string/backup_BAc_import"
android:title="@string/backup_BAc_import" /> android:title="@string/backup_BAc_import" />
@ -18,6 +14,20 @@
android:key="@string/backup_BAc_export" android:key="@string/backup_BAc_export"
android:title="@string/backup_BAc_export" /> android:title="@string/backup_BAc_export" />
<PreferenceCategory
android:title="@string/google_drive_backup">
<SwitchPreferenceCompat
android:key="@string/google_drive_backup"
android:title="@string/enabled" />
<Preference
android:key="@string/p_google_drive_backup_account"
android:title="@string/account"
android:summary="@string/none"/>
</PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="@string/android_auto_backup"> android:title="@string/android_auto_backup">

Loading…
Cancel
Save