Display Google Tasks subtasks in all sort modes

gtask_related_email
Alex Baker 6 years ago
parent 7dada2a044
commit aca3a1e933

@ -384,7 +384,7 @@ public final class TaskListFragment extends InjectingFragment
filter.supportsSubtasks()
|| BuiltInFilterExposer.isInbox(context, filter)
|| BuiltInFilterExposer.isTodayFilter(context, filter);
SortDialog.newSortDialog(supportsManualSort)
SortDialog.newSortDialog(supportsManualSort, filter instanceof GtasksFilter)
.show(getChildFragmentManager(), FRAG_TAG_SORT_DIALOG);
return true;
case R.id.menu_show_hidden:

@ -9,65 +9,14 @@ import org.tasks.BuildConfig;
import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskDao;
import org.tasks.data.TaskContainer;
import org.tasks.tasklist.ViewHolder;
public final class GoogleTaskAdapter extends TaskAdapter {
public final class GoogleTaskAdapter extends GoogleTaskManualSortAdapter {
private final TaskDao taskDao;
private final GoogleTaskDao googleTaskDao;
private final boolean newTasksOnTop;
GoogleTaskAdapter(TaskDao taskDao, GoogleTaskDao googleTaskDao) {
this.taskDao = taskDao;
this.googleTaskDao = googleTaskDao;
}
@Override
public int getIndent(TaskContainer task) {
return task.getIndent();
}
@Override
public boolean canMove(ViewHolder sourceVh, ViewHolder targetVh) {
TaskContainer source = sourceVh.task;
int to = targetVh.getAdapterPosition();
if (!source.hasChildren() || to <= 0 || to >= getCount() - 1) {
return true;
}
TaskContainer target = targetVh.task;
if (sourceVh.getAdapterPosition() < to) {
if (target.hasChildren()) {
return false;
}
if (target.hasParent()) {
return target.isLastSubtask();
}
return true;
} else {
if (target.hasChildren()) {
return true;
}
if (target.hasParent()) {
return target.getParent() == source.getId() && target.secondarySort == 0;
}
return true;
}
}
@Override
public int maxIndent(int previousPosition, TaskContainer task) {
return task.hasChildren() ? 0 : 1;
}
@Override
public int minIndent(int nextPosition, TaskContainer task) {
return task.hasChildren() || !getTask(nextPosition).hasParent() ? 0 : 1;
}
@Override
public boolean supportsParentingOrManualSort() {
return true;
GoogleTaskAdapter(TaskDao taskDao, GoogleTaskDao googleTaskDao, boolean newTasksOnTop) {
super(taskDao, googleTaskDao);
this.newTasksOnTop = newTasksOnTop;
}
@Override
@ -75,33 +24,21 @@ public final class GoogleTaskAdapter extends TaskAdapter {
TaskContainer task = getTask(from);
GoogleTask googleTask = task.getGoogleTask();
TaskContainer previous = to > 0 ? getTask(to - 1) : null;
if (previous == null) {
googleTaskDao.move(googleTask, 0, 0);
} else if (to == getCount() || to <= from) {
if (indent == 0) {
googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + 1);
} else if (previous.hasParent()) {
googleTaskDao.move(googleTask, previous.getParent(), previous.getSecondarySort() + 1);
} else {
googleTaskDao.move(googleTask, previous.getId(), 0);
if (googleTask.getIndent() == 0) {
return;
}
} else {
if (indent == 0) {
googleTaskDao.move(
googleTask,
0,
task.hasParent() ? previous.getPrimarySort() + 1 : previous.getPrimarySort());
} else if (previous.hasParent()) {
googleTaskDao.move(
googleTask,
previous.getParent(),
task.getParent() == previous.getParent()
? previous.getSecondarySort()
: previous.getSecondarySort() + 1);
googleTask, 0, newTasksOnTop ? 0 : googleTaskDao.getBottom(googleTask.getListId(), 0));
} else {
googleTaskDao.move(googleTask, previous.getId(), 0);
long newParent = previous.hasParent() ? previous.getParent() : previous.getId();
if (googleTask.getParent() == newParent) {
return;
}
googleTaskDao.move(
googleTask,
newParent,
newTasksOnTop ? 0 : googleTaskDao.getBottom(googleTask.getListId(), newParent));
}
Task update = task.getTask();

@ -0,0 +1,116 @@
package com.todoroo.astrid.adapter;
import static com.todoroo.andlib.utility.DateUtilities.now;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import org.tasks.BuildConfig;
import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskDao;
import org.tasks.data.TaskContainer;
import org.tasks.tasklist.ViewHolder;
public class GoogleTaskManualSortAdapter extends TaskAdapter {
protected final TaskDao taskDao;
protected final GoogleTaskDao googleTaskDao;
GoogleTaskManualSortAdapter(TaskDao taskDao, GoogleTaskDao googleTaskDao) {
this.taskDao = taskDao;
this.googleTaskDao = googleTaskDao;
}
@Override
public int getIndent(TaskContainer task) {
return task.getIndent();
}
@Override
public boolean canMove(ViewHolder sourceVh, ViewHolder targetVh) {
TaskContainer source = sourceVh.task;
int to = targetVh.getAdapterPosition();
if (!source.hasChildren() || to <= 0 || to >= getCount() - 1) {
return true;
}
TaskContainer target = targetVh.task;
if (sourceVh.getAdapterPosition() < to) {
if (target.hasChildren()) {
return false;
}
if (target.hasParent()) {
return target.isLastSubtask();
}
return true;
} else {
if (target.hasChildren()) {
return true;
}
if (target.hasParent()) {
return target.getParent() == source.getId() && target.secondarySort == 0;
}
return true;
}
}
@Override
public int maxIndent(int previousPosition, TaskContainer task) {
return task.hasChildren() ? 0 : 1;
}
@Override
public int minIndent(int nextPosition, TaskContainer task) {
return task.hasChildren() || !getTask(nextPosition).hasParent() ? 0 : 1;
}
@Override
public boolean supportsParentingOrManualSort() {
return true;
}
@Override
public void moved(int from, int to, int indent) {
TaskContainer task = getTask(from);
GoogleTask googleTask = task.getGoogleTask();
TaskContainer previous = to > 0 ? getTask(to - 1) : null;
if (previous == null) {
googleTaskDao.move(googleTask, 0, 0);
} else if (to == getCount() || to <= from) {
if (indent == 0) {
googleTaskDao.move(googleTask, 0, previous.getPrimarySort() + 1);
} else if (previous.hasParent()) {
googleTaskDao.move(googleTask, previous.getParent(), previous.getSecondarySort() + 1);
} else {
googleTaskDao.move(googleTask, previous.getId(), 0);
}
} else {
if (indent == 0) {
googleTaskDao.move(
googleTask,
0,
task.hasParent() ? previous.getPrimarySort() + 1 : previous.getPrimarySort());
} else if (previous.hasParent()) {
googleTaskDao.move(
googleTask,
previous.getParent(),
task.getParent() == previous.getParent()
? previous.getSecondarySort()
: previous.getSecondarySort() + 1);
} else {
googleTaskDao.move(googleTask, previous.getId(), 0);
}
}
Task update = task.getTask();
update.setModificationDate(now());
update.putTransitory(SyncFlags.FORCE_SYNC, true);
taskDao.save(update);
if (BuildConfig.DEBUG) {
googleTaskDao.validateSorting(task.getGoogleTaskList());
}
}
}

@ -73,9 +73,7 @@ public class TaskAdapterProvider {
GtasksFilter gtasksFilter = (GtasksFilter) filter;
GoogleTaskList list = gtasksListService.getList(gtasksFilter.getStoreId());
if (list != null) {
return preferences.isManualSort()
? createManualGoogleTaskAdapter(gtasksFilter)
: new TaskAdapter();
return createGoogleTaskAdapter(gtasksFilter);
}
} else if (filter instanceof CaldavFilter) {
CaldavFilter caldavFilter = (CaldavFilter) filter;
@ -105,10 +103,12 @@ public class TaskAdapterProvider {
return new AstridTaskAdapter(list, filter, updater, taskDao);
}
private TaskAdapter createManualGoogleTaskAdapter(GtasksFilter filter) {
String query = GtasksFilter.toManualOrder(filter.getSqlQuery());
private TaskAdapter createGoogleTaskAdapter(GtasksFilter filter) {
String query = GtasksFilter.toSubtaskQuery(preferences, filter.getSqlQuery());
filter.setFilterQueryOverride(query);
return new GoogleTaskAdapter(taskDao, googleTaskDao);
return preferences.isManualSort()
? new GoogleTaskManualSortAdapter(taskDao, googleTaskDao)
: new GoogleTaskAdapter(taskDao, googleTaskDao, preferences.addGoogleTasksToTop());
}
private TaskAdapter createManualFilterTaskAdapter(Filter filter) {

@ -6,7 +6,9 @@ import androidx.annotation.NonNull;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Field;
import com.todoroo.andlib.sql.Join;
import com.todoroo.andlib.sql.OrderType;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task;
import java.util.HashMap;
@ -14,6 +16,7 @@ import java.util.Map;
import org.tasks.R;
import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskList;
import org.tasks.preferences.Preferences;
public class GtasksFilter extends Filter {
@ -49,13 +52,56 @@ public class GtasksFilter extends Filter {
icon = list.getIcon();
}
public static String toManualOrder(String query) {
public static String toSubtaskQuery(Preferences preferences, String query) {
boolean manualSort = preferences.isManualSort();
String parentSort, childPrimarySort, childSecondarySort;
OrderType sortOrder;
OrderType titleOrder = OrderType.ASC;
if (manualSort) {
parentSort = "google_tasks.gt_order";
childPrimarySort = "p.gt_order";
childSecondarySort = "c.gt_order";
sortOrder = OrderType.ASC;
} else {
int sortMode = preferences.getSortMode();
parentSort = SortHelper.orderSelectForSortTypeRecursive(sortMode)
.replaceFirst("AS .*", "");
childPrimarySort = SortHelper.orderSelectForSortTypeRecursive(sortMode)
.replaceFirst("AS .*", "")
.replaceAll("tasks\\.", "parent_tasks.");
childSecondarySort = SortHelper.orderSelectForSortTypeRecursive(sortMode)
.replaceFirst("AS .*", "")
.replaceAll("tasks\\.", "child_tasks.");
sortOrder = sortMode == SortHelper.SORT_MODIFIED ? OrderType.DESC : OrderType.ASC;
if (preferences.isReverseSort() && sortMode == SortHelper.SORT_ALPHA) {
titleOrder = OrderType.DESC;
}
}
if (preferences.isReverseSort()) {
sortOrder = sortOrder == OrderType.DESC ? OrderType.ASC : OrderType.DESC;
}
query =
query.replace(
"WHERE",
"JOIN (SELECT google_tasks.*, COUNT(c.gt_id) AS children, 0 AS siblings, google_tasks.gt_order AS primary_sort, NULL AS secondary_sort FROM google_tasks LEFT JOIN google_tasks AS c ON c.gt_parent = google_tasks.gt_task WHERE google_tasks.gt_parent = 0 GROUP BY google_tasks.gt_task UNION SELECT c.*, 0 AS children, COUNT(s.gt_id) AS siblings, p.gt_order AS primary_sort, c.gt_order AS secondary_sort FROM google_tasks AS c LEFT JOIN google_tasks AS p ON c.gt_parent = p.gt_task LEFT JOIN tasks ON c.gt_parent = tasks._id LEFT JOIN google_tasks AS s ON s.gt_parent = p.gt_task WHERE c.gt_parent > 0 AND ((tasks.completed=0) AND (tasks.deleted=0) AND (tasks.hideUntil<(strftime('%s','now')*1000))) GROUP BY c.gt_task) as g2 ON g2.gt_id = google_tasks.gt_id WHERE");
"JOIN ("
+ "SELECT 0 AS indent, google_tasks.*, COUNT(c.gt_id) AS children, 0 AS siblings, " + parentSort + " AS primary_sort, NULL AS secondary_sort, UPPER(tasks.title) AS primary_title, NULL AS secondary_title "
+ "FROM google_tasks "
+ "LEFT JOIN google_tasks AS c ON c.gt_parent = google_tasks.gt_task "
+ "LEFT JOIN tasks ON tasks._id = google_tasks.gt_task "
+ "WHERE google_tasks.gt_parent = 0 "
+ "GROUP BY google_tasks.gt_task "
+ "UNION "
+ "SELECT 1 AS indent, c.*, 0 AS children, COUNT(s.gt_id) AS siblings, " + childPrimarySort + " AS primary_sort, " + childSecondarySort + " AS secondary_sort, UPPER(parent_tasks.title) AS primary_title, UPPER(child_tasks.title) AS secondary_title "
+ "FROM google_tasks AS c "
+ "LEFT JOIN google_tasks AS p ON c.gt_parent = p.gt_task "
+ "LEFT JOIN tasks AS parent_tasks ON c.gt_parent = parent_tasks._id "
+ "LEFT JOIN tasks AS child_tasks ON c.gt_task = child_tasks._id "
+ "LEFT JOIN google_tasks AS s ON s.gt_parent = p.gt_task "
+ "WHERE c.gt_parent > 0 AND ((parent_tasks.completed=0) AND (parent_tasks.deleted=0) AND (parent_tasks.hideUntil<(strftime('%s','now')*1000))) "
+ "GROUP BY c.gt_task"
+ ") as g2 ON g2.gt_id = google_tasks.gt_id WHERE");
query = query.replaceAll("ORDER BY .*", "");
query = query + "ORDER BY primary_sort ASC, secondary_sort ASC";
query = query + "ORDER BY primary_sort " + sortOrder + ", primary_title " + titleOrder + ", indent ASC" + ", secondary_sort " + sortOrder + ", secondary_title " + titleOrder;
return query;
}

@ -136,7 +136,7 @@ public class SubtasksHelper {
if (shouldUseSubtasksFragmentForFilter(filter)) {
if (filter instanceof GtasksFilter) {
query = GtasksFilter.toManualOrder(query);
query = GtasksFilter.toSubtaskQuery(preferences, query);
} else {
TagData tagData = tagDataDao.getTagByName(filter.listingTitle);
TaskListMetadata tlm = null;

@ -117,7 +117,7 @@ public class GoogleTask {
}
public int getIndent() {
return parent > 0 ? 0 : 1;
return parent > 0 ? 1 : 0;
}
public long getRemoteOrder() {

@ -23,6 +23,7 @@ import timber.log.Timber;
public class SortDialog extends InjectingDialogFragment {
private static final String EXTRA_MANUAL_ENABLED = "extra_manual_enabled";
private static final String EXTRA_IS_GOOGLE_TASKS = "extra_is_google_tasks";
private static final String EXTRA_SELECTED_INDEX = "extra_selected_index";
@Inject Preferences preferences;
@Inject DialogBuilder dialogBuilder;
@ -31,9 +32,12 @@ public class SortDialog extends InjectingDialogFragment {
private AlertDialog alertDialog;
private SortDialogCallback callback;
public static SortDialog newSortDialog(boolean manualEnabled) {
public static SortDialog newSortDialog(boolean manualEnabled, boolean isGoogleTasks) {
SortDialog sortDialog = new SortDialog();
sortDialog.manualEnabled = manualEnabled;
Bundle args = new Bundle();
args.putBoolean(EXTRA_MANUAL_ENABLED, manualEnabled);
args.putBoolean(EXTRA_IS_GOOGLE_TASKS, isGoogleTasks);
sortDialog.setArguments(args);
return sortDialog;
}
@ -42,6 +46,10 @@ public class SortDialog extends InjectingDialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
onCreate(savedInstanceState);
Bundle arguments = getArguments();
manualEnabled = arguments.getBoolean(EXTRA_MANUAL_ENABLED);
boolean isGoogleTasks = arguments.getBoolean(EXTRA_IS_GOOGLE_TASKS);
if (savedInstanceState != null) {
manualEnabled = savedInstanceState.getBoolean(EXTRA_MANUAL_ENABLED);
selectedIndex = savedInstanceState.getInt(EXTRA_SELECTED_INDEX);
@ -52,7 +60,7 @@ public class SortDialog extends InjectingDialogFragment {
List<String> items = new ArrayList<>();
if (manualEnabled) {
items.add(getString(R.string.SSD_sort_drag));
items.add(getString(isGoogleTasks ? R.string.SSD_sort_my_order : R.string.SSD_sort_drag));
}
items.add(getString(R.string.SSD_sort_auto));

@ -33,6 +33,7 @@ File %1$s contained %2$s.\n\n
<string name="action_call">Call</string>
<string name="action_open">Open</string>
<string name="SSD_sort_drag">Manual order with subtasks</string>
<string name="SSD_sort_my_order">My order</string>
<string name="SSD_sort_auto">Smart sort</string>
<string name="SSD_sort_alpha">By title</string>
<string name="SSD_sort_due">By due date</string>

Loading…
Cancel
Save