diff --git a/app/src/androidTest/java/com/todoroo/astrid/model/TaskTest.java b/app/src/androidTest/java/com/todoroo/astrid/model/TaskTest.java index 80b23b470..87df4c52d 100644 --- a/app/src/androidTest/java/com/todoroo/astrid/model/TaskTest.java +++ b/app/src/androidTest/java/com/todoroo/astrid/model/TaskTest.java @@ -2,7 +2,6 @@ package com.todoroo.astrid.model; import android.support.test.runner.AndroidJUnit4; -import com.todoroo.andlib.data.AbstractModel; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.data.Task; @@ -11,15 +10,11 @@ import org.junit.runner.RunWith; import org.tasks.Snippet; import org.tasks.injection.InjectingTestCase; import org.tasks.injection.TestComponent; -import org.tasks.preferences.Preferences; - -import java.util.Map; import javax.inject.Inject; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; import static org.tasks.Freeze.freezeClock; import static org.tasks.time.DateTimeUtils.currentTimeMillis; @@ -27,11 +22,10 @@ import static org.tasks.time.DateTimeUtils.currentTimeMillis; public class TaskTest extends InjectingTestCase { @Inject TaskDao taskDao; - @Inject Preferences preferences; @Test public void testNewTaskHasNoCreationDate() { - assertFalse(new Task().containsValue(Task.CREATION_DATE)); + assertFalse(new Task().isModified(Task.CREATION_DATE)); } @Test @@ -51,17 +45,6 @@ public class TaskTest extends InjectingTestCase { assertEquals(task, fromDb); } - @Test - public void testDefaults() { - preferences.setDefaults(); - Map> defaults = new Task().getRoomGetters(); - assertTrue(defaults.containsKey(Task.TITLE.name)); - assertTrue(defaults.containsKey(Task.DUE_DATE.name)); - assertTrue(defaults.containsKey(Task.HIDE_UNTIL.name)); - assertTrue(defaults.containsKey(Task.COMPLETION_DATE.name)); - assertTrue(defaults.containsKey(Task.IMPORTANCE.name)); - } - @Override protected void inject(TestComponent component) { component.inject(this); diff --git a/app/src/googleplay/java/com/todoroo/astrid/gtasks/GtasksSubtaskListFragment.java b/app/src/googleplay/java/com/todoroo/astrid/gtasks/GtasksSubtaskListFragment.java index 267cddd48..f047f6604 100644 --- a/app/src/googleplay/java/com/todoroo/astrid/gtasks/GtasksSubtaskListFragment.java +++ b/app/src/googleplay/java/com/todoroo/astrid/gtasks/GtasksSubtaskListFragment.java @@ -59,7 +59,6 @@ public class GtasksSubtaskListFragment extends GtasksListFragment { Property[] baseProperties = TaskAdapter.PROPERTIES; ArrayList> properties = new ArrayList<>(Arrays.asList(baseProperties)); properties.add(GoogleTask.INDENT); - properties.add(GoogleTask.ORDER); return properties.toArray(new Property[properties.size()]); } diff --git a/app/src/googleplay/java/com/todoroo/astrid/gtasks/OrderedMetadataListFragmentHelper.java b/app/src/googleplay/java/com/todoroo/astrid/gtasks/OrderedMetadataListFragmentHelper.java index 1df5145d1..ea5b8c509 100644 --- a/app/src/googleplay/java/com/todoroo/astrid/gtasks/OrderedMetadataListFragmentHelper.java +++ b/app/src/googleplay/java/com/todoroo/astrid/gtasks/OrderedMetadataListFragmentHelper.java @@ -72,13 +72,13 @@ class OrderedMetadataListFragmentHelper { @Override public int getIndent(Task task) { - return task.getValue(GoogleTask.INDENT); + return task.getGoogleTaskIndent(); } @Override public boolean canIndent(int position, Task task) { Task parent = taskAdapter.getTask(position - 1); - return parent != null && getIndent(task) <= parent.getValue(GoogleTask.INDENT); + return parent != null && getIndent(task) <= parent.getGoogleTaskIndent(); } @Override @@ -134,10 +134,9 @@ class OrderedMetadataListFragmentHelper { ArrayList chained = chainedCompletions.get(itemId); if(chained != null) { for(Long taskId : chained) { - Task model = new Task(); - model.setId(taskId); - model.setCompletionDate(completionDate); - taskDao.save(model); + Task task = taskDao.fetch(taskId); + task.setCompletionDate(completionDate); + taskDao.save(task); } taskAdapter.notifyDataSetInvalidated(); } @@ -145,7 +144,7 @@ class OrderedMetadataListFragmentHelper { } final ArrayList chained = new ArrayList<>(); - final int parentIndent = item.getValue(GoogleTask.INDENT); + final int parentIndent = item.getGoogleTaskIndent(); updater.applyToChildren(list, itemId, node -> { Task childTask = taskDao.fetch(node.taskId); if(!TextUtils.isEmpty(childTask.getRecurrence())) { @@ -153,11 +152,8 @@ class OrderedMetadataListFragmentHelper { googleTask.setIndent(parentIndent); googleTaskDao.update(googleTask); } - - Task model = new Task(); - model.setId(node.taskId); - model.setCompletionDate(completionDate); - taskDao.save(model); + childTask.setCompletionDate(completionDate); + taskDao.save(childTask); chained.add(node.taskId); }); diff --git a/app/src/googleplay/java/org/tasks/gtasks/GoogleTaskSyncAdapter.java b/app/src/googleplay/java/org/tasks/gtasks/GoogleTaskSyncAdapter.java index 142e6839c..c6fb7f6e8 100644 --- a/app/src/googleplay/java/org/tasks/gtasks/GoogleTaskSyncAdapter.java +++ b/app/src/googleplay/java/org/tasks/gtasks/GoogleTaskSyncAdapter.java @@ -249,33 +249,26 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter //If task was newly created but without a title, don't sync--we're in the middle of //creating a task which may end up being cancelled. Also don't sync new but already //deleted tasks - if (newlyCreated && - (!task.containsValue(Task.TITLE) || TextUtils.isEmpty(task.getTitle()) || task.getDeletionDate() > 0)) { + if (newlyCreated && (TextUtils.isEmpty(task.getTitle()) || task.getDeletionDate() > 0)) { return; } //Update the remote model's changed properties - if (task.containsValue(Task.DELETION_DATE) && task.isDeleted()) { + if (task.isDeleted()) { remoteModel.setDeleted(true); } - if (task.containsValue(Task.TITLE)) { - remoteModel.setTitle(task.getTitle()); - } - if (task.containsValue(Task.NOTES)) { - remoteModel.setNotes(task.getNotes()); - } - if (task.containsValue(Task.DUE_DATE) && task.hasDueDate()) { + remoteModel.setTitle(task.getTitle()); + remoteModel.setNotes(task.getNotes()); + if (task.hasDueDate()) { remoteModel.setDue(GtasksApiUtilities.unixTimeToGtasksDueDate(task.getDueDate())); } - if (task.containsValue(Task.COMPLETION_DATE)) { - if (task.isCompleted()) { - remoteModel.setCompleted(GtasksApiUtilities.unixTimeToGtasksCompletionTime(task.getCompletionDate())); - remoteModel.setStatus("completed"); //$NON-NLS-1$ - } else { - remoteModel.setCompleted(null); - remoteModel.setStatus("needsAction"); //$NON-NLS-1$ - } + if (task.isCompleted()) { + remoteModel.setCompleted(GtasksApiUtilities.unixTimeToGtasksCompletionTime(task.getCompletionDate())); + remoteModel.setStatus("completed"); //$NON-NLS-1$ + } else { + remoteModel.setCompleted(null); + remoteModel.setStatus("needsAction"); //$NON-NLS-1$ } if (!newlyCreated) { @@ -382,8 +375,8 @@ public class GoogleTaskSyncAdapter extends InjectingAbstractThreadedSyncAdapter if(task.task.isSaved()) { Task local = taskDao.fetch(task.task.getId()); if (local == null) { - task.task.clearValue(Task.ID); - task.task.clearValue(Task.UUID); + task.task.setId(NO_ID); + task.task.setUuid(NO_UUID); } else { mergeDates(task.task, local); } diff --git a/app/src/googleplay/java/org/tasks/receivers/GoogleTaskPusher.java b/app/src/googleplay/java/org/tasks/receivers/GoogleTaskPusher.java index 5c3c0e25d..bc34baeb3 100644 --- a/app/src/googleplay/java/org/tasks/receivers/GoogleTaskPusher.java +++ b/app/src/googleplay/java/org/tasks/receivers/GoogleTaskPusher.java @@ -1,13 +1,13 @@ package org.tasks.receivers; -import android.content.ContentValues; - import com.todoroo.andlib.data.Property; import com.todoroo.astrid.data.SyncFlags; import com.todoroo.astrid.data.Task; import org.tasks.gtasks.SyncAdapterHelper; +import java.util.ArrayList; + import javax.inject.Inject; public class GoogleTaskPusher { @@ -22,7 +22,7 @@ public class GoogleTaskPusher { this.syncAdapterHelper = syncAdapterHelper; } - void push(Task task, ContentValues modifiedValues) { + void push(Task task, ArrayList modifiedValues) { if(!syncAdapterHelper.isEnabled()) { return; } @@ -36,12 +36,12 @@ public class GoogleTaskPusher { } } - private boolean checkValuesForProperties(ContentValues values, Property[] properties) { + private boolean checkValuesForProperties(ArrayList values, Property[] properties) { if (values == null) { return false; } for (Property property : properties) { - if (property != Task.ID && values.containsKey(property.name)) { + if (property != Task.ID && values.contains(property.name)) { return true; } } diff --git a/app/src/googleplay/java/org/tasks/receivers/PushReceiver.java b/app/src/googleplay/java/org/tasks/receivers/PushReceiver.java index e77d96505..f787cbea5 100644 --- a/app/src/googleplay/java/org/tasks/receivers/PushReceiver.java +++ b/app/src/googleplay/java/org/tasks/receivers/PushReceiver.java @@ -1,6 +1,5 @@ package org.tasks.receivers; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; @@ -10,14 +9,16 @@ import com.todoroo.astrid.data.Task; import org.tasks.injection.BroadcastComponent; import org.tasks.injection.InjectingBroadcastReceiver; +import java.util.ArrayList; + import javax.inject.Inject; public class PushReceiver extends InjectingBroadcastReceiver { - public static void broadcast(Context context, Task task, ContentValues values) { + public static void broadcast(Context context, Task task, ArrayList values) { Intent intent = new Intent(context, PushReceiver.class); intent.putExtra(AstridApiConstants.EXTRAS_TASK, task); - intent.putExtra(AstridApiConstants.EXTRAS_VALUES, values); + intent.putStringArrayListExtra(AstridApiConstants.EXTRAS_VALUES, values); context.sendBroadcast(intent); } @@ -29,7 +30,7 @@ public class PushReceiver extends InjectingBroadcastReceiver { googleTaskPusher.push( intent.getParcelableExtra(AstridApiConstants.EXTRAS_TASK), - intent.getParcelableExtra(AstridApiConstants.EXTRAS_VALUES)); + intent.getStringArrayListExtra(AstridApiConstants.EXTRAS_VALUES)); } @Override diff --git a/app/src/main/java/com/todoroo/andlib/data/AbstractModel.java b/app/src/main/java/com/todoroo/andlib/data/AbstractModel.java index 02ebba70a..0c11edca0 100644 --- a/app/src/main/java/com/todoroo/andlib/data/AbstractModel.java +++ b/app/src/main/java/com/todoroo/andlib/data/AbstractModel.java @@ -8,22 +8,18 @@ package com.todoroo.andlib.data; import android.arch.persistence.room.Ignore; import android.content.ContentValues; -import com.todoroo.andlib.data.Property.IntegerProperty; import com.todoroo.andlib.data.Property.LongProperty; -import com.todoroo.andlib.data.Property.PropertyVisitor; -import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.astrid.data.Task; import org.tasks.data.Tag; import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; +import java.util.HashSet; import java.util.Map.Entry; +import java.util.Set; -import timber.log.Timber; - -import static com.todoroo.andlib.data.Property.DoubleProperty; +import static com.google.common.collect.Sets.newHashSet; /** * AbstractModel represents a row in a database. @@ -37,8 +33,6 @@ import static com.todoroo.andlib.data.Property.DoubleProperty; */ public abstract class AbstractModel { - private static final ContentValuesSavingVisitor saver = new ContentValuesSavingVisitor(); - /** id property common to all models */ protected static final String ID_PROPERTY_NAME = "_id"; //$NON-NLS-1$ @@ -50,13 +44,10 @@ public abstract class AbstractModel { // --- abstract methods - public interface ValueReader { - TYPE getValue(Task instance); + public interface ValueWriter { + void setValue(Task instance, TYPE value); } - /** Get the default values for this object */ - abstract public Map> getRoomGetters(); - // --- data store variables and management /* Data Source Ordering: @@ -68,46 +59,15 @@ public abstract class AbstractModel { /** User set values */ @Ignore - protected ContentValues setValues = null; - - /** Values from database */ - @Ignore - protected ContentValues values = null; + protected final Set setValues = new HashSet<>(); /** Transitory Metadata (not saved in database) */ @Ignore protected HashMap transitoryData = null; - protected AbstractModel() { - } - - protected AbstractModel(TodorooCursor cursor) { - readPropertiesFromCursor(cursor); - } - /** Get the user-set values for this object */ - public ContentValues getSetValues() { - return setValues; - } - - /** Get a list of all field/value pairs merged across data sources */ - public ContentValues getMergedValues() { - ContentValues mergedValues = new ContentValues(); - - for (Map.Entry> entry : getRoomGetters().entrySet()) { - Object value = entry.getValue().getValue((Task) this); - if (value != null) { - AndroidUtilities.putInto(mergedValues, entry.getKey(), value); - } - } - if (values != null) { - mergedValues.putAll(values); - } - if(setValues != null) { - mergedValues.putAll(setValues); - } - - return mergedValues; + public Set getSetValues() { + return newHashSet(setValues); } /** @@ -115,93 +75,18 @@ public abstract class AbstractModel { * saved - future saves will not need to write all the data as before. */ public void markSaved() { - if(values == null) { - values = setValues; - } else if(setValues != null) { - values.putAll(setValues); - } - setValues = null; + setValues.clear(); } - /** - * Use merged values to compare two models to each other. Must be of - * exactly the same class. - */ - @Override - public boolean equals(Object other) { - if(other == null || other.getClass() != getClass()) { - return false; + private void setValue(String columnName, Object value) { + ValueWriter writer = Task.roomSetters.get(columnName); + if (writer == null) { + throw new RuntimeException(); } - - return getMergedValues().equals(((AbstractModel) other).getMergedValues()); + writer.setValue((Task) this, value); + setValues.add(columnName); } - @Override - public int hashCode() { - return getMergedValues().hashCode() ^ getClass().hashCode(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "\n" + "set values:\n" + setValues + "\n" + "values:\n" + values + "\n"; - } - - /** - * Reads all properties from the supplied cursor and store - */ - void readPropertiesFromCursor(TodorooCursor cursor) { - if (values == null) { - values = new ContentValues(); - } - - // clears user-set values - setValues = null; - transitoryData = null; - - for (Property property : cursor.getProperties()) { - try { - saver.save(property, values, cursor.get(property)); - } catch (IllegalArgumentException e) { - // underlying cursor may have changed, suppress - Timber.e(e, e.getMessage()); - } - } - } - - /** - * Reads the given property. Make sure this model has this property! - */ - public synchronized TYPE getValue(Property property) { - Object value; - String columnName = property.getColumnName(); - if(setValues != null && setValues.containsKey(columnName)) { - value = setValues.get(columnName); - } else if(values != null && values.containsKey(columnName)) { - value = values.get(columnName); - } else if(getRoomGetters().containsKey(columnName)) { - value = getRoomGetters().get(columnName).getValue((Task) this); - } else { - throw new UnsupportedOperationException( - "Model Error: Did not read property " + property.name); //$NON-NLS-1$ - } - - // resolve properties that were retrieved with a different type than accessed - try { - if(value instanceof String && property instanceof LongProperty) { - return (TYPE) Long.valueOf((String) value); - } else if(value instanceof String && property instanceof IntegerProperty) { - return (TYPE) Integer.valueOf((String) value); - } else if(value instanceof Integer && property instanceof LongProperty) { - return (TYPE) Long.valueOf(((Number) value).longValue()); - } else if(value instanceof String && property instanceof DoubleProperty) { - return (TYPE) Double.valueOf((String) value); - } - return (TYPE) value; - } catch (NumberFormatException e) { - Timber.e(e, e.getMessage()); - return (TYPE) getRoomGetters().get(property.name).getValue((Task) this); - } - } /** * Utility method to get the identifier of the model, if it exists. @@ -211,15 +96,7 @@ public abstract class AbstractModel { abstract public long getId(); public void setId(long id) { - if (setValues == null) { - setValues = new ContentValues(); - } - - if(id == NO_ID) { - clearValue(ID_PROPERTY); - } else { - setValues.put(ID_PROPERTY_NAME, id); - } + setValue(ID_PROPERTY, id); } /** @@ -232,54 +109,17 @@ public abstract class AbstractModel { /** * @return true if setValues or values contains this property */ - public boolean containsValue(Property property) { - if(setValues != null && setValues.containsKey(property.getColumnName())) { - return true; - } - if(values != null && values.containsKey(property.getColumnName())) { - return true; - } - return false; + public boolean isModified(Property property) { + return setValues.contains(property.getColumnName()); } // --- data storage - /** - * Check whether the user has changed this property value and it should be - * stored for saving in the database - */ - private synchronized boolean shouldSaveValue(Property property, TYPE newValue) { - // we've already decided to save it, so overwrite old value - if (setValues.containsKey(property.getColumnName())) { - return true; - } - - TYPE value = getValue(property); - if (value == null) { - if (newValue == null) { - return false; - } - } else if (value.equals(newValue)) { - return false; - } - - // otherwise, good to save - return true; - } - /** * Sets the given property. Make sure this model has this property! */ - public synchronized void setValue(Property property, - TYPE value) { - if (setValues == null) { - setValues = new ContentValues(); - } - if (!shouldSaveValue(property, value)) { - return; - } - - saver.save(property, setValues, value); + public synchronized void setValue(Property property, TYPE value) { + setValue(property.getColumnName(), value); } /** @@ -287,26 +127,11 @@ public abstract class AbstractModel { * keeping the existing value if one already exists */ public synchronized void mergeWithoutReplacement(ContentValues other) { - if (setValues == null) { - setValues = new ContentValues(); - } for (Entry item : other.valueSet()) { - if (setValues.containsKey(item.getKey())) { - continue; + String columnName = item.getKey(); + if (setValues.add(columnName)) { + setValue(columnName, item.getValue()); } - AndroidUtilities.putInto(setValues, item.getKey(), item.getValue()); - } - } - - /** - * Clear the key for the given property - */ - public synchronized void clearValue(Property property) { - if(setValues != null && setValues.containsKey(property.getColumnName())) { - setValues.remove(property.getColumnName()); - } - if(values != null && values.containsKey(property.getColumnName())) { - values.remove(property.getColumnName()); } } @@ -355,50 +180,4 @@ public abstract class AbstractModel { Object trans = clearTransitory(flag); return trans != null; } - - /** - * Visitor that saves a value into a content values store - * - * @author Tim Su - * - */ - public static class ContentValuesSavingVisitor implements PropertyVisitor { - - private ContentValues store; - - public synchronized void save(Property property, ContentValues newStore, Object value) { - this.store = newStore; - - // we don't allow null values, as they indicate unset properties - // when the database was written - - if(value != null) { - property.accept(this, value); - } - } - - @Override - public Void visitInteger(Property property, Object value) { - store.put(property.getColumnName(), (Integer) value); - return null; - } - - @Override - public Void visitLong(Property property, Object value) { - store.put(property.getColumnName(), (Long) value); - return null; - } - - @Override - public Void visitDouble(Property property, Object value) { - store.put(property.getColumnName(), (Double) value); - return null; - } - - @Override - public Void visitString(Property property, Object value) { - store.put(property.getColumnName(), (String) value); - return null; - } - } } diff --git a/app/src/main/java/com/todoroo/andlib/data/Property.java b/app/src/main/java/com/todoroo/andlib/data/Property.java index 8f386bd1d..e0c493b73 100644 --- a/app/src/main/java/com/todoroo/andlib/data/Property.java +++ b/app/src/main/java/com/todoroo/andlib/data/Property.java @@ -192,30 +192,6 @@ public abstract class Property extends Field implements Cloneable { } } - /** - * Double property type. See {@link Property} - * - * @author Tim Su - * - */ - public static class DoubleProperty extends Property { - - public DoubleProperty(Table table, String name) { - super(table, name); - } - - @Override - public RETURN accept( - PropertyVisitor visitor, PARAMETER data) { - return visitor.visitDouble(this, data); - } - - @Override - public DoubleProperty cloneAs(String tableAlias, String columnAlias) { - return (DoubleProperty) super.cloneAs(tableAlias, columnAlias); - } - } - /** * Long property type. See {@link Property} * diff --git a/app/src/main/java/com/todoroo/andlib/data/TodorooCursor.java b/app/src/main/java/com/todoroo/andlib/data/TodorooCursor.java index 83394defe..49275def6 100644 --- a/app/src/main/java/com/todoroo/andlib/data/TodorooCursor.java +++ b/app/src/main/java/com/todoroo/andlib/data/TodorooCursor.java @@ -70,7 +70,7 @@ public class TodorooCursor extends CursorWrapper { * @param type to return * @param property to retrieve */ - public PROPERTY_TYPE get(Property property) { + public PROPERTY_TYPE get(Property property) { return (PROPERTY_TYPE)property.accept(reader, this); } diff --git a/app/src/main/java/com/todoroo/astrid/dao/Database.java b/app/src/main/java/com/todoroo/astrid/dao/Database.java index 85259242e..131241382 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/Database.java +++ b/app/src/main/java/com/todoroo/astrid/dao/Database.java @@ -95,7 +95,7 @@ public abstract class Database extends RoomDatabase { return this; } - private void onDatabaseUpdated() { + public void onDatabaseUpdated() { if (onDatabaseUpdated != null) { onDatabaseUpdated.run(); } diff --git a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java index cb0fde154..242deebe6 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java +++ b/app/src/main/java/com/todoroo/astrid/dao/TaskDao.java @@ -7,11 +7,10 @@ package com.todoroo.astrid.dao; import android.arch.persistence.room.Dao; import android.arch.persistence.room.Insert; -import android.content.ContentValues; +import android.arch.persistence.room.Update; import android.content.Context; import android.database.Cursor; -import com.todoroo.andlib.data.AbstractModel; import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Criterion; @@ -28,7 +27,7 @@ import org.tasks.jobs.AfterSaveIntentService; import org.tasks.receivers.PushReceiver; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.Set; import timber.log.Timber; @@ -154,7 +153,7 @@ public abstract class TaskDao { * */ public void save(Task task) { - ContentValues modifiedValues = saveExisting(task); + Set modifiedValues = saveExisting(task); if (modifiedValues != null) { AfterSaveIntentService.enqueue(context, task.getId(), modifiedValues); } else if (task.checkTransitory(SyncFlags.FORCE_SYNC)) { @@ -165,35 +164,30 @@ public abstract class TaskDao { @Insert abstract long insert(Task task); + @Update + abstract int update(Task task); + public void createNew(Task task) { task.id = null; task.remoteId = task.getUuid(); - task.setId(insert(task)); + long insert = insert(task); + task.setId(insert); } - private ContentValues saveExisting(Task item) { - ContentValues values = item.getSetValues(); + private Set saveExisting(Task item) { + Set values = item.getSetValues(); if (values == null || values.size() == 0) { return null; } if (!TaskApiDao.insignificantChange(values)) { - if (!values.containsKey(Task.MODIFICATION_DATE.name)) { + if (!values.contains(Task.MODIFICATION_DATE.name)) { item.setModificationDate(now()); } } - DatabaseChangeOp update = new DatabaseChangeOp() { - @Override - public boolean makeChange() { - return database.update(values, - AbstractModel.ID_PROPERTY.eq(item.getId()).toString()) > 0; - } - - @Override - public String toString() { - return "UPDATE"; - } - }; - if (updateAndRecordChanges(item, update)) { + int updated = update(item); + if (updated == 1) { + item.markSaved(); + database.onDatabaseUpdated(); return values; } return null; @@ -229,23 +223,5 @@ public abstract class TaskDao { Cursor cursor = database.rawQuery(queryString); return new TodorooCursor(cursor, query.getFields()); } - - private interface DatabaseChangeOp { - boolean makeChange(); - } - - private boolean updateAndRecordChanges(Task item, DatabaseChangeOp op) { - final AtomicBoolean result = new AtomicBoolean(false); - synchronized(database) { - result.set(op.makeChange()); - if (result.get()) { - item.markSaved(); - if (BuildConfig.DEBUG) { - Timber.v("%s %s", op, item.toString()); - } - } - } - return result.get(); - } } diff --git a/app/src/main/java/com/todoroo/astrid/data/Task.java b/app/src/main/java/com/todoroo/astrid/data/Task.java index 84b3c34dc..04e14945f 100644 --- a/app/src/main/java/com/todoroo/astrid/data/Task.java +++ b/app/src/main/java/com/todoroo/astrid/data/Task.java @@ -29,6 +29,7 @@ import com.todoroo.andlib.utility.DateUtilities; import org.tasks.backup.XmlReader; import org.tasks.backup.XmlWriter; +import org.tasks.data.GoogleTask; import org.tasks.time.DateTime; import java.util.HashMap; @@ -36,6 +37,7 @@ import java.util.Map; import timber.log.Timber; +import static com.google.common.collect.Lists.newArrayList; import static org.tasks.date.DateTimeUtils.newDateTime; /** @@ -228,39 +230,35 @@ public class Task extends AbstractModel implements Parcelable { public static final int IMPORTANCE_SHOULD_DO = 2; public static final int IMPORTANCE_NONE = 3; - // --- defaults - - /** Default values container */ - private static final Map> roomGetters = new HashMap<>(); + public static final Map> roomSetters = new HashMap<>(); static { - roomGetters.put(CALENDAR_URI.name, t -> t.calendarUri); - roomGetters.put(COMPLETION_DATE.name, t -> t.completed); - roomGetters.put(CREATION_DATE.name, t -> t.created); - roomGetters.put(DELETION_DATE.name, t -> t.deleted); - roomGetters.put(DUE_DATE.name, t -> t.dueDate); - roomGetters.put(ELAPSED_SECONDS.name, t -> t.elapsedSeconds); - roomGetters.put(ESTIMATED_SECONDS.name, t -> t.estimatedSeconds); - roomGetters.put(HIDE_UNTIL.name, t -> t.hideUntil); - roomGetters.put(ID.name, t -> t.id); - roomGetters.put(IMPORTANCE.name, t -> t.importance); - roomGetters.put(MODIFICATION_DATE.name, t -> t.modified); - roomGetters.put(NOTES.name, t -> t.notes); - roomGetters.put(RECURRENCE.name, t -> t.recurrence); - roomGetters.put(REMINDER_FLAGS.name, t -> t.notificationFlags); - roomGetters.put(REMINDER_LAST.name, t -> t.lastNotified); - roomGetters.put(REMINDER_PERIOD.name, t -> t.notifications); - roomGetters.put(REMINDER_SNOOZE.name, t -> t.snoozeTime); - roomGetters.put(REPEAT_UNTIL.name, t -> t.repeatUntil); - roomGetters.put(TIMER_START.name, t -> t.timerStart); - roomGetters.put(TITLE.name, t -> t.title); - roomGetters.put(UUID.name, t -> t.remoteId); + roomSetters.put(CALENDAR_URI.name, (t, v) -> t.calendarUri = (String) v); + roomSetters.put(COMPLETION_DATE.name, (t, v) -> t.completed = (Long) v); + roomSetters.put(CREATION_DATE.name, (t, v) -> t.created = (Long) v); + roomSetters.put(DELETION_DATE.name, (t, v) -> t.deleted = (Long) v); + roomSetters.put(DUE_DATE.name, (t, v) -> t.dueDate = v instanceof String ? Long.valueOf((String) v) : (Long) v); + roomSetters.put(ELAPSED_SECONDS.name, (t, v) -> t.elapsedSeconds = (Integer) v); + roomSetters.put(ESTIMATED_SECONDS.name, (t, v) -> t.estimatedSeconds = (Integer) v); + roomSetters.put(HIDE_UNTIL.name, (t, v) -> t.hideUntil = (Long) v); + roomSetters.put(ID.name, (t, v) -> t.id = (Long) v); + roomSetters.put(IMPORTANCE.name, (t, v) -> t.importance = v instanceof String ? Integer.valueOf((String) v) : (Integer) v); + roomSetters.put(MODIFICATION_DATE.name, (t, v) -> t.modified = (Long) v); + roomSetters.put(NOTES.name, (t, v) -> t.notes = (String) v); + roomSetters.put(RECURRENCE.name, (t, v) -> t.recurrence = (String) v); + roomSetters.put(REMINDER_FLAGS.name, (t, v) -> t.notificationFlags = (Integer) v); + roomSetters.put(REMINDER_LAST.name, (t, v) -> t.lastNotified = (Long) v); + roomSetters.put(REMINDER_PERIOD.name, (t, v) -> t.notifications = (Long) v); + roomSetters.put(REMINDER_SNOOZE.name, (t, v) -> t.snoozeTime = (Long) v); + roomSetters.put(REPEAT_UNTIL.name, (t, v) -> t.repeatUntil = (Long) v); + roomSetters.put(TIMER_START.name, (t, v) -> t.timerStart = (Long) v); + roomSetters.put(TITLE.name, (t, v) -> t.title = (String) v); + roomSetters.put(UUID.name, (t, v) -> t.remoteId = (String) v); + roomSetters.put(GoogleTask.INDENT.name, (t, v) -> t.googleTaskIndent = (Integer) v); } - @Override - public Map> getRoomGetters() { - return roomGetters; - } + @Ignore + private int googleTaskIndent; // --- data access boilerplate @@ -270,7 +268,17 @@ public class Task extends AbstractModel implements Parcelable { @Ignore public Task(TodorooCursor cursor) { - super(cursor); + for (Property property : cursor.getProperties()) { + try { + ValueWriter writer = roomSetters.get(property.getColumnName()); + if (writer != null) { + writer.setValue(this, cursor.get(property)); + } + } catch (IllegalArgumentException e) { + // underlying cursor may have changed, suppress + Timber.e(e, e.getMessage()); + } + } } @Ignore @@ -343,34 +351,17 @@ public class Task extends AbstractModel implements Parcelable { timerStart = parcel.readLong(); title = parcel.readString(); remoteId = parcel.readString(); - setValues = parcel.readParcelable(ContentValues.class.getClassLoader()); - values = parcel.readParcelable(ContentValues.class.getClassLoader()); + setValues.addAll(parcel.readArrayList(getClass().getClassLoader())); transitoryData = parcel.readHashMap(ContentValues.class.getClassLoader()); } @Override public long getId() { - if(setValues != null && setValues.containsKey(ID.name)) { - return setValues.getAsLong(ID.name); - } else if(values != null && values.containsKey(ID.name)) { - return values.getAsLong(ID.name); - } else if (id != null) { - return id; - } else { - return NO_ID; - } + return id == null ? NO_ID : id; } public String getUuid() { - if(setValues != null && setValues.containsKey(UUID.name)) { - return setValues.getAsString(UUID.name); - } else if(values != null && values.containsKey(UUID.name)) { - return values.getAsString(UUID.name); - } else if (!Strings.isNullOrEmpty(remoteId)) { - return remoteId; - } else { - return NO_UUID; - } + return Strings.isNullOrEmpty(remoteId) ? NO_UUID : remoteId; } // --- parcelable helpers @@ -391,31 +382,26 @@ public class Task extends AbstractModel implements Parcelable { /** Checks whether task is done. Requires COMPLETION_DATE */ public boolean isCompleted() { - return getValue(COMPLETION_DATE) > 0; + return completed > 0; } /** Checks whether task is deleted. Will return false if DELETION_DATE not read */ public boolean isDeleted() { - // assume false if we didn't load deletion date - if(!containsValue(DELETION_DATE)) { - return false; - } else { - return getValue(DELETION_DATE) > 0; - } + return deleted > 0; } /** Checks whether task is hidden. Requires HIDDEN_UNTIL */ public boolean isHidden() { - return getValue(HIDE_UNTIL) > DateUtilities.now(); + return hideUntil > DateUtilities.now(); } public boolean hasHideUntilDate() { - return getValue(HIDE_UNTIL) > 0; + return hideUntil > 0; } /** Checks whether task is done. Requires DUE_DATE */ public boolean hasDueDate() { - return getValue(DUE_DATE) > 0; + return dueDate > 0; } // --- due and hide until date management @@ -423,12 +409,12 @@ public class Task extends AbstractModel implements Parcelable { /** urgency array index -> significance */ public static final int URGENCY_NONE = 0; - public static final int URGENCY_TODAY = 1; - public static final int URGENCY_TOMORROW = 2; - public static final int URGENCY_DAY_AFTER = 3; - public static final int URGENCY_NEXT_WEEK = 4; - public static final int URGENCY_IN_TWO_WEEKS = 5; - public static final int URGENCY_NEXT_MONTH = 6; + static final int URGENCY_TODAY = 1; + static final int URGENCY_TOMORROW = 2; + static final int URGENCY_DAY_AFTER = 3; + static final int URGENCY_NEXT_WEEK = 4; + static final int URGENCY_IN_TWO_WEEKS = 5; + static final int URGENCY_NEXT_MONTH = 6; public static final int URGENCY_SPECIFIC_DAY = 7; public static final int URGENCY_SPECIFIC_DAY_TIME = 8; /** hide until array index -> significance */ @@ -514,13 +500,13 @@ public class Task extends AbstractModel implements Parcelable { return 0; case HIDE_UNTIL_DUE: case HIDE_UNTIL_DUE_TIME: - date = getValue(DUE_DATE); + date = dueDate; break; case HIDE_UNTIL_DAY_BEFORE: - date = getValue(DUE_DATE) - DateUtilities.ONE_DAY; + date = dueDate - DateUtilities.ONE_DAY; break; case HIDE_UNTIL_WEEK_BEFORE: - date = getValue(DUE_DATE) - DateUtilities.ONE_WEEK; + date = dueDate - DateUtilities.ONE_WEEK; break; case HIDE_UNTIL_SPECIFIC_DAY: case HIDE_UNTIL_SPECIFIC_DAY_TIME: @@ -580,7 +566,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getDueDate() { - return getValue(DUE_DATE); + return dueDate; } public void setDueDate(Long dueDate) { @@ -588,9 +574,9 @@ public class Task extends AbstractModel implements Parcelable { } public void setDueDateAdjustingHideUntil(Long dueDate) { - long oldDueDate = getValue(DUE_DATE); + long oldDueDate = dueDate; if (oldDueDate > 0) { - long hideUntil = getValue(HIDE_UNTIL); + long hideUntil = this.hideUntil; if (hideUntil > 0) { setHideUntil(dueDate > 0 ? hideUntil + dueDate - oldDueDate : 0); } @@ -599,7 +585,7 @@ public class Task extends AbstractModel implements Parcelable { } public String getRecurrence() { - return getValue(RECURRENCE); + return recurrence; } public void setRecurrence(String recurrence) { @@ -611,7 +597,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getCreationDate() { - return getValue(CREATION_DATE); + return created; } public void setCreationDate(Long creationDate) { @@ -619,7 +605,7 @@ public class Task extends AbstractModel implements Parcelable { } public String getTitle() { - return getValue(TITLE); + return title; } public void setTitle(String title) { @@ -627,7 +613,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getDeletionDate() { - return getValue(DELETION_DATE); + return deleted; } public void setDeletionDate(Long deletionDate) { @@ -635,7 +621,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getHideUntil() { - return getValue(HIDE_UNTIL); + return hideUntil; } public void setHideUntil(Long hideUntil) { @@ -643,7 +629,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getReminderLast() { - return getValue(REMINDER_LAST); + return lastNotified; } public void setReminderLast(Long reminderLast) { @@ -651,7 +637,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getReminderSnooze() { - return getValue(REMINDER_SNOOZE); + return snoozeTime; } public void setReminderSnooze(Long reminderSnooze) { @@ -659,11 +645,11 @@ public class Task extends AbstractModel implements Parcelable { } public Integer getElapsedSeconds() { - return getValue(ELAPSED_SECONDS); + return elapsedSeconds; } public Long getTimerStart() { - return getValue(TIMER_START); + return timerStart; } public void setTimerStart(Long timerStart) { @@ -671,7 +657,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getRepeatUntil() { - return getValue(REPEAT_UNTIL); + return repeatUntil; } public void setRepeatUntil(Long repeatUntil) { @@ -679,11 +665,11 @@ public class Task extends AbstractModel implements Parcelable { } public String getCalendarURI() { - return getValue(CALENDAR_URI); + return calendarUri; } public Integer getImportance() { - return getValue(IMPORTANCE); + return importance; } public void setImportance(Integer importance) { @@ -691,7 +677,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getCompletionDate() { - return getValue(COMPLETION_DATE); + return completed; } public void setCompletionDate(Long completionDate) { @@ -699,11 +685,11 @@ public class Task extends AbstractModel implements Parcelable { } public String getNotes() { - return getValue(NOTES); + return notes; } public boolean hasNotes() { - return !TextUtils.isEmpty(getValue(NOTES)); + return !TextUtils.isEmpty(notes); } public void setNotes(String notes) { @@ -715,7 +701,7 @@ public class Task extends AbstractModel implements Parcelable { } public Integer getReminderFlags() { - return getValue(REMINDER_FLAGS); + return notificationFlags; } public void setReminderFlags(Integer reminderFlags) { @@ -723,7 +709,7 @@ public class Task extends AbstractModel implements Parcelable { } public Long getReminderPeriod() { - return getValue(REMINDER_PERIOD); + return notifications; } public void setReminderPeriod(Long reminderPeriod) { @@ -731,7 +717,7 @@ public class Task extends AbstractModel implements Parcelable { } public Integer getEstimatedSeconds() { - return getValue(ESTIMATED_SECONDS); + return estimatedSeconds; } public void setElapsedSeconds(Integer elapsedSeconds) { @@ -763,7 +749,7 @@ public class Task extends AbstractModel implements Parcelable { } private boolean isReminderFlagSet(int flag) { - return (getReminderFlags() & flag) > 0; + return (notificationFlags & flag) > 0; } public boolean isNew() { @@ -781,15 +767,7 @@ public class Task extends AbstractModel implements Parcelable { } public void setUuid(String uuid) { - if (setValues == null) { - setValues = new ContentValues(); - } - - if(NO_UUID.equals(uuid)) { - clearValue(UUID); - } else { - setValues.put(UUID.name, uuid); - } + setValue(UUID, uuid); } public static boolean isUuidEmpty(String uuid) { @@ -830,8 +808,40 @@ public class Task extends AbstractModel implements Parcelable { dest.writeLong(timerStart); dest.writeString(title); dest.writeString(remoteId); - dest.writeParcelable(setValues, 0); - dest.writeParcelable(values, 0); + dest.writeList(newArrayList(setValues)); dest.writeMap(transitoryData); } + + @Override + public String toString() { + return "Task{" + + "id=" + id + + ", title='" + title + '\'' + + ", importance=" + importance + + ", setValues=" + setValues + + ", dueDate=" + dueDate + + ", transitoryData=" + transitoryData + + ", hideUntil=" + hideUntil + + ", created=" + created + + ", modified=" + modified + + ", completed=" + completed + + ", deleted=" + deleted + + ", notes='" + notes + '\'' + + ", estimatedSeconds=" + estimatedSeconds + + ", elapsedSeconds=" + elapsedSeconds + + ", timerStart=" + timerStart + + ", notificationFlags=" + notificationFlags + + ", notifications=" + notifications + + ", lastNotified=" + lastNotified + + ", snoozeTime=" + snoozeTime + + ", recurrence='" + recurrence + '\'' + + ", repeatUntil=" + repeatUntil + + ", calendarUri='" + calendarUri + '\'' + + ", remoteId='" + remoteId + '\'' + + '}'; + } + + public int getGoogleTaskIndent() { + return googleTaskIndent; + } } diff --git a/app/src/main/java/com/todoroo/astrid/data/TaskApiDao.java b/app/src/main/java/com/todoroo/astrid/data/TaskApiDao.java index 27e63373c..207cc0916 100644 --- a/app/src/main/java/com/todoroo/astrid/data/TaskApiDao.java +++ b/app/src/main/java/com/todoroo/astrid/data/TaskApiDao.java @@ -5,7 +5,8 @@ */ package com.todoroo.astrid.data; -import android.content.ContentValues; +import java.util.Collection; +import java.util.Set; /** * Data access object for accessing Astrid's {@link Task} table. If you @@ -18,22 +19,22 @@ import android.content.ContentValues; public class TaskApiDao { /** @return true if task change shouldn't be broadcast */ - public static boolean insignificantChange(ContentValues values) { + public static boolean insignificantChange(Collection values) { if(values == null || values.size() == 0) { return true; } - if(values.containsKey(Task.REMINDER_LAST.name) && + if(values.contains(Task.REMINDER_LAST.name) && values.size() <= 2) { return true; } - if(values.containsKey(Task.REMINDER_SNOOZE.name) && + if(values.contains(Task.REMINDER_SNOOZE.name) && values.size() <= 2) { return true; } - if(values.containsKey(Task.TIMER_START.name) && + if(values.contains(Task.TIMER_START.name) && values.size() <= 2) { return true; } diff --git a/app/src/main/java/com/todoroo/astrid/service/TaskCreator.java b/app/src/main/java/com/todoroo/astrid/service/TaskCreator.java index fa9bfc4a2..c7712adba 100644 --- a/app/src/main/java/com/todoroo/astrid/service/TaskCreator.java +++ b/app/src/main/java/com/todoroo/astrid/service/TaskCreator.java @@ -114,16 +114,16 @@ public class TaskCreator { task.mergeWithoutReplacement(forTask); } - if (!task.containsValue(Task.IMPORTANCE)) { + if (!task.isModified(Task.IMPORTANCE)) { task.setImportance(preferences.getIntegerFromString(R.string.p_default_importance_key, Task.IMPORTANCE_SHOULD_DO)); } - if(!task.containsValue(Task.DUE_DATE)) { + if(!task.isModified(Task.DUE_DATE)) { task.setDueDate(Task.createDueDate( preferences.getIntegerFromString(R.string.p_default_urgency_key, Task.URGENCY_NONE), 0)); } - if(!task.containsValue(Task.HIDE_UNTIL)) { + if(!task.isModified(Task.HIDE_UNTIL)) { int setting = preferences.getIntegerFromString(R.string.p_default_hideUntil_key, Task.HIDE_UNTIL_NONE); task.setHideUntil(task.createHideUntil(setting, 0)); @@ -137,13 +137,13 @@ public class TaskCreator { } public static void setDefaultReminders(Preferences preferences, Task task) { - if(!task.containsValue(Task.REMINDER_PERIOD)) { + if(!task.isModified(Task.REMINDER_PERIOD)) { task.setReminderPeriod(DateUtilities.ONE_HOUR * preferences.getIntegerFromString(R.string.p_rmd_default_random_hours, 0)); } - if(!task.containsValue(Task.REMINDER_FLAGS)) { + if(!task.isModified(Task.REMINDER_FLAGS)) { task.setReminderFlags(preferences.getDefaultReminders() | preferences.getDefaultRingMode()); } } diff --git a/app/src/main/java/org/tasks/data/GoogleTask.java b/app/src/main/java/org/tasks/data/GoogleTask.java index c3c791b4f..54df20276 100644 --- a/app/src/main/java/org/tasks/data/GoogleTask.java +++ b/app/src/main/java/org/tasks/data/GoogleTask.java @@ -23,9 +23,6 @@ public class GoogleTask { @Deprecated public static final Property.IntegerProperty INDENT = new Property.IntegerProperty(GoogleTask.TABLE, "indent"); - @Deprecated - public static final Property.LongProperty ORDER = new Property.LongProperty(GoogleTask.TABLE, "`order`"); - @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "_id") private long id; diff --git a/app/src/main/java/org/tasks/jobs/AfterSaveIntentService.java b/app/src/main/java/org/tasks/jobs/AfterSaveIntentService.java index 54875041d..8b7aa850c 100644 --- a/app/src/main/java/org/tasks/jobs/AfterSaveIntentService.java +++ b/app/src/main/java/org/tasks/jobs/AfterSaveIntentService.java @@ -26,10 +26,15 @@ import org.tasks.notifications.NotificationManager; import org.tasks.receivers.PushReceiver; import org.tasks.scheduling.RefreshScheduler; +import java.util.ArrayList; +import java.util.Set; + import javax.inject.Inject; import timber.log.Timber; +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; import static com.todoroo.astrid.dao.TaskDao.TRANS_SUPPRESS_REFRESH; public class AfterSaveIntentService extends InjectingJobIntentService { @@ -37,10 +42,10 @@ public class AfterSaveIntentService extends InjectingJobIntentService { private static final String EXTRA_TASK_ID = "extra_task_id"; private static final String EXTRA_MODIFIED_VALUES = "extra_modified_values"; - public static void enqueue(Context context, long taskId, ContentValues modifiedValues) { + public static void enqueue(Context context, long taskId, Set modifiedValues) { Intent intent = new Intent(); intent.putExtra(EXTRA_TASK_ID, taskId); - intent.putExtra(EXTRA_MODIFIED_VALUES, modifiedValues); + intent.putStringArrayListExtra(EXTRA_MODIFIED_VALUES, newArrayList(modifiedValues)); AfterSaveIntentService.enqueueWork(context, AfterSaveIntentService.class, JobManager.JOB_ID_TASK_STATUS_CHANGE, intent); } @@ -59,7 +64,7 @@ public class AfterSaveIntentService extends InjectingJobIntentService { super.onHandleWork(intent); long taskId = intent.getLongExtra(EXTRA_TASK_ID, -1); - ContentValues modifiedValues = intent.getParcelableExtra(EXTRA_MODIFIED_VALUES); + ArrayList modifiedValues = intent.getStringArrayListExtra(EXTRA_MODIFIED_VALUES); if (taskId == -1 || modifiedValues == null) { Timber.e("Invalid extras, taskId=%s modifiedValues=%s", taskId, modifiedValues); @@ -72,11 +77,11 @@ public class AfterSaveIntentService extends InjectingJobIntentService { return; } - if(modifiedValues.containsKey(Task.DUE_DATE.name) || - modifiedValues.containsKey(Task.REMINDER_FLAGS.name) || - modifiedValues.containsKey(Task.REMINDER_PERIOD.name) || - modifiedValues.containsKey(Task.REMINDER_LAST.name) || - modifiedValues.containsKey(Task.REMINDER_SNOOZE.name)) { + if(modifiedValues.contains(Task.DUE_DATE.name) || + modifiedValues.contains(Task.REMINDER_FLAGS.name) || + modifiedValues.contains(Task.REMINDER_PERIOD.name) || + modifiedValues.contains(Task.REMINDER_LAST.name) || + modifiedValues.contains(Task.REMINDER_SNOOZE.name)) { reminderService.scheduleAlarm(task); } @@ -84,8 +89,8 @@ public class AfterSaveIntentService extends InjectingJobIntentService { return; } - boolean completionDateModified = modifiedValues.containsKey(Task.COMPLETION_DATE.name); - boolean deletionDateModified = modifiedValues.containsKey(Task.DELETION_DATE.name); + boolean completionDateModified = modifiedValues.contains(Task.COMPLETION_DATE.name); + boolean deletionDateModified = modifiedValues.contains(Task.DELETION_DATE.name); boolean justCompleted = completionDateModified && task.isCompleted(); boolean justDeleted = deletionDateModified && task.isDeleted(); diff --git a/app/src/main/java/org/tasks/tasklist/ViewHolder.java b/app/src/main/java/org/tasks/tasklist/ViewHolder.java index 7ee987bdf..a3c08b623 100644 --- a/app/src/main/java/org/tasks/tasklist/ViewHolder.java +++ b/app/src/main/java/org/tasks/tasklist/ViewHolder.java @@ -195,7 +195,7 @@ class ViewHolder extends MultiSelectorBindingHolder { void bindView(TodorooCursor cursor) { tagsString = cursor.get(TaskAdapter.TAGS); - hasFiles = cursor.get(TaskAdapter.FILE_ID_PROPERTY) > 0; + hasFiles = (Long) cursor.get(TaskAdapter.FILE_ID_PROPERTY) > 0; // TODO: see if this is a performance issue task = new Task(cursor); diff --git a/app/src/main/java/org/tasks/ui/CalendarControlSet.java b/app/src/main/java/org/tasks/ui/CalendarControlSet.java index 2de5ee546..212776011 100644 --- a/app/src/main/java/org/tasks/ui/CalendarControlSet.java +++ b/app/src/main/java/org/tasks/ui/CalendarControlSet.java @@ -161,14 +161,13 @@ public class CalendarControlSet extends TaskEditControlFragment { ContentValues updateValues = new ContentValues(); // check if we need to update the item - ContentValues setValues = task.getSetValues(); - if(setValues.containsKey(Task.TITLE.name)) { + if(task.isModified(Task.TITLE)) { updateValues.put(CalendarContract.Events.TITLE, task.getTitle()); } - if(setValues.containsKey(Task.NOTES.name)) { + if(task.isModified(Task.NOTES)) { updateValues.put(CalendarContract.Events.DESCRIPTION, task.getNotes()); } - if(setValues.containsKey(Task.DUE_DATE.name) || setValues.containsKey(Task.ESTIMATED_SECONDS.name)) { + if(task.isModified(Task.DUE_DATE) || task.isModified(Task.ESTIMATED_SECONDS)) { gcalHelper.createStartAndEndDate(task, updateValues); } diff --git a/app/src/main/java/org/tasks/ui/DescriptionControlSet.java b/app/src/main/java/org/tasks/ui/DescriptionControlSet.java index 40808d052..149b07248 100644 --- a/app/src/main/java/org/tasks/ui/DescriptionControlSet.java +++ b/app/src/main/java/org/tasks/ui/DescriptionControlSet.java @@ -16,6 +16,8 @@ import org.tasks.injection.FragmentComponent; import butterknife.BindView; import butterknife.OnTextChanged; +import static com.google.common.base.Strings.isNullOrEmpty; + public class DescriptionControlSet extends TaskEditControlFragment { public static final int TAG = R.string.TEA_ctrl_notes_pref; @@ -34,7 +36,7 @@ public class DescriptionControlSet extends TaskEditControlFragment { } else { description = savedInstanceState.getString(EXTRA_DESCRIPTION); } - if (!Strings.isNullOrEmpty(description)) { + if (!isNullOrEmpty(description)) { editText.setTextKeepState(description); } return view; @@ -74,7 +76,9 @@ public class DescriptionControlSet extends TaskEditControlFragment { @Override public boolean hasChanges(Task original) { - return !description.equals(original.getNotes()); + return isNullOrEmpty(description) + ? isNullOrEmpty(original.getNotes()) + : description.equals(original.getNotes()); } @Override