mirror of https://github.com/tasks/tasks
Convert workers to Kotlin
parent
cde5bcfb87
commit
641b60be9b
@ -1,152 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import static com.todoroo.astrid.dao.TaskDao.TRANS_SUPPRESS_REFRESH;
|
||||
import static org.tasks.Strings.isNullOrEmpty;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.provider.CalendarContract;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.Data.Builder;
|
||||
import androidx.work.WorkerParameters;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.data.SyncFlags;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import com.todoroo.astrid.reminders.ReminderService;
|
||||
import com.todoroo.astrid.repeats.RepeatTaskHelper;
|
||||
import com.todoroo.astrid.timers.TimerPlugin;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.R;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.injection.ApplicationContext;
|
||||
import org.tasks.injection.InjectingWorker;
|
||||
import org.tasks.location.GeofenceApi;
|
||||
import org.tasks.notifications.NotificationManager;
|
||||
import org.tasks.scheduling.RefreshScheduler;
|
||||
import org.tasks.sync.SyncAdapters;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class AfterSaveWork extends InjectingWorker {
|
||||
|
||||
private static final String EXTRA_ID = "extra_id";
|
||||
private static final String EXTRA_ORIG_COMPLETED = "extra_was_completed";
|
||||
private static final String EXTRA_ORIG_DELETED = "extra_was_deleted";
|
||||
private static final String EXTRA_PUSH_GTASKS = "extra_push_gtasks";
|
||||
private static final String EXTRA_PUSH_CALDAV = "extra_push_caldav";
|
||||
private static final String EXTRA_SUPPRESS_REFRESH = "extra_suppress_refresh";
|
||||
|
||||
@Inject RepeatTaskHelper repeatTaskHelper;
|
||||
@Inject @ApplicationContext Context context;
|
||||
@Inject NotificationManager notificationManager;
|
||||
@Inject GeofenceApi geofenceApi;
|
||||
@Inject TimerPlugin timerPlugin;
|
||||
@Inject ReminderService reminderService;
|
||||
@Inject RefreshScheduler refreshScheduler;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
@Inject TaskDao taskDao;
|
||||
@Inject SyncAdapters syncAdapters;
|
||||
@Inject WorkManager workManager;
|
||||
@Inject CaldavDao caldavDao;
|
||||
|
||||
public AfterSaveWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
static Data getInputData(Task current, Task original) {
|
||||
boolean suppress = current.checkTransitory(SyncFlags.SUPPRESS_SYNC);
|
||||
boolean forceCaldav = current.checkTransitory(SyncFlags.FORCE_CALDAV_SYNC);
|
||||
Builder builder =
|
||||
new Builder()
|
||||
.putLong(EXTRA_ID, current.getId())
|
||||
.putBoolean(EXTRA_PUSH_GTASKS, !suppress && !current.googleTaskUpToDate(original))
|
||||
.putBoolean(
|
||||
EXTRA_PUSH_CALDAV, !suppress && (!current.caldavUpToDate(original) || forceCaldav))
|
||||
.putBoolean(EXTRA_SUPPRESS_REFRESH, current.checkTransitory(TRANS_SUPPRESS_REFRESH));
|
||||
if (original != null) {
|
||||
builder
|
||||
.putLong(EXTRA_ORIG_COMPLETED, original.getCompletionDate())
|
||||
.putLong(EXTRA_ORIG_DELETED, original.getDeletionDate());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result run() {
|
||||
Data data = getInputData();
|
||||
long taskId = data.getLong(EXTRA_ID, -1);
|
||||
Task task = taskDao.fetch(taskId);
|
||||
if (task == null) {
|
||||
Timber.e("Missing saved task");
|
||||
return Result.failure();
|
||||
}
|
||||
|
||||
reminderService.scheduleAlarm(task);
|
||||
|
||||
boolean completionDateModified =
|
||||
!Objects.equals(task.getCompletionDate(), data.getLong(EXTRA_ORIG_COMPLETED, 0));
|
||||
boolean deletionDateModified =
|
||||
!Objects.equals(task.getDeletionDate(), data.getLong(EXTRA_ORIG_DELETED, 0));
|
||||
|
||||
boolean justCompleted = completionDateModified && task.isCompleted();
|
||||
boolean justDeleted = deletionDateModified && task.isDeleted();
|
||||
|
||||
if (justCompleted || justDeleted) {
|
||||
notificationManager.cancel(taskId);
|
||||
}
|
||||
if (completionDateModified || deletionDateModified) {
|
||||
geofenceApi.update(taskId);
|
||||
}
|
||||
|
||||
if (justCompleted) {
|
||||
updateCalendarTitle(task);
|
||||
CaldavAccount account = caldavDao.getAccountForTask(taskId);
|
||||
if (account == null || !account.isSuppressRepeatingTasks()) {
|
||||
repeatTaskHelper.handleRepeat(task);
|
||||
}
|
||||
if (task.getTimerStart() > 0) {
|
||||
timerPlugin.stopTimer(task);
|
||||
}
|
||||
}
|
||||
|
||||
if ((data.getBoolean(EXTRA_PUSH_GTASKS, false) && syncAdapters.isGoogleTaskSyncEnabled())
|
||||
|| (data.getBoolean(EXTRA_PUSH_CALDAV, false) && syncAdapters.isCaldavSyncEnabled())) {
|
||||
workManager.sync(false);
|
||||
}
|
||||
|
||||
refreshScheduler.scheduleRefresh(task);
|
||||
if (!data.getBoolean(EXTRA_SUPPRESS_REFRESH, false)) {
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void updateCalendarTitle(Task task) {
|
||||
String calendarUri = task.getCalendarURI();
|
||||
if (!isNullOrEmpty(calendarUri)) {
|
||||
try {
|
||||
// change title of calendar event
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(
|
||||
CalendarContract.Events.TITLE,
|
||||
context.getString(R.string.gcal_completed_title, task.getTitle()));
|
||||
cr.update(Uri.parse(calendarUri), values, null, null);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.CalendarContract
|
||||
import androidx.work.Data
|
||||
import androidx.work.WorkerParameters
|
||||
import com.todoroo.astrid.dao.TaskDao
|
||||
import com.todoroo.astrid.data.SyncFlags
|
||||
import com.todoroo.astrid.data.Task
|
||||
import com.todoroo.astrid.reminders.ReminderService
|
||||
import com.todoroo.astrid.repeats.RepeatTaskHelper
|
||||
import com.todoroo.astrid.timers.TimerPlugin
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.R
|
||||
import org.tasks.Strings.isNullOrEmpty
|
||||
import org.tasks.data.CaldavDao
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.injection.ApplicationContext
|
||||
import org.tasks.injection.InjectingWorker
|
||||
import org.tasks.location.GeofenceApi
|
||||
import org.tasks.notifications.NotificationManager
|
||||
import org.tasks.scheduling.RefreshScheduler
|
||||
import org.tasks.sync.SyncAdapters
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class AfterSaveWork(context: Context, workerParams: WorkerParameters) : InjectingWorker(context, workerParams) {
|
||||
@Inject lateinit var repeatTaskHelper: RepeatTaskHelper
|
||||
@Inject @ApplicationContext lateinit var context: Context
|
||||
@Inject lateinit var notificationManager: NotificationManager
|
||||
@Inject lateinit var geofenceApi: GeofenceApi
|
||||
@Inject lateinit var timerPlugin: TimerPlugin
|
||||
@Inject lateinit var reminderService: ReminderService
|
||||
@Inject lateinit var refreshScheduler: RefreshScheduler
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
@Inject lateinit var taskDao: TaskDao
|
||||
@Inject lateinit var syncAdapters: SyncAdapters
|
||||
@Inject lateinit var workManager: WorkManager
|
||||
@Inject lateinit var caldavDao: CaldavDao
|
||||
|
||||
override fun run(): Result {
|
||||
val data = inputData
|
||||
val taskId = data.getLong(EXTRA_ID, -1)
|
||||
val task = taskDao.fetch(taskId)
|
||||
if (task == null) {
|
||||
Timber.e("Missing saved task")
|
||||
return Result.failure()
|
||||
}
|
||||
reminderService.scheduleAlarm(task)
|
||||
val completionDateModified = task.completionDate != data.getLong(EXTRA_ORIG_COMPLETED, 0)
|
||||
val deletionDateModified = task.deletionDate != data.getLong(EXTRA_ORIG_DELETED, 0)
|
||||
val justCompleted = completionDateModified && task.isCompleted
|
||||
val justDeleted = deletionDateModified && task.isDeleted
|
||||
if (justCompleted || justDeleted) {
|
||||
notificationManager.cancel(taskId)
|
||||
}
|
||||
if (completionDateModified || deletionDateModified) {
|
||||
geofenceApi.update(taskId)
|
||||
}
|
||||
if (justCompleted) {
|
||||
updateCalendarTitle(task)
|
||||
val account = caldavDao.getAccountForTask(taskId)
|
||||
if (account == null || !account.isSuppressRepeatingTasks) {
|
||||
repeatTaskHelper.handleRepeat(task)
|
||||
}
|
||||
if (task.timerStart > 0) {
|
||||
timerPlugin.stopTimer(task)
|
||||
}
|
||||
}
|
||||
if (data.getBoolean(EXTRA_PUSH_GTASKS, false) && syncAdapters.isGoogleTaskSyncEnabled
|
||||
|| data.getBoolean(EXTRA_PUSH_CALDAV, false) && syncAdapters.isCaldavSyncEnabled) {
|
||||
workManager.sync(false)
|
||||
}
|
||||
refreshScheduler.scheduleRefresh(task)
|
||||
if (!data.getBoolean(EXTRA_SUPPRESS_REFRESH, false)) {
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun updateCalendarTitle(task: Task) {
|
||||
val calendarUri = task.calendarURI
|
||||
if (!isNullOrEmpty(calendarUri)) {
|
||||
try {
|
||||
// change title of calendar event
|
||||
val cr = context.contentResolver
|
||||
val values = ContentValues()
|
||||
values.put(
|
||||
CalendarContract.Events.TITLE,
|
||||
context.getString(R.string.gcal_completed_title, task.title))
|
||||
cr.update(Uri.parse(calendarUri), values, null, null)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun inject(component: ApplicationComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_ID = "extra_id"
|
||||
private const val EXTRA_ORIG_COMPLETED = "extra_was_completed"
|
||||
private const val EXTRA_ORIG_DELETED = "extra_was_deleted"
|
||||
private const val EXTRA_PUSH_GTASKS = "extra_push_gtasks"
|
||||
private const val EXTRA_PUSH_CALDAV = "extra_push_caldav"
|
||||
private const val EXTRA_SUPPRESS_REFRESH = "extra_suppress_refresh"
|
||||
fun getInputData(current: Task, original: Task?): Data {
|
||||
val suppress = current.checkTransitory(SyncFlags.SUPPRESS_SYNC)
|
||||
val forceCaldav = current.checkTransitory(SyncFlags.FORCE_CALDAV_SYNC)
|
||||
val builder = Data.Builder()
|
||||
.putLong(EXTRA_ID, current.id)
|
||||
.putBoolean(EXTRA_PUSH_GTASKS, !suppress && !current.googleTaskUpToDate(original))
|
||||
.putBoolean(
|
||||
EXTRA_PUSH_CALDAV, !suppress && (!current.caldavUpToDate(original) || forceCaldav))
|
||||
.putBoolean(EXTRA_SUPPRESS_REFRESH, current.checkTransitory(TaskDao.TRANS_SUPPRESS_REFRESH))
|
||||
if (original != null) {
|
||||
builder
|
||||
.putLong(EXTRA_ORIG_COMPLETED, original.completionDate)
|
||||
.putLong(EXTRA_ORIG_DELETED, original.deletionDate)
|
||||
}
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.skip;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static com.todoroo.andlib.utility.DateUtilities.now;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.work.WorkerParameters;
|
||||
import com.google.common.base.Predicate;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.backup.TasksJsonExporter;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.injection.ApplicationContext;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class BackupWork extends RepeatingWorker {
|
||||
|
||||
static final int DAYS_TO_KEEP_BACKUP = 7;
|
||||
static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.json";
|
||||
private static final Predicate<String> FILENAME_FILTER = f -> f.matches(BACKUP_FILE_NAME_REGEX);
|
||||
static final FileFilter FILE_FILTER = f -> FILENAME_FILTER.apply(f.getName());
|
||||
private static final Comparator<File> BY_LAST_MODIFIED =
|
||||
(f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified());
|
||||
private static final Comparator<DocumentFile> DOCUMENT_FILE_COMPARATOR =
|
||||
(d1, d2) -> Long.compare(d2.lastModified(), d1.lastModified());
|
||||
@Inject @ApplicationContext Context context;
|
||||
@Inject TasksJsonExporter tasksJsonExporter;
|
||||
@Inject Preferences preferences;
|
||||
@Inject WorkManager workManager;
|
||||
|
||||
public BackupWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
static List<File> getDeleteList(File[] fileArray, int keepNewest) {
|
||||
if (fileArray == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<File> files = Arrays.asList(fileArray);
|
||||
Collections.sort(files, BY_LAST_MODIFIED);
|
||||
return newArrayList(skip(files, keepNewest));
|
||||
}
|
||||
|
||||
private static List<DocumentFile> getDeleteList(DocumentFile[] fileArray) {
|
||||
if (fileArray == null) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
List<DocumentFile> files = Arrays.asList(fileArray);
|
||||
files = newArrayList(filter(files, file -> FILENAME_FILTER.apply(file.getName())));
|
||||
Collections.sort(files, DOCUMENT_FILE_COMPARATOR);
|
||||
return newArrayList(skip(files, DAYS_TO_KEEP_BACKUP));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result run() {
|
||||
preferences.setLong(R.string.p_last_backup, now());
|
||||
startBackup(context);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduleNext() {
|
||||
workManager.scheduleBackup();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void startBackup(Context context) {
|
||||
try {
|
||||
deleteOldLocalBackups();
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
|
||||
try {
|
||||
tasksJsonExporter.exportTasks(
|
||||
context, TasksJsonExporter.ExportType.EXPORT_TYPE_SERVICE, null);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteOldLocalBackups() {
|
||||
Uri uri = preferences.getBackupDirectory();
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
switch (uri.getScheme()) {
|
||||
case ContentResolver.SCHEME_CONTENT:
|
||||
DocumentFile dir = DocumentFile.fromTreeUri(context, uri);
|
||||
for (DocumentFile file : getDeleteList(dir.listFiles())) {
|
||||
if (!file.delete()) {
|
||||
Timber.e("Unable to delete: %s", file);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ContentResolver.SCHEME_FILE:
|
||||
File astridDir = new File(uri.getPath());
|
||||
File[] fileArray = astridDir.listFiles(FILE_FILTER);
|
||||
for (File file : getDeleteList(fileArray, DAYS_TO_KEEP_BACKUP)) {
|
||||
if (!file.delete()) {
|
||||
Timber.e("Unable to delete: %s", file);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.work.WorkerParameters
|
||||
import com.todoroo.andlib.utility.DateUtilities
|
||||
import org.tasks.R
|
||||
import org.tasks.backup.TasksJsonExporter
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.injection.ApplicationContext
|
||||
import org.tasks.preferences.Preferences
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileFilter
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class BackupWork(context: Context, workerParams: WorkerParameters) : RepeatingWorker(context, workerParams) {
|
||||
@Inject @ApplicationContext lateinit var context: Context
|
||||
@Inject lateinit var tasksJsonExporter: TasksJsonExporter
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var workManager: WorkManager
|
||||
|
||||
override fun run(): Result {
|
||||
preferences.setLong(R.string.p_last_backup, DateUtilities.now())
|
||||
startBackup(context)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
override fun scheduleNext() = workManager.scheduleBackup()
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
|
||||
private fun startBackup(context: Context?) {
|
||||
try {
|
||||
deleteOldLocalBackups()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
try {
|
||||
tasksJsonExporter.exportTasks(
|
||||
context, TasksJsonExporter.ExportType.EXPORT_TYPE_SERVICE, null)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteOldLocalBackups() {
|
||||
val uri = preferences.backupDirectory
|
||||
when (uri?.scheme) {
|
||||
ContentResolver.SCHEME_CONTENT -> {
|
||||
val dir = DocumentFile.fromTreeUri(context, uri)
|
||||
for (file in getDeleteList(dir?.listFiles())) {
|
||||
if (!file.delete()) {
|
||||
Timber.e("Unable to delete: %s", file)
|
||||
}
|
||||
}
|
||||
}
|
||||
ContentResolver.SCHEME_FILE -> {
|
||||
val astridDir = File(uri.path)
|
||||
val fileArray = astridDir.listFiles(FILE_FILTER)
|
||||
for (file in getDeleteList(fileArray, DAYS_TO_KEEP_BACKUP)) {
|
||||
if (!file.delete()) {
|
||||
Timber.e("Unable to delete: %s", file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DAYS_TO_KEEP_BACKUP = 7
|
||||
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 DOCUMENT_FILE_COMPARATOR = Comparator { d1: DocumentFile, d2: DocumentFile -> d2.lastModified().compareTo(d1.lastModified()) }
|
||||
|
||||
fun getDeleteList(fileArray: Array<File>?, keepNewest: Int) =
|
||||
fileArray?.sortedWith(BY_LAST_MODIFIED)?.drop(keepNewest) ?: emptyList()
|
||||
|
||||
private fun getDeleteList(fileArray: Array<DocumentFile>?) =
|
||||
fileArray
|
||||
?.filter { FILENAME_FILTER.invoke(it.name!!) }
|
||||
?.sortedWith(DOCUMENT_FILE_COMPARATOR)
|
||||
?.drop(DAYS_TO_KEEP_BACKUP)
|
||||
?: emptyList()
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.WorkerParameters;
|
||||
import com.todoroo.astrid.alarms.AlarmService;
|
||||
import com.todoroo.astrid.reminders.ReminderService;
|
||||
import com.todoroo.astrid.timers.TimerPlugin;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.data.DeletionDao;
|
||||
import org.tasks.data.Geofence;
|
||||
import org.tasks.data.LocationDao;
|
||||
import org.tasks.data.TaskAttachment;
|
||||
import org.tasks.data.TaskAttachmentDao;
|
||||
import org.tasks.data.UserActivity;
|
||||
import org.tasks.data.UserActivityDao;
|
||||
import org.tasks.files.FileHelper;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.injection.InjectingWorker;
|
||||
import org.tasks.location.GeofenceApi;
|
||||
import org.tasks.notifications.NotificationManager;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class CleanupWork extends InjectingWorker {
|
||||
|
||||
static final String EXTRA_TASK_IDS = "extra_task_ids";
|
||||
private final Context context;
|
||||
@Inject NotificationManager notificationManager;
|
||||
@Inject GeofenceApi geofenceApi;
|
||||
@Inject TimerPlugin timerPlugin;
|
||||
@Inject ReminderService reminderService;
|
||||
@Inject AlarmService alarmService;
|
||||
@Inject TaskAttachmentDao taskAttachmentDao;
|
||||
@Inject UserActivityDao userActivityDao;
|
||||
@Inject LocationDao locationDao;
|
||||
@Inject DeletionDao deletionDao;
|
||||
|
||||
public CleanupWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result run() {
|
||||
long[] tasks = getInputData().getLongArray(EXTRA_TASK_IDS);
|
||||
if (tasks == null) {
|
||||
Timber.e("No task ids provided");
|
||||
return Result.failure();
|
||||
}
|
||||
for (long task : tasks) {
|
||||
alarmService.cancelAlarms(task);
|
||||
reminderService.cancelReminder(task);
|
||||
notificationManager.cancel(task);
|
||||
for (Geofence geofence : locationDao.getGeofencesForTask(task)) {
|
||||
locationDao.delete(geofence);
|
||||
geofenceApi.update(geofence.getPlace());
|
||||
}
|
||||
for (TaskAttachment attachment : taskAttachmentDao.getAttachments(task)) {
|
||||
FileHelper.delete(context, attachment.parseUri());
|
||||
taskAttachmentDao.delete(attachment);
|
||||
}
|
||||
for (UserActivity comment : userActivityDao.getComments(task)) {
|
||||
FileHelper.delete(context, comment.getPictureUri());
|
||||
userActivityDao.delete(comment);
|
||||
}
|
||||
}
|
||||
timerPlugin.updateNotifications();
|
||||
deletionDao.purgeDeleted();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import com.todoroo.astrid.alarms.AlarmService
|
||||
import com.todoroo.astrid.reminders.ReminderService
|
||||
import com.todoroo.astrid.timers.TimerPlugin
|
||||
import org.tasks.data.DeletionDao
|
||||
import org.tasks.data.LocationDao
|
||||
import org.tasks.data.TaskAttachmentDao
|
||||
import org.tasks.data.UserActivityDao
|
||||
import org.tasks.files.FileHelper
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.injection.InjectingWorker
|
||||
import org.tasks.location.GeofenceApi
|
||||
import org.tasks.notifications.NotificationManager
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class CleanupWork(private val context: Context, workerParams: WorkerParameters) : InjectingWorker(context, workerParams) {
|
||||
|
||||
@Inject lateinit var notificationManager: NotificationManager
|
||||
@Inject lateinit var geofenceApi: GeofenceApi
|
||||
@Inject lateinit var timerPlugin: TimerPlugin
|
||||
@Inject lateinit var reminderService: ReminderService
|
||||
@Inject lateinit var alarmService: AlarmService
|
||||
@Inject lateinit var taskAttachmentDao: TaskAttachmentDao
|
||||
@Inject lateinit var userActivityDao: UserActivityDao
|
||||
@Inject lateinit var locationDao: LocationDao
|
||||
@Inject lateinit var deletionDao: DeletionDao
|
||||
|
||||
public override fun run(): Result {
|
||||
val tasks = inputData.getLongArray(EXTRA_TASK_IDS)
|
||||
if (tasks == null) {
|
||||
Timber.e("No task ids provided")
|
||||
return Result.failure()
|
||||
}
|
||||
tasks.forEach { task ->
|
||||
alarmService.cancelAlarms(task)
|
||||
reminderService.cancelReminder(task)
|
||||
notificationManager.cancel(task)
|
||||
locationDao.getGeofencesForTask(task).forEach {
|
||||
locationDao.delete(it)
|
||||
geofenceApi.update(it.place!!)
|
||||
}
|
||||
taskAttachmentDao.getAttachments(task).forEach {
|
||||
FileHelper.delete(context, it.parseUri())
|
||||
taskAttachmentDao.delete(it)
|
||||
}
|
||||
userActivityDao.getComments(task).forEach {
|
||||
FileHelper.delete(context, it.pictureUri)
|
||||
userActivityDao.delete(it)
|
||||
}
|
||||
}
|
||||
timerPlugin.updateNotifications()
|
||||
deletionDao.purgeDeleted()
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
|
||||
companion object {
|
||||
const val EXTRA_TASK_IDS = "extra_task_ids"
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import static com.google.common.collect.Iterables.skip;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.tasks.Strings.isNullOrEmpty;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.WorkerParameters;
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
|
||||
import com.google.api.services.drive.model.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.net.ssl.SSLException;
|
||||
import org.tasks.R;
|
||||
import org.tasks.drive.DriveInvoker;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.injection.ApplicationContext;
|
||||
import org.tasks.injection.InjectingWorker;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class DriveUploader extends InjectingWorker {
|
||||
|
||||
private static final String FOLDER_NAME = "Tasks Backups";
|
||||
private static final String EXTRA_URI = "extra_uri";
|
||||
private static final String EXTRA_PURGE = "extra_purge";
|
||||
private static final Comparator<File> DRIVE_FILE_COMPARATOR =
|
||||
(f1, f2) -> Long.compare(f2.getModifiedTime().getValue(), f1.getModifiedTime().getValue());
|
||||
|
||||
@Inject @ApplicationContext Context context;
|
||||
@Inject DriveInvoker drive;
|
||||
@Inject Preferences preferences;
|
||||
|
||||
public DriveUploader(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
static Data getInputData(Uri uri, boolean purge) {
|
||||
return new Data.Builder()
|
||||
.putString(EXTRA_URI, uri.toString())
|
||||
.putBoolean(EXTRA_PURGE, purge)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static List<File> getDeleteList(List<File> files) {
|
||||
Collections.sort(files, DRIVE_FILE_COMPARATOR);
|
||||
return newArrayList(skip(files, BackupWork.DAYS_TO_KEEP_BACKUP));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result run() {
|
||||
Data inputData = getInputData();
|
||||
Uri uri = Uri.parse(inputData.getString(EXTRA_URI));
|
||||
try {
|
||||
File folder = getFolder();
|
||||
preferences.setString(R.string.p_google_drive_backup_folder, folder.getId());
|
||||
drive.createFile(folder.getId(), uri);
|
||||
|
||||
if (inputData.getBoolean(EXTRA_PURGE, false)) {
|
||||
List<File> files = drive.getFilesByPrefix(folder.getId(), "auto.");
|
||||
for (File file : getDeleteList(files)) {
|
||||
try {
|
||||
drive.delete(file);
|
||||
} catch (GoogleJsonResponseException e) {
|
||||
if (e.getStatusCode() == 404) {
|
||||
Timber.e(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
} catch (SocketTimeoutException | SSLException | ConnectException | UnknownHostException e) {
|
||||
Timber.e(e);
|
||||
return Result.retry();
|
||||
} catch (IOException e) {
|
||||
firebase.reportException(e);
|
||||
return Result.failure();
|
||||
}
|
||||
}
|
||||
|
||||
private File getFolder() throws IOException {
|
||||
String folderId = preferences.getStringValue(R.string.p_google_drive_backup_folder);
|
||||
File file = null;
|
||||
if (!isNullOrEmpty(folderId)) {
|
||||
try {
|
||||
file = drive.getFile(folderId);
|
||||
} catch (GoogleJsonResponseException e) {
|
||||
if (e.getStatusCode() != 404) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return file == null || file.getTrashed() ? drive.createFolder(FOLDER_NAME) : file;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.work.Data
|
||||
import androidx.work.WorkerParameters
|
||||
import com.google.api.client.googleapis.json.GoogleJsonResponseException
|
||||
import com.google.api.services.drive.model.File
|
||||
import org.tasks.R
|
||||
import org.tasks.Strings.isNullOrEmpty
|
||||
import org.tasks.drive.DriveInvoker
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.injection.ApplicationContext
|
||||
import org.tasks.injection.InjectingWorker
|
||||
import org.tasks.preferences.Preferences
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.net.ConnectException
|
||||
import java.net.SocketTimeoutException
|
||||
import java.net.UnknownHostException
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.SSLException
|
||||
|
||||
class DriveUploader(context: Context, workerParams: WorkerParameters) : InjectingWorker(context, workerParams) {
|
||||
@Inject @ApplicationContext lateinit var context: Context
|
||||
@Inject lateinit var drive: DriveInvoker
|
||||
@Inject lateinit var preferences: Preferences
|
||||
|
||||
override fun run(): Result {
|
||||
val inputData = inputData
|
||||
val uri = Uri.parse(inputData.getString(EXTRA_URI))
|
||||
return try {
|
||||
val folder = folder
|
||||
preferences.setString(R.string.p_google_drive_backup_folder, folder.id)
|
||||
drive.createFile(folder.id, uri)
|
||||
if (inputData.getBoolean(EXTRA_PURGE, false)) {
|
||||
val files = drive.getFilesByPrefix(folder.id, "auto.")
|
||||
for (file in getDeleteList(files)) {
|
||||
try {
|
||||
drive.delete(file)
|
||||
} catch (e: GoogleJsonResponseException) {
|
||||
if (e.statusCode == 404) {
|
||||
Timber.e(e)
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Result.success()
|
||||
} catch (e: SocketTimeoutException) {
|
||||
Timber.e(e)
|
||||
Result.retry()
|
||||
} catch (e: SSLException) {
|
||||
Timber.e(e)
|
||||
Result.retry()
|
||||
} catch (e: ConnectException) {
|
||||
Timber.e(e)
|
||||
Result.retry()
|
||||
} catch (e: UnknownHostException) {
|
||||
Timber.e(e)
|
||||
Result.retry()
|
||||
} catch (e: IOException) {
|
||||
firebase.reportException(e)
|
||||
Result.failure()
|
||||
}
|
||||
}
|
||||
|
||||
@get:Throws(IOException::class)
|
||||
private val folder: File
|
||||
get() {
|
||||
val folderId = preferences.getStringValue(R.string.p_google_drive_backup_folder)
|
||||
var file: File? = null
|
||||
if (!isNullOrEmpty(folderId)) {
|
||||
try {
|
||||
file = drive.getFile(folderId)
|
||||
} catch (e: GoogleJsonResponseException) {
|
||||
if (e.statusCode != 404) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
return if (file == null || file.trashed) drive.createFolder(FOLDER_NAME) else file
|
||||
}
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
|
||||
companion object {
|
||||
private const val FOLDER_NAME = "Tasks Backups"
|
||||
private const val EXTRA_URI = "extra_uri"
|
||||
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) =
|
||||
Data.Builder()
|
||||
.putString(EXTRA_URI, uri.toString())
|
||||
.putBoolean(EXTRA_PURGE, purge)
|
||||
.build()
|
||||
|
||||
private fun getDeleteList(files: List<File>) =
|
||||
files.sortedWith(DRIVE_FILE_COMPARATOR).drop(BackupWork.DAYS_TO_KEEP_BACKUP)
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.WorkerParameters;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
|
||||
public class MidnightRefreshWork extends RepeatingWorker {
|
||||
|
||||
@Inject WorkManager workManager;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
|
||||
public MidnightRefreshWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result run() {
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduleNext() {
|
||||
workManager.scheduleMidnightRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import javax.inject.Inject
|
||||
|
||||
class MidnightRefreshWork(context: Context, workerParams: WorkerParameters) : RepeatingWorker(context, workerParams) {
|
||||
@Inject lateinit var workManager: WorkManager
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
|
||||
override fun run(): Result {
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
override fun scheduleNext() = workManager.scheduleMidnightRefresh()
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.WorkerParameters;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.scheduling.RefreshScheduler;
|
||||
|
||||
public class RefreshWork extends RepeatingWorker {
|
||||
|
||||
@Inject RefreshScheduler refreshScheduler;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
|
||||
public RefreshWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result run() {
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduleNext() {
|
||||
refreshScheduler.scheduleNext();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.scheduling.RefreshScheduler
|
||||
import javax.inject.Inject
|
||||
|
||||
class RefreshWork(context: Context, workerParams: WorkerParameters) : RepeatingWorker(context, workerParams) {
|
||||
@Inject lateinit var refreshScheduler: RefreshScheduler
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
|
||||
public override fun run(): Result {
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
|
||||
override fun scheduleNext() = refreshScheduler.scheduleNext()
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.WorkerParameters;
|
||||
import org.tasks.injection.InjectingWorker;
|
||||
|
||||
public abstract class RepeatingWorker extends InjectingWorker {
|
||||
|
||||
RepeatingWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public final Result doWork() {
|
||||
Result result = super.doWork();
|
||||
scheduleNext();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract void scheduleNext();
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import org.tasks.injection.InjectingWorker
|
||||
|
||||
abstract class RepeatingWorker internal constructor(context: Context, workerParams: WorkerParameters) : InjectingWorker(context, workerParams) {
|
||||
override fun doWork(): Result {
|
||||
val result = super.doWork()
|
||||
scheduleNext()
|
||||
return result
|
||||
}
|
||||
|
||||
protected abstract fun scheduleNext()
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
package org.tasks.jobs;
|
||||
|
||||
import static java.util.concurrent.Executors.newFixedThreadPool;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.WorkerParameters;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.caldav.CaldavSynchronizer;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.data.GoogleTaskAccount;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.etesync.EteSynchronizer;
|
||||
import org.tasks.gtasks.GoogleTaskSynchronizer;
|
||||
import org.tasks.injection.ApplicationComponent;
|
||||
import org.tasks.injection.InjectingWorker;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.sync.SyncAdapters;
|
||||
|
||||
public class SyncWork extends InjectingWorker {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
@Inject CaldavSynchronizer caldavSynchronizer;
|
||||
@Inject EteSynchronizer eteSynchronizer;
|
||||
@Inject GoogleTaskSynchronizer googleTaskSynchronizer;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
@Inject Preferences preferences;
|
||||
@Inject CaldavDao caldavDao;
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
@Inject SyncAdapters syncAdapters;
|
||||
|
||||
public SyncWork(@NonNull Context context, @NonNull WorkerParameters workerParams) {
|
||||
super(context, workerParams);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Result run() {
|
||||
if (!syncAdapters.isSyncEnabled()) {
|
||||
return Result.success();
|
||||
}
|
||||
synchronized (LOCK) {
|
||||
if (preferences.isSyncOngoing()) {
|
||||
return Result.retry();
|
||||
}
|
||||
}
|
||||
preferences.setSyncOngoing(true);
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
try {
|
||||
sync();
|
||||
} catch (Exception e) {
|
||||
firebase.reportException(e);
|
||||
} finally {
|
||||
preferences.setSyncOngoing(false);
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void sync() throws InterruptedException {
|
||||
int numThreads = Runtime.getRuntime().availableProcessors();
|
||||
ExecutorService executor = newFixedThreadPool(numThreads);
|
||||
|
||||
for (CaldavAccount account : caldavDao.getAccounts()) {
|
||||
executor.execute(
|
||||
() -> {
|
||||
if (account.isCaldavAccount()) {
|
||||
caldavSynchronizer.sync(account);
|
||||
} else if (account.isEteSyncAccount()) {
|
||||
eteSynchronizer.sync(account);
|
||||
}
|
||||
});
|
||||
}
|
||||
List<GoogleTaskAccount> accounts = googleTaskListDao.getAccounts();
|
||||
for (int i = 0; i < accounts.size(); i++) {
|
||||
int count = i;
|
||||
executor.execute(() -> googleTaskSynchronizer.sync(accounts.get(count), count));
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(15, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(ApplicationComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package org.tasks.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.caldav.CaldavSynchronizer
|
||||
import org.tasks.data.CaldavDao
|
||||
import org.tasks.data.GoogleTaskListDao
|
||||
import org.tasks.etesync.EteSynchronizer
|
||||
import org.tasks.gtasks.GoogleTaskSynchronizer
|
||||
import org.tasks.injection.ApplicationComponent
|
||||
import org.tasks.injection.InjectingWorker
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.sync.SyncAdapters
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class SyncWork(context: Context, workerParams: WorkerParameters) : InjectingWorker(context, workerParams) {
|
||||
@Inject lateinit var caldavSynchronizer: CaldavSynchronizer
|
||||
@Inject lateinit var eteSynchronizer: EteSynchronizer
|
||||
@Inject lateinit var googleTaskSynchronizer: GoogleTaskSynchronizer
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var caldavDao: CaldavDao
|
||||
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
|
||||
@Inject lateinit var syncAdapters: SyncAdapters
|
||||
|
||||
public override fun run(): Result {
|
||||
if (!syncAdapters.isSyncEnabled) {
|
||||
return Result.success()
|
||||
}
|
||||
synchronized(LOCK) {
|
||||
if (preferences.isSyncOngoing) {
|
||||
return Result.retry()
|
||||
}
|
||||
}
|
||||
preferences.isSyncOngoing = true
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
try {
|
||||
sync()
|
||||
} catch (e: Exception) {
|
||||
firebase.reportException(e)
|
||||
} finally {
|
||||
preferences.isSyncOngoing = false
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
@Throws(InterruptedException::class)
|
||||
private fun sync() {
|
||||
val numThreads = Runtime.getRuntime().availableProcessors()
|
||||
val executor = Executors.newFixedThreadPool(numThreads)
|
||||
for (account in caldavDao.getAccounts()) {
|
||||
executor.execute {
|
||||
if (account.isCaldavAccount) {
|
||||
caldavSynchronizer.sync(account)
|
||||
} else if (account.isEteSyncAccount) {
|
||||
eteSynchronizer.sync(account)
|
||||
}
|
||||
}
|
||||
}
|
||||
val accounts = googleTaskListDao.getAccounts()
|
||||
for (i in accounts.indices) {
|
||||
executor.execute { googleTaskSynchronizer.sync(accounts[i], i) }
|
||||
}
|
||||
executor.shutdown()
|
||||
executor.awaitTermination(15, TimeUnit.MINUTES)
|
||||
}
|
||||
|
||||
override fun inject(component: ApplicationComponent) = component.inject(this)
|
||||
|
||||
companion object {
|
||||
private val LOCK = Any()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue