Fix race condition when opening tasks

pull/795/head
Alex Baker 6 years ago
parent ebd7c1f9d8
commit 7caa63a766

@ -6,10 +6,13 @@
package com.todoroo.astrid.activity; package com.todoroo.astrid.activity;
import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread;
import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop;
import static com.todoroo.astrid.activity.TaskEditFragment.newTaskEditFragment; import static com.todoroo.astrid.activity.TaskEditFragment.newTaskEditFragment;
import static org.tasks.tasklist.ActionUtils.applySupportActionModeColor; import static org.tasks.tasklist.ActionUtils.applySupportActionModeColor;
import static org.tasks.ui.NavigationDrawerFragment.OnFilterItemClickedListener; import static org.tasks.ui.NavigationDrawerFragment.OnFilterItemClickedListener;
import static org.tasks.ui.NavigationDrawerFragment.REQUEST_NEW_LIST;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
@ -35,6 +38,7 @@ import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksListService; import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.gtasks.GtasksSubtaskListFragment; import com.todoroo.astrid.gtasks.GtasksSubtaskListFragment;
import com.todoroo.astrid.service.TaskCreator;
import com.todoroo.astrid.subtasks.SubtasksHelper; import com.todoroo.astrid.subtasks.SubtasksHelper;
import com.todoroo.astrid.subtasks.SubtasksListFragment; import com.todoroo.astrid.subtasks.SubtasksListFragment;
import com.todoroo.astrid.subtasks.SubtasksTagListFragment; import com.todoroo.astrid.subtasks.SubtasksTagListFragment;
@ -74,7 +78,6 @@ import org.tasks.ui.EmptyTaskEditFragment;
import org.tasks.ui.NavigationDrawerFragment; import org.tasks.ui.NavigationDrawerFragment;
import org.tasks.ui.PriorityControlSet; import org.tasks.ui.PriorityControlSet;
import org.tasks.ui.TaskListViewModel; import org.tasks.ui.TaskListViewModel;
import timber.log.Timber;
public class MainActivity extends InjectingAppCompatActivity public class MainActivity extends InjectingAppCompatActivity
implements OnFilterItemClickedListener, implements OnFilterItemClickedListener,
@ -109,6 +112,7 @@ public class MainActivity extends InjectingAppCompatActivity
@Inject TaskDao taskDao; @Inject TaskDao taskDao;
@Inject CaldavDao caldavDao; @Inject CaldavDao caldavDao;
@Inject LocalBroadcastManager localBroadcastManager; @Inject LocalBroadcastManager localBroadcastManager;
@Inject TaskCreator taskCreator;
@BindView(R.id.drawer_layout) @BindView(R.id.drawer_layout)
DrawerLayout drawerLayout; DrawerLayout drawerLayout;
@ -171,6 +175,33 @@ public class MainActivity extends InjectingAppCompatActivity
outState.putParcelable(EXTRA_FILTER, filter); outState.putParcelable(EXTRA_FILTER, filter);
} }
private Single<TaskListFragment> taskListFragmentSingle(Intent intent) {
if (intent.hasExtra(OPEN_FILTER)) {
filter = intent.getParcelableExtra(OPEN_FILTER);
intent.removeExtra(OPEN_FILTER);
return Single.fromCallable(() -> newTaskListFragment(filter))
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess(this::openTaskListFragment);
} else if (intent.hasExtra(LOAD_FILTER)) {
String filter = intent.getStringExtra(LOAD_FILTER);
intent.removeExtra(LOAD_FILTER);
return Single.fromCallable(
() -> newTaskListFragment(defaultFilterProvider.getFilterFromPreference(filter)))
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess(this::openTaskListFragment);
}
TaskListFragment taskListFragment = getTaskListFragment();
if (taskListFragment == null || taskListFragment.filter != filter) {
return Single.fromCallable(() -> newTaskListFragment(filter))
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess(this::openTaskListFragment);
} else {
applyTheme(taskListFragment);
return Single.just(taskListFragment).observeOn(AndroidSchedulers.mainThread());
}
}
private void handleIntent() { private void handleIntent() {
Intent intent = getIntent(); Intent intent = getIntent();
@ -187,48 +218,44 @@ public class MainActivity extends InjectingAppCompatActivity
showDetailFragment(); showDetailFragment();
} }
TaskListFragment taskListFragment = getTaskListFragment(); finishActionMode();
if (intent.hasExtra(OPEN_FILTER)) { navigationDrawer.closeDrawer();
Filter filter = intent.getParcelableExtra(OPEN_FILTER);
intent.removeExtra(OPEN_FILTER); Single<TaskListFragment> single = taskListFragmentSingle(intent).subscribeOn(Schedulers.io());
loadTaskListFragment(filter);
} else if (intent.hasExtra(LOAD_FILTER)) {
Filter filter =
defaultFilterProvider.getFilterFromPreference(intent.getStringExtra(LOAD_FILTER));
intent.removeExtra(LOAD_FILTER);
loadTaskListFragment(filter);
} else if (taskListFragment == null) {
loadTaskListFragment(filter);
} else {
applyTheme(taskListFragment);
}
if (intent.hasExtra(OPEN_TASK)) { if (intent.hasExtra(OPEN_TASK)) {
long taskId = intent.getLongExtra(OPEN_TASK, 0); long taskId = intent.getLongExtra(OPEN_TASK, 0);
intent.removeExtra(OPEN_TASK); intent.removeExtra(OPEN_TASK);
navigationDrawer.closeDrawer(); disposables.add(
if (taskId > 0) { single
Task task = taskDao.fetch(taskId); .observeOn(Schedulers.io())
if (task != null) { .map(
onTaskListItemClicked(task); tlf ->
} else { taskId > 0
Timber.e("Failed to find task %s", taskId); ? taskDao.fetch(taskId)
} : taskCreator.createWithValues(tlf.filter, ""))
} else { .observeOn(AndroidSchedulers.mainThread())
.subscribe(
task -> {
getSupportFragmentManager().executePendingTransactions(); getSupportFragmentManager().executePendingTransactions();
Task task = getTaskListFragment().addTask("");
onTaskListItemClicked(task); onTaskListItemClicked(task);
} }));
} else if (intent.hasExtra(OPEN_NEW_TASK)) { } else if (intent.hasExtra(OPEN_NEW_TASK)) {
Task task = intent.getParcelableExtra(OPEN_NEW_TASK); Task task = intent.getParcelableExtra(OPEN_NEW_TASK);
intent.removeExtra(OPEN_NEW_TASK); intent.removeExtra(OPEN_NEW_TASK);
onTaskListItemClicked(task); disposables.add(single.subscribe(tlf -> onTaskListItemClicked(task)));
} else if (intent.hasExtra(TOKEN_CREATE_NEW_LIST_NAME)) { } else if (intent.hasExtra(TOKEN_CREATE_NEW_LIST_NAME)) {
final String listName = intent.getStringExtra(TOKEN_CREATE_NEW_LIST_NAME); final String listName = intent.getStringExtra(TOKEN_CREATE_NEW_LIST_NAME);
intent.removeExtra(TOKEN_CREATE_NEW_LIST_NAME); intent.removeExtra(TOKEN_CREATE_NEW_LIST_NAME);
disposables.add(
single.subscribe(
tlf -> {
Intent activityIntent = new Intent(MainActivity.this, TagSettingsActivity.class); Intent activityIntent = new Intent(MainActivity.this, TagSettingsActivity.class);
activityIntent.putExtra(TagSettingsActivity.TOKEN_AUTOPOPULATE_NAME, listName); activityIntent.putExtra(TagSettingsActivity.TOKEN_AUTOPOPULATE_NAME, listName);
startActivityForResult(activityIntent, NavigationDrawerFragment.REQUEST_NEW_LIST); startActivityForResult(activityIntent, REQUEST_NEW_LIST);
}));
} else {
disposables.add(single.subscribe());
} }
} }
@ -251,33 +278,23 @@ public class MainActivity extends InjectingAppCompatActivity
} }
} }
private void loadTaskListFragment(Filter filter) { private void openTaskListFragment(TaskListFragment taskListFragment) {
finishActionMode(); assertMainThread();
navigationDrawer.closeDrawer();
disposables.add(
Single.fromCallable(() -> newTaskListFragment(filter))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
taskListFragment -> {
if (taskListFragment != null) { if (taskListFragment != null) {
navigationDrawer.setSelected(taskListFragment.filter); filter = taskListFragment.filter;
applyTheme(taskListFragment); navigationDrawer.setSelected(filter);
applyTheme();
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager fragmentManager
.beginTransaction() .beginTransaction()
.replace(R.id.master, taskListFragment, FRAG_TAG_TASK_LIST) .replace(R.id.master, taskListFragment, FRAG_TAG_TASK_LIST)
.commit(); .commit();
} }
}));
} }
private void applyTheme(TaskListFragment taskListFragment) { private void applyTheme() {
filter = taskListFragment.filter;
ThemeColor filterColor = getFilterColor(); ThemeColor filterColor = getFilterColor();
filterColor.applyToStatusBar(drawerLayout); filterColor.applyToStatusBar(drawerLayout);
filterColor.applyToNavigationBar(this); filterColor.applyToNavigationBar(this);
filterColor.applyTaskDescription(this, filter.listingTitle); filterColor.applyTaskDescription(this, filter.listingTitle);
@ -329,13 +346,6 @@ public class MainActivity extends InjectingAppCompatActivity
disposables.add(syncAdapters.checkPlayServices(this)); disposables.add(syncAdapters.checkPlayServices(this));
} }
@Override
protected void onDestroy() {
super.onDestroy();
disposables.dispose();
}
public void restart() { public void restart() {
recreate(); recreate();
} }
@ -355,6 +365,8 @@ public class MainActivity extends InjectingAppCompatActivity
super.onPause(); super.onPause();
localBroadcastManager.unregisterReceiver(repeatConfirmationReceiver); localBroadcastManager.unregisterReceiver(repeatConfirmationReceiver);
disposables.dispose();
} }
@Override @Override
@ -373,6 +385,8 @@ public class MainActivity extends InjectingAppCompatActivity
} }
private TaskListFragment newTaskListFragment(Filter filter) { private TaskListFragment newTaskListFragment(Filter filter) {
assertNotMainThread();
if (filter == null) { if (filter == null) {
filter = defaultFilterProvider.getDefaultFilter(); filter = defaultFilterProvider.getDefaultFilter();
} }
@ -410,6 +424,8 @@ public class MainActivity extends InjectingAppCompatActivity
@Override @Override
public void onTaskListItemClicked(Task task) { public void onTaskListItemClicked(Task task) {
assertMainThread();
if (task == null) { if (task == null) {
return; return;
} }

@ -2,11 +2,13 @@ package com.todoroo.astrid.activity;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow;
import static org.tasks.intents.TaskIntents.getEditTaskStack; import static org.tasks.intents.TaskIntents.getTaskListIntent;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.app.TaskStackBuilder;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TaskCreator; import com.todoroo.astrid.service.TaskCreator;
import java.util.ArrayList; import java.util.ArrayList;
@ -52,21 +54,27 @@ public final class ShareLinkActivity extends InjectingAppCompatActivity {
if (atLeastMarshmallow() && Intent.ACTION_PROCESS_TEXT.equals(action)) { if (atLeastMarshmallow() && Intent.ACTION_PROCESS_TEXT.equals(action)) {
CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT); CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);
if (text != null) { if (text != null) {
Task task = taskCreator.createWithValues(null, text.toString()); Task task = taskCreator.createWithValues(text.toString());
getEditTaskStack(this, null, task).startActivities(); getEditTaskStack(this, task).startActivities();
} }
} else if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) { } else if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT); String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
Task task = taskCreator.createWithValues(null, subject); Task task = taskCreator.createWithValues(subject);
task.setNotes(intent.getStringExtra(Intent.EXTRA_TEXT)); task.setNotes(intent.getStringExtra(Intent.EXTRA_TEXT));
task.putTransitory(TaskAttachment.KEY, getAttachments(intent)); task.putTransitory(TaskAttachment.KEY, getAttachments(intent));
getEditTaskStack(this, null, task).startActivities(); getEditTaskStack(this, task).startActivities();
} else { } else {
Timber.e("Unhandled intent: %s", intent); Timber.e("Unhandled intent: %s", intent);
} }
finish(); finish();
} }
private static TaskStackBuilder getEditTaskStack(Context context, Task task) {
Intent intent = getTaskListIntent(context, null);
intent.putExtra(MainActivity.OPEN_NEW_TASK, task);
return TaskStackBuilder.create(context).addNextIntent(intent);
}
private ArrayList<Uri> getAttachments(Intent intent) { private ArrayList<Uri> getAttachments(Intent intent) {
String type = intent.getType(); String type = intent.getType();
if (type != null) { if (type != null) {

@ -393,8 +393,8 @@ public class TaskListFragment extends InjectingFragment
onTaskListItemClicked(addTask("")); onTaskListItemClicked(addTask(""));
} }
public Task addTask(String title) { Task addTask(String title) {
return taskCreator.createWithValues(filter.valuesForNewTasks, title); return taskCreator.createWithValues(filter, title);
} }
private void setupRefresh(SwipeRefreshLayout layout) { private void setupRefresh(SwipeRefreshLayout layout) {

@ -6,6 +6,7 @@ import static com.todoroo.astrid.helper.UUIDHelper.newUUID;
import android.content.ContentValues; import android.content.ContentValues;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.CaldavFilter; import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
@ -83,7 +84,7 @@ public class TaskCreator {
public Task basicQuickAddTask(String title) { public Task basicQuickAddTask(String title) {
title = title.trim(); title = title.trim();
Task task = createWithValues(null, title); Task task = createWithValues(title);
taskDao.createNew(task); taskDao.createNew(task);
boolean gcalCreateEventEnabled = boolean gcalCreateEventEnabled =
@ -116,11 +117,18 @@ public class TaskCreator {
return task; return task;
} }
public Task createWithValues(String title) {
return create(null, title);
}
public Task createWithValues(Filter filter, String title) {
return create(filter.valuesForNewTasks, title);
}
/** /**
* Create task from the given content values, saving it. This version doesn't need to start with a * Create task from the given content values, saving it. This version doesn't need to start with a
* base task model. * base task model.
*/ */
public Task createWithValues(Map<String, Object> values, String title) { private Task create(@Nullable Map<String, Object> values, String title) {
Task task = new Task(); Task task = new Task();
task.setCreationDate(now()); task.setCreationDate(now());
task.setModificationDate(now()); task.setModificationDate(now());

@ -363,7 +363,7 @@ public class CaldavSynchronizer {
Task task; Task task;
CaldavTask caldavTask = caldavDao.getTask(caldavCalendar.getUuid(), fileName); CaldavTask caldavTask = caldavDao.getTask(caldavCalendar.getUuid(), fileName);
if (caldavTask == null) { if (caldavTask == null) {
task = taskCreator.createWithValues(null, ""); task = taskCreator.createWithValues("");
taskDao.createNew(task); taskDao.createNew(task);
caldavTask = caldavTask =
new CaldavTask(task.getId(), caldavCalendar.getUuid(), remote.getUid(), fileName); new CaldavTask(task.getId(), caldavCalendar.getUuid(), remote.getUid(), fileName);

@ -367,7 +367,7 @@ public class GoogleTaskSynchronizer {
continue; continue;
} }
if (task == null) { if (task == null) {
task = taskCreator.createWithValues(null, ""); task = taskCreator.createWithValues("");
} }
GtasksTaskContainer container = new GtasksTaskContainer(gtask, task, listId, googleTask); GtasksTaskContainer container = new GtasksTaskContainer(gtask, task, listId, googleTask);
container.gtaskMetadata.setRemoteOrder(Long.parseLong(gtask.getPosition())); container.gtaskMetadata.setRemoteOrder(Long.parseLong(gtask.getPosition()));

@ -7,16 +7,9 @@ import androidx.core.app.TaskStackBuilder;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.todoroo.astrid.activity.MainActivity; import com.todoroo.astrid.activity.MainActivity;
import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.data.Task;
public class TaskIntents { public class TaskIntents {
public static TaskStackBuilder getEditTaskStack(Context context, final Filter filter, Task task) {
Intent intent = getTaskListIntent(context, filter);
intent.putExtra(MainActivity.OPEN_NEW_TASK, task);
return TaskStackBuilder.create(context).addNextIntent(intent);
}
public static TaskStackBuilder getEditTaskStack( public static TaskStackBuilder getEditTaskStack(
Context context, final Filter filter, final long taskId) { Context context, final Filter filter, final long taskId) {
Intent intent = getTaskListIntent(context, filter); Intent intent = getTaskListIntent(context, filter);

Loading…
Cancel
Save