diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListFragment.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListFragment.java index 838dd78b9..a22b15a5b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListFragment.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListFragment.java @@ -27,7 +27,7 @@ import com.todoroo.astrid.data.Task; import com.todoroo.astrid.helper.ProgressBarSyncResultCallback; import com.todoroo.astrid.service.SyncV2Service; import com.todoroo.astrid.service.ThemeService; -import com.todoroo.astrid.subtasks.OrderedListFragmentHelper; +import com.todoroo.astrid.subtasks.NewOrderedListFragmentHelper; import com.todoroo.astrid.subtasks.SubtasksListFragment; public class GtasksListFragment extends SubtasksListFragment { @@ -60,8 +60,8 @@ public class GtasksListFragment extends SubtasksListFragment { }; @Override - protected OrderedListFragmentHelper createFragmentHelper() { - return new OrderedListFragmentHelper(this, gtasksTaskListUpdater); + protected NewOrderedListFragmentHelper createFragmentHelper() { + return new NewOrderedListFragmentHelper(this, null /*gtasksTaskListUpdater*/); } @Override @@ -75,7 +75,7 @@ public class GtasksListFragment extends SubtasksListFragment { long storeObjectId = extras.getLong(TOKEN_STORE_ID, 0); list = storeObjectDao.fetch(storeObjectId, LIST_PROPERTIES); - ((OrderedListFragmentHelper)helper).setList(list); + ((NewOrderedListFragmentHelper)helper).setList(list); } @Override diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListFragmentHelper.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListFragmentHelper.java new file mode 100644 index 000000000..5ad342c51 --- /dev/null +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListFragmentHelper.java @@ -0,0 +1,321 @@ +package com.todoroo.astrid.subtasks; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import android.app.Activity; +import android.content.Context; +import android.database.Cursor; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.MarginLayoutParams; +import android.widget.ListView; + +import com.commonsware.cwac.tlv.TouchListView.DropListener; +import com.commonsware.cwac.tlv.TouchListView.GrabberClickListener; +import com.commonsware.cwac.tlv.TouchListView.SwipeListener; +import com.timsu.astrid.R; +import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.andlib.utility.DateUtilities; +import com.todoroo.andlib.utility.DialogUtilities; +import com.todoroo.andlib.utility.Preferences; +import com.todoroo.astrid.activity.TaskListFragment; +import com.todoroo.astrid.adapter.TaskAdapter; +import com.todoroo.astrid.adapter.TaskAdapter.OnCompletedTaskListener; +import com.todoroo.astrid.api.Filter; +import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.service.MetadataService; +import com.todoroo.astrid.service.TaskService; +import com.todoroo.astrid.service.ThemeService; +import com.todoroo.astrid.ui.DraggableListView; +import com.todoroo.astrid.utility.AstridPreferences; + +public class NewOrderedListFragmentHelper { + + + private final DisplayMetrics metrics = new DisplayMetrics(); + private final NewOrderedListUpdater updater; + private final TaskListFragment fragment; + + @Autowired TaskService taskService; + @Autowired MetadataService metadataService; + + private DraggableTaskAdapter taskAdapter; + + private LIST list; + + public NewOrderedListFragmentHelper(TaskListFragment fragment, NewOrderedListUpdater updater) { + DependencyInjectionService.getInstance().inject(this); + this.fragment = fragment; + this.updater = updater; + } + + // --- ui component setup + + private Activity getActivity() { + return fragment.getActivity(); + } + + private ListView getListView() { + return fragment.getListView(); + } + + private Filter getFilter() { + return fragment.getFilter(); + } + + public DraggableListView getTouchListView() { + DraggableListView tlv = (DraggableListView) fragment.getListView(); + return tlv; + } + + public void setUpUiComponents() { + TypedValue tv = new TypedValue(); + getActivity().getTheme().resolveAttribute(R.attr.asThemeTextColor, tv, false); + getTouchListView().setDragndropBackgroundColor(tv.data); + getTouchListView().setDropListener(dropListener); + getTouchListView().setClickListener(rowClickListener); + getTouchListView().setSwipeListener(swipeListener); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); + + if(Preferences.getInt(AstridPreferences.P_SUBTASKS_HELP, 0) == 0) + showSubtasksHelp(); + } + + @SuppressWarnings("nls") + private void showSubtasksHelp() { + String body = String.format("

%s

" + + "
%s



%s", + getActivity().getString(R.string.subtasks_help_1), + "subtasks_vertical.png", + getActivity().getString(R.string.subtasks_help_2), + "subtasks_horizontal.png", + getActivity().getString(R.string.subtasks_help_3)); + + String color = ThemeService.getDialogTextColorString(); + String html = String.format("%s", + color, body); + + DialogUtilities.htmlDialog(getActivity(), html, R.string.subtasks_help_title); + Preferences.setInt(AstridPreferences.P_SUBTASKS_HELP, 1); + } + + public void beforeSetUpTaskList(Filter filter) { + updater.initialize(list, filter); + } + +// public Property[] taskProperties() { +// ArrayList> properties = new ArrayList>(Arrays.asList(TaskAdapter.PROPERTIES)); +// properties.add(updater.indentProperty()); +// properties.add(updater.orderProperty()); +// return properties.toArray(new Property[properties.size()]); +// } + + + private final DropListener dropListener = new DropListener() { + @Override + public void drop(int from, int to) { + long targetTaskId = taskAdapter.getItemId(from); + if (targetTaskId <= 0) return; // This can happen with gestures on empty parts of the list (e.g. extra space below tasks) + long destinationTaskId = taskAdapter.getItemId(to); + + try { + if(to >= getListView().getCount()) + updater.moveTo(targetTaskId, -1); + else + updater.moveTo(targetTaskId, destinationTaskId); + } catch (Exception e) { + Log.e("drag", "Drag Error", e); //$NON-NLS-1$ //$NON-NLS-2$ + } + + fragment.loadTaskListContent(true); + } + }; + + private final SwipeListener swipeListener = new SwipeListener() { + @Override + public void swipeRight(int which) { + indent(which, 1); + } + + @Override + public void swipeLeft(int which) { + indent(which, -1); + } + + protected void indent(int which, int delta) { + long targetTaskId = taskAdapter.getItemId(which); + if (targetTaskId <= 0) return; // This can happen with gestures on empty parts of the list (e.g. extra space below tasks) + try { + updater.indent(targetTaskId, delta); + } catch (Exception e) { + Log.e("drag", "Indent Error", e); //$NON-NLS-1$ //$NON-NLS-2$ + } + fragment.loadTaskListContent(true); + } + }; + + private final GrabberClickListener rowClickListener = new GrabberClickListener() { + @Override + public void onLongClick(final View v) { + if(v == null) + return; + + fragment.registerForContextMenu(getListView()); + getListView().showContextMenuForChild(v); + fragment.unregisterForContextMenu(getListView()); + } + + @Override + public void onClick(View v) { + if(v == null) + return; + ((DraggableTaskAdapter) taskAdapter).getListener().onClick(v); + } + }; + + public TaskAdapter createTaskAdapter(TodorooCursor cursor, + AtomicReference sqlQueryTemplate) { + int resource = Preferences.getBoolean(R.string.p_taskRowStyle, false) ? + R.layout.task_adapter_row_simple : R.layout.task_adapter_row; + + taskAdapter = new DraggableTaskAdapter(fragment, resource, + cursor, sqlQueryTemplate, false, null); + + taskAdapter.addOnCompletedTaskListener(new OnCompletedTaskListener() { + @Override + public void onCompletedTask(Task item, boolean newState) { + setCompletedForItemAndSubtasks(item, newState); + } + }); + + return taskAdapter; + } + + private final class DraggableTaskAdapter extends TaskAdapter { + + private DraggableTaskAdapter(TaskListFragment activity, int resource, + Cursor c, AtomicReference query, boolean autoRequery, + OnCompletedTaskListener onCompletedTaskListener) { + super(activity, resource, c, query, autoRequery, + onCompletedTaskListener); + + applyListeners = APPLY_LISTENERS_NONE; + } + + @Override + protected ViewHolder getTagFromCheckBox(View v) { + return (ViewHolder)((View)v.getParent()).getTag(); + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + View view = super.newView(context, cursor, parent); + view.getLayoutParams().height = Math.round(45 * metrics.density); + + ViewHolder vh = (ViewHolder) view.getTag(); + + MarginLayoutParams rowParams = (MarginLayoutParams) vh.rowBody.getLayoutParams(); + rowParams.topMargin = rowParams.bottomMargin = 0; + + ViewGroup.LayoutParams pictureParams = vh.picture.getLayoutParams(); + pictureParams.width = pictureParams.height = Math.round(38 * metrics.density); + + pictureParams = vh.pictureBorder.getLayoutParams(); + pictureParams.width = pictureParams.height = Math.round(38 * metrics.density); + + return view; + } + + @Override + public synchronized void setFieldContentsAndVisibility(View view) { + super.setFieldContentsAndVisibility(view); + + ViewHolder vh = (ViewHolder) view.getTag(); + int indent = updater.getIndentForTask(vh.task.getId()); + vh.rowBody.setPadding(Math.round(indent * 20 * metrics.density), 0, 0, 0); + } + + @Override + protected void addListeners(View container) { + super.addListeners(container); + } + + public TaskRowListener getListener() { + return listener; + } + } + + private final Map> chainedCompletions = + Collections.synchronizedMap(new HashMap>()); + + private void setCompletedForItemAndSubtasks(final Task item, final boolean completedState) { + final long itemId = item.getId(); + + final Task model = new Task(); + final long completionDate = completedState ? DateUtilities.now() : 0; + + if(completedState == false) { + ArrayList chained = chainedCompletions.get(itemId); + if(chained != null) { + for(Long taskId : chained) { + model.setId(taskId); + model.setValue(Task.COMPLETION_DATE, completionDate); + taskService.save(model); + model.clear(); + + taskAdapter.getCompletedItems().put(taskId, false); + } + taskAdapter.notifyDataSetInvalidated(); + } + return; + } + + final ArrayList chained = new ArrayList(); +// final int parentIndent = item.getValue(updater.indentProperty()); + updater.applyToDescendants(itemId, new NewOrderedListUpdater.OrderedListNodeVisitor() { + @Override + public void visitNode(NewOrderedListUpdater.Node node) { +// Task childTask = taskService.fetchById(node.taskId, Task.RECURRENCE); +// +// if(!TextUtils.isEmpty(childTask.getValue(Task.RECURRENCE))) { +// Metadata metadata = updater.getTaskMetadata(list, node.taskId); +// metadata.setValue(updater.indentProperty(), parentIndent); +// metadataService.save(metadata); +// } + + model.setId(node.taskId); + model.setValue(Task.COMPLETION_DATE, completionDate); + taskService.save(model); + model.clear(); + + taskAdapter.getCompletedItems().put(node.taskId, true); + chained.add(node.taskId); + } + }); + + if(chained.size() > 0) { + chainedCompletions.put(itemId, chained); + taskAdapter.notifyDataSetInvalidated(); + } + } + + public void setList(LIST list) { + this.list = list; + } + + public void onDeleteTask(Task task) { + updater.onDeleteTask(task.getId()); + taskAdapter.notifyDataSetInvalidated(); + } + + +} diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListUpdater.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListUpdater.java index cffa5c554..0dc2e51ee 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListUpdater.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/NewOrderedListUpdater.java @@ -12,6 +12,7 @@ import android.util.Log; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.astrid.api.Filter; +import com.todoroo.astrid.data.Task; public abstract class NewOrderedListUpdater { @@ -20,8 +21,8 @@ public abstract class NewOrderedListUpdater { idToNode = new HashMap(); } - public interface OrderedListIterator { - public void processTask(Node node); + public interface OrderedListNodeVisitor { + public void visitNode(Node node); } protected static class Node { @@ -41,7 +42,8 @@ public abstract class NewOrderedListUpdater { private final HashMap idToNode; - protected abstract String getSerializedTree(); + protected abstract String getSerializedTree(LIST list); + protected abstract void writeSerialization(LIST list, String serialized); public int getIndentForTask(long targetTaskId) { Node n = idToNode.get(targetTaskId); @@ -51,7 +53,7 @@ public abstract class NewOrderedListUpdater { } protected void initialize(LIST list, Filter filter) { - treeRoot = buildTreeModel(getSerializedTree()); + treeRoot = buildTreeModel(getSerializedTree(list)); } public Long[] getOrderedIds() { @@ -60,6 +62,17 @@ public abstract class NewOrderedListUpdater { return ids.toArray(new Long[ids.size()]); } + public String getOrderString() { + Long[] ids = getOrderedIds(); + StringBuilder builder = new StringBuilder(); + for (int i = ids.length - 1; i >= 0; i--) { + builder.append(Task.ID.eq(ids[i]).toString()); + if (i > 0) + builder.append(", "); //$NON-NLS-1$ + } + return builder.toString(); + } + private void orderedIdHelper(Node node, List ids) { if (node != treeRoot) ids.add(node.taskId); @@ -69,6 +82,25 @@ public abstract class NewOrderedListUpdater { } } + public void applyToDescendants(long taskId, OrderedListNodeVisitor visitor) { + Node n = idToNode.get(taskId); + if (n == null) + return; + applyToDescendantsHelper(n, visitor); + } + + private void applyToDescendantsHelper(Node n, OrderedListNodeVisitor visitor) { + ArrayList children = n.children; + for (Node child : children) { + visitor.visitNode(child); + applyToDescendantsHelper(child, visitor); + } + } + + public void iterateOverList(OrderedListNodeVisitor visitor) { + applyToDescendantsHelper(treeRoot, visitor); + } + public void indent(long targetTaskId, int delta) { Node node = idToNode.get(targetTaskId); indentHelper(node, delta); @@ -148,6 +180,20 @@ public abstract class NewOrderedListUpdater { moveThis.parent = treeRoot; } + public void onDeleteTask(long taskId) { + Node task = idToNode.get(taskId); + if (task == null) + return; + + Node parent = task.parent; + ArrayList siblings = parent.children; + siblings.remove(task); + for (Node child : task.children) { + indentHelper(child, -1); + } + idToNode.remove(taskId); + } + private Node buildTreeModel(String serializedTree) { Node root = new Node(-1, null, -1); try { diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksListFragment.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksListFragment.java index 633d8466f..f9eee2894 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksListFragment.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksListFragment.java @@ -10,10 +10,10 @@ import android.view.View; import android.view.ViewGroup; import com.timsu.astrid.R; -import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.astrid.activity.TaskListFragment; import com.todoroo.astrid.adapter.TaskAdapter; +import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; /** @@ -24,7 +24,7 @@ import com.todoroo.astrid.data.Task; */ public class SubtasksListFragment extends TaskListFragment { - protected OrderedListFragmentHelper helper; + protected NewOrderedListFragmentHelper helper; @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -32,10 +32,10 @@ public class SubtasksListFragment extends TaskListFragment { super.onActivityCreated(savedInstanceState); } - protected OrderedListFragmentHelper createFragmentHelper() { - OrderedListFragmentHelper olfh = - new OrderedListFragmentHelper(this, new SubtasksUpdater()); - olfh.setList(SubtasksMetadata.LIST_ACTIVE_TASKS); + protected NewOrderedListFragmentHelper createFragmentHelper() { + NewOrderedListFragmentHelper olfh = + new NewOrderedListFragmentHelper(this, new SubtasksUpdater()); + olfh.setList(getActiveTagData()); return olfh; } @@ -60,12 +60,6 @@ public class SubtasksListFragment extends TaskListFragment { unregisterForContextMenu(getListView()); } - @Override - public Property[] taskProperties() { - return helper.taskProperties(); - } - - @Override protected boolean isDraggable() { return true; diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksTagListFragment.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksTagListFragment.java index d5bc1b66e..0bc86d9a4 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksTagListFragment.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksTagListFragment.java @@ -9,25 +9,24 @@ import android.view.View; import android.view.ViewGroup; import com.timsu.astrid.R; -import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.astrid.actfm.TagViewFragment; import com.todoroo.astrid.adapter.TaskAdapter; +import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; public class SubtasksTagListFragment extends TagViewFragment { - private final OrderedListFragmentHelper helper; + private final NewOrderedListFragmentHelper helper; public SubtasksTagListFragment() { super(); - helper = new OrderedListFragmentHelper(this, new SubtasksUpdater()); + helper = new NewOrderedListFragmentHelper(this, new SubtasksUpdater()); } @Override protected void postLoadTagData() { - String list = "td:" + tagData.getId(); //$NON-NLS-1$ - helper.setList(list); + helper.setList(tagData); } @Override @@ -58,12 +57,6 @@ public class SubtasksTagListFragment extends TagViewFragment { unregisterForContextMenu(getListView()); } - @Override - public Property[] taskProperties() { - return helper.taskProperties(); - } - - @Override protected boolean isDraggable() { return true; diff --git a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksUpdater.java b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksUpdater.java index 888c82677..fe357fbfd 100644 --- a/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksUpdater.java +++ b/astrid/plugin-src/com/todoroo/astrid/subtasks/SubtasksUpdater.java @@ -5,154 +5,64 @@ */ package com.todoroo.astrid.subtasks; -import java.util.HashSet; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import com.todoroo.andlib.data.Property.IntegerProperty; -import com.todoroo.andlib.data.Property.LongProperty; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.sql.Criterion; -import com.todoroo.andlib.sql.Query; +import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; -import com.todoroo.astrid.data.Metadata; +import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.service.MetadataService; +import com.todoroo.astrid.service.TagDataService; import com.todoroo.astrid.service.TaskService; -public class SubtasksUpdater extends OrderedListUpdater { - - private static final String METADATA_ID = "mdi"; //$NON-NLS-1$ +public class SubtasksUpdater extends NewOrderedListUpdater { - @Autowired MetadataService metadataService; + @Autowired TagDataService tagDataService; @Autowired TaskService taskService; - @Override - protected IntegerProperty indentProperty() { - return SubtasksMetadata.INDENT; - } + public static final String ACTIVE_TASKS_ORDER = "active_tasks_order"; //$NON-NLS-1$ @Override - protected LongProperty orderProperty() { - return SubtasksMetadata.ORDER; - } - @Override - protected LongProperty parentProperty() { - return null; + protected void initialize(TagData list, Filter filter) { + super.initialize(list, filter); + applySubtasksToFilter(filter); } - @Override - protected void initialize(String list, Filter filter) { - applySubtasksToFilter(filter, list); - sanitizeTaskList(filter, list); - } + @SuppressWarnings("nls") + public void applySubtasksToFilter(Filter filter) { + String query = filter.getSqlQuery(); - @Override - protected Metadata getTaskMetadata(String list, long taskId) { - TodorooCursor cursor = metadataService.query(Query.select(Metadata.PROPERTIES).where( - Criterion.and( - Metadata.TASK.eq(taskId), - Metadata.KEY.eq(SubtasksMetadata.METADATA_KEY), - SubtasksMetadata.TAG.eq(list)))); - try { - cursor.moveToFirst(); - if(cursor.isAfterLast()) - return null; - return new Metadata(cursor); - } finally { - cursor.close(); - } - } + query = query.replaceAll("ORDER BY .*", ""); + query = query + String.format(" ORDER BY %s, %s, %s, %s)", + Task.DELETION_DATE, Task.COMPLETION_DATE, + getOrderString(), Task.CREATION_DATE); + query = query.replace(TaskCriteria.isVisible().toString(), + Criterion.all.toString()); - @Override - protected Metadata createEmptyMetadata(String list, long taskId) { - Metadata m = new Metadata(); - m.setValue(Metadata.TASK, taskId); - m.setValue(Metadata.KEY, SubtasksMetadata.METADATA_KEY); - m.setValue(SubtasksMetadata.TAG, list); - return m; + filter.setFilterQueryOverride(query); } @Override - protected void iterateThroughList(Filter filter, String list, OrderedListIterator iterator) { - TodorooCursor cursor = taskService.query(Query.select(Task.ID, - Metadata.ID.as(METADATA_ID), Metadata.TASK, Metadata.KEY, SubtasksMetadata.INDENT, - SubtasksMetadata.ORDER).withQueryTemplate(filter.getSqlQuery())); - TodorooCursor metadataCursor = new TodorooCursor(cursor.getCursor(), - cursor.getProperties()); - Metadata metadata = new Metadata(); - try { - for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { - metadata.readFromCursor(metadataCursor); - metadata.setId(cursor.getLong(cursor.getColumnIndex(METADATA_ID))); - iterator.processTask(cursor.get(Task.ID), metadata); - } - } finally { - cursor.close(); + protected String getSerializedTree(TagData list) { + if (list == null) { + String order = Preferences.getStringValue(ACTIVE_TASKS_ORDER); + if (order == null) + order = "{}"; //$NON-NLS-1$ + return order; } + return list.getValue(TagData.NAME); } - @SuppressWarnings("nls") - public void applySubtasksToFilter(Filter filter, String tagName) { - String query = filter.getSqlQuery(); - - if(tagName == null) - tagName = SubtasksMetadata.LIST_ACTIVE_TASKS; - String subtaskJoin = String.format("LEFT JOIN %s ON (%s = %s AND %s = '%s' AND %s = '%s') ", - Metadata.TABLE, Task.ID, Metadata.TASK, - Metadata.KEY, SubtasksMetadata.METADATA_KEY, - SubtasksMetadata.TAG, tagName); - - if(!query.contains(subtaskJoin)) { - query = subtaskJoin + query; - query = query.replaceAll("ORDER BY .*", ""); - query = query + String.format(" ORDER BY %s, %s, IFNULL(CAST(%s AS LONG), %s)", - Task.DELETION_DATE, Task.COMPLETION_DATE, - SubtasksMetadata.ORDER, Task.CREATION_DATE); - query = query.replace(TaskCriteria.isVisible().toString(), - Criterion.all.toString()); - - filter.setFilterQueryOverride(query); + @Override + protected void writeSerialization(TagData list, String serialized) { + if (list == null) + Preferences.setString(ACTIVE_TASKS_ORDER, serialized); + else { + list.setValue(TagData.NAME, serialized); + tagDataService.save(list); } } - public void sanitizeTaskList(Filter filter, String list) { - final AtomicInteger previousIndent = new AtomicInteger(-1); - final AtomicLong previousOrder = new AtomicLong(-1); - final HashSet taskIds = new HashSet(); - - iterateThroughList(filter, list, new OrderedListIterator() { - @Override - public void processTask(long taskId, Metadata metadata) { - if(!metadata.isSaved()) - return; - - if(taskIds.contains(taskId)) { - metadataService.delete(metadata); - return; - } - - long order = metadata.getValue(SubtasksMetadata.ORDER); - if(order <= previousOrder.get()) // bad - order = previousOrder.get() + 1; - - int indent = metadata.getValue(SubtasksMetadata.INDENT); - if(indent < 0 || indent > previousIndent.get() + 1) // bad - indent = Math.max(0, previousIndent.get() + 1); - - metadata.setValue(SubtasksMetadata.ORDER, order); - metadata.setValue(SubtasksMetadata.INDENT, indent); - saveAndUpdateModifiedDate(metadata); - - previousIndent.set(indent); - previousOrder.set(order); - taskIds.add(taskId); - } - }); - } - }