diff --git a/.travis.yml b/.travis.yml index e20e6a3e7..c611f8ab8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ jdk: oraclejdk8 env: global: - TARGET_API=27 - - BUILD_TOOLS=27.0.0 + - BUILD_TOOLS=27.0.3 matrix: - EMULATOR_API=21 ANDROID_ABI=armeabi-v7a android: diff --git a/app/build.gradle b/app/build.gradle index 0552d4872..f91d7d093 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -141,7 +141,6 @@ dependencies { compile 'com.jakewharton:process-phoenix:2.0.0' compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0' compile 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' - compile 'com.bignerdranch.android:recyclerview-multiselect:0.2' compile ('com.rubiconproject.oss:jchronic:0.2.6') { transitive = false } diff --git a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.java b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.java index 93c784385..2e3c94cf7 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.java +++ b/app/src/main/java/com/todoroo/astrid/adapter/TaskAdapter.java @@ -16,6 +16,13 @@ import com.todoroo.astrid.data.Task; import org.tasks.data.TaskAttachment; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.primitives.Longs.asList; + /** * Adapter for displaying a user's tasks as a list * @@ -25,6 +32,7 @@ import org.tasks.data.TaskAttachment; public class TaskAdapter { private PagedListAdapterHelper helper; + private Set selected = new HashSet<>(); public int getCount() { return helper.getItemCount(); @@ -34,6 +42,14 @@ public class TaskAdapter { this.helper = helper; } + public List getSelected() { + return newArrayList(selected); + } + + public void clearSelections() { + selected.clear(); + } + public interface OnCompletedTaskListener { void onCompletedTask(Task item, boolean newState); } @@ -58,6 +74,24 @@ public class TaskAdapter { return false; } + public void setSelected(long... ids) { + selected.clear(); + selected.addAll(asList(ids)); + } + + public boolean isSelected(Task task) { + return selected.contains(task.getId()); + } + + public void toggleSelection(Task task) { + long id = task.getId(); + if (selected.contains(id)) { + selected.remove(id); + } else { + selected.add(id); + } + } + public boolean isManuallySorted() { return false; } 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 3c58d809e..7d58346cd 100644 --- a/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java +++ b/app/src/main/java/com/todoroo/astrid/service/TaskDeleter.java @@ -64,11 +64,12 @@ public class TaskDeleter { taskDao.save(item); } - public int markDeleted(List tasks) { + public List markDeleted(List taskIds) { + List tasks = taskDao.fetch(taskIds); for (Task task : tasks) { markDeleted(task); } - return tasks.size(); + return tasks; } public int clearCompleted(Filter filter) { @@ -81,6 +82,9 @@ public class TaskDeleter { completed.add(task); } } - return markDeleted(completed); + for (Task task : completed) { + markDeleted(task); + } + return completed.size(); } } diff --git a/app/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java b/app/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java index eeb1676bb..a5053d691 100644 --- a/app/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java +++ b/app/src/main/java/com/todoroo/astrid/service/TaskDuplicator.java @@ -38,9 +38,9 @@ public class TaskDuplicator { this.googleTaskDao = googleTaskDao; } - public List duplicate(List tasks) { + public List duplicate(List taskIds) { List result = new ArrayList<>(); - for (Task task : tasks) { + for (Task task : taskDao.fetch(taskIds)) { result.add(clone(task)); } localBroadcastManager.broadcastRefresh(); diff --git a/app/src/main/java/com/todoroo/astrid/timers/TimerPlugin.java b/app/src/main/java/com/todoroo/astrid/timers/TimerPlugin.java index 813b921e4..ec5620639 100644 --- a/app/src/main/java/com/todoroo/astrid/timers/TimerPlugin.java +++ b/app/src/main/java/com/todoroo/astrid/timers/TimerPlugin.java @@ -49,6 +49,10 @@ public class TimerPlugin { updateTimer(task, true); } + public void stopTimer(Long task) { + stopTimer(taskDao.fetch(task)); + } + public void stopTimer(Task task) { updateTimer(task, false); } diff --git a/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java b/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java index 985249e28..a0a190836 100644 --- a/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java +++ b/app/src/main/java/org/tasks/tasklist/TaskListRecyclerAdapter.java @@ -18,8 +18,6 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.ViewGroup; -import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback; -import com.bignerdranch.android.multiselector.MultiSelector; import com.google.common.primitives.Longs; import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.activity.TaskListFragment; @@ -35,12 +33,8 @@ import org.tasks.analytics.Tracking; import org.tasks.dialogs.DialogBuilder; import org.tasks.ui.MenuColorizer; -import java.util.ArrayList; import java.util.List; -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Lists.transform; - public class TaskListRecyclerAdapter extends RecyclerView.Adapter implements ViewHolder.ViewHolderCallbacks, ListUpdateCallback { @@ -58,8 +52,6 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter } }; - private final MultiSelector multiSelector = new MultiSelector(); - private final Activity activity; private final TaskAdapter adapter; private final ViewHolderFactory viewHolderFactory; @@ -99,42 +91,26 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter public Bundle getSaveState() { Bundle information = new Bundle(); - List selectedTasks = transform(multiSelector.getSelectedPositions(), adapterHelper::getItem); - List selectedTaskIds = transform(selectedTasks, Task::getId); + List selectedTaskIds = adapter.getSelected(); information.putLongArray(EXTRA_SELECTED_TASK_IDS, Longs.toArray(selectedTaskIds)); return information; } public void restoreSaveState(Bundle savedState) { long[] longArray = savedState.getLongArray(EXTRA_SELECTED_TASK_IDS); - if (longArray.length > 0) { + if (longArray != null && longArray.length > 0) { mode = ((TaskListActivity) activity).startSupportActionMode(actionModeCallback); - multiSelector.setSelectable(true); - - for (int position : getTaskPositions(Longs.asList(longArray))) { - multiSelector.setSelected(position, 0L, true); - } + adapter.setSelected(longArray); updateModeTitle(); } } - private List getTaskPositions(List longs) { - List result = new ArrayList<>(); - for (int i = 0 ; i < adapterHelper.getItemCount() ; i++) { - Task item = adapterHelper.getItem(i); - if (longs.contains(item.getId())) { - result.add(i); - } - } - return result; - } - @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ViewGroup view = (ViewGroup) LayoutInflater.from(activity) .inflate(R.layout.task_adapter_row_simple, parent, false); - return viewHolderFactory.newViewHolder(view, this, multiSelector); + return viewHolderFactory.newViewHolder(view, this); } @Override @@ -144,6 +120,7 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter holder.bindView(task); holder.setMoving(false); holder.setIndent(adapter.getIndent(task)); + holder.setSelected(adapter.isSelected(task)); } } @@ -173,9 +150,9 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter } private void toggle(ViewHolder viewHolder) { - multiSelector.setSelectable(true); - multiSelector.tapSelection(viewHolder); - if (multiSelector.getSelectedPositions().isEmpty()) { + adapter.toggleSelection(viewHolder.task); + notifyItemChanged(viewHolder.getAdapterPosition()); + if (adapter.getSelected().isEmpty()) { dragging = false; if (mode != null) { mode.finish(); @@ -196,22 +173,18 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter } } - private List getSelectedTasks() { - return newArrayList(transform(multiSelector.getSelectedPositions(), adapterHelper::getItem)); - } - private void deleteSelectedItems() { tracker.reportEvent(Tracking.Events.MULTISELECT_DELETE); - List tasks = getSelectedTasks(); + List tasks = adapter.getSelected(); mode.finish(); - int result = taskDeleter.markDeleted(tasks); - taskList.onTaskDelete(tasks); - taskList.makeSnackbar(activity.getString(R.string.delete_multiple_tasks_confirmation, Integer.toString(result))).show(); + List result = taskDeleter.markDeleted(tasks); + taskList.onTaskDelete(result); + taskList.makeSnackbar(activity.getString(R.string.delete_multiple_tasks_confirmation, Integer.toString(result.size()))).show(); } private void copySelectedItems() { tracker.reportEvent(Tracking.Events.MULTISELECT_CLONE); - List tasks = getSelectedTasks(); + List tasks = adapter.getSelected(); mode.finish(); List duplicates = taskDuplicator.duplicate(tasks); taskList.onTaskCreated(duplicates); @@ -220,11 +193,11 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter private void updateModeTitle() { if (mode != null) { - mode.setTitle(Integer.toString(multiSelector.getSelectedPositions().size())); + mode.setTitle(Integer.toString(adapter.getSelected().size())); } } - private ModalMultiSelectorCallback actionModeCallback = new ModalMultiSelectorCallback(multiSelector) { + private ActionMode.Callback actionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { MenuInflater inflater = actionMode.getMenuInflater(); @@ -233,6 +206,11 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter return true; } + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { @@ -255,9 +233,9 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter @Override public void onDestroyActionMode(ActionMode actionMode) { - super.onDestroyActionMode(actionMode); - multiSelector.clearSelections(); + adapter.clearSelections(); TaskListRecyclerAdapter.this.mode = null; + notifyDataSetChanged(); } }; diff --git a/app/src/main/java/org/tasks/tasklist/ViewHolder.java b/app/src/main/java/org/tasks/tasklist/ViewHolder.java index 51f7fd6d2..2fa74e3eb 100644 --- a/app/src/main/java/org/tasks/tasklist/ViewHolder.java +++ b/app/src/main/java/org/tasks/tasklist/ViewHolder.java @@ -5,6 +5,7 @@ import android.app.PendingIntent; import android.content.Context; import android.graphics.Paint; import android.support.v7.app.AlertDialog; +import android.support.v7.widget.RecyclerView; import android.text.SpannableString; import android.text.TextUtils; import android.text.method.LinkMovementMethod; @@ -15,8 +16,6 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import com.bignerdranch.android.multiselector.MultiSelector; -import com.bignerdranch.android.multiselector.MultiSelectorBindingHolder; import com.google.common.collect.Lists; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.api.TaskAction; @@ -43,21 +42,9 @@ import static com.google.common.collect.Lists.newArrayList; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastKitKat; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop; -class ViewHolder extends MultiSelectorBindingHolder { +class ViewHolder extends RecyclerView.ViewHolder { - @Override - public void setSelectable(boolean selectable) { - this.selectable = selectable; - updateBackground(); - } - - @Override - public boolean isSelectable() { - return selectable; - } - - @Override - public void setActivated(boolean selected) { + public void setSelected(boolean selected) { this.selected = selected; updateBackground(); } @@ -70,16 +57,13 @@ class ViewHolder extends MultiSelectorBindingHolder { private void updateBackground() { if (selected || moving) { rowBody.setBackgroundColor(selectedColor); - } else if (selectable) { - rowBody.setBackgroundColor(0); } else { rowBody.setBackgroundResource(background); rowBody.getBackground().jumpToCurrentState(); } } - @Override - public boolean isActivated() { + public boolean isSelected() { return selected; } @@ -114,7 +98,6 @@ class ViewHolder extends MultiSelectorBindingHolder { private final int selectedColor; private final int textColorOverdue; private int indent; - private boolean selectable = false; private boolean selected; private boolean moving; @@ -122,9 +105,8 @@ class ViewHolder extends MultiSelectorBindingHolder { CheckBoxes checkBoxes, TagFormatter tagFormatter, int textColorOverdue, int textColorSecondary, int textColorHint, TaskDao taskDao, DialogBuilder dialogBuilder, ViewHolderCallbacks callback, - DisplayMetrics metrics, int background, int selectedColor, MultiSelector multiSelector, - int rowPadding) { - super(view, multiSelector); + DisplayMetrics metrics, int background, int selectedColor, int rowPadding) { + super(view); this.context = context; this.checkBoxes = checkBoxes; this.tagFormatter = tagFormatter; diff --git a/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.java b/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.java index 39e8a60c1..61b62504c 100644 --- a/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.java +++ b/app/src/main/java/org/tasks/tasklist/ViewHolderFactory.java @@ -4,7 +4,6 @@ import android.content.Context; import android.util.DisplayMetrics; import android.view.ViewGroup; -import com.bignerdranch.android.multiselector.MultiSelector; import com.todoroo.astrid.dao.TaskDao; import org.tasks.R; @@ -57,9 +56,9 @@ public class ViewHolderFactory { rowPadding = convertDpToPixels(metrics, preferences.getInt(R.string.p_rowPadding, 16)); } - ViewHolder newViewHolder(ViewGroup viewGroup, ViewHolder.ViewHolderCallbacks callbacks, MultiSelector multiSelector) { + ViewHolder newViewHolder(ViewGroup viewGroup, ViewHolder.ViewHolderCallbacks callbacks) { return new ViewHolder(context, viewGroup, showFullTaskTitle, fontSize, checkBoxes, tagFormatter, textColorOverdue, textColorSecondary, textColorHint, taskDao, - dialogBuilder, callbacks, metrics, background, selectedColor, multiSelector, rowPadding); + dialogBuilder, callbacks, metrics, background, selectedColor, rowPadding); } }