diff --git a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java index dbc1da35a..aa59f2a0c 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java +++ b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java @@ -136,9 +136,11 @@ public abstract class TaskDao { public abstract int clearCompletedCalendarEvents(); @Transaction - public List fetchTasks(Function> getQueries) { + public List fetchTasks(QueryCallback callback) { long start = BuildConfig.DEBUG ? now() : 0; - List queries = getQueries.apply(atLeastLollipop() && hasSubtasks()); + boolean includeGoogleSubtasks = atLeastLollipop() && hasGoogleTaskSubtasks(); + boolean includeCaldavSubtasks = atLeastLollipop() && hasCaldavSubtasks(); + List queries = callback.getQueries(includeGoogleSubtasks, includeCaldavSubtasks); SupportSQLiteDatabase db = database.getOpenHelper().getWritableDatabase(); int last = queries.size() - 1; for (int i = 0 ; i < last ; i++) { @@ -155,12 +157,11 @@ public abstract class TaskDao { @RawQuery abstract int count(SimpleSQLiteQuery query); - @Query( - "SELECT EXISTS(" - + "SELECT 1 FROM google_tasks WHERE gt_parent > 0 AND gt_deleted = 0" - + " UNION ALL " - + "SELECT 1 FROM caldav_tasks WHERE cd_parent > 0 AND cd_deleted = 0);") - public abstract boolean hasSubtasks(); + @Query("SELECT EXISTS(SELECT 1 FROM caldav_tasks WHERE cd_parent > 0 AND cd_deleted = 0)") + abstract boolean hasCaldavSubtasks(); + + @Query("SELECT EXISTS(SELECT 1 FROM google_tasks WHERE gt_parent > 0 AND gt_deleted = 0)") + abstract boolean hasGoogleTaskSubtasks(); @Query("UPDATE tasks SET modified = datetime('now', 'localtime') WHERE _id in (:ids)") public abstract void touch(List ids); @@ -293,4 +294,8 @@ public abstract class TaskDao { return Task.HIDE_UNTIL.gte(0); } } + + public interface QueryCallback { + List getQueries(boolean includeGoogleTaskSubtasks, boolean includeCaldavSubtasks); + } } diff --git a/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java b/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java index 93d7bdb86..c234f6370 100644 --- a/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java +++ b/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java @@ -95,8 +95,11 @@ public class TaskDeleter { .getOriginalSqlQuery() .replace(isVisible().toString(), includeHidden().toString()) .replace(notCompleted().toString(), includeCompleted().toString())); - List tasks = taskDao.fetchTasks( - hasSubtasks -> TaskListViewModel.getQuery(preferences, deleteFilter, hasSubtasks)); + List tasks = + taskDao.fetchTasks( + (includeGoogleSubtasks, includeCaldavSubtasks) -> + TaskListViewModel.getQuery( + preferences, deleteFilter, includeGoogleSubtasks, includeCaldavSubtasks)); for (TaskContainer task : tasks) { if (task.isCompleted()) { completed.add(task.getId()); diff --git a/app/src/main/java/org/tasks/ui/TaskListViewModel.java b/app/src/main/java/org/tasks/ui/TaskListViewModel.java index d85465e06..77c15b3c1 100644 --- a/app/src/main/java/org/tasks/ui/TaskListViewModel.java +++ b/app/src/main/java/org/tasks/ui/TaskListViewModel.java @@ -100,10 +100,14 @@ public class TaskListViewModel extends ViewModel { tasks.observe(owner, observer); } - public static List getQuery(Preferences preferences, Filter filter, boolean subtasks) { + public static List getQuery( + Preferences preferences, + Filter filter, + boolean includeGoogleTaskSubtasks, + boolean includeCaldavSubtasks) { List fields = newArrayList(TASKS, GTASK, CALDAV, GEOFENCE, PLACE); - if (subtasks + if ((includeGoogleTaskSubtasks || includeCaldavSubtasks) && filter.supportsSubtasks() && !(preferences.isManualSort() && filter.supportsManualSort())) { String tagQuery = @@ -178,28 +182,14 @@ public class TaskListViewModel extends ViewModel { .where(TaskCriteria.activeAndVisible()); } else { parentQuery = PermaSql.replacePlaceholdersForQuery(filter.getSqlQuery()); - subtaskQuery - .join( - Join.left( - GoogleTask.TABLE, - Criterion.and( - GoogleTask.PARENT.gt(0), - GoogleTask.TASK.eq(Task.ID), - GoogleTask.DELETED.eq(0)))) - .join( - Join.left( - CaldavTask.TABLE, - Criterion.and( - CaldavTask.PARENT.gt(0), - CaldavTask.TASK.eq(Task.ID), - CaldavTask.DELETED.eq(0)))) - .join( - Join.inner( - RECURSIVE, - Criterion.or( - GoogleTask.PARENT.eq(RECURSIVE_TASK), - CaldavTask.PARENT.eq(RECURSIVE_TASK)))) - .where(TaskCriteria.activeAndVisible()); + if (includeGoogleTaskSubtasks && includeCaldavSubtasks) { + addGoogleAndCaldavSubtasks(subtaskQuery); + } else if (includeGoogleTaskSubtasks) { + addGoogleSubtasks(subtaskQuery); + } else { + addCaldavSubtasks(subtaskQuery); + } + subtaskQuery.where(TaskCriteria.activeAndVisible()); joinedQuery += " AND indent = (select max(indent) from recursive_tasks where tasks._id = recursive_tasks.task) "; } @@ -268,6 +258,50 @@ public class TaskListViewModel extends ViewModel { } } + private static void addGoogleSubtasks(QueryTemplate subtaskQuery) { + subtaskQuery + .join(Join.inner(RECURSIVE, GoogleTask.PARENT.eq(RECURSIVE_TASK))) + .join( + Join.inner( + GoogleTask.TABLE, + Criterion.and( + GoogleTask.TASK.eq(Task.ID), + GoogleTask.DELETED.eq(0)))); + } + + private static void addCaldavSubtasks(QueryTemplate subtaskQuery) { + subtaskQuery + .join(Join.inner(RECURSIVE, CaldavTask.PARENT.eq(RECURSIVE_TASK))) + .join( + Join.inner( + CaldavTask.TABLE, + Criterion.and( + CaldavTask.TASK.eq(Task.ID), + CaldavTask.DELETED.eq(0)))); + } + + private static void addGoogleAndCaldavSubtasks(QueryTemplate subtaskQuery) { + subtaskQuery + .join( + Join.inner( + RECURSIVE, + Criterion.or( + GoogleTask.PARENT.eq(RECURSIVE_TASK), + CaldavTask.PARENT.eq(RECURSIVE_TASK)))) + .join( + Join.left( + GoogleTask.TABLE, + Criterion.and( + GoogleTask.TASK.eq(Task.ID), + GoogleTask.DELETED.eq(0)))) + .join( + Join.left( + CaldavTask.TABLE, + Criterion.and( + CaldavTask.TASK.eq(Task.ID), + CaldavTask.DELETED.eq(0)))); + } + public void searchByFilter(Filter filter) { this.filter = filter; invalidate(); @@ -276,7 +310,14 @@ public class TaskListViewModel extends ViewModel { public void invalidate() { disposable.add( Single.fromCallable( - () -> taskDao.fetchTasks(hasSubtasks -> getQuery(preferences, filter, hasSubtasks))) + () -> + taskDao.fetchTasks( + ((includeGoogleSubtasks, includeCaldavSubtasks) -> + getQuery( + preferences, + filter, + includeGoogleSubtasks, + includeCaldavSubtasks)))) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(tasks::postValue, Timber::e)); diff --git a/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.java b/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.java index 062911f97..e3aed1674 100644 --- a/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.java +++ b/app/src/main/java/org/tasks/widget/ScrollableViewsFactory.java @@ -82,7 +82,10 @@ class ScrollableViewsFactory implements RemoteViewsService.RemoteViewsFactory { @Override public void onDataSetChanged() { updateSettings(); - tasks = taskDao.fetchTasks(hasSubtasks -> getQuery(filter, hasSubtasks)); + tasks = + taskDao.fetchTasks( + (includeGoogleSubtasks, includeCaldavSubtasks) -> + getQuery(filter, includeGoogleSubtasks, includeCaldavSubtasks)); } @Override @@ -196,7 +199,8 @@ class ScrollableViewsFactory implements RemoteViewsService.RemoteViewsFactory { return position < tasks.size() ? tasks.get(position) : null; } - private List getQuery(Filter filter, boolean hasSubtasks) { + private List getQuery( + Filter filter, boolean includeGoogleSubtasks, boolean includeCaldavSubtasks) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.scrollable_widget); rv.setTextViewText(R.id.widget_title, filter.listingTitle); @@ -204,7 +208,9 @@ class ScrollableViewsFactory implements RemoteViewsService.RemoteViewsFactory { rv.setInt(R.id.widget, "setLayoutDirection", Locale.getInstance(context).getDirectionality()); } appWidgetManager.partiallyUpdateAppWidget(widgetId, rv); - List queries = TaskListViewModel.getQuery(preferences, filter, hasSubtasks); + List queries = + TaskListViewModel.getQuery( + preferences, filter, includeGoogleSubtasks, includeCaldavSubtasks); int last = queries.size() - 1; queries.set(last, subtasksHelper.applySubtasksToWidgetFilter(filter, queries.get(last))); return queries;