mirror of https://github.com/tasks/tasks
Convert json import/export to Kotlin
parent
6d023fd700
commit
9d7df21deb
@ -1,159 +0,0 @@
|
|||||||
package org.tasks.backup;
|
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
|
||||||
import static java.util.Collections.emptyMap;
|
|
||||||
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.tasks.backup.TasksJsonImporter.LegacyLocation;
|
|
||||||
import org.tasks.data.Alarm;
|
|
||||||
import org.tasks.data.CaldavAccount;
|
|
||||||
import org.tasks.data.CaldavCalendar;
|
|
||||||
import org.tasks.data.CaldavTask;
|
|
||||||
import org.tasks.data.Filter;
|
|
||||||
import org.tasks.data.Geofence;
|
|
||||||
import org.tasks.data.GoogleTask;
|
|
||||||
import org.tasks.data.GoogleTaskAccount;
|
|
||||||
import org.tasks.data.GoogleTaskList;
|
|
||||||
import org.tasks.data.Place;
|
|
||||||
import org.tasks.data.Tag;
|
|
||||||
import org.tasks.data.TagData;
|
|
||||||
import org.tasks.data.TaskAttachment;
|
|
||||||
import org.tasks.data.UserActivity;
|
|
||||||
|
|
||||||
class BackupContainer {
|
|
||||||
|
|
||||||
private final List<TaskBackup> tasks;
|
|
||||||
private final List<Place> places;
|
|
||||||
private final List<TagData> tags;
|
|
||||||
private final List<Filter> filters;
|
|
||||||
private final List<GoogleTaskList> googleTaskLists;
|
|
||||||
private final List<GoogleTaskAccount> googleTaskAccounts;
|
|
||||||
private final List<CaldavAccount> caldavAccounts;
|
|
||||||
private final List<CaldavCalendar> caldavCalendars;
|
|
||||||
private final Map<String, Integer> intPrefs;
|
|
||||||
private final Map<String, Long> longPrefs;
|
|
||||||
private final Map<String, String> stringPrefs;
|
|
||||||
private final Map<String, Boolean> boolPrefs;
|
|
||||||
|
|
||||||
BackupContainer(
|
|
||||||
List<TaskBackup> tasks,
|
|
||||||
List<Place> places,
|
|
||||||
List<TagData> tags,
|
|
||||||
List<Filter> filters,
|
|
||||||
List<GoogleTaskAccount> googleTaskAccounts,
|
|
||||||
List<GoogleTaskList> googleTaskLists,
|
|
||||||
List<CaldavAccount> caldavAccounts,
|
|
||||||
List<CaldavCalendar> caldavCalendars,
|
|
||||||
Map<String, Integer> intPrefs,
|
|
||||||
Map<String, Long> longPrefs,
|
|
||||||
Map<String, String> stringPrefs,
|
|
||||||
Map<String, Boolean> boolPrefs) {
|
|
||||||
this.tasks = tasks;
|
|
||||||
this.places = places;
|
|
||||||
this.tags = tags;
|
|
||||||
this.filters = filters;
|
|
||||||
this.googleTaskAccounts = googleTaskAccounts;
|
|
||||||
this.googleTaskLists = googleTaskLists;
|
|
||||||
this.caldavAccounts = caldavAccounts;
|
|
||||||
this.caldavCalendars = caldavCalendars;
|
|
||||||
this.intPrefs = intPrefs;
|
|
||||||
this.longPrefs = longPrefs;
|
|
||||||
this.stringPrefs = stringPrefs;
|
|
||||||
this.boolPrefs = boolPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TaskBackup> getTasks() {
|
|
||||||
return tasks == null ? emptyList() : tasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TagData> getTags() {
|
|
||||||
return tags == null ? emptyList() : tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Filter> getFilters() {
|
|
||||||
return filters == null ? emptyList() : filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<GoogleTaskList> getGoogleTaskLists() {
|
|
||||||
return googleTaskLists == null ? emptyList() : googleTaskLists;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CaldavAccount> getCaldavAccounts() {
|
|
||||||
return caldavAccounts == null ? emptyList() : caldavAccounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CaldavCalendar> getCaldavCalendars() {
|
|
||||||
return caldavCalendars == null ? emptyList() : caldavCalendars;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<GoogleTaskAccount> getGoogleTaskAccounts() {
|
|
||||||
return googleTaskAccounts == null ? emptyList() : googleTaskAccounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Place> getPlaces() {
|
|
||||||
return places == null ? emptyList() : places;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Integer> getIntPrefs() {
|
|
||||||
return intPrefs == null ? emptyMap() : intPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Long> getLongPrefs() {
|
|
||||||
return longPrefs == null ? emptyMap() : longPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> getStringPrefs() {
|
|
||||||
return stringPrefs == null ? emptyMap() : stringPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Boolean> getBoolPrefs() {
|
|
||||||
return boolPrefs == null ? emptyMap() : boolPrefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TaskBackup {
|
|
||||||
|
|
||||||
final Task task;
|
|
||||||
final List<Alarm> alarms;
|
|
||||||
final List<LegacyLocation> locations;
|
|
||||||
final List<Tag> tags;
|
|
||||||
final List<GoogleTask> google;
|
|
||||||
final List<UserActivity> comments;
|
|
||||||
private final List<Geofence> geofences;
|
|
||||||
private final List<TaskAttachment> attachments;
|
|
||||||
private final List<CaldavTask> caldavTasks;
|
|
||||||
|
|
||||||
TaskBackup(
|
|
||||||
Task task,
|
|
||||||
List<Alarm> alarms,
|
|
||||||
List<Geofence> geofences,
|
|
||||||
List<Tag> tags,
|
|
||||||
List<GoogleTask> google,
|
|
||||||
List<UserActivity> comments,
|
|
||||||
List<TaskAttachment> attachments,
|
|
||||||
List<CaldavTask> caldavTasks) {
|
|
||||||
this.task = task;
|
|
||||||
this.alarms = alarms;
|
|
||||||
this.geofences = geofences;
|
|
||||||
this.tags = tags;
|
|
||||||
this.google = google;
|
|
||||||
this.comments = comments;
|
|
||||||
this.attachments = attachments;
|
|
||||||
this.caldavTasks = caldavTasks;
|
|
||||||
locations = emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TaskAttachment> getAttachments() {
|
|
||||||
return attachments == null ? emptyList() : attachments;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CaldavTask> getCaldavTasks() {
|
|
||||||
return caldavTasks == null ? emptyList() : caldavTasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Geofence> getGeofences() {
|
|
||||||
return geofences == null ? emptyList() : geofences;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package org.tasks.backup
|
||||||
|
|
||||||
|
import com.todoroo.astrid.data.Task
|
||||||
|
import org.tasks.backup.TasksJsonImporter.LegacyLocation
|
||||||
|
import org.tasks.data.*
|
||||||
|
|
||||||
|
class BackupContainer(
|
||||||
|
val tasks: List<TaskBackup>?,
|
||||||
|
val places: List<Place>?,
|
||||||
|
val tags: List<TagData>?,
|
||||||
|
val filters: List<Filter>?,
|
||||||
|
val googleTaskAccounts: List<GoogleTaskAccount>?,
|
||||||
|
val googleTaskLists: List<GoogleTaskList>?,
|
||||||
|
val caldavAccounts: List<CaldavAccount>?,
|
||||||
|
val caldavCalendars: List<CaldavCalendar>?,
|
||||||
|
val intPrefs: Map<String, Int>?,
|
||||||
|
val longPrefs: Map<String, Long>?,
|
||||||
|
val stringPrefs: Map<String, String>?,
|
||||||
|
val boolPrefs: Map<String, Boolean>?) {
|
||||||
|
|
||||||
|
class TaskBackup(
|
||||||
|
val task: Task,
|
||||||
|
val alarms: List<Alarm>,
|
||||||
|
val geofences: List<Geofence>?,
|
||||||
|
val tags: List<Tag>,
|
||||||
|
val google: List<GoogleTask>,
|
||||||
|
val comments: List<UserActivity>,
|
||||||
|
val attachments: List<TaskAttachment>?,
|
||||||
|
val caldavTasks: List<CaldavTask>?) {
|
||||||
|
|
||||||
|
val locations: List<LegacyLocation> = emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,266 +0,0 @@
|
|||||||
package org.tasks.backup;
|
|
||||||
|
|
||||||
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.app.backup.BackupManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import com.google.common.io.Files;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.todoroo.andlib.utility.DialogUtilities;
|
|
||||||
import com.todoroo.astrid.backup.BackupConstants;
|
|
||||||
import com.todoroo.astrid.dao.TaskDao;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.BuildConfig;
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.data.AlarmDao;
|
|
||||||
import org.tasks.data.CaldavDao;
|
|
||||||
import org.tasks.data.FilterDao;
|
|
||||||
import org.tasks.data.GoogleTaskDao;
|
|
||||||
import org.tasks.data.GoogleTaskListDao;
|
|
||||||
import org.tasks.data.LocationDao;
|
|
||||||
import org.tasks.data.TagDao;
|
|
||||||
import org.tasks.data.TagDataDao;
|
|
||||||
import org.tasks.data.TaskAttachmentDao;
|
|
||||||
import org.tasks.data.UserActivityDao;
|
|
||||||
import org.tasks.files.FileHelper;
|
|
||||||
import org.tasks.jobs.WorkManager;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public class TasksJsonExporter {
|
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed")
|
|
||||||
static final Charset UTF_8 = Charset.forName("UTF-8");
|
|
||||||
private static final String MIME = "application/json";
|
|
||||||
private static final String EXTENSION = ".json";
|
|
||||||
|
|
||||||
// --- public interface
|
|
||||||
private final TagDataDao tagDataDao;
|
|
||||||
|
|
||||||
// --- implementation
|
|
||||||
private final AlarmDao alarmDao;
|
|
||||||
private final LocationDao locationDao;
|
|
||||||
private final TagDao tagDao;
|
|
||||||
private final GoogleTaskDao googleTaskDao;
|
|
||||||
private final FilterDao filterDao;
|
|
||||||
private final GoogleTaskListDao googleTaskListDao;
|
|
||||||
private final TaskAttachmentDao taskAttachmentDao;
|
|
||||||
private final CaldavDao caldavDao;
|
|
||||||
private final WorkManager workManager;
|
|
||||||
private final TaskDao taskDao;
|
|
||||||
private final UserActivityDao userActivityDao;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private Context context;
|
|
||||||
private int exportCount = 0;
|
|
||||||
private ProgressDialog progressDialog;
|
|
||||||
private Handler handler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public TasksJsonExporter(
|
|
||||||
TagDataDao tagDataDao,
|
|
||||||
TaskDao taskDao,
|
|
||||||
UserActivityDao userActivityDao,
|
|
||||||
Preferences preferences,
|
|
||||||
AlarmDao alarmDao,
|
|
||||||
LocationDao locationDao,
|
|
||||||
TagDao tagDao,
|
|
||||||
GoogleTaskDao googleTaskDao,
|
|
||||||
FilterDao filterDao,
|
|
||||||
GoogleTaskListDao googleTaskListDao,
|
|
||||||
TaskAttachmentDao taskAttachmentDao,
|
|
||||||
CaldavDao caldavDao,
|
|
||||||
WorkManager workManager) {
|
|
||||||
this.tagDataDao = tagDataDao;
|
|
||||||
this.taskDao = taskDao;
|
|
||||||
this.userActivityDao = userActivityDao;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.alarmDao = alarmDao;
|
|
||||||
this.locationDao = locationDao;
|
|
||||||
this.tagDao = tagDao;
|
|
||||||
this.googleTaskDao = googleTaskDao;
|
|
||||||
this.filterDao = filterDao;
|
|
||||||
this.googleTaskListDao = googleTaskListDao;
|
|
||||||
this.taskAttachmentDao = taskAttachmentDao;
|
|
||||||
this.caldavDao = caldavDao;
|
|
||||||
this.workManager = workManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getDateForExport() {
|
|
||||||
return newDateTime().toString("yyMMdd-HHmm");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void post(Runnable runnable) {
|
|
||||||
if (handler != null) {
|
|
||||||
handler.post(runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setProgress(final int taskNumber, final int total) {
|
|
||||||
post(
|
|
||||||
() -> {
|
|
||||||
progressDialog.setMax(total);
|
|
||||||
progressDialog.setProgress(taskNumber);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void exportTasks(
|
|
||||||
final Context context,
|
|
||||||
final ExportType exportType,
|
|
||||||
@Nullable final ProgressDialog progressDialog) {
|
|
||||||
this.context = context;
|
|
||||||
this.exportCount = 0;
|
|
||||||
this.progressDialog = progressDialog;
|
|
||||||
|
|
||||||
if (exportType == ExportType.EXPORT_TYPE_MANUAL) {
|
|
||||||
handler = new Handler();
|
|
||||||
new Thread(() -> runBackup(exportType)).start();
|
|
||||||
} else {
|
|
||||||
runBackup(exportType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runBackup(ExportType exportType) {
|
|
||||||
try {
|
|
||||||
String filename = getFileName(exportType);
|
|
||||||
List<Task> tasks = taskDao.getAll();
|
|
||||||
if (tasks.size() > 0) {
|
|
||||||
File file =
|
|
||||||
new File(
|
|
||||||
String.format("%s/%s", context.getFilesDir(), BackupConstants.INTERNAL_BACKUP));
|
|
||||||
file.delete();
|
|
||||||
file.createNewFile();
|
|
||||||
Uri internalStorageBackup = Uri.fromFile(file);
|
|
||||||
OutputStream os = context.getContentResolver().openOutputStream(internalStorageBackup);
|
|
||||||
doTasksExport(os, tasks);
|
|
||||||
os.close();
|
|
||||||
|
|
||||||
Uri externalStorageBackup =
|
|
||||||
FileHelper.newFile(
|
|
||||||
context,
|
|
||||||
preferences.getBackupDirectory(),
|
|
||||||
MIME,
|
|
||||||
Files.getNameWithoutExtension(filename),
|
|
||||||
EXTENSION);
|
|
||||||
|
|
||||||
FileHelper.copyStream(context, internalStorageBackup, externalStorageBackup);
|
|
||||||
|
|
||||||
workManager.scheduleDriveUpload(externalStorageBackup, exportType == ExportType.EXPORT_TYPE_SERVICE);
|
|
||||||
|
|
||||||
new BackupManager(context).dataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exportType == ExportType.EXPORT_TYPE_MANUAL) {
|
|
||||||
onFinishExport(filename);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Timber.e(e);
|
|
||||||
} finally {
|
|
||||||
post(
|
|
||||||
() -> {
|
|
||||||
if (progressDialog != null
|
|
||||||
&& progressDialog.isShowing()
|
|
||||||
&& context instanceof Activity) {
|
|
||||||
DialogUtilities.dismissDialog((Activity) context, progressDialog);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doTasksExport(OutputStream os, List<Task> tasks) throws IOException {
|
|
||||||
|
|
||||||
List<BackupContainer.TaskBackup> taskBackups = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Task task : tasks) {
|
|
||||||
setProgress(taskBackups.size(), tasks.size());
|
|
||||||
long taskId = task.getId();
|
|
||||||
taskBackups.add(
|
|
||||||
new BackupContainer.TaskBackup(
|
|
||||||
task,
|
|
||||||
alarmDao.getAlarms(taskId),
|
|
||||||
locationDao.getGeofencesForTask(taskId),
|
|
||||||
tagDao.getTagsForTask(taskId),
|
|
||||||
googleTaskDao.getAllByTaskId(taskId),
|
|
||||||
userActivityDao.getCommentsForTask(task.getUuid()),
|
|
||||||
taskAttachmentDao.getAttachments(task.getUuid()),
|
|
||||||
caldavDao.getTasks(taskId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
|
||||||
data.put("version", BuildConfig.VERSION_CODE);
|
|
||||||
data.put("timestamp", System.currentTimeMillis());
|
|
||||||
data.put(
|
|
||||||
"data",
|
|
||||||
new BackupContainer(
|
|
||||||
taskBackups,
|
|
||||||
locationDao.getPlaces(),
|
|
||||||
tagDataDao.getAll(),
|
|
||||||
filterDao.getAll(),
|
|
||||||
googleTaskListDao.getAccounts(),
|
|
||||||
googleTaskListDao.getAllLists(),
|
|
||||||
caldavDao.getAccounts(),
|
|
||||||
caldavDao.getCalendars(),
|
|
||||||
preferences.getPrefs(Integer.class),
|
|
||||||
preferences.getPrefs(Long.class),
|
|
||||||
preferences.getPrefs(String.class),
|
|
||||||
preferences.getPrefs(Boolean.class)));
|
|
||||||
|
|
||||||
OutputStreamWriter out = new OutputStreamWriter(os, UTF_8);
|
|
||||||
Gson gson = BuildConfig.DEBUG ? new GsonBuilder().setPrettyPrinting().create() : new Gson();
|
|
||||||
out.write(gson.toJson(data));
|
|
||||||
out.close();
|
|
||||||
exportCount = taskBackups.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFinishExport(final String outputFile) {
|
|
||||||
post(
|
|
||||||
() -> {
|
|
||||||
if (exportCount == 0) {
|
|
||||||
Toast.makeText(
|
|
||||||
context, context.getString(R.string.export_toast_no_tasks), Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
} else {
|
|
||||||
CharSequence text =
|
|
||||||
String.format(
|
|
||||||
context.getString(R.string.export_toast),
|
|
||||||
context
|
|
||||||
.getResources()
|
|
||||||
.getQuantityString(R.plurals.Ntasks, exportCount, exportCount),
|
|
||||||
outputFile);
|
|
||||||
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getFileName(ExportType type) {
|
|
||||||
switch (type) {
|
|
||||||
case EXPORT_TYPE_SERVICE:
|
|
||||||
return String.format(BackupConstants.BACKUP_FILE_NAME, getDateForExport());
|
|
||||||
case EXPORT_TYPE_MANUAL:
|
|
||||||
return String.format(BackupConstants.EXPORT_FILE_NAME, getDateForExport());
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unhandled export type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ExportType {
|
|
||||||
EXPORT_TYPE_SERVICE,
|
|
||||||
EXPORT_TYPE_MANUAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
package org.tasks.backup
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.ProgressDialog
|
||||||
|
import android.app.backup.BackupManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Handler
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.google.common.io.Files
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import com.todoroo.andlib.utility.DialogUtilities
|
||||||
|
import com.todoroo.astrid.backup.BackupConstants
|
||||||
|
import com.todoroo.astrid.dao.TaskDao
|
||||||
|
import com.todoroo.astrid.data.Task
|
||||||
|
import org.tasks.BuildConfig
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.backup.BackupContainer.TaskBackup
|
||||||
|
import org.tasks.data.*
|
||||||
|
import org.tasks.date.DateTimeUtils.newDateTime
|
||||||
|
import org.tasks.files.FileHelper
|
||||||
|
import org.tasks.jobs.WorkManager
|
||||||
|
import org.tasks.preferences.Preferences
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.io.OutputStreamWriter
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class TasksJsonExporter @Inject constructor(
|
||||||
|
private val tagDataDao: TagDataDao,
|
||||||
|
private val taskDao: TaskDao,
|
||||||
|
private val userActivityDao: UserActivityDao,
|
||||||
|
private val preferences: Preferences,
|
||||||
|
private val alarmDao: AlarmDao,
|
||||||
|
private val locationDao: LocationDao,
|
||||||
|
private val tagDao: TagDao,
|
||||||
|
private val googleTaskDao: GoogleTaskDao,
|
||||||
|
private val filterDao: FilterDao,
|
||||||
|
private val googleTaskListDao: GoogleTaskListDao,
|
||||||
|
private val taskAttachmentDao: TaskAttachmentDao,
|
||||||
|
private val caldavDao: CaldavDao,
|
||||||
|
private val workManager: WorkManager) {
|
||||||
|
|
||||||
|
private var context: Context? = null
|
||||||
|
private var exportCount = 0
|
||||||
|
private var progressDialog: ProgressDialog? = null
|
||||||
|
private var handler: Handler? = null
|
||||||
|
|
||||||
|
private fun post(runnable: () -> Unit) = handler?.post(runnable)
|
||||||
|
|
||||||
|
private fun setProgress(taskNumber: Int, total: Int) = post {
|
||||||
|
progressDialog?.max = total
|
||||||
|
progressDialog?.progress = taskNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exportTasks(context: Context?, exportType: ExportType, progressDialog: ProgressDialog?) {
|
||||||
|
this.context = context
|
||||||
|
exportCount = 0
|
||||||
|
this.progressDialog = progressDialog
|
||||||
|
if (exportType == ExportType.EXPORT_TYPE_MANUAL) {
|
||||||
|
handler = Handler()
|
||||||
|
Thread(Runnable { runBackup(exportType) }).start()
|
||||||
|
} else {
|
||||||
|
runBackup(exportType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runBackup(exportType: ExportType) {
|
||||||
|
try {
|
||||||
|
val filename = getFileName(exportType)
|
||||||
|
val tasks = taskDao.getAll()
|
||||||
|
if (tasks.isNotEmpty()) {
|
||||||
|
val file = File(String.format("%s/%s", context!!.filesDir, BackupConstants.INTERNAL_BACKUP))
|
||||||
|
file.delete()
|
||||||
|
file.createNewFile()
|
||||||
|
val internalStorageBackup = Uri.fromFile(file)
|
||||||
|
val os = context!!.contentResolver.openOutputStream(internalStorageBackup)
|
||||||
|
doTasksExport(os, tasks)
|
||||||
|
os!!.close()
|
||||||
|
val externalStorageBackup = FileHelper.newFile(
|
||||||
|
context,
|
||||||
|
preferences.backupDirectory,
|
||||||
|
MIME,
|
||||||
|
Files.getNameWithoutExtension(filename),
|
||||||
|
EXTENSION)
|
||||||
|
FileHelper.copyStream(context, internalStorageBackup, externalStorageBackup)
|
||||||
|
workManager.scheduleDriveUpload(externalStorageBackup, exportType == ExportType.EXPORT_TYPE_SERVICE)
|
||||||
|
BackupManager(context).dataChanged()
|
||||||
|
}
|
||||||
|
if (exportType == ExportType.EXPORT_TYPE_MANUAL) {
|
||||||
|
onFinishExport(filename)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Timber.e(e)
|
||||||
|
} finally {
|
||||||
|
post {
|
||||||
|
if (progressDialog != null && progressDialog!!.isShowing
|
||||||
|
&& context is Activity) {
|
||||||
|
DialogUtilities.dismissDialog(context as Activity?, progressDialog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun doTasksExport(os: OutputStream?, tasks: List<Task>) {
|
||||||
|
val taskBackups: MutableList<TaskBackup> = ArrayList()
|
||||||
|
for (task in tasks) {
|
||||||
|
setProgress(taskBackups.size, tasks.size)
|
||||||
|
val taskId = task.id
|
||||||
|
taskBackups.add(
|
||||||
|
TaskBackup(
|
||||||
|
task,
|
||||||
|
alarmDao.getAlarms(taskId),
|
||||||
|
locationDao.getGeofencesForTask(taskId),
|
||||||
|
tagDao.getTagsForTask(taskId),
|
||||||
|
googleTaskDao.getAllByTaskId(taskId),
|
||||||
|
userActivityDao.getCommentsForTask(task.uuid),
|
||||||
|
taskAttachmentDao.getAttachments(task.uuid),
|
||||||
|
caldavDao.getTasks(taskId)))
|
||||||
|
}
|
||||||
|
val data: MutableMap<String, Any> = HashMap()
|
||||||
|
data["version"] = BuildConfig.VERSION_CODE
|
||||||
|
data["timestamp"] = System.currentTimeMillis()
|
||||||
|
data["data"] = BackupContainer(
|
||||||
|
taskBackups,
|
||||||
|
locationDao.getPlaces(),
|
||||||
|
tagDataDao.getAll(),
|
||||||
|
filterDao.getAll(),
|
||||||
|
googleTaskListDao.getAccounts(),
|
||||||
|
googleTaskListDao.getAllLists(),
|
||||||
|
caldavDao.getAccounts(),
|
||||||
|
caldavDao.getCalendars(),
|
||||||
|
preferences.getPrefs(Int::class.java),
|
||||||
|
preferences.getPrefs(Long::class.java),
|
||||||
|
preferences.getPrefs(String::class.java),
|
||||||
|
preferences.getPrefs(Boolean::class.java))
|
||||||
|
val out = OutputStreamWriter(os, UTF_8)
|
||||||
|
val gson = if (BuildConfig.DEBUG) GsonBuilder().setPrettyPrinting().create() else Gson()
|
||||||
|
out.write(gson.toJson(data))
|
||||||
|
out.close()
|
||||||
|
exportCount = taskBackups.size
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onFinishExport(outputFile: String) = post {
|
||||||
|
if (exportCount == 0) {
|
||||||
|
Toast.makeText(
|
||||||
|
context, context!!.getString(R.string.export_toast_no_tasks), Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
val text: CharSequence = String.format(
|
||||||
|
context!!.getString(R.string.export_toast),
|
||||||
|
context!!
|
||||||
|
.resources
|
||||||
|
.getQuantityString(R.plurals.Ntasks, exportCount, exportCount),
|
||||||
|
outputFile)
|
||||||
|
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getFileName(type: ExportType): String {
|
||||||
|
return when (type) {
|
||||||
|
ExportType.EXPORT_TYPE_SERVICE -> String.format(BackupConstants.BACKUP_FILE_NAME, dateForExport)
|
||||||
|
ExportType.EXPORT_TYPE_MANUAL -> String.format(BackupConstants.EXPORT_FILE_NAME, dateForExport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ExportType {
|
||||||
|
EXPORT_TYPE_SERVICE, EXPORT_TYPE_MANUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val UTF_8: Charset = Charset.forName("UTF-8")
|
||||||
|
private const val MIME = "application/json"
|
||||||
|
private const val EXTENSION = ".json"
|
||||||
|
private val dateForExport: String
|
||||||
|
get() = newDateTime().toString("yyMMdd-HHmm")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,300 +0,0 @@
|
|||||||
package org.tasks.backup;
|
|
||||||
|
|
||||||
import static org.tasks.backup.TasksJsonExporter.UTF_8;
|
|
||||||
import static org.tasks.data.Place.newPlace;
|
|
||||||
import static org.tasks.preferences.Preferences.P_CURRENT_VERSION;
|
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Handler;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.todoroo.astrid.dao.TaskDao;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import com.todoroo.astrid.service.TaskMover;
|
|
||||||
import com.todoroo.astrid.service.Upgrader;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.LocalBroadcastManager;
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.data.Alarm;
|
|
||||||
import org.tasks.data.AlarmDao;
|
|
||||||
import org.tasks.data.CaldavAccount;
|
|
||||||
import org.tasks.data.CaldavCalendar;
|
|
||||||
import org.tasks.data.CaldavDao;
|
|
||||||
import org.tasks.data.CaldavTask;
|
|
||||||
import org.tasks.data.Filter;
|
|
||||||
import org.tasks.data.FilterDao;
|
|
||||||
import org.tasks.data.Geofence;
|
|
||||||
import org.tasks.data.GoogleTask;
|
|
||||||
import org.tasks.data.GoogleTaskAccount;
|
|
||||||
import org.tasks.data.GoogleTaskDao;
|
|
||||||
import org.tasks.data.GoogleTaskList;
|
|
||||||
import org.tasks.data.GoogleTaskListDao;
|
|
||||||
import org.tasks.data.LocationDao;
|
|
||||||
import org.tasks.data.Place;
|
|
||||||
import org.tasks.data.Tag;
|
|
||||||
import org.tasks.data.TagDao;
|
|
||||||
import org.tasks.data.TagData;
|
|
||||||
import org.tasks.data.TagDataDao;
|
|
||||||
import org.tasks.data.TaskAttachment;
|
|
||||||
import org.tasks.data.TaskAttachmentDao;
|
|
||||||
import org.tasks.data.UserActivity;
|
|
||||||
import org.tasks.data.UserActivityDao;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public class TasksJsonImporter {
|
|
||||||
|
|
||||||
private final TagDataDao tagDataDao;
|
|
||||||
private final UserActivityDao userActivityDao;
|
|
||||||
private final TaskDao taskDao;
|
|
||||||
private final LocalBroadcastManager localBroadcastManager;
|
|
||||||
private final AlarmDao alarmDao;
|
|
||||||
private final TagDao tagDao;
|
|
||||||
private final GoogleTaskDao googleTaskDao;
|
|
||||||
private final GoogleTaskListDao googleTaskListDao;
|
|
||||||
private final FilterDao filterDao;
|
|
||||||
private final TaskAttachmentDao taskAttachmentDao;
|
|
||||||
private final CaldavDao caldavDao;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final TaskMover taskMover;
|
|
||||||
private final LocationDao locationDao;
|
|
||||||
|
|
||||||
private final ImportResult result = new ImportResult();
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public TasksJsonImporter(
|
|
||||||
TagDataDao tagDataDao,
|
|
||||||
UserActivityDao userActivityDao,
|
|
||||||
TaskDao taskDao,
|
|
||||||
LocationDao locationDao,
|
|
||||||
LocalBroadcastManager localBroadcastManager,
|
|
||||||
AlarmDao alarmDao,
|
|
||||||
TagDao tagDao,
|
|
||||||
GoogleTaskDao googleTaskDao,
|
|
||||||
GoogleTaskListDao googleTaskListDao,
|
|
||||||
FilterDao filterDao,
|
|
||||||
TaskAttachmentDao taskAttachmentDao,
|
|
||||||
CaldavDao caldavDao,
|
|
||||||
Preferences preferences,
|
|
||||||
TaskMover taskMover) {
|
|
||||||
this.tagDataDao = tagDataDao;
|
|
||||||
this.userActivityDao = userActivityDao;
|
|
||||||
this.taskDao = taskDao;
|
|
||||||
this.locationDao = locationDao;
|
|
||||||
this.localBroadcastManager = localBroadcastManager;
|
|
||||||
this.alarmDao = alarmDao;
|
|
||||||
this.tagDao = tagDao;
|
|
||||||
this.googleTaskDao = googleTaskDao;
|
|
||||||
this.googleTaskListDao = googleTaskListDao;
|
|
||||||
this.filterDao = filterDao;
|
|
||||||
this.taskAttachmentDao = taskAttachmentDao;
|
|
||||||
this.caldavDao = caldavDao;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.taskMover = taskMover;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setProgressMessage(
|
|
||||||
Handler handler, ProgressDialog progressDialog, final String message) {
|
|
||||||
if (progressDialog == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.post(() -> progressDialog.setMessage(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImportResult importTasks(Context context, Uri backupFile, @Nullable ProgressDialog progressDialog) {
|
|
||||||
Handler handler = new Handler(context.getMainLooper());
|
|
||||||
Gson gson = new Gson();
|
|
||||||
InputStream is;
|
|
||||||
try {
|
|
||||||
is = context.getContentResolver().openInputStream(backupFile);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
InputStreamReader reader = new InputStreamReader(is, UTF_8);
|
|
||||||
JsonObject input = gson.fromJson(reader, JsonObject.class);
|
|
||||||
|
|
||||||
try {
|
|
||||||
JsonElement data = input.get("data");
|
|
||||||
int version = input.get("version").getAsInt();
|
|
||||||
BackupContainer backupContainer = gson.fromJson(data, BackupContainer.class);
|
|
||||||
for (TagData tagData : backupContainer.getTags()) {
|
|
||||||
tagData.setColor(themeToColor(context, version, tagData.getColor()));
|
|
||||||
if (tagDataDao.getByUuid(tagData.getRemoteId()) == null) {
|
|
||||||
tagDataDao.createNew(tagData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (GoogleTaskAccount googleTaskAccount : backupContainer.getGoogleTaskAccounts()) {
|
|
||||||
if (googleTaskListDao.getAccount(googleTaskAccount.getAccount()) == null) {
|
|
||||||
googleTaskListDao.insert(googleTaskAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Place place : backupContainer.getPlaces()) {
|
|
||||||
if (locationDao.getByUid(place.getUid()) == null) {
|
|
||||||
locationDao.insert(place);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (GoogleTaskList googleTaskList : backupContainer.getGoogleTaskLists()) {
|
|
||||||
googleTaskList.setColor(themeToColor(context, version, googleTaskList.getColor()));
|
|
||||||
if (googleTaskListDao.getByRemoteId(googleTaskList.getRemoteId()) == null) {
|
|
||||||
googleTaskListDao.insert(googleTaskList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Filter filter : backupContainer.getFilters()) {
|
|
||||||
filter.setColor(themeToColor(context, version, filter.getColor()));
|
|
||||||
if (filterDao.getByName(filter.getTitle()) == null) {
|
|
||||||
filterDao.insert(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (CaldavAccount account : backupContainer.getCaldavAccounts()) {
|
|
||||||
if (caldavDao.getAccountByUuid(account.getUuid()) == null) {
|
|
||||||
caldavDao.insert(account);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (CaldavCalendar calendar : backupContainer.getCaldavCalendars()) {
|
|
||||||
calendar.setColor(themeToColor(context, version, calendar.getColor()));
|
|
||||||
if (caldavDao.getCalendarByUuid(calendar.getUuid()) == null) {
|
|
||||||
caldavDao.insert(calendar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (BackupContainer.TaskBackup backup : backupContainer.getTasks()) {
|
|
||||||
result.taskCount++;
|
|
||||||
setProgressMessage(
|
|
||||||
handler,
|
|
||||||
progressDialog,
|
|
||||||
context.getString(R.string.import_progress_read, result.taskCount));
|
|
||||||
Task task = backup.task;
|
|
||||||
if (taskDao.fetch(task.getUuid()) != null) {
|
|
||||||
result.skipCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
task.suppressRefresh();
|
|
||||||
task.suppressSync();
|
|
||||||
taskDao.createNew(task);
|
|
||||||
long taskId = task.getId();
|
|
||||||
String taskUuid = task.getUuid();
|
|
||||||
for (Alarm alarm : backup.alarms) {
|
|
||||||
alarm.setTask(taskId);
|
|
||||||
alarmDao.insert(alarm);
|
|
||||||
}
|
|
||||||
for (UserActivity comment : backup.comments) {
|
|
||||||
comment.setTargetId(taskUuid);
|
|
||||||
if (version < 546) {
|
|
||||||
comment.convertPictureUri();
|
|
||||||
}
|
|
||||||
userActivityDao.createNew(comment);
|
|
||||||
}
|
|
||||||
for (GoogleTask googleTask : backup.google) {
|
|
||||||
googleTask.setTask(taskId);
|
|
||||||
googleTaskDao.insert(googleTask);
|
|
||||||
}
|
|
||||||
for (LegacyLocation location : backup.locations) {
|
|
||||||
Place place = newPlace();
|
|
||||||
place.setLongitude(location.longitude);
|
|
||||||
place.setLatitude(location.latitude);
|
|
||||||
place.setName(location.name);
|
|
||||||
place.setAddress(location.address);
|
|
||||||
place.setUrl(location.url);
|
|
||||||
place.setPhone(location.phone);
|
|
||||||
locationDao.insert(place);
|
|
||||||
Geofence geofence = new Geofence();
|
|
||||||
geofence.setTask(taskId);
|
|
||||||
geofence.setPlace(place.getUid());
|
|
||||||
geofence.setRadius(location.radius);
|
|
||||||
geofence.setArrival(location.arrival);
|
|
||||||
geofence.setDeparture(location.departure);
|
|
||||||
locationDao.insert(geofence);
|
|
||||||
}
|
|
||||||
for (Tag tag : backup.tags) {
|
|
||||||
tag.setTask(taskId);
|
|
||||||
tag.setTaskUid(taskUuid);
|
|
||||||
tagDao.insert(tag);
|
|
||||||
}
|
|
||||||
for (Geofence geofence : backup.getGeofences()) {
|
|
||||||
geofence.setTask(taskId);
|
|
||||||
locationDao.insert(geofence);
|
|
||||||
}
|
|
||||||
for (TaskAttachment attachment : backup.getAttachments()) {
|
|
||||||
attachment.setTaskId(taskUuid);
|
|
||||||
if (version < 546) {
|
|
||||||
attachment.convertPathUri();
|
|
||||||
}
|
|
||||||
taskAttachmentDao.insert(attachment);
|
|
||||||
}
|
|
||||||
for (CaldavTask caldavTask : backup.getCaldavTasks()) {
|
|
||||||
caldavTask.setTask(taskId);
|
|
||||||
caldavDao.insert(caldavTask);
|
|
||||||
}
|
|
||||||
result.importCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
googleTaskDao.updateParents();
|
|
||||||
caldavDao.updateParents();
|
|
||||||
|
|
||||||
for (Entry<String, Integer> entry : backupContainer.getIntPrefs().entrySet()) {
|
|
||||||
if (P_CURRENT_VERSION.equals(entry.getKey())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
preferences.setInt(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
for (Entry<String, Long> entry : backupContainer.getLongPrefs().entrySet()) {
|
|
||||||
preferences.setLong(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
for (Entry<String, String> entry : backupContainer.getStringPrefs().entrySet()) {
|
|
||||||
preferences.setString(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
for (Entry<String, Boolean> entry : backupContainer.getBoolPrefs().entrySet()) {
|
|
||||||
preferences.setBoolean(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version < Upgrader.V8_2) {
|
|
||||||
int themeIndex = preferences.getInt(R.string.p_theme_color, 7);
|
|
||||||
preferences.setInt(
|
|
||||||
R.string.p_theme_color,
|
|
||||||
Upgrader.getAndroidColor(context, themeIndex));
|
|
||||||
}
|
|
||||||
if (version < Upgrader.V9_6) {
|
|
||||||
taskMover.migrateLocalTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.close();
|
|
||||||
is.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Timber.e(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
localBroadcastManager.broadcastRefresh();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int themeToColor(Context context, int version, int color) {
|
|
||||||
return version < Upgrader.V8_2 ? Upgrader.getAndroidColor(context, color) : color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ImportResult {
|
|
||||||
public int taskCount;
|
|
||||||
public int importCount;
|
|
||||||
public int skipCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class LegacyLocation {
|
|
||||||
String name;
|
|
||||||
String address;
|
|
||||||
String phone;
|
|
||||||
String url;
|
|
||||||
double latitude;
|
|
||||||
double longitude;
|
|
||||||
int radius;
|
|
||||||
boolean arrival;
|
|
||||||
boolean departure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,230 @@
|
|||||||
|
package org.tasks.backup
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Handler
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.todoroo.astrid.dao.TaskDao
|
||||||
|
import com.todoroo.astrid.service.TaskMover
|
||||||
|
import com.todoroo.astrid.service.Upgrader
|
||||||
|
import com.todoroo.astrid.service.Upgrader.Companion.getAndroidColor
|
||||||
|
import org.tasks.LocalBroadcastManager
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.data.*
|
||||||
|
import org.tasks.data.Place.Companion.newPlace
|
||||||
|
import org.tasks.preferences.Preferences
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class TasksJsonImporter @Inject constructor(
|
||||||
|
private val tagDataDao: TagDataDao,
|
||||||
|
private val userActivityDao: UserActivityDao,
|
||||||
|
private val taskDao: TaskDao,
|
||||||
|
private val locationDao: LocationDao,
|
||||||
|
private val localBroadcastManager: LocalBroadcastManager,
|
||||||
|
private val alarmDao: AlarmDao,
|
||||||
|
private val tagDao: TagDao,
|
||||||
|
private val googleTaskDao: GoogleTaskDao,
|
||||||
|
private val googleTaskListDao: GoogleTaskListDao,
|
||||||
|
private val filterDao: FilterDao,
|
||||||
|
private val taskAttachmentDao: TaskAttachmentDao,
|
||||||
|
private val caldavDao: CaldavDao,
|
||||||
|
private val preferences: Preferences,
|
||||||
|
private val taskMover: TaskMover) {
|
||||||
|
|
||||||
|
private val result = ImportResult()
|
||||||
|
|
||||||
|
private fun setProgressMessage(
|
||||||
|
handler: Handler, progressDialog: ProgressDialog?, message: String) {
|
||||||
|
if (progressDialog == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler.post { progressDialog.setMessage(message) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importTasks(context: Context, backupFile: Uri?, progressDialog: ProgressDialog?): ImportResult {
|
||||||
|
val handler = Handler(context.mainLooper)
|
||||||
|
val gson = Gson()
|
||||||
|
val `is`: InputStream?
|
||||||
|
`is` = try {
|
||||||
|
context.contentResolver.openInputStream(backupFile!!)
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
throw IllegalStateException(e)
|
||||||
|
}
|
||||||
|
val reader = InputStreamReader(`is`, TasksJsonExporter.UTF_8)
|
||||||
|
val input = gson.fromJson(reader, JsonObject::class.java)
|
||||||
|
try {
|
||||||
|
val data = input["data"]
|
||||||
|
val version = input["version"].asInt
|
||||||
|
val backupContainer = gson.fromJson(data, BackupContainer::class.java)
|
||||||
|
backupContainer.tags?.forEach { tagData ->
|
||||||
|
tagData.setColor(themeToColor(context, version, tagData.getColor()!!))
|
||||||
|
if (tagDataDao.getByUuid(tagData.remoteId!!) == null) {
|
||||||
|
tagDataDao.createNew(tagData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.googleTaskAccounts?.forEach { googleTaskAccount ->
|
||||||
|
if (googleTaskListDao.getAccount(googleTaskAccount.account!!) == null) {
|
||||||
|
googleTaskListDao.insert(googleTaskAccount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.places?.forEach { place ->
|
||||||
|
if (locationDao.getByUid(place.uid!!) == null) {
|
||||||
|
locationDao.insert(place)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.googleTaskLists?.forEach { googleTaskList ->
|
||||||
|
googleTaskList.setColor(themeToColor(context, version, googleTaskList.getColor()!!))
|
||||||
|
if (googleTaskListDao.getByRemoteId(googleTaskList.remoteId!!) == null) {
|
||||||
|
googleTaskListDao.insert(googleTaskList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.filters?.forEach { filter ->
|
||||||
|
filter.setColor(themeToColor(context, version, filter.getColor()!!))
|
||||||
|
if (filterDao.getByName(filter.title!!) == null) {
|
||||||
|
filterDao.insert(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.caldavAccounts?.forEach { account ->
|
||||||
|
if (caldavDao.getAccountByUuid(account.uuid!!) == null) {
|
||||||
|
caldavDao.insert(account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.caldavCalendars?.forEach { calendar ->
|
||||||
|
calendar.color = themeToColor(context, version, calendar.color)
|
||||||
|
if (caldavDao.getCalendarByUuid(calendar.uuid!!) == null) {
|
||||||
|
caldavDao.insert(calendar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupContainer.tasks?.forEach { backup ->
|
||||||
|
result.taskCount++
|
||||||
|
setProgressMessage(
|
||||||
|
handler,
|
||||||
|
progressDialog,
|
||||||
|
context.getString(R.string.import_progress_read, result.taskCount))
|
||||||
|
val task = backup.task
|
||||||
|
if (taskDao.fetch(task.uuid) != null) {
|
||||||
|
result.skipCount++
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
task.suppressRefresh()
|
||||||
|
task.suppressSync()
|
||||||
|
taskDao.createNew(task)
|
||||||
|
val taskId = task.id
|
||||||
|
val taskUuid = task.uuid
|
||||||
|
for (alarm in backup.alarms) {
|
||||||
|
alarm.task = taskId
|
||||||
|
alarmDao.insert(alarm)
|
||||||
|
}
|
||||||
|
for (comment in backup.comments) {
|
||||||
|
comment.targetId = taskUuid
|
||||||
|
if (version < 546) {
|
||||||
|
comment.convertPictureUri()
|
||||||
|
}
|
||||||
|
userActivityDao.createNew(comment)
|
||||||
|
}
|
||||||
|
for (googleTask in backup.google) {
|
||||||
|
googleTask.task = taskId
|
||||||
|
googleTaskDao.insert(googleTask)
|
||||||
|
}
|
||||||
|
for (location in backup.locations) {
|
||||||
|
val place = newPlace()
|
||||||
|
place.longitude = location.longitude
|
||||||
|
place.latitude = location.latitude
|
||||||
|
place.name = location.name
|
||||||
|
place.address = location.address
|
||||||
|
place.url = location.url
|
||||||
|
place.phone = location.phone
|
||||||
|
locationDao.insert(place)
|
||||||
|
val geofence = Geofence()
|
||||||
|
geofence.task = taskId
|
||||||
|
geofence.place = place.uid
|
||||||
|
geofence.radius = location.radius
|
||||||
|
geofence.isArrival = location.arrival
|
||||||
|
geofence.isDeparture = location.departure
|
||||||
|
locationDao.insert(geofence)
|
||||||
|
}
|
||||||
|
for (tag in backup.tags) {
|
||||||
|
tag.task = taskId
|
||||||
|
tag.setTaskUid(taskUuid)
|
||||||
|
tagDao.insert(tag)
|
||||||
|
}
|
||||||
|
backup.geofences?.forEach { geofence ->
|
||||||
|
geofence.task = taskId
|
||||||
|
locationDao.insert(geofence)
|
||||||
|
}
|
||||||
|
backup.attachments?.forEach { attachment ->
|
||||||
|
attachment.taskId = taskUuid
|
||||||
|
if (version < 546) {
|
||||||
|
attachment.convertPathUri()
|
||||||
|
}
|
||||||
|
taskAttachmentDao.insert(attachment)
|
||||||
|
}
|
||||||
|
backup.caldavTasks?.forEach { caldavTask ->
|
||||||
|
caldavTask.task = taskId
|
||||||
|
caldavDao.insert(caldavTask)
|
||||||
|
}
|
||||||
|
result.importCount++
|
||||||
|
}
|
||||||
|
googleTaskDao.updateParents()
|
||||||
|
caldavDao.updateParents()
|
||||||
|
backupContainer.intPrefs?.forEach { (key, value) ->
|
||||||
|
if (Preferences.P_CURRENT_VERSION == key) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
preferences.setInt(key, value)
|
||||||
|
}
|
||||||
|
backupContainer.longPrefs?.forEach { (key, value) ->
|
||||||
|
preferences.setLong(key, value)
|
||||||
|
}
|
||||||
|
backupContainer.stringPrefs?.forEach { (key, value) ->
|
||||||
|
preferences.setString(key, value)
|
||||||
|
}
|
||||||
|
backupContainer.boolPrefs?.forEach { (key, value) ->
|
||||||
|
preferences.setBoolean(key, value)
|
||||||
|
}
|
||||||
|
if (version < Upgrader.V8_2) {
|
||||||
|
val themeIndex = preferences.getInt(R.string.p_theme_color, 7)
|
||||||
|
preferences.setInt(
|
||||||
|
R.string.p_theme_color,
|
||||||
|
getAndroidColor(context, themeIndex))
|
||||||
|
}
|
||||||
|
if (version < Upgrader.V9_6) {
|
||||||
|
taskMover.migrateLocalTasks()
|
||||||
|
}
|
||||||
|
reader.close()
|
||||||
|
`is`!!.close()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
localBroadcastManager.broadcastRefresh()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun themeToColor(context: Context, version: Int, color: Int) =
|
||||||
|
if (version < Upgrader.V8_2) getAndroidColor(context, color) else color
|
||||||
|
|
||||||
|
class ImportResult {
|
||||||
|
var taskCount = 0
|
||||||
|
var importCount = 0
|
||||||
|
var skipCount = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class LegacyLocation {
|
||||||
|
var name: String? = null
|
||||||
|
var address: String? = null
|
||||||
|
var phone: String? = null
|
||||||
|
var url: String? = null
|
||||||
|
var latitude = 0.0
|
||||||
|
var longitude = 0.0
|
||||||
|
var radius = 0
|
||||||
|
var arrival = false
|
||||||
|
var departure = false
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue