diff --git a/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.java b/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.java deleted file mode 100755 index c20afef0c..000000000 --- a/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ - -package com.todoroo.astrid.backup; - -/** - * Constants for backup XML attributes and nodes. - * - * @author Tim Su - */ -public class BackupConstants { - - // Do NOT edit the constants in this file! You will break compatibility with old backups - - // --- general xml - - /** Tag containing Astrid backup data */ - public static final String ASTRID_TAG = "astrid"; - - /** Attribute indicating backup file format */ - public static final String ASTRID_ATTR_FORMAT = "format"; - - // --- format 2 - - /** Tag containing a task */ - public static final String TASK_TAG = "task"; - - /** Tag containing a comment item */ - public static final String COMMENT_TAG = "comment"; - - /** Tag containing a metadata item */ - public static final String METADATA_TAG = "metadata"; - - /** Tag containing a tagdata item */ - public static final String TAGDATA_TAG = "tagdata"; - - // --- general - - public static final String INTERNAL_BACKUP = "backup.json"; - - public static final String EXPORT_FILE_NAME = "user.%s.json"; - - public static final String BACKUP_FILE_NAME = "auto.%s.json"; -} diff --git a/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.kt b/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.kt new file mode 100755 index 000000000..b15475ab6 --- /dev/null +++ b/app/src/main/java/com/todoroo/astrid/backup/BackupConstants.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012 Todoroo Inc + * + * See the file "LICENSE" for the full license governing this code. + */ +package com.todoroo.astrid.backup + +import com.google.api.services.drive.model.File +import org.tasks.time.DateTime +import java.util.regex.Pattern + +/** + * Constants for backup XML attributes and nodes. + * + * @author Tim Su @todoroo.com> + */ +object BackupConstants { + // Do NOT edit the constants in this file! You will break compatibility with old backups + // --- general xml + /** Tag containing Astrid backup data */ + const val ASTRID_TAG = "astrid" + + /** Attribute indicating backup file format */ + const val ASTRID_ATTR_FORMAT = "format" + // --- format 2 + /** Tag containing a task */ + const val TASK_TAG = "task" + + /** Tag containing a comment item */ + const val COMMENT_TAG = "comment" + + /** Tag containing a metadata item */ + const val METADATA_TAG = "metadata" + + /** Tag containing a tagdata item */ + const val TAGDATA_TAG = "tagdata" + + // --- general + const val INTERNAL_BACKUP = "backup.json" + const val EXPORT_FILE_NAME = "user.%s.json" + const val BACKUP_FILE_NAME = "auto.%s.json" + + private val MATCHER = Pattern.compile("(auto|user)\\.(\\d{2})(\\d{2})(\\d{2})-(\\d{2})(\\d{2})\\.json") + + fun isBackupFile(name: String) = MATCHER.matcher(name).matches() + + fun getTimestamp(file: java.io.File): Long { + return getTimestampFromFilename(file.name) ?: file.lastModified() + } + + fun getTimestamp(file: File): Long { + return getTimestampFromFilename(file.name) ?: file.modifiedTime.value + } + + private fun getTimestampFromFilename(name: String): Long? { + return MATCHER + .matcher(name) + .takeIf { it.matches() } + ?.let { + DateTime( + 2000 + it.group(2)!!.toInt(), + it.group(3)!!.toInt(), + it.group(4)!!.toInt(), + it.group(5)!!.toInt(), + it.group(6)!!.toInt()) + .millis + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/drive/DriveInvoker.kt b/app/src/main/java/org/tasks/drive/DriveInvoker.kt index b26a5eab2..41a3c91cb 100644 --- a/app/src/main/java/org/tasks/drive/DriveInvoker.kt +++ b/app/src/main/java/org/tasks/drive/DriveInvoker.kt @@ -12,6 +12,7 @@ import com.google.api.services.drive.DriveRequest import com.google.api.services.drive.DriveScopes import com.google.api.services.drive.model.File import com.todoroo.andlib.utility.DateUtilities +import com.todoroo.astrid.backup.BackupConstants import com.todoroo.astrid.gtasks.api.HttpCredentialsAdapter import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers @@ -58,8 +59,9 @@ class DriveInvoker @Inject constructor( .list() .setQ(query) .setSpaces("drive") - .setFields("files(id, modifiedTime)")) + .setFields("files(id, name, modifiedTime)")) ?.files + ?.filter { BackupConstants.isBackupFile(it.name) } ?.sortedWith(DRIVE_FILE_COMPARATOR) ?: emptyList() } @@ -142,7 +144,7 @@ class DriveInvoker @Inject constructor( companion object { private const val MIME_FOLDER = "application/vnd.google-apps.folder" private val DRIVE_FILE_COMPARATOR = Comparator { f1, f2 -> - f2.modifiedTime.value.compareTo(f1.modifiedTime.value) + BackupConstants.getTimestamp(f2).compareTo(BackupConstants.getTimestamp(f1)) } } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/jobs/BackupWork.kt b/app/src/main/java/org/tasks/jobs/BackupWork.kt index 675ff3447..96c110ca2 100644 --- a/app/src/main/java/org/tasks/jobs/BackupWork.kt +++ b/app/src/main/java/org/tasks/jobs/BackupWork.kt @@ -7,6 +7,7 @@ import androidx.hilt.Assisted import androidx.hilt.work.WorkerInject import androidx.work.WorkerParameters import com.todoroo.andlib.utility.DateUtilities +import com.todoroo.astrid.backup.BackupConstants import org.tasks.R import org.tasks.analytics.Firebase import org.tasks.backup.TasksJsonExporter @@ -74,7 +75,9 @@ class BackupWork @WorkerInject constructor( val BACKUP_FILE_NAME_REGEX = Regex("auto\\.[-\\d]+\\.json") private val FILENAME_FILTER = { f: String -> f.matches(BACKUP_FILE_NAME_REGEX) } val FILE_FILTER = FileFilter { f: File -> FILENAME_FILTER.invoke(f.name) } - private val BY_LAST_MODIFIED = Comparator { f1: File, f2: File -> f2.lastModified().compareTo(f1.lastModified()) } + private val BY_LAST_MODIFIED = { f1: File, f2: File -> + BackupConstants.getTimestamp(f2).compareTo(BackupConstants.getTimestamp(f1)) + } private val DOCUMENT_FILE_COMPARATOR = Comparator { d1: DocumentFile, d2: DocumentFile -> d2.lastModified().compareTo(d1.lastModified()) } fun getDeleteList(fileArray: Array?, keepNewest: Int) = 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 c56c6306c..b2402f2a6 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Backups.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Backups.kt @@ -8,6 +8,7 @@ import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat 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 @@ -88,7 +89,10 @@ class Backups : InjectingPreferenceFragment() { if (files.isEmpty()) { getString(R.string.last_backup_never) } else { - DateUtilities.getLongDateStringWithTime(files[0].modifiedTime.value, locale) + DateUtilities.getLongDateStringWithTime( + BackupConstants.getTimestamp(files[0]), + locale + ) }) } } diff --git a/app/src/test/java/com/todoroo/astrid/backup/BackupConstantsTest.kt b/app/src/test/java/com/todoroo/astrid/backup/BackupConstantsTest.kt new file mode 100644 index 000000000..e65d3c4c0 --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/backup/BackupConstantsTest.kt @@ -0,0 +1,38 @@ +package com.todoroo.astrid.backup + +import org.junit.Assert.* +import org.junit.Test +import org.tasks.time.DateTime + +class BackupConstantsTest { + @Test + fun autoBackupMatchesFilename() { + assertTrue(BackupConstants.isBackupFile("auto.200909-0003.json")) + } + + @Test + fun userBackupMatchesFilename() { + assertTrue(BackupConstants.isBackupFile("user.200909-1503.json")) + } + + @Test + fun ignoreCopiedFile() { + assertFalse(BackupConstants.isBackupFile("user.200909-1503 (1).json")) + } + + @Test + fun getTimestampFromAutoBackup() { + assertEquals( + DateTime(2020, 9, 10, 15, 3).millis, + BackupConstants.getTimestampFromFilename("auto.200910-1503.json") + ) + } + + @Test + fun getTimestampFromUserBackup() { + assertEquals( + DateTime(2020, 9, 10, 15, 3).millis, + BackupConstants.getTimestampFromFilename("user.200910-1503.json") + ) + } +} \ No newline at end of file