|
|
|
@ -8,14 +8,12 @@ import android.net.Uri
|
|
|
|
import android.os.Handler
|
|
|
|
import android.os.Handler
|
|
|
|
import com.google.common.io.Files
|
|
|
|
import com.google.common.io.Files
|
|
|
|
import com.todoroo.andlib.utility.DialogUtilities
|
|
|
|
import com.todoroo.andlib.utility.DialogUtilities
|
|
|
|
import kotlinx.serialization.encodeToString
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
|
|
|
|
import kotlinx.coroutines.withContext
|
|
|
|
|
|
|
|
import kotlinx.serialization.Serializable
|
|
|
|
import kotlinx.serialization.json.Json
|
|
|
|
import kotlinx.serialization.json.Json
|
|
|
|
import kotlinx.serialization.json.JsonObject
|
|
|
|
|
|
|
|
import kotlinx.serialization.json.JsonPrimitive
|
|
|
|
|
|
|
|
import kotlinx.serialization.json.encodeToJsonElement
|
|
|
|
|
|
|
|
import org.tasks.BuildConfig
|
|
|
|
import org.tasks.BuildConfig
|
|
|
|
import org.tasks.R
|
|
|
|
import org.tasks.R
|
|
|
|
import org.tasks.backup.BackupContainer.TaskBackup
|
|
|
|
|
|
|
|
import org.tasks.caldav.VtodoCache
|
|
|
|
import org.tasks.caldav.VtodoCache
|
|
|
|
import org.tasks.data.*
|
|
|
|
import org.tasks.data.*
|
|
|
|
import org.tasks.data.dao.AlarmDao
|
|
|
|
import org.tasks.data.dao.AlarmDao
|
|
|
|
@ -28,7 +26,6 @@ import org.tasks.data.dao.TaskAttachmentDao
|
|
|
|
import org.tasks.data.dao.TaskDao
|
|
|
|
import org.tasks.data.dao.TaskDao
|
|
|
|
import org.tasks.data.dao.TaskListMetadataDao
|
|
|
|
import org.tasks.data.dao.TaskListMetadataDao
|
|
|
|
import org.tasks.data.dao.UserActivityDao
|
|
|
|
import org.tasks.data.dao.UserActivityDao
|
|
|
|
import org.tasks.data.entity.Task
|
|
|
|
|
|
|
|
import org.tasks.date.DateTimeUtils.newDateTime
|
|
|
|
import org.tasks.date.DateTimeUtils.newDateTime
|
|
|
|
import org.tasks.extensions.Context.toast
|
|
|
|
import org.tasks.extensions.Context.toast
|
|
|
|
import org.tasks.files.FileHelper
|
|
|
|
import org.tasks.files.FileHelper
|
|
|
|
@ -39,8 +36,9 @@ import timber.log.Timber
|
|
|
|
import java.io.File
|
|
|
|
import java.io.File
|
|
|
|
import java.io.IOException
|
|
|
|
import java.io.IOException
|
|
|
|
import java.io.OutputStream
|
|
|
|
import java.io.OutputStream
|
|
|
|
import java.io.OutputStreamWriter
|
|
|
|
import java.io.Writer
|
|
|
|
import java.nio.charset.Charset
|
|
|
|
import java.nio.charset.Charset
|
|
|
|
|
|
|
|
import java.util.Set
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Inject
|
|
|
|
|
|
|
|
|
|
|
|
class TasksJsonExporter @Inject constructor(
|
|
|
|
class TasksJsonExporter @Inject constructor(
|
|
|
|
@ -57,8 +55,7 @@ class TasksJsonExporter @Inject constructor(
|
|
|
|
private val workManager: WorkManager,
|
|
|
|
private val workManager: WorkManager,
|
|
|
|
private val taskListMetadataDao: TaskListMetadataDao,
|
|
|
|
private val taskListMetadataDao: TaskListMetadataDao,
|
|
|
|
private val vtodoCache: VtodoCache,
|
|
|
|
private val vtodoCache: VtodoCache,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
|
|
|
|
|
|
|
|
private var context: Context? = null
|
|
|
|
private var context: Context? = null
|
|
|
|
private var exportCount = 0
|
|
|
|
private var exportCount = 0
|
|
|
|
private var progressDialog: ProgressDialog? = null
|
|
|
|
private var progressDialog: ProgressDialog? = null
|
|
|
|
@ -84,7 +81,7 @@ class TasksJsonExporter @Inject constructor(
|
|
|
|
private suspend fun runBackup(exportType: ExportType) {
|
|
|
|
private suspend fun runBackup(exportType: ExportType) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
val filename = getFileName(exportType)
|
|
|
|
val filename = getFileName(exportType)
|
|
|
|
val tasks = taskDao.getAll()
|
|
|
|
val tasks = taskDao.getAllTaskIds()
|
|
|
|
val file = File(String.format("%s/%s", context!!.filesDir, BackupConstants.INTERNAL_BACKUP))
|
|
|
|
val file = File(String.format("%s/%s", context!!.filesDir, BackupConstants.INTERNAL_BACKUP))
|
|
|
|
file.delete()
|
|
|
|
file.delete()
|
|
|
|
file.createNewFile()
|
|
|
|
file.createNewFile()
|
|
|
|
@ -117,53 +114,50 @@ class TasksJsonExporter @Inject constructor(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Throws(IOException::class)
|
|
|
|
@Throws(IOException::class)
|
|
|
|
private suspend fun doTasksExport(os: OutputStream?, tasks: List<Task>) {
|
|
|
|
private suspend fun doTasksExport(os: OutputStream?, taskIds: List<Long>) = withContext(Dispatchers.IO) {
|
|
|
|
val taskBackups: MutableList<TaskBackup> = ArrayList()
|
|
|
|
val writer = os!!.bufferedWriter()
|
|
|
|
for (task in tasks) {
|
|
|
|
with (JsonWriter(writer)) {
|
|
|
|
setProgress(taskBackups.size, tasks.size)
|
|
|
|
write("{")
|
|
|
|
val taskId = task.id
|
|
|
|
write("version", BuildConfig.VERSION_CODE)
|
|
|
|
val caldavTasks = caldavDao.getTasks(taskId)
|
|
|
|
write("timestamp", currentTimeMillis())
|
|
|
|
taskBackups.add(
|
|
|
|
write("\"data\":{")
|
|
|
|
TaskBackup(
|
|
|
|
write("\"tasks\":[")
|
|
|
|
task = task,
|
|
|
|
taskIds.forEachIndexed { index, id ->
|
|
|
|
alarms = alarmDao.getAlarms(taskId),
|
|
|
|
setProgress(index, taskIds.size)
|
|
|
|
geofences = locationDao.getGeofencesForTask(taskId),
|
|
|
|
write("{")
|
|
|
|
tags = tagDao.getTagsForTask(taskId),
|
|
|
|
write("task", taskDao.fetch(id)!!)
|
|
|
|
comments = userActivityDao.getComments(taskId),
|
|
|
|
write("alarms", alarmDao.getAlarms(id))
|
|
|
|
attachments = taskAttachmentDao.getAttachmentsForTask(taskId),
|
|
|
|
write("geofences", locationDao.getGeofencesForTask(id))
|
|
|
|
caldavTasks = caldavTasks,
|
|
|
|
write("tags", tagDao.getTagsForTask(id))
|
|
|
|
vtodo = vtodoCache.getVtodo(caldavTasks.firstOrNull { !it.isDeleted() })
|
|
|
|
write("comments", userActivityDao.getComments(id))
|
|
|
|
)
|
|
|
|
write("attachments", taskAttachmentDao.getAttachmentsForTask(id))
|
|
|
|
)
|
|
|
|
val caldavTasks = caldavDao.getTasks(id)
|
|
|
|
|
|
|
|
vtodoCache
|
|
|
|
|
|
|
|
.getVtodo(caldavTasks.firstOrNull { !it.isDeleted() })
|
|
|
|
|
|
|
|
?.let { write("vtodo", it) }
|
|
|
|
|
|
|
|
write("caldavTasks", caldavTasks, lastItem = true)
|
|
|
|
|
|
|
|
write("}")
|
|
|
|
|
|
|
|
if (index < taskIds.size - 1) write(",")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
write("],")
|
|
|
|
|
|
|
|
write("places", locationDao.getPlaces())
|
|
|
|
|
|
|
|
write("tags", tagDataDao.getAll())
|
|
|
|
|
|
|
|
write("filters", filterDao.getFilters())
|
|
|
|
|
|
|
|
write("caldavAccounts", caldavDao.getAccounts())
|
|
|
|
|
|
|
|
write("caldavCalendars", caldavDao.getCalendars())
|
|
|
|
|
|
|
|
write("taskListMetadata", taskListMetadataDao.getAll())
|
|
|
|
|
|
|
|
write("taskAttachments", taskAttachmentDao.getAttachments())
|
|
|
|
|
|
|
|
write("intPrefs", preferences.getPrefs(Integer::class.java))
|
|
|
|
|
|
|
|
write("longPrefs", preferences.getPrefs(java.lang.Long::class.java))
|
|
|
|
|
|
|
|
write("stringPrefs", preferences.getPrefs(String::class.java))
|
|
|
|
|
|
|
|
write("boolPrefs", preferences.getPrefs(java.lang.Boolean::class.java))
|
|
|
|
|
|
|
|
write("setPrefs", preferences.getPrefs(Set::class.java) as Map<String, Set<String>>, lastItem = true)
|
|
|
|
|
|
|
|
write("}")
|
|
|
|
|
|
|
|
write("}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val data = JsonObject(
|
|
|
|
writer.close()
|
|
|
|
mapOf(
|
|
|
|
os.close()
|
|
|
|
"version" to JsonPrimitive(BuildConfig.VERSION_CODE),
|
|
|
|
exportCount = taskIds.size
|
|
|
|
"timestamp" to JsonPrimitive(currentTimeMillis()),
|
|
|
|
|
|
|
|
"data" to Json.encodeToJsonElement(
|
|
|
|
|
|
|
|
BackupContainer(
|
|
|
|
|
|
|
|
taskBackups,
|
|
|
|
|
|
|
|
locationDao.getPlaces(),
|
|
|
|
|
|
|
|
tagDataDao.getAll(),
|
|
|
|
|
|
|
|
filterDao.getFilters(),
|
|
|
|
|
|
|
|
caldavDao.getAccounts(),
|
|
|
|
|
|
|
|
caldavDao.getCalendars(),
|
|
|
|
|
|
|
|
taskListMetadataDao.getAll(),
|
|
|
|
|
|
|
|
taskAttachmentDao.getAttachments(),
|
|
|
|
|
|
|
|
preferences.getPrefs(Integer::class.java),
|
|
|
|
|
|
|
|
preferences.getPrefs(java.lang.Long::class.java),
|
|
|
|
|
|
|
|
preferences.getPrefs(String::class.java),
|
|
|
|
|
|
|
|
preferences.getPrefs(java.lang.Boolean::class.java),
|
|
|
|
|
|
|
|
preferences.getPrefs(java.util.Set::class.java) as Map<String, java.util.Set<String>>,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
val out = OutputStreamWriter(os, UTF_8)
|
|
|
|
|
|
|
|
val json = if (BuildConfig.DEBUG) Json { prettyPrint = true } else Json
|
|
|
|
|
|
|
|
out.write(json.encodeToString(data))
|
|
|
|
|
|
|
|
out.close()
|
|
|
|
|
|
|
|
exportCount = taskBackups.size
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun onFinishExport(outputFile: String) = post {
|
|
|
|
private fun onFinishExport(outputFile: String) = post {
|
|
|
|
@ -193,5 +187,12 @@ class TasksJsonExporter @Inject constructor(
|
|
|
|
private const val EXTENSION = ".json"
|
|
|
|
private const val EXTENSION = ".json"
|
|
|
|
private val dateForExport: String
|
|
|
|
private val dateForExport: String
|
|
|
|
get() = newDateTime().toString("yyyyMMdd'T'HHmm")
|
|
|
|
get() = newDateTime().toString("yyyyMMdd'T'HHmm")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class JsonWriter(val writer: Writer, val json: Json = Json) {
|
|
|
|
|
|
|
|
fun write(data: String) = writer.write(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline fun <reified T> write(key: String, value: @Serializable T, lastItem: Boolean = false) where T : Any =
|
|
|
|
|
|
|
|
writer.write("\"$key\":${json.encodeToString(value)}${if (lastItem) "" else ","}")
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|