Use non-blocking daos in json importer

pull/1052/head
Alex Baker 4 years ago
parent 523893a2d9
commit e65a855b02

@ -1,59 +0,0 @@
package org.tasks.backup;
import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.FileBackupHelper;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import com.todoroo.astrid.backup.BackupConstants;
import dagger.hilt.EntryPoint;
import dagger.hilt.InstallIn;
import dagger.hilt.android.EntryPointAccessors;
import dagger.hilt.android.components.ApplicationComponent;
import java.io.File;
import java.io.IOException;
import timber.log.Timber;
public class TasksBackupAgent extends BackupAgentHelper {
@EntryPoint
@InstallIn(ApplicationComponent.class)
interface TasksBackupAgentEntryPoint {
TasksJsonImporter getTasksJsonImporter();
}
private static final String BACKUP_KEY = "backup";
private TasksJsonImporter importer;
@Override
public void onCreate() {
TasksBackupAgentEntryPoint hilt =
EntryPointAccessors.fromApplication(getApplicationContext(), TasksBackupAgentEntryPoint.class);
importer = hilt.getTasksJsonImporter();
addHelper(BACKUP_KEY, new FileBackupHelper(this, BackupConstants.INTERNAL_BACKUP));
}
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
super.onRestore(data, appVersionCode, newState);
File backup =
new File(
String.format(
"%s/%s", getFilesDir().getAbsolutePath(), BackupConstants.INTERNAL_BACKUP));
if (backup.exists()) {
importer.importTasks(this, Uri.fromFile(backup), null);
} else {
Timber.w("%s not found", backup.getAbsolutePath());
}
}
@Override
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
Timber.e("onQuotaExceeded(%s, %s)", backupDataBytes, quotaBytes);
}
}

@ -0,0 +1,54 @@
package org.tasks.backup
import android.app.backup.BackupAgentHelper
import android.app.backup.BackupDataInput
import android.app.backup.FileBackupHelper
import android.net.Uri
import android.os.ParcelFileDescriptor
import com.todoroo.astrid.backup.BackupConstants
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.android.components.ApplicationComponent
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import java.io.File
import java.io.IOException
class TasksBackupAgent : BackupAgentHelper() {
@EntryPoint
@InstallIn(ApplicationComponent::class)
internal interface TasksBackupAgentEntryPoint {
val tasksJsonImporter: TasksJsonImporter
}
private lateinit var importer: TasksJsonImporter
override fun onCreate() {
val hilt = EntryPointAccessors.fromApplication(applicationContext, TasksBackupAgentEntryPoint::class.java)
importer = hilt.tasksJsonImporter
addHelper(BACKUP_KEY, FileBackupHelper(this, BackupConstants.INTERNAL_BACKUP))
}
@Throws(IOException::class)
override fun onRestore(data: BackupDataInput, appVersionCode: Int, newState: ParcelFileDescriptor) {
super.onRestore(data, appVersionCode, newState)
val backup = File(String.format(
"%s/%s", filesDir.absolutePath, BackupConstants.INTERNAL_BACKUP))
if (backup.exists()) {
runBlocking {
importer.importTasks(this@TasksBackupAgent, Uri.fromFile(backup), null)
}
} else {
Timber.w("%s not found", backup.absolutePath)
}
}
override fun onQuotaExceeded(backupDataBytes: Long, quotaBytes: Long) {
Timber.e("onQuotaExceeded(%s, %s)", backupDataBytes, quotaBytes)
}
companion object {
private const val BACKUP_KEY = "backup"
}
}

@ -6,7 +6,7 @@ import android.net.Uri
import android.os.Handler
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.todoroo.astrid.dao.TaskDaoBlocking
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
@ -23,21 +23,21 @@ import java.io.InputStreamReader
import javax.inject.Inject
class TasksJsonImporter @Inject constructor(
private val tagDataDao: TagDataDaoBlocking,
private val userActivityDao: UserActivityDaoBlocking,
private val taskDao: TaskDaoBlocking,
private val locationDao: LocationDaoBlocking,
private val tagDataDao: TagDataDao,
private val userActivityDao: UserActivityDao,
private val taskDao: TaskDao,
private val locationDao: LocationDao,
private val localBroadcastManager: LocalBroadcastManager,
private val alarmDao: AlarmDaoBlocking,
private val tagDao: TagDaoBlocking,
private val googleTaskDao: GoogleTaskDaoBlocking,
private val googleTaskListDao: GoogleTaskListDaoBlocking,
private val filterDao: FilterDaoBlocking,
private val taskAttachmentDao: TaskAttachmentDaoBlocking,
private val caldavDao: CaldavDaoBlocking,
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 taskListMetadataDao: TaskListMetadataDaoBlocking) {
private val taskListMetadataDao: TaskListMetadataDao) {
private val result = ImportResult()
@ -49,7 +49,7 @@ class TasksJsonImporter @Inject constructor(
handler.post { progressDialog.setMessage(message) }
}
fun importTasks(context: Context, backupFile: Uri?, progressDialog: ProgressDialog?): ImportResult {
suspend fun importTasks(context: Context, backupFile: Uri?, progressDialog: ProgressDialog?): ImportResult {
val handler = Handler(context.mainLooper)
val gson = Gson()
val `is`: InputStream?

@ -1,95 +0,0 @@
package org.tasks.dialogs;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import androidx.fragment.app.DialogFragment;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.astrid.backup.TasksXmlImporter;
import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;
import org.tasks.R;
import org.tasks.backup.TasksJsonImporter;
import org.tasks.backup.TasksJsonImporter.ImportResult;
import org.tasks.ui.Toaster;
@AndroidEntryPoint
public class ImportTasksDialog extends DialogFragment {
private static final String EXTRA_URI = "extra_uri";
private static final String EXTRA_EXTENSION = "extra_extension";
@Inject TasksXmlImporter xmlImporter;
@Inject TasksJsonImporter jsonImporter;
@Inject DialogBuilder dialogBuilder;
@Inject Activity context;
@Inject Toaster toaster;
public static ImportTasksDialog newImportTasksDialog(Uri data, String extension) {
ImportTasksDialog importTasksDialog = new ImportTasksDialog();
Bundle args = new Bundle();
args.putParcelable(EXTRA_URI, data);
args.putString(EXTRA_EXTENSION, extension);
importTasksDialog.setArguments(args);
return importTasksDialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
Uri data = arguments.getParcelable(EXTRA_URI);
String extension = arguments.getString(EXTRA_EXTENSION);
ProgressDialog progressDialog = dialogBuilder.newProgressDialog();
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.show();
setCancelable(false);
switch (extension) {
case "json":
Handler handler = new Handler();
new Thread(
() -> {
ImportResult result =
jsonImporter.importTasks(getActivity(), data, progressDialog);
handler.post(() -> {
if (progressDialog.isShowing()) {
DialogUtilities.dismissDialog((Activity) context, progressDialog);
}
showSummary(result);
});
})
.start();
break;
case "xml":
xmlImporter.importTasks(getActivity(), data, progressDialog);
break;
default:
throw new RuntimeException("Invalid extension: " + extension);
}
return progressDialog;
}
private void showSummary(ImportResult result) {
Resources r = context.getResources();
dialogBuilder
.newDialog(R.string.import_summary_title)
.setMessage(
context.getString(
R.string.import_summary_message,
"",
r.getQuantityString(R.plurals.Ntasks, result.getTaskCount(), result.getTaskCount()),
r.getQuantityString(
R.plurals.Ntasks,
result.getImportCount(),
result.getImportCount()),
r.getQuantityString(R.plurals.Ntasks, result.getSkipCount(), result.getSkipCount()),
r.getQuantityString(R.plurals.Ntasks, 0, 0)))
.setPositiveButton(android.R.string.ok, (dialog, id) -> dialog.dismiss())
.show();
}
}

@ -0,0 +1,90 @@
package org.tasks.dialogs
import android.app.Activity
import android.app.Dialog
import android.app.ProgressDialog
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.todoroo.astrid.backup.TasksXmlImporter
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.R
import org.tasks.backup.TasksJsonImporter
import org.tasks.backup.TasksJsonImporter.ImportResult
import org.tasks.ui.Toaster
import javax.inject.Inject
@AndroidEntryPoint
class ImportTasksDialog : DialogFragment() {
@Inject lateinit var xmlImporter: TasksXmlImporter
@Inject lateinit var jsonImporter: TasksJsonImporter
@Inject lateinit var dialogBuilder: DialogBuilder
@Inject lateinit var context: Activity
@Inject lateinit var toaster: Toaster
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val arguments = requireArguments()
val data = arguments.getParcelable<Uri>(EXTRA_URI)
val extension = arguments.getString(EXTRA_EXTENSION)
val progressDialog = dialogBuilder.newProgressDialog()
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER)
progressDialog.setCancelable(false)
progressDialog.isIndeterminate = true
progressDialog.show()
isCancelable = false
when (extension) {
"json" -> {
val activity = requireActivity()
lifecycleScope.launch {
val result = withContext(NonCancellable) {
jsonImporter.importTasks(activity, data, progressDialog)
}
if (progressDialog.isShowing) {
progressDialog.dismiss()
}
showSummary(result)
}
}
"xml" -> xmlImporter.importTasks(activity, data, progressDialog)
else -> throw RuntimeException("Invalid extension: $extension")
}
return progressDialog
}
private fun showSummary(result: ImportResult) {
val r = requireContext().resources
dialogBuilder
.newDialog(R.string.import_summary_title)
.setMessage(
r.getString(
R.string.import_summary_message,
"",
r.getQuantityString(R.plurals.Ntasks, result.taskCount, result.taskCount),
r.getQuantityString(
R.plurals.Ntasks,
result.importCount,
result.importCount),
r.getQuantityString(R.plurals.Ntasks, result.skipCount, result.skipCount),
r.getQuantityString(R.plurals.Ntasks, 0, 0)))
.setPositiveButton(android.R.string.ok, null)
.show()
}
companion object {
private const val EXTRA_URI = "extra_uri"
private const val EXTRA_EXTENSION = "extra_extension"
fun newImportTasksDialog(data: Uri?, extension: String?): ImportTasksDialog {
val importTasksDialog = ImportTasksDialog()
val args = Bundle()
args.putParcelable(EXTRA_URI, data)
args.putString(EXTRA_EXTENSION, extension)
importTasksDialog.arguments = args
return importTasksDialog
}
}
}
Loading…
Cancel
Save