Batch move tasks between remote lists

pull/699/head
Alex Baker 8 years ago
parent 9b850f91e6
commit 9b4c767273

@ -24,7 +24,6 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.files.FilesControlSet;
@ -49,7 +48,6 @@ import org.tasks.injection.InjectingFragment;
import org.tasks.notifications.NotificationManager;
import org.tasks.preferences.Preferences;
import org.tasks.ui.MenuColorizer;
import org.tasks.ui.RemoteListFragment;
import org.tasks.ui.TaskEditControlFragment;
public final class TaskEditFragment extends InjectingFragment
@ -231,10 +229,6 @@ public final class TaskEditFragment extends InjectingFragment
return getFragment(EditTitleControlSet.TAG);
}
private RemoteListFragment getRemoteListFragment() {
return getFragment(RemoteListFragment.TAG);
}
private RepeatControlSet getRepeatControlSet() {
return getFragment(RepeatControlSet.TAG);
}
@ -316,10 +310,6 @@ public final class TaskEditFragment extends InjectingFragment
getEditTitleControlSet().repeatChanged(repeat);
}
public void onRemoteListChanged(Filter list) {
getRemoteListFragment().setList(list);
}
public void onDueDateChanged(long dueDate) {
RepeatControlSet repeatControlSet = getRepeatControlSet();
if (repeatControlSet != null) {

@ -81,8 +81,7 @@ public class TaskListActivity extends InjectingAppCompatActivity
DeadlineControlSet.DueDateChangeListener,
TaskEditFragment.TaskEditFragmentCallbackHandler,
CommentBarFragment.CommentBarFragmentCallback,
SortDialog.SortDialogCallback,
RemoteListSelectionHandler {
SortDialog.SortDialogCallback {
/** For indicating the new list screen should be launched at fragment setup time */
public static final String TOKEN_CREATE_NEW_LIST_NAME = "newListName"; // $NON-NLS-1$
@ -496,11 +495,6 @@ public class TaskListActivity extends InjectingAppCompatActivity
onFilterItemClicked(filter);
}
@Override
public void selectedList(Filter list) {
getTaskEditFragment().onRemoteListChanged(list);
}
@Override
public void onSupportActionModeStarted(@NonNull ActionMode mode) {
super.onSupportActionModeStarted(mode);

@ -5,6 +5,7 @@
*/
package com.todoroo.astrid.activity;
import static android.app.Activity.RESULT_OK;
import static android.support.v4.content.ContextCompat.getColor;
import android.app.Activity;
@ -45,12 +46,14 @@ import com.todoroo.astrid.gtasks.GtasksSubtaskListFragment;
import com.todoroo.astrid.service.TaskCreator;
import com.todoroo.astrid.service.TaskDeleter;
import com.todoroo.astrid.service.TaskDuplicator;
import com.todoroo.astrid.service.TaskMover;
import com.todoroo.astrid.timers.TimerPlugin;
import java.util.List;
import javax.inject.Inject;
import org.tasks.LocalBroadcastManager;
import org.tasks.R;
import org.tasks.activities.FilterSettingsActivity;
import org.tasks.activities.RemoteListSupportPicker;
import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking;
import org.tasks.dialogs.DialogBuilder;
@ -84,6 +87,7 @@ public class TaskListFragment extends InjectingFragment
// --- instance variables
private static final int REQUEST_EDIT_FILTER = 11544;
public static final int REQUEST_MOVE_TASKS = 11545;
private final RefreshReceiver refreshReceiver = new RefreshReceiver();
@Inject protected Tracker tracker;
protected Filter filter;
@ -100,6 +104,7 @@ public class TaskListFragment extends InjectingFragment
@Inject ViewHolderFactory viewHolderFactory;
@Inject LocalBroadcastManager localBroadcastManager;
@Inject Device device;
@Inject TaskMover taskMover;
@BindView(R.id.swipe_layout)
SwipeRefreshLayout swipeRefreshLayout;
@ -496,7 +501,7 @@ public class TaskListFragment extends InjectingFragment
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_RECOGNITION_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
if (resultCode == RESULT_OK) {
List<String> match = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (match != null && match.size() > 0 && match.get(0).length() > 0) {
String recognizedSpeech = match.get(0);
@ -508,7 +513,7 @@ public class TaskListFragment extends InjectingFragment
}
}
} else if (requestCode == REQUEST_EDIT_FILTER) {
if (resultCode == Activity.RESULT_OK) {
if (resultCode == RESULT_OK) {
String action = data.getAction();
TaskListActivity activity = (TaskListActivity) getActivity();
if (FilterSettingsActivity.ACTION_FILTER_DELETED.equals(action)) {
@ -522,6 +527,13 @@ public class TaskListFragment extends InjectingFragment
activity.recreate();
}
}
} else if (requestCode == REQUEST_MOVE_TASKS) {
if (resultCode == RESULT_OK) {
taskMover.move(
taskAdapter.getSelected(),
data.getParcelableExtra(RemoteListSupportPicker.EXTRA_SELECTED));
recyclerAdapter.finishActionMode();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}

@ -0,0 +1,81 @@
package com.todoroo.astrid.service;
import static com.todoroo.andlib.utility.DateUtilities.now;
import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.GtasksFilter;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.UUIDHelper;
import java.util.List;
import javax.inject.Inject;
import org.tasks.data.CaldavDao;
import org.tasks.data.CaldavTask;
import org.tasks.data.GoogleTask;
import org.tasks.data.GoogleTaskDao;
import org.tasks.sync.SyncAdapters;
public class TaskMover {
private final TaskDao taskDao;
private final CaldavDao caldavDao;
private final GoogleTaskDao googleTaskDao;
private final SyncAdapters syncAdapters;
@Inject
public TaskMover(TaskDao taskDao, CaldavDao caldavDao, GoogleTaskDao googleTaskDao, SyncAdapters syncAdapters) {
this.taskDao = taskDao;
this.caldavDao = caldavDao;
this.googleTaskDao = googleTaskDao;
this.syncAdapters = syncAdapters;
}
public void move(List<Long> tasks, Filter selectedList) {
List<Task> fetch = taskDao.fetch(tasks);
for (Task task : fetch) {
performMove(task, selectedList);
task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
task.setModificationDate(now());
taskDao.save(task);
}
syncAdapters.syncNow();
}
public void move(Task task, Filter selectedList) {
performMove(task, selectedList);
}
private void performMove(Task task, Filter selectedList) {
long id = task.getId();
GoogleTask googleTask = googleTaskDao.getByTaskId(id);
if (googleTask != null
&& selectedList instanceof GtasksFilter
&& googleTask.getListId().equals(((GtasksFilter) selectedList).getRemoteId())) {
return;
}
CaldavTask caldavTask = caldavDao.getTask(id);
if (caldavTask != null
&& selectedList instanceof CaldavFilter
&& caldavTask.getCalendar().equals(((CaldavFilter) selectedList).getUuid())) {
return;
}
task.putTransitory(SyncFlags.FORCE_SYNC, true);
if (googleTask != null) {
googleTask.setDeleted(now());
googleTaskDao.update(googleTask);
}
if (caldavTask != null) {
caldavTask.setDeleted(now());
caldavDao.update(caldavTask);
}
if (selectedList instanceof GtasksFilter) {
googleTaskDao.insert(new GoogleTask(id, ((GtasksFilter) selectedList).getRemoteId()));
} else if (selectedList instanceof CaldavFilter) {
caldavDao.insert(
new CaldavTask(id, ((CaldavFilter) selectedList).getUuid(), UUIDHelper.newUUID()));
}
}
}

@ -2,8 +2,10 @@ package org.tasks.activities;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import com.todoroo.astrid.adapter.FilterAdapter;
import com.todoroo.astrid.api.CaldavFilter;
@ -18,18 +20,20 @@ import org.tasks.injection.InjectingDialogFragment;
public class RemoteListSupportPicker extends InjectingDialogFragment {
private static final String EXTRA_SELECTED = "extra_selected";
public static final String EXTRA_SELECTED = "extra_selected";
@Inject DialogBuilder dialogBuilder;
@Inject FilterAdapter filterAdapter;
private RemoteListSelectionHandler handler;
public static RemoteListSupportPicker newRemoteListSupportPicker(Filter selected) {
public static RemoteListSupportPicker newRemoteListSupportPicker(
Filter selected, Fragment targetFragment, int requestCode) {
RemoteListSupportPicker dialog = new RemoteListSupportPicker();
Bundle arguments = new Bundle();
if (selected != null) {
arguments.putParcelable(EXTRA_SELECTED, selected);
}
dialog.setArguments(arguments);
dialog.setTargetFragment(targetFragment, requestCode);
return dialog;
}
@ -64,14 +68,15 @@ public class RemoteListSupportPicker extends InjectingDialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
Filter selected = arguments == null ? null : arguments.getParcelable(EXTRA_SELECTED);
return createDialog(filterAdapter, dialogBuilder, selected, list -> handler.selectedList(list));
return createDialog(filterAdapter, dialogBuilder, selected, this::selected);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
handler = (RemoteListSelectionHandler) activity;
private void selected(Filter filter) {
getTargetFragment()
.onActivityResult(
getTargetRequestCode(),
Activity.RESULT_OK,
new Intent().putExtra(EXTRA_SELECTED, filter));
}
@Override

@ -1,5 +1,7 @@
package org.tasks.tasklist;
import static org.tasks.activities.RemoteListSupportPicker.newRemoteListSupportPicker;
import android.app.Activity;
import android.arch.paging.AsyncPagedListDiffer;
import android.arch.paging.PagedList;
@ -34,6 +36,7 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter<ViewHolder>
implements ViewHolder.ViewHolderCallbacks, ListUpdateCallback {
private static final String EXTRA_SELECTED_TASK_IDS = "extra_selected_task_ids";
private static final String FRAG_TAG_REMOTE_LIST_PICKER = "frag_tag_remote_list_picker";
private final Activity activity;
private final TaskAdapter adapter;
@ -66,6 +69,10 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter<ViewHolder>
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.move_tasks:
newRemoteListSupportPicker(null, taskList, TaskListFragment.REQUEST_MOVE_TASKS)
.show(taskList.getFragmentManager(), FRAG_TAG_REMOTE_LIST_PICKER);
return true;
case R.id.delete:
dialogBuilder
.newMessageDialog(R.string.delete_selected_tasks)
@ -243,7 +250,7 @@ public class TaskListRecyclerAdapter extends RecyclerView.Adapter<ViewHolder>
}
}
private void finishActionMode() {
public void finishActionMode() {
if (mode != null) {
mode.finish();
}

@ -1,8 +1,9 @@
package org.tasks.ui;
import static com.todoroo.andlib.utility.DateUtilities.now;
import static android.app.Activity.RESULT_OK;
import static org.tasks.activities.RemoteListSupportPicker.newRemoteListSupportPicker;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
@ -14,12 +15,12 @@ import butterknife.OnClick;
import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.GtasksFilter;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.helper.UUIDHelper;
import com.todoroo.astrid.service.TaskMover;
import javax.inject.Inject;
import org.tasks.R;
import org.tasks.activities.RemoteListSupportPicker;
import org.tasks.data.CaldavCalendar;
import org.tasks.data.CaldavDao;
import org.tasks.data.CaldavTask;
@ -35,6 +36,7 @@ public class RemoteListFragment extends TaskEditControlFragment {
"frag_tag_google_task_list_selection";
private static final String EXTRA_ORIGINAL_LIST = "extra_original_list";
private static final String EXTRA_SELECTED_LIST = "extra_selected_list";
private static final int REQUEST_CODE_SELECT_LIST = 10101;
@BindView(R.id.google_task_list)
TextView textView;
@ -43,6 +45,7 @@ public class RemoteListFragment extends TaskEditControlFragment {
@Inject GoogleTaskDao googleTaskDao;
@Inject CaldavDao caldavDao;
@Inject DefaultFilterProvider defaultFilterProvider;
@Inject TaskMover taskMover;
@Nullable private Filter originalList;
@Nullable private Filter selectedList;
@ -61,7 +64,8 @@ public class RemoteListFragment extends TaskEditControlFragment {
originalList =
new GtasksFilter(gtasksListService.getList(task.getTransitory(GoogleTask.KEY)));
} else if (task.hasTransitory(CaldavTask.KEY)) {
originalList = new CaldavFilter(caldavDao.getCalendarByUuid(task.getTransitory(CaldavTask.KEY)));
originalList =
new CaldavFilter(caldavDao.getCalendarByUuid(task.getTransitory(CaldavTask.KEY)));
} else {
originalList = defaultFilterProvider.getDefaultRemoteList();
}
@ -114,43 +118,13 @@ public class RemoteListFragment extends TaskEditControlFragment {
@OnClick(R.id.google_task_list)
void clickGoogleTaskList(View view) {
newRemoteListSupportPicker(selectedList)
.show(getChildFragmentManager(), FRAG_TAG_GOOGLE_TASK_LIST_SELECTION);
newRemoteListSupportPicker(selectedList, this, REQUEST_CODE_SELECT_LIST)
.show(getFragmentManager(), FRAG_TAG_GOOGLE_TASK_LIST_SELECTION);
}
@Override
public void apply(Task task) {
GoogleTask googleTask = googleTaskDao.getByTaskId(task.getId());
if (googleTask != null
&& selectedList instanceof GtasksFilter
&& googleTask.getListId().equals(((GtasksFilter) selectedList).getRemoteId())) {
return;
}
CaldavTask caldavTask = caldavDao.getTask(task.getId());
if (caldavTask != null
&& selectedList instanceof CaldavFilter
&& caldavTask.getCalendar().equals(((CaldavFilter) selectedList).getUuid())) {
return;
}
task.putTransitory(SyncFlags.FORCE_SYNC, true);
if (googleTask != null) {
googleTask.setDeleted(now());
googleTaskDao.update(googleTask);
}
if (caldavTask != null) {
caldavTask.setDeleted(now());
caldavDao.update(caldavTask);
}
if (selectedList instanceof GtasksFilter) {
googleTaskDao.insert(
new GoogleTask(task.getId(), ((GtasksFilter) selectedList).getRemoteId()));
} else if (selectedList instanceof CaldavFilter) {
caldavDao.insert(
new CaldavTask(
task.getId(), ((CaldavFilter) selectedList).getUuid(), UUIDHelper.newUUID()));
}
taskMover.move(task, selectedList);
}
@Override
@ -163,7 +137,18 @@ public class RemoteListFragment extends TaskEditControlFragment {
component.inject(this);
}
public void setList(Filter list) {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_SELECT_LIST) {
if (resultCode == RESULT_OK) {
setList(data.getParcelableExtra(RemoteListSupportPicker.EXTRA_SELECTED));
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void setList(Filter list) {
if (list == null) {
this.selectedList = null;
} else if (list instanceof GtasksFilter || list instanceof CaldavFilter) {

@ -2,6 +2,12 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/move_tasks"
android:icon="@drawable/ic_cloud_black_24dp"
android:title="@string/move"
app:showAsAction="ifRoom" />
<item
android:id="@+id/copy_tasks"
android:icon="@drawable/ic_content_copy_black_24dp"

@ -738,6 +738,7 @@ File %1$s contained %2$s.\n\n
<string name="list_settings">List settings</string>
<string name="delete">Delete</string>
<string name="copy">Copy</string>
<string name="move">Move</string>
<string name="filter_settings">Filter Settings</string>
<string name="show_hidden">Show hidden</string>
<string name="show_completed">Show completed</string>

Loading…
Cancel
Save