Fix race condition when opening tasks

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

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

@ -2,11 +2,13 @@ package com.todoroo.astrid.activity;
import static com.google.common.collect.Lists.newArrayList;
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.net.Uri;
import android.os.Bundle;
import androidx.core.app.TaskStackBuilder;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.service.TaskCreator;
import java.util.ArrayList;
@ -52,21 +54,27 @@ public final class ShareLinkActivity extends InjectingAppCompatActivity {
if (atLeastMarshmallow() && Intent.ACTION_PROCESS_TEXT.equals(action)) {
CharSequence text = intent.getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);
if (text != null) {
Task task = taskCreator.createWithValues(null, text.toString());
getEditTaskStack(this, null, task).startActivities();
Task task = taskCreator.createWithValues(text.toString());
getEditTaskStack(this, task).startActivities();
}
} else if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
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.putTransitory(TaskAttachment.KEY, getAttachments(intent));
getEditTaskStack(this, null, task).startActivities();
getEditTaskStack(this, task).startActivities();
} else {
Timber.e("Unhandled intent: %s", intent);
}
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) {
String type = intent.getType();
if (type != null) {

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

@ -6,6 +6,7 @@ import static com.todoroo.astrid.helper.UUIDHelper.newUUID;
import android.content.ContentValues;
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter;
@ -83,7 +84,7 @@ public class TaskCreator {
public Task basicQuickAddTask(String title) {
title = title.trim();
Task task = createWithValues(null, title);
Task task = createWithValues(title);
taskDao.createNew(task);
boolean gcalCreateEventEnabled =
@ -116,11 +117,18 @@ public class TaskCreator {
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
* 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.setCreationDate(now());
task.setModificationDate(now());

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

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

@ -7,16 +7,9 @@ import androidx.core.app.TaskStackBuilder;
import com.google.common.base.Strings;
import com.todoroo.astrid.activity.MainActivity;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.data.Task;
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(
Context context, final Filter filter, final long taskId) {
Intent intent = getTaskListIntent(context, filter);

Loading…
Cancel
Save