diff --git a/api/src/com/todoroo/andlib/data/AbstractDatabase.java b/api/src/com/todoroo/andlib/data/AbstractDatabase.java index 1e5479736..7ab91eae1 100644 --- a/api/src/com/todoroo/andlib/data/AbstractDatabase.java +++ b/api/src/com/todoroo/andlib/data/AbstractDatabase.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; @@ -230,7 +231,15 @@ abstract public class AbstractDatabase { * @see android.database.sqlite.SQLiteDatabase#insert(String table, String nullColumnHack, ContentValues values) */ public synchronized long insert(String table, String nullColumnHack, ContentValues values) { - long result = getDatabase().insert(table, nullColumnHack, values); + long result = -1; + try { + result = getDatabase().insertOrThrow(table, nullColumnHack, values); + } catch (SQLiteConstraintException e) { // Throw these exceptions + throw e; + } catch (Exception e) { // Suppress others + Log.e("SQLiteDatabase", "Error inserting " + values, e); + result = -1; + } onDatabaseUpdated(); return result; } diff --git a/api/src/com/todoroo/andlib/data/Property.java b/api/src/com/todoroo/andlib/data/Property.java index 9a4665bf2..b1526e629 100644 --- a/api/src/com/todoroo/andlib/data/Property.java +++ b/api/src/com/todoroo/andlib/data/Property.java @@ -30,6 +30,9 @@ public abstract class Property extends Field implements Cloneable { /** The database column name for this property */ public final String name; + /** Can this field be null? */ + public boolean nullable = false; + /** * Create a property by table and column name. Uses the default property * expression which is derived from default table name @@ -38,6 +41,15 @@ public abstract class Property extends Field implements Cloneable { this(table, columnName, (table == null) ? (columnName) : (table.name + "." + columnName)); } + /** + * Create a property by table and column name. Uses the default property + * expression which is derived from default table name + */ + protected Property(Table table, String columnName, boolean nullable) { + this(table, columnName, (table == null) ? (columnName) : (table.name + "." + columnName)); + this.nullable = nullable; + } + /** * Create a property by table and column name, manually specifying an * expression to use in SQL @@ -98,6 +110,10 @@ public abstract class Property extends Field implements Cloneable { super(table, name); } + public IntegerProperty(Table table, String name, boolean nullable) { + super(table, name, nullable); + } + protected IntegerProperty(Table table, String name, String expression) { super(table, name, expression); } @@ -121,6 +137,10 @@ public abstract class Property extends Field implements Cloneable { super(table, name); } + public StringProperty(Table table, String name, boolean nullable) { + super(table, name, nullable); + } + protected StringProperty(Table table, String name, String expression) { super(table, name, expression); } @@ -144,6 +164,10 @@ public abstract class Property extends Field implements Cloneable { super(table, name); } + public DoubleProperty(Table table, String name, boolean nullable) { + super(table, name, nullable); + } + protected DoubleProperty(Table table, String name, String expression) { super(table, name, expression); } @@ -168,6 +192,10 @@ public abstract class Property extends Field implements Cloneable { super(table, name); } + public LongProperty(Table table, String name, boolean nullable) { + super(table, name, nullable); + } + protected LongProperty(Table table, String name, String expression) { super(table, name, expression); } diff --git a/api/src/com/todoroo/andlib/data/TodorooCursor.java b/api/src/com/todoroo/andlib/data/TodorooCursor.java index 781fbac94..29f2dacaa 100644 --- a/api/src/com/todoroo/andlib/data/TodorooCursor.java +++ b/api/src/com/todoroo/andlib/data/TodorooCursor.java @@ -98,23 +98,38 @@ public class TodorooCursor extends CursorWrapper { public Object visitDouble(Property property, TodorooCursor cursor) { - return cursor.getDouble(cursor.getColumnIndexFromCache(property.name)); + int column = columnIndex(property, cursor); + if(property.nullable && cursor.isNull(column)) + return null; + return cursor.getDouble(column); } public Object visitInteger(Property property, TodorooCursor cursor) { - return cursor.getInt(cursor.getColumnIndexFromCache(property.name)); + int column = columnIndex(property, cursor); + if(property.nullable && cursor.isNull(column)) + return null; + return cursor.getInt(column); } public Object visitLong(Property property, TodorooCursor cursor) { - return cursor.getLong(cursor.getColumnIndexFromCache(property.name)); + int column = columnIndex(property, cursor); + if(property.nullable && cursor.isNull(column)) + return null; + return cursor.getLong(column); } public Object visitString(Property property, TodorooCursor cursor) { - return cursor.getString(cursor.getColumnIndexFromCache(property.name)); + int column = columnIndex(property, cursor); + if(property.nullable && cursor.isNull(column)) + return null; + return cursor.getString(column); } + private int columnIndex(Property property, TodorooCursor cursor) { + return cursor.getColumnIndexFromCache(property.name); + } } } diff --git a/api/src/com/todoroo/astrid/data/Task.java b/api/src/com/todoroo/astrid/data/Task.java index cc20dfa10..889bddeeb 100644 --- a/api/src/com/todoroo/astrid/data/Task.java +++ b/api/src/com/todoroo/astrid/data/Task.java @@ -135,7 +135,7 @@ public final class Task extends RemoteModel { /** Remote id */ public static final LongProperty REMOTE_ID = new LongProperty( - TABLE, REMOTE_ID_PROPERTY_NAME); + TABLE, REMOTE_ID_PROPERTY_NAME, true); /** Assigned user id */ public static final LongProperty USER_ID = new LongProperty( @@ -252,7 +252,7 @@ public final class Task extends RemoteModel { defaultValues.put(DETAILS_DATE.name, 0); defaultValues.put(LAST_SYNC.name, 0); - defaultValues.put(REMOTE_ID.name, 0); + defaultValues.putNull(REMOTE_ID.name); defaultValues.put(USER_ID.name, 0); defaultValues.put(CREATOR_ID.name, 0); defaultValues.put(USER.name, "{}"); diff --git a/api/src/com/todoroo/astrid/data/TaskApiDao.java b/api/src/com/todoroo/astrid/data/TaskApiDao.java index d7cd59fe1..5015918f0 100644 --- a/api/src/com/todoroo/astrid/data/TaskApiDao.java +++ b/api/src/com/todoroo/astrid/data/TaskApiDao.java @@ -3,6 +3,7 @@ package com.todoroo.astrid.data; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.database.SQLException; import com.todoroo.andlib.data.ContentResolverDao; import com.todoroo.andlib.data.TodorooCursor; @@ -143,9 +144,24 @@ public class TaskApiDao extends ContentResolverDao { @Override public boolean save(Task model) { ContentValues setValues = model.getSetValues(); - if(super.save(model)) { - afterSave(model, setValues); - return true; + try { + if(super.save(model)) { + afterSave(model, setValues); + return true; + } + } catch (SQLException e) { + if (model.containsNonNullValue(Task.REMOTE_ID)) { + TodorooCursor cursor = query(Query.select(Task.ID).where(Task.REMOTE_ID.eq(model.getValue(Task.REMOTE_ID)))); + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + model.setId(cursor.get(Task.ID)); + setValues = model.getSetValues(); + if (super.save(model)) { + afterSave(model, setValues); + return true; + } + } + } } return false; } diff --git a/astrid/.classpath b/astrid/.classpath index ecbf95127..91166000d 100644 --- a/astrid/.classpath +++ b/astrid/.classpath @@ -3,7 +3,7 @@ - + diff --git a/astrid/common-src/com/localytics/android/ExceptionHandler.java b/astrid/common-src/com/localytics/android/ExceptionHandler.java index 1a55ecd4e..7fb8c9eed 100644 --- a/astrid/common-src/com/localytics/android/ExceptionHandler.java +++ b/astrid/common-src/com/localytics/android/ExceptionHandler.java @@ -33,4 +33,4 @@ import android.util.Log; } } } -} \ No newline at end of file +} diff --git a/astrid/common-src/com/localytics/android/ReflectionUtils.java b/astrid/common-src/com/localytics/android/ReflectionUtils.java index d98d2a7f9..dc4d608c3 100644 --- a/astrid/common-src/com/localytics/android/ReflectionUtils.java +++ b/astrid/common-src/com/localytics/android/ReflectionUtils.java @@ -106,4 +106,4 @@ public final class ReflectionUtils throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/astrid/common-src/com/todoroo/andlib/widget/Api4GestureDetector.java b/astrid/common-src/com/todoroo/andlib/widget/Api4GestureDetector.java index 9c52756bf..966820468 100644 --- a/astrid/common-src/com/todoroo/andlib/widget/Api4GestureDetector.java +++ b/astrid/common-src/com/todoroo/andlib/widget/Api4GestureDetector.java @@ -40,4 +40,4 @@ public class Api4GestureDetector implements OnGesturePerformedListener { } } } -} \ No newline at end of file +} diff --git a/astrid/common-src/com/todoroo/andlib/widget/DateControlSet.java b/astrid/common-src/com/todoroo/andlib/widget/DateControlSet.java index 4a8dabf7a..1eea3ed8b 100644 --- a/astrid/common-src/com/todoroo/andlib/widget/DateControlSet.java +++ b/astrid/common-src/com/todoroo/andlib/widget/DateControlSet.java @@ -138,4 +138,4 @@ public class DateControlSet implements OnTimeSetListener, }); } } -} \ No newline at end of file +} diff --git a/astrid/common-src/com/todoroo/andlib/widget/DateWithNullControlSet.java b/astrid/common-src/com/todoroo/andlib/widget/DateWithNullControlSet.java index 3cd1a1d34..d8ba506c9 100644 --- a/astrid/common-src/com/todoroo/andlib/widget/DateWithNullControlSet.java +++ b/astrid/common-src/com/todoroo/andlib/widget/DateWithNullControlSet.java @@ -66,4 +66,4 @@ public class DateWithNullControlSet extends DateControlSet { super.setDate(newDate); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java b/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java index 365ec3656..43e571ed9 100644 --- a/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java +++ b/astrid/plugin-src/com/timsu/astrid/C2DMReceiver.java @@ -132,7 +132,7 @@ public class C2DMReceiver extends BroadcastReceiver { try { TagData tagData = new TagData(); if(cursor.getCount() == 0) { - tagData.setValue(Task.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); + tagData.setValue(TagData.REMOTE_ID, Long.parseLong(intent.getStringExtra("tag_id"))); Flags.set(Flags.ACTFM_SUPPRESS_SYNC); tagDataService.save(tagData); } else { @@ -192,7 +192,17 @@ public class C2DMReceiver extends BroadcastReceiver { Intent notifyIntent = null; int notifId; - final long user_id = intent.getLongExtra("oid", -2L); + long user_idTemp = -2; + final String user_idString = intent.getStringExtra("oid"); + if (user_idString != null) { + try { + user_idTemp = Long.parseLong(user_idString); + } catch(NumberFormatException e) { + // We tried + Log.e("c2dm-receive", "oid-parse", e); + } + } + final long user_id = user_idTemp; final String token_id = intent.getStringExtra("tid"); // unregister if (!actFmPreferenceService.isLoggedIn() || user_id != ActFmPreferenceService.userId()) { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmGoogleAuthActivity.java b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmGoogleAuthActivity.java index a63c57838..fd5e61571 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmGoogleAuthActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmGoogleAuthActivity.java @@ -191,4 +191,4 @@ public class ActFmGoogleAuthActivity extends ListActivity { } } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmPreferences.java b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmPreferences.java index 27834e7eb..63460c1cc 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/ActFmPreferences.java @@ -76,4 +76,4 @@ public class ActFmPreferences extends SyncProviderPreferences { } } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java index 838b0728d..17d8690bf 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/EditPeopleControlSet.java @@ -695,9 +695,12 @@ public class EditPeopleControlSet extends PopupControlSet { @SuppressWarnings("nls") protected Object[] buildSharingArgs(JSONArray emails) throws JSONException { ArrayList values = new ArrayList(); - long currentTaskID = task.getValue(Task.REMOTE_ID); - values.add("id"); - values.add(currentTaskID); + + if(task.containsNonNullValue(Task.REMOTE_ID)) { + long currentTaskID = task.getValue(Task.REMOTE_ID); + values.add("id"); + values.add(currentTaskID); + } if(emails != null) { for(int i = 0; i < emails.length(); i++) { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/OAuthLoginActivity.java b/astrid/plugin-src/com/todoroo/astrid/actfm/OAuthLoginActivity.java index b0ce99f7c..d6dc4ec99 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/OAuthLoginActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/OAuthLoginActivity.java @@ -126,4 +126,4 @@ public class OAuthLoginActivity extends FragmentActivity { webView.loadUrl(urlParam); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/TagUpdatesFragment.java b/astrid/plugin-src/com/todoroo/astrid/actfm/TagUpdatesFragment.java index 90f50073d..1752b5445 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/TagUpdatesFragment.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/TagUpdatesFragment.java @@ -41,7 +41,6 @@ import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.adapter.UpdateAdapter; import com.todoroo.astrid.dao.UpdateDao; import com.todoroo.astrid.data.TagData; -import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Update; import com.todoroo.astrid.helper.ImageDiskCache; import com.todoroo.astrid.helper.ProgressBarSyncResultCallback; @@ -205,7 +204,7 @@ public class TagUpdatesFragment extends ListFragment { } public void setLastViewed() { - if(tagData != null && tagData.getValue(Task.REMOTE_ID) > 0) { + if(tagData != null && tagData.getValue(TagData.REMOTE_ID) > 0) { Preferences.setLong(UPDATES_LAST_VIEWED + tagData.getValue(TagData.REMOTE_ID), DateUtilities.now()); Activity activity = getActivity(); if (activity instanceof TaskListActivity) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/TagViewFragment.java b/astrid/plugin-src/com/todoroo/astrid/actfm/TagViewFragment.java index 5ded00988..5da005c80 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/TagViewFragment.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/TagViewFragment.java @@ -39,6 +39,7 @@ import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmSyncService; +import com.todoroo.astrid.activity.FilterListFragment; import com.todoroo.astrid.activity.TaskListActivity; import com.todoroo.astrid.activity.TaskListFragment; import com.todoroo.astrid.api.AstridApiConstants; @@ -454,9 +455,16 @@ public class TagViewFragment extends TaskListFragment { if (requestCode == REQUEST_CODE_SETTINGS && resultCode == Activity.RESULT_OK) { tagData = tagDataService.fetchById(tagData.getId(), TagData.PROPERTIES); filter = TagFilterExposer.filterFromTagData(getActivity(), tagData); + getActivity().getIntent().putExtra(TOKEN_FILTER, filter); + Activity activity = getActivity(); + if (activity instanceof TaskListActivity) { + ((TaskListActivity) activity).setListsTitle(filter.title); + FilterListFragment flf = ((TaskListActivity) activity).getFilterListFragment(); + if (flf != null) + flf.clear(); + } taskAdapter = null; refresh(); - //loadTaskListContent(true); } else { super.onActivityResult(requestCode, resultCode, data); } diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java index 190dfe6e9..49b9168b8 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmDataService.java @@ -64,7 +64,7 @@ public final class ActFmDataService { */ public void clearMetadata() { ContentValues values = new ContentValues(); - values.put(Task.REMOTE_ID.name, 0); + values.putNull(Task.REMOTE_ID.name); taskDao.updateMultiple(values, Criterion.all); } @@ -75,7 +75,7 @@ public final class ActFmDataService { */ public TodorooCursor getLocallyCreated(Property[] properties) { return taskDao.query(Query.select(properties).where(Criterion.and(TaskCriteria.isActive(), - Task.REMOTE_ID.eq(0)))); + Task.REMOTE_ID.isNull()))); } /** @@ -89,7 +89,7 @@ public final class ActFmDataService { return taskDao.query(Query.select(properties).where(Criterion.none)); return taskDao.query(Query.select(properties). - where(Criterion.and(Task.REMOTE_ID.gt(0), + where(Criterion.and(Task.REMOTE_ID.isNotNull(), Task.MODIFICATION_DATE.gt(lastSyncDate), Task.MODIFICATION_DATE.gt(Task.LAST_SYNC))).groupBy(Task.ID)); } diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmPreferenceService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmPreferenceService.java index 3cb407732..b0fbb38cf 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmPreferenceService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmPreferenceService.java @@ -123,4 +123,4 @@ public class ActFmPreferenceService extends SyncProviderUtilities { return Preferences.getStringValue(PREF_NAME); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncProvider.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncProvider.java deleted file mode 100644 index 89bfc7b88..000000000 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncProvider.java +++ /dev/null @@ -1,363 +0,0 @@ -/** - * See the file "LICENSE" for the full license governing this code. - */ -package com.todoroo.astrid.actfm.sync; - -import java.io.IOException; -import java.util.ArrayList; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import android.app.Activity; -import android.app.Notification; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; - -import com.timsu.astrid.C2DMReceiver; -import com.timsu.astrid.R; -import com.todoroo.andlib.data.TodorooCursor; -import com.todoroo.andlib.service.Autowired; -import com.todoroo.andlib.service.ContextManager; -import com.todoroo.andlib.sql.Criterion; -import com.todoroo.andlib.sql.Query; -import com.todoroo.andlib.utility.DateUtilities; -import com.todoroo.andlib.utility.Preferences; -import com.todoroo.astrid.actfm.ActFmBackgroundService; -import com.todoroo.astrid.actfm.ActFmLoginActivity; -import com.todoroo.astrid.actfm.ActFmPreferences; -import com.todoroo.astrid.actfm.sync.ActFmSyncService.JsonHelper; -import com.todoroo.astrid.api.AstridApiConstants; -import com.todoroo.astrid.core.PluginServices; -import com.todoroo.astrid.dao.TagDataDao; -import com.todoroo.astrid.dao.TaskDao; -import com.todoroo.astrid.data.Metadata; -import com.todoroo.astrid.data.TagData; -import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.notes.NoteMetadata; -import com.todoroo.astrid.service.AstridDependencyInjector; -import com.todoroo.astrid.service.StatisticsConstants; -import com.todoroo.astrid.service.StatisticsService; -import com.todoroo.astrid.sync.SyncProvider; -import com.todoroo.astrid.sync.SyncProviderUtilities; -import com.todoroo.astrid.utility.Constants; - -@SuppressWarnings("nls") -public class ActFmSyncProvider extends SyncProvider { - - private ActFmInvoker invoker = null; - - @Autowired ActFmDataService actFmDataService; - @Autowired ActFmSyncService actFmSyncService; - @Autowired ActFmPreferenceService actFmPreferenceService; - @Autowired TagDataDao tagDataDao; - - static { - AstridDependencyInjector.initialize(); - } - - // ---------------------------------------------------------------------- - // ------------------------------------------------------ utility methods - // ---------------------------------------------------------------------- - - @Override - protected SyncProviderUtilities getUtilities() { - return actFmPreferenceService; - } - - /** - * Sign out of service, deleting all synchronization metadata - */ - public void signOut() { - actFmPreferenceService.setToken(null); - actFmPreferenceService.clearLastSyncDate(); - C2DMReceiver.unregister(); - } - - // ---------------------------------------------------------------------- - // ------------------------------------------------------ initiating sync - // ---------------------------------------------------------------------- - - /** - * initiate sync in background - */ - @Override - protected void initiateBackground() { - try { - C2DMReceiver.register(); - String authToken = actFmPreferenceService.getToken(); - invoker = new ActFmInvoker(authToken); - - // check if we have a token & it works - if(authToken != null) { - performSync(); - } - } catch (IllegalStateException e) { - // occurs when application was closed - } catch (Exception e) { - handleException("actfm-authenticate", e, false); - } finally { - actFmPreferenceService.stopOngoing(); - } - } - - /** - * If user isn't already signed in, show sign in dialog. Else perform sync. - */ - @Override - protected void initiateManual(Activity activity) { - String authToken = actFmPreferenceService.getToken(); - actFmPreferenceService.stopOngoing(); - - // check if we have a token & it works - if(authToken == null) { - // display login-activity - Intent intent = new Intent(activity, ActFmLoginActivity.class); - activity.startActivityForResult(intent, 0); - } else { - activity.startService(new Intent(null, null, - activity, ActFmBackgroundService.class)); - } - } - - // ---------------------------------------------------------------------- - // ----------------------------------------------------- synchronization! - // ---------------------------------------------------------------------- - - protected void performSync() { - actFmPreferenceService.recordSyncStart(); - String syncSuccess = "failed"; - - try { - int serverTime = Preferences.getInt(ActFmPreferenceService.PREF_SERVER_TIME, 0); - - ArrayList remoteTasks = new ArrayList(); - - // int newServerTime = fetchRemoteTasks(serverTime, remoteTasks); - if (serverTime == 0) { // If we've never synced, we may lose some empty tags - pushUnsavedTagData(); - } - // fetchRemoteTagData(serverTime); - - /* SyncData syncData = populateSyncData(remoteTasks); - - try { - synchronizeTasks(syncData); - } finally { - syncData.localCreated.close(); - syncData.localUpdated.close(); - } - - Preferences.setInt(ActFmPreferenceService.PREF_SERVER_TIME, newServerTime); */ - - actFmPreferenceService.recordSuccessfulSync(); - - syncSuccess = getFinalSyncStatus(); - Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH); - ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); - - } catch (IllegalStateException e) { - // occurs when application was closed - } catch (Exception e) { - handleException("actfm-sync", e, false); //$NON-NLS-1$ - } finally { - StatisticsService.reportEvent(StatisticsConstants.ACTFM_SYNC_FINISHED, - "success", syncSuccess); //$NON-NLS-1$ - } - } - - //Pushes unsaved, empty tag data, which will otherwise be deleted by the fetch tags call - private void pushUnsavedTagData() { - TodorooCursor unsavedTagData = tagDataDao.query(Query.select(TagData.ID, TagData.TASK_COUNT).where(Criterion.and(TagData.TASK_COUNT.eq(0), TagData.REMOTE_ID.eq(0)))); - TagData data = new TagData(); - for (unsavedTagData.moveToFirst(); !unsavedTagData.isAfterLast(); unsavedTagData.moveToNext()) { - data.readFromCursor(unsavedTagData); - actFmSyncService.pushTag(data.getId()); - } - } - - /** - * Read remote tag data and merge with local - * @param serverTime last sync time - */ - private void fetchRemoteTagData(int serverTime) throws ActFmServiceException, IOException, JSONException { - actFmSyncService.fetchTags(serverTime); - } - - /** - * Read remote task data into remote task array - * @param serverTime last sync time - */ - private int fetchRemoteTasks(int serverTime, - ArrayList remoteTasks) throws IOException, - ActFmServiceException, JSONException { - JSONObject result; - if(serverTime == 0) - result = invoker.invoke("task_list", "active", 1); - else - result = invoker.invoke("task_list", "modified_after", serverTime); - - JSONArray taskList = result.getJSONArray("list"); - for(int i = 0; i < taskList.length(); i++) { - ActFmTaskContainer remote = parseRemoteTask(taskList.getJSONObject(i)); - - // update reminder flags for incoming remote tasks to prevent annoying - if(remote.task.hasDueDate() && remote.task.getValue(Task.DUE_DATE) < DateUtilities.now()) - remote.task.setFlag(Task.REMINDER_FLAGS, Task.NOTIFY_AFTER_DEADLINE, false); - - actFmDataService.findLocalMatch(remote); - - remoteTasks.add(remote); - } - return result.optInt("time", 0); - } - - // ---------------------------------------------------------------------- - // ------------------------------------------------------------ sync data - // ---------------------------------------------------------------------- - - /** - * Populate SyncData data structure - * @throws JSONException - */ - private SyncData populateSyncData(ArrayList remoteTasks) throws JSONException { - // fetch locally created tasks - TodorooCursor localCreated = actFmDataService.getLocallyCreated(Task.PROPERTIES); - - // fetch locally updated tasks - TodorooCursor localUpdated = actFmDataService.getLocallyUpdated(Task.PROPERTIES); - - return new SyncData(remoteTasks, localCreated, localUpdated); - } - - // ---------------------------------------------------------------------- - // ------------------------------------------------- create / push / pull - // ---------------------------------------------------------------------- - - @Override - protected ActFmTaskContainer create(ActFmTaskContainer local) throws IOException { - return push(local, null); - } - - /** Create a task container for the given remote task - * @throws JSONException */ - private ActFmTaskContainer parseRemoteTask(JSONObject remoteTask) throws JSONException { - Task task = new Task(); - - ArrayList metadata = new ArrayList(); - - JsonHelper.taskFromJson(remoteTask, task, metadata); - ActFmTaskContainer container = new ActFmTaskContainer(task, metadata, remoteTask); - - return container; - } - - @Override - protected ActFmTaskContainer pull(ActFmTaskContainer task) throws IOException { - if(task.task.getValue(Task.REMOTE_ID) == 0) - throw new ActFmServiceException("Tried to read an invalid task"); //$NON-NLS-1$ - - JSONObject remote = invoker.invoke("task_show", "id", task.task.getValue(Task.REMOTE_ID)); - try { - return parseRemoteTask(remote); - } catch (JSONException e) { - throw new ActFmServiceException(e); - } - } - - /** - * Send changes for the given Task across the wire. - */ - @Override - protected ActFmTaskContainer push(ActFmTaskContainer local, ActFmTaskContainer remote) throws IOException { - long id = local.task.getValue(Task.REMOTE_ID); - - actFmSyncService.pushTaskOnSave(local.task, local.task.getDatabaseValues()); - - // push unsaved comments - for(Metadata item : local.metadata) { - if(NoteMetadata.METADATA_KEY.equals(item.getValue(Metadata.KEY))) - if(TextUtils.isEmpty(item.getValue(NoteMetadata.EXT_ID))) { - JSONObject comment = invoker.invoke("comment_add", - "task_id", id, - "message", item.getValue(NoteMetadata.BODY)); - item.setValue(NoteMetadata.EXT_ID, comment.optString("id")); - } - } - - return local; - } - - @Override - protected void readRemotelyUpdated(SyncData data) throws IOException { - int serverTime = Preferences.getInt(ActFmPreferenceService.PREF_SERVER_TIME, 0); - ArrayList remoteTasks = new ArrayList(); - - try { - fetchRemoteTasks(serverTime, remoteTasks); - data.remoteUpdated = remoteTasks; - } catch (JSONException e) { - // Ingnored - } - super.readRemotelyUpdated(data); - } - - // ---------------------------------------------------------------------- - // --------------------------------------------------------- read / write - // ---------------------------------------------------------------------- - - @Override - protected ActFmTaskContainer read(TodorooCursor cursor) throws IOException { - return actFmDataService.readTaskAndMetadata(cursor); - } - - @Override - protected void write(ActFmTaskContainer task) throws IOException { - if(task.task.isSaved()) { - Task local = PluginServices.getTaskService().fetchById(task.task.getId(), Task.COMPLETION_DATE); - if(task.task.isCompleted() && !local.isCompleted()) - StatisticsService.reportEvent(StatisticsConstants.ACTFM_TASK_COMPLETED); - } else { // Set default reminders for remotely created tasks - TaskDao.setDefaultReminders(task.task); - } - task.task.setValue(Task.LAST_SYNC, DateUtilities.now() + 1000); - actFmDataService.saveTaskAndMetadata(task); - } - - // ---------------------------------------------------------------------- - // --------------------------------------------------------- misc helpers - // ---------------------------------------------------------------------- - - @Override - protected int matchTask(ArrayList tasks, ActFmTaskContainer target) { - int length = tasks.size(); - for(int i = 0; i < length; i++) { - ActFmTaskContainer task = tasks.get(i); - if (task.task.getValue(Task.REMOTE_ID) == target.task.getValue(Task.REMOTE_ID)) - return i; - } - return -1; - } - - @Override - protected int updateNotification(Context context, Notification notification) { - String notificationTitle = context.getString(R.string.actfm_notification_title); - Intent intent = new Intent(context, ActFmPreferences.class); - PendingIntent notificationIntent = PendingIntent.getActivity(context, 0, - intent, 0); - notification.setLatestEventInfo(context, - notificationTitle, context.getString(R.string.SyP_progress), - notificationIntent); - return Constants.NOTIFICATION_SYNC; - } - - @Override - protected void transferIdentifiers(ActFmTaskContainer source, - ActFmTaskContainer destination) { - destination.task.setValue(Task.REMOTE_ID, source.task.getValue(Task.REMOTE_ID)); - } - -} diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java index ad99fe4d2..f58173faa 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncService.java @@ -298,13 +298,14 @@ public final class ActFmSyncService { public void pushTaskOnSave(Task task, ContentValues values) { Task taskForRemote = taskService.fetchById(task.getId(), Task.REMOTE_ID, Task.CREATION_DATE); - long remoteId; - if(task.containsValue(Task.REMOTE_ID)) { + long remoteId = 0; + if(task.containsNonNullValue(Task.REMOTE_ID)) { remoteId = task.getValue(Task.REMOTE_ID); } else { if(taskForRemote == null) return; - remoteId = taskForRemote.getValue(Task.REMOTE_ID); + if(taskForRemote.containsNonNullValue(Task.REMOTE_ID)) + remoteId = taskForRemote.getValue(Task.REMOTE_ID); } long creationDate; @@ -627,6 +628,12 @@ public final class ActFmSyncService { Order.asc(TagData.REMOTE_ID))); return cursorToMap(cursor, taskDao, TagData.REMOTE_ID, TagData.ID); } + + @Override + protected Class typeClass() { + return TagData.class; + } + }, done, "goals"); } @@ -747,6 +754,11 @@ public final class ActFmSyncService { Order.asc(Task.REMOTE_ID))); return cursorToMap(cursor, taskDao, Task.REMOTE_ID, Task.ID); } + + @Override + protected Class typeClass() { + return Task.class; + } }, done, "active_tasks"); } @@ -796,6 +808,11 @@ public final class ActFmSyncService { Order.asc(Task.REMOTE_ID))); return cursorToMap(cursor, taskDao, Task.REMOTE_ID, Task.ID); } + + @Override + protected Class typeClass() { + return Task.class; + } }, done, "tasks:" + tagData.getId(), "tag_id", tagData.getValue(TagData.REMOTE_ID)); } @@ -860,22 +877,15 @@ public final class ActFmSyncService { TodorooCursor cursor = updateDao.query(Query.select(Update.ID, Update.PICTURE).where(criterion)); pushQueuedUpdates(cursor); - Log.d("ActFmSyncService", "Push queued updates for tag"); - } private void pushQueuedUpdates(Task task) { - - Criterion criterion = null; - if (task.getValue(Task.REMOTE_ID) < 1) { - criterion = Criterion.and(Update.REMOTE_ID.eq(0), - Update.TASK_LOCAL.eq(task.getId())); - } - else { + if (task.containsNonNullValue(Task.REMOTE_ID)) { criterion = Criterion.and(Update.REMOTE_ID.eq(0), Criterion.or(Update.TASK.eq(task.getValue(Task.REMOTE_ID)), Update.TASK_LOCAL.eq(task.getId()))); - } + } else + return; Update template = new Update(); template.setValue(Update.TASK, task.getValue(Task.REMOTE_ID)); //$NON-NLS-1$ @@ -883,8 +893,6 @@ public final class ActFmSyncService { TodorooCursor cursor = updateDao.query(Query.select(Update.ID, Update.PICTURE).where(criterion)); pushQueuedUpdates(cursor); - Log.d("ActFmSyncService", "Push queued updates for task"); - } private void pushQueuedUpdates( TodorooCursor cursor) { @@ -896,18 +904,15 @@ public final class ActFmSyncService { final Update update = new Update(cursor); new Thread(new Runnable() { public void run() { - try { - Bitmap picture = null; - if(imageCache != null && imageCache.contains(update.getValue(update.PICTURE))) { - try { - picture = imageCache.get(update.getValue(update.PICTURE)); - } catch (IOException e) { - e.printStackTrace(); - } + Bitmap picture = null; + if(imageCache != null && imageCache.contains(update.getValue(Update.PICTURE))) { + try { + picture = imageCache.get(update.getValue(Update.PICTURE)); + } catch (IOException e) { + e.printStackTrace(); } - pushUpdate(update.getId(), picture); - } finally { } + pushUpdate(update.getId(), picture); } }).start(); } @@ -916,11 +921,6 @@ public final class ActFmSyncService { } } - - - - - private class UpdateListItemProcessor extends ListItemProcessor { @Override protected void mergeAndSave(JSONArray list, HashMap locals) throws JSONException { @@ -946,6 +946,11 @@ public final class ActFmSyncService { Order.asc(Update.REMOTE_ID))); return cursorToMap(cursor, updateDao, Update.REMOTE_ID, Update.ID); } + + @Override + protected Class typeClass() { + return Update.class; + } } /** @@ -999,16 +1004,19 @@ public final class ActFmSyncService { abstract protected HashMap getLocalModels(); + abstract protected Class typeClass(); + abstract protected void mergeAndSave(JSONArray list, HashMap locals) throws JSONException; public void process(JSONArray list) throws JSONException { readRemoteIds(list); - HashMap locals = getLocalModels(); - mergeAndSave(list, locals); + synchronized (typeClass()) { + HashMap locals = getLocalModels(); + mergeAndSave(list, locals); + } } - protected void readRemoteIds(JSONArray list) throws JSONException { remoteIds = new Long[list.length()]; for(int i = 0; i < list.length(); i++) diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java index 969e277e9..bfdf1776e 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncV2Provider.java @@ -213,8 +213,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider { TodorooCursor taskCursor = taskService.query(Query.select(Task.PROPERTIES). where(Criterion.or( Criterion.and(TaskCriteria.isActive(), - Task.REMOTE_ID.eq(0)), - Criterion.and(Task.REMOTE_ID.gt(0), + Task.REMOTE_ID.isNull()), + Criterion.and(Task.REMOTE_ID.isNotNull(), Task.MODIFICATION_DATE.gt(Task.LAST_SYNC))))); pushQueued(callback, finisher, taskCursor, false, taskPusher); diff --git a/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java b/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java index 3345dfe63..a3df9ef49 100644 --- a/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/backup/BackupPreferences.java @@ -128,4 +128,4 @@ public class BackupPreferences extends TodorooPreferenceActivity { } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/core/DefaultsPreferences.java b/astrid/plugin-src/com/todoroo/astrid/core/DefaultsPreferences.java index 67aa5bdb6..8e9e24c65 100644 --- a/astrid/plugin-src/com/todoroo/astrid/core/DefaultsPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/core/DefaultsPreferences.java @@ -103,4 +103,4 @@ public class DefaultsPreferences extends TodorooPreferenceActivity { } } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/core/OldTaskPreferences.java b/astrid/plugin-src/com/todoroo/astrid/core/OldTaskPreferences.java index cb1b75fe0..412e32c81 100644 --- a/astrid/plugin-src/com/todoroo/astrid/core/OldTaskPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/core/OldTaskPreferences.java @@ -291,4 +291,4 @@ public class OldTaskPreferences extends TodorooPreferenceActivity { // :) } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gcal/Calendars.java b/astrid/plugin-src/com/todoroo/astrid/gcal/Calendars.java index b2e2b02be..c8a556c5a 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gcal/Calendars.java +++ b/astrid/plugin-src/com/todoroo/astrid/gcal/Calendars.java @@ -233,4 +233,4 @@ public class Calendars { return Preferences.getStringValue(R.string.gcal_p_default); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java index 8bd2100a4..18958c2f9 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksListService.java @@ -77,7 +77,7 @@ public class GtasksListService { } @SuppressWarnings("nls") - public void updateLists(TaskLists remoteLists) { + public synchronized void updateLists(TaskLists remoteLists) { readLists(); for(StoreObject list : lists) diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java index 8c438bbc0..55a4ff3be 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksMetadataService.java @@ -78,7 +78,7 @@ public final class GtasksMetadataService extends SyncMetadataService cursor = metadataDao.query(Query.select(Metadata.PROPERTIES). diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java index 456d180c8..79d8be4cd 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/GtasksPreferences.java @@ -71,4 +71,4 @@ public class GtasksPreferences extends SyncProviderPreferences { super.onPause(); new GtasksBackgroundService().scheduleService(); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.java index c98f877a4..c532d9c3f 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/auth/GtasksLoginActivity.java @@ -233,4 +233,4 @@ public class GtasksLoginActivity extends ListActivity { } } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncService.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncService.java index 2e4e1d4d7..eadeedb04 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncService.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncService.java @@ -230,7 +230,7 @@ public final class GtasksSyncService { } task.setValue(Task.MODIFICATION_DATE, DateUtilities.now()); - gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now()); + gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L); metadataService.save(gtasksMetadata); Flags.set(Flags.GTASKS_SUPPRESS_SYNC); taskDao.saveExisting(task); diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncV2Provider.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncV2Provider.java index c6fb19400..fb419d3df 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncV2Provider.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksSyncV2Provider.java @@ -208,7 +208,7 @@ public class GtasksSyncV2Provider extends SyncV2Provider { gtasksMetadataService.findLocalMatch(container); container.gtaskMetadata.setValue(GtasksMetadata.GTASKS_ORDER, Long.parseLong(t.getPosition())); container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK, gtasksMetadataService.localIdForGtasksId(t.getParent())); - container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now()); + container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L); write(container); callback.incrementProgress(10); } diff --git a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksTaskContainer.java b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksTaskContainer.java index 3450188bf..d8c556c26 100644 --- a/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksTaskContainer.java +++ b/astrid/plugin-src/com/todoroo/astrid/gtasks/sync/GtasksTaskContainer.java @@ -53,4 +53,4 @@ public class GtasksTaskContainer extends SyncContainer { super.prepareForSaving(); metadata.add(gtaskMetadata); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java b/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java index 249f21e49..8712e3903 100644 --- a/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java +++ b/astrid/plugin-src/com/todoroo/astrid/locale/LocaleEditAlerts.java @@ -337,4 +337,4 @@ public final class LocaleEditAlerts extends ListActivity { return super.onOptionsItemSelected(item); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/notes/EditNoteActivity.java b/astrid/plugin-src/com/todoroo/astrid/notes/EditNoteActivity.java index 81ae8e8dd..a283fc700 100644 --- a/astrid/plugin-src/com/todoroo/astrid/notes/EditNoteActivity.java +++ b/astrid/plugin-src/com/todoroo/astrid/notes/EditNoteActivity.java @@ -121,7 +121,6 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene } public void loadViewForTaskID(long t){ - task = PluginServices.getTaskService().fetchById(t, Task.NOTES, Task.ID, Task.REMOTE_ID, Task.TITLE); if(task == null) { return; @@ -130,7 +129,7 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene setUpListAdapter(); if(actFmPreferenceService.isLoggedIn()) { - if(task.getValue(Task.REMOTE_ID) == 0) + if(!task.containsNonNullValue(Task.REMOTE_ID)) refreshData(true, null); else { String fetchKey = LAST_FETCH_KEY + task.getId(); @@ -257,7 +256,7 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene TodorooCursor updates; - if (task.getValue(Task.REMOTE_ID) < 1) { + if (!task.containsNonNullValue(Task.REMOTE_ID)) { updates = updateDao.query(Query.select(Update.PROPERTIES).where(Update.TASK_LOCAL.eq(task.getId()))); } else { @@ -406,7 +405,7 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene } // push task if it hasn't been pushed - if(task.getValue(Task.REMOTE_ID) == 0 && !TextUtils.isEmpty(task.getValue(Task.TITLE))) { + if(!task.containsNonNullValue(Task.REMOTE_ID) && !TextUtils.isEmpty(task.getValue(Task.TITLE))) { new Thread(new Runnable() { @Override public void run() { @@ -446,7 +445,8 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene update.setValue(Update.MESSAGE, message); update.setValue(Update.ACTION_CODE, actionCode); update.setValue(Update.USER_ID, 0L); - update.setValue(Update.TASK, task.getValue(Task.REMOTE_ID)); + if(task.containsNonNullValue(Task.REMOTE_ID)) + update.setValue(Update.TASK, task.getValue(Task.REMOTE_ID)); update.setValue(Update.TASK_LOCAL, task.getId()); update.setValue(Update.CREATION_DATE, DateUtilities.now()); diff --git a/astrid/plugin-src/com/todoroo/astrid/opencrx/OpencrxControlSet.java b/astrid/plugin-src/com/todoroo/astrid/opencrx/OpencrxControlSet.java index 6dc93b9a5..4f802ac9f 100644 --- a/astrid/plugin-src/com/todoroo/astrid/opencrx/OpencrxControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/opencrx/OpencrxControlSet.java @@ -405,4 +405,4 @@ public class OpencrxControlSet extends PopupControlSet { // Nothing to do } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java index acd637d75..60c24457b 100644 --- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java @@ -277,4 +277,4 @@ public class ProducteevControlSet extends PopupControlSet { // TODO Auto-generated method stub } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java index a08a1cd25..04987352f 100644 --- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevPreferences.java @@ -94,4 +94,4 @@ public class ProducteevPreferences extends SyncProviderPreferences { ((ListPreference)preference).getEntries()[index])); } } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevUtilities.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevUtilities.java index d0bbfd1be..dbc2fb699 100644 --- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevUtilities.java +++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevUtilities.java @@ -76,4 +76,4 @@ public class ProducteevUtilities extends SyncProviderUtilities { return Preferences.getStringValue(R.string.producteev_PPr_email); } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderPreferences.java b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderPreferences.java index 3f3780cfd..99a8f8d3f 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderPreferences.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderPreferences.java @@ -101,4 +101,4 @@ public class ReminderPreferences extends TodorooPreferenceActivity { } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java index c25204e3f..148d98a45 100644 --- a/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/repeats/RepeatControlSet.java @@ -420,4 +420,4 @@ public class RepeatControlSet extends PopupControlSet { return d; } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitControlSet.java b/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitControlSet.java index de95fcff7..43938a291 100644 --- a/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitControlSet.java @@ -212,7 +212,7 @@ public class TaskRabbitControlSet extends TaskEditControlSet implements Assigned statusText.setText(status); getDisplayView().setVisibility(View.VISIBLE); } - else if (taskRabbitTask.getLocalTaskData() != null) { + else if (taskRabbitTask != null && taskRabbitTask.getLocalTaskData() != null) { TextView statusText = (TextView) getDisplayView().findViewById(R.id.display_row_edit); statusText.setText(fragment.getActivity().getString(R.string.tr_status_draft)); getDisplayView().setVisibility(View.VISIBLE); diff --git a/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitTaskContainer.java b/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitTaskContainer.java index 0b59c1e2f..93c8446ab 100644 --- a/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitTaskContainer.java +++ b/astrid/plugin-src/com/todoroo/astrid/taskrabbit/TaskRabbitTaskContainer.java @@ -81,4 +81,4 @@ public class TaskRabbitTaskContainer extends SyncContainer { public boolean isTaskRabbit() { return getTaskID() > 0; } -} \ No newline at end of file +} diff --git a/astrid/plugin-src/com/todoroo/astrid/timers/TimerControlSet.java b/astrid/plugin-src/com/todoroo/astrid/timers/TimerControlSet.java index 1a62aa555..991a34b3c 100644 --- a/astrid/plugin-src/com/todoroo/astrid/timers/TimerControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/timers/TimerControlSet.java @@ -104,4 +104,4 @@ public class TimerControlSet extends PopupControlSet implements TimerActionListe return; } -} \ No newline at end of file +} diff --git a/astrid/res/drawable-hdpi/home_button_blue.png b/astrid/res/drawable-hdpi/home_button_blue.png index 4da7d8c5c..8cf1a5967 100644 Binary files a/astrid/res/drawable-hdpi/home_button_blue.png and b/astrid/res/drawable-hdpi/home_button_blue.png differ diff --git a/astrid/res/drawable-hdpi/home_button_dark_blue.png b/astrid/res/drawable-hdpi/home_button_dark_blue.png index 110411072..dc59aaaf2 100644 Binary files a/astrid/res/drawable-hdpi/home_button_dark_blue.png and b/astrid/res/drawable-hdpi/home_button_dark_blue.png differ diff --git a/astrid/res/drawable-hdpi/home_button_red.png b/astrid/res/drawable-hdpi/home_button_red.png index 74d2e4180..ed88be77e 100644 Binary files a/astrid/res/drawable-hdpi/home_button_red.png and b/astrid/res/drawable-hdpi/home_button_red.png differ diff --git a/astrid/res/drawable-hdpi/icn_menu_tasks.png b/astrid/res/drawable-hdpi/icn_menu_tasks.png new file mode 100644 index 000000000..6d997af58 Binary files /dev/null and b/astrid/res/drawable-hdpi/icn_menu_tasks.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_blue_off.png b/astrid/res/drawable-hdpi/menu_button_blue_off.png index 4fb128ecd..10dd86f7f 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_blue_off.png and b/astrid/res/drawable-hdpi/menu_button_blue_off.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_blue_on.png b/astrid/res/drawable-hdpi/menu_button_blue_on.png index 3634553dc..cbeb28804 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_blue_on.png and b/astrid/res/drawable-hdpi/menu_button_blue_on.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_dark_blue_off.png b/astrid/res/drawable-hdpi/menu_button_dark_blue_off.png index 977df9067..7ca38bd7b 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_dark_blue_off.png and b/astrid/res/drawable-hdpi/menu_button_dark_blue_off.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_dark_blue_on.png b/astrid/res/drawable-hdpi/menu_button_dark_blue_on.png index 074ad0bba..e36927ff2 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_dark_blue_on.png and b/astrid/res/drawable-hdpi/menu_button_dark_blue_on.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_red_off.png b/astrid/res/drawable-hdpi/menu_button_red_off.png index b59b797e1..b6665c344 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_red_off.png and b/astrid/res/drawable-hdpi/menu_button_red_off.png differ diff --git a/astrid/res/drawable-hdpi/menu_button_red_on.png b/astrid/res/drawable-hdpi/menu_button_red_on.png index f36ac2b7d..a3fe48206 100644 Binary files a/astrid/res/drawable-hdpi/menu_button_red_on.png and b/astrid/res/drawable-hdpi/menu_button_red_on.png differ diff --git a/astrid/res/drawable/home_button_blue.png b/astrid/res/drawable/home_button_blue.png index e49ba79ed..79e0cf743 100644 Binary files a/astrid/res/drawable/home_button_blue.png and b/astrid/res/drawable/home_button_blue.png differ diff --git a/astrid/res/drawable/home_button_dark_blue.png b/astrid/res/drawable/home_button_dark_blue.png index d7e93fcac..277cca1b4 100644 Binary files a/astrid/res/drawable/home_button_dark_blue.png and b/astrid/res/drawable/home_button_dark_blue.png differ diff --git a/astrid/res/drawable/home_button_red.png b/astrid/res/drawable/home_button_red.png index c622b3e17..3dca30613 100644 Binary files a/astrid/res/drawable/home_button_red.png and b/astrid/res/drawable/home_button_red.png differ diff --git a/astrid/res/drawable/icn_menu_tasks.png b/astrid/res/drawable/icn_menu_tasks.png index 6e5c25d1c..3bf1e50ac 100644 Binary files a/astrid/res/drawable/icn_menu_tasks.png and b/astrid/res/drawable/icn_menu_tasks.png differ diff --git a/astrid/res/drawable/menu_button_blue_on.png b/astrid/res/drawable/menu_button_blue_on.png index b3e240494..1cfc26db7 100644 Binary files a/astrid/res/drawable/menu_button_blue_on.png and b/astrid/res/drawable/menu_button_blue_on.png differ diff --git a/astrid/res/drawable/menu_button_dark_blue_on.png b/astrid/res/drawable/menu_button_dark_blue_on.png index 3323aa279..d15368a49 100644 Binary files a/astrid/res/drawable/menu_button_dark_blue_on.png and b/astrid/res/drawable/menu_button_dark_blue_on.png differ diff --git a/astrid/res/drawable/menu_button_red_off.png b/astrid/res/drawable/menu_button_red_off.png index b3cac75dc..796a2ddf0 100644 Binary files a/astrid/res/drawable/menu_button_red_off.png and b/astrid/res/drawable/menu_button_red_off.png differ diff --git a/astrid/res/drawable/menu_button_red_on.png b/astrid/res/drawable/menu_button_red_on.png index 5bbff4b60..fd84469bd 100644 Binary files a/astrid/res/drawable/menu_button_red_on.png and b/astrid/res/drawable/menu_button_red_on.png differ diff --git a/astrid/res/layout/task_adapter_draggable_row.xml b/astrid/res/layout/task_adapter_draggable_row.xml index 544a3675a..929fad535 100644 --- a/astrid/res/layout/task_adapter_draggable_row.xml +++ b/astrid/res/layout/task_adapter_draggable_row.xml @@ -40,8 +40,9 @@ diff --git a/astrid/res/layout/task_adapter_row.xml b/astrid/res/layout/task_adapter_row.xml index 68f33fffb..a3e0de467 100644 --- a/astrid/res/layout/task_adapter_row.xml +++ b/astrid/res/layout/task_adapter_row.xml @@ -19,8 +19,8 @@ android:id="@+id/rowBody" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_marginTop="6dip" - android:layout_marginBottom="6dip" + android:layout_marginTop="5dip" + android:layout_marginBottom="5dip" android:minHeight="45dip"> @@ -82,7 +81,6 @@ android:id="@+id/taskActionContainer" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minHeight="40dip" android:layout_marginRight="4dip" android:orientation="vertical" android:gravity="right|center_vertical"> diff --git a/astrid/res/values/strings-actfm.xml b/astrid/res/values/strings-actfm.xml index c4100cf1c..95ffd7003 100644 --- a/astrid/res/values/strings-actfm.xml +++ b/astrid/res/values/strings-actfm.xml @@ -251,7 +251,7 @@ - Astrid.com (Beta!) + Astrid.com Use HTTPS HTTPS enabled (slower) diff --git a/astrid/res/values/strings-core.xml b/astrid/res/values/strings-core.xml index 856965c5a..b464849e4 100644 --- a/astrid/res/values/strings-core.xml +++ b/astrid/res/values/strings-core.xml @@ -403,7 +403,7 @@ Task Title Who When - ----More Section---- + ----Details---- Importance Lists Notes diff --git a/astrid/res/values/strings-gtasks.xml b/astrid/res/values/strings-gtasks.xml index a42f11e25..26e8a13bd 100644 --- a/astrid/res/values/strings-gtasks.xml +++ b/astrid/res/values/strings-gtasks.xml @@ -86,7 +86,7 @@ - Google Tasks (Beta!) + Google Tasks diff --git a/astrid/res/xml/preferences.xml b/astrid/res/xml/preferences.xml index 3ff0d9181..f6cf88c77 100644 --- a/astrid/res/xml/preferences.xml +++ b/astrid/res/xml/preferences.xml @@ -6,6 +6,7 @@ + @@ -54,6 +55,12 @@ android:key="@string/p_showSmartConfirmation_key" android:title="@string/EPr_showSmartConfirmation_title" android:defaultValue="true"/> + + + @@ -85,11 +92,6 @@ android:key="@string/p_statistics" android:title="@string/EPr_statistics_title" android:defaultValue="true" /> - - diff --git a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java index 89b3ab780..23f3dad6c 100644 --- a/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java +++ b/astrid/rmilk-src/org/weloveastrid/rmilk/MilkPreferences.java @@ -36,4 +36,4 @@ public class MilkPreferences extends SyncProviderPreferences { return MilkUtilities.INSTANCE; } -} \ No newline at end of file +} diff --git a/astrid/rmilk-src/org/weloveastrid/rmilk/sync/MilkTaskContainer.java b/astrid/rmilk-src/org/weloveastrid/rmilk/sync/MilkTaskContainer.java index 997c47158..64dae133c 100644 --- a/astrid/rmilk-src/org/weloveastrid/rmilk/sync/MilkTaskContainer.java +++ b/astrid/rmilk-src/org/weloveastrid/rmilk/sync/MilkTaskContainer.java @@ -65,4 +65,4 @@ public class MilkTaskContainer extends SyncContainer { metadata.add(MilkTaskFields.create(this)); } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/activity/AboutActivity.java b/astrid/src/com/todoroo/astrid/activity/AboutActivity.java index b3aa726b3..5994e01a0 100644 --- a/astrid/src/com/todoroo/astrid/activity/AboutActivity.java +++ b/astrid/src/com/todoroo/astrid/activity/AboutActivity.java @@ -65,4 +65,4 @@ class About { private About() { // don't construct me } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/activity/AstridActivity.java b/astrid/src/com/todoroo/astrid/activity/AstridActivity.java index 3a2f7b28e..f42987526 100644 --- a/astrid/src/com/todoroo/astrid/activity/AstridActivity.java +++ b/astrid/src/com/todoroo/astrid/activity/AstridActivity.java @@ -12,6 +12,7 @@ import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.View; +import android.view.WindowManager.BadTokenException; import com.timsu.astrid.R; import com.todoroo.andlib.service.ContextManager; @@ -130,8 +131,16 @@ public class AstridActivity extends FragmentActivity @Override protected void onPause() { super.onPause(); - unregisterReceiver(reminderReceiver); - unregisterReceiver(repeatConfirmationReceiver); + tryUnregisterReceiver(reminderReceiver); + tryUnregisterReceiver(repeatConfirmationReceiver); + } + + public void tryUnregisterReceiver(BroadcastReceiver receiver) { + try { + unregisterReceiver(receiver); + } catch (IllegalArgumentException e) { + // Receiver wasn't registered for some reason + } } /** @@ -337,13 +346,24 @@ public class AstridActivity extends FragmentActivity private class ReminderReceiver extends BroadcastReceiver { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(Context context, final Intent intent) { // Process in app notification Intent customIntent = intent.getExtras().getParcelable(Notifications.EXTRAS_CUSTOM_INTENT); long taskId = customIntent.getLongExtra(NotificationFragment.TOKEN_ID, 0); if (taskId > 0) { String text = intent.getStringExtra(Notifications.EXTRAS_TEXT); - new ReminderDialog(AstridActivity.this, taskId, text).show(); + try { + new ReminderDialog(AstridActivity.this, taskId, text).show(); + } catch (BadTokenException e) { // Activity not running when tried to show dialog--rebroadcast + new Thread() { + @Override + public void run() { + AndroidUtilities.sleepDeep(500L); + sendBroadcast(intent); + } + }.start(); + return; + } } // Remove broadcast @@ -354,7 +374,7 @@ public class AstridActivity extends FragmentActivity private class RepeatConfirmationReceiver extends BroadcastReceiver { @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(Context context, final Intent intent) { long taskId = intent.getLongExtra( AstridApiConstants.EXTRAS_TASK_ID, 0); if (taskId > 0) { @@ -365,8 +385,17 @@ public class AstridActivity extends FragmentActivity Task task = PluginServices.getTaskService().fetchById(taskId, DateChangedAlerts.REPEAT_RESCHEDULED_PROPERTIES); - DateChangedAlerts.showRepeatTaskRescheduledDialog( - AstridActivity.this, task, oldDueDate, newDueDate); + try { + DateChangedAlerts.showRepeatTaskRescheduledDialog( + AstridActivity.this, task, oldDueDate, newDueDate); + } catch (BadTokenException e) { // Activity not running when tried to show dialog--rebroadcast + new Thread() { + @Override + public void run() { + sendBroadcast(intent); + } + }.start(); + } } } } diff --git a/astrid/src/com/todoroo/astrid/activity/EditPreferences.java b/astrid/src/com/todoroo/astrid/activity/EditPreferences.java index d2303b89b..434bc4bda 100644 --- a/astrid/src/com/todoroo/astrid/activity/EditPreferences.java +++ b/astrid/src/com/todoroo/astrid/activity/EditPreferences.java @@ -465,4 +465,4 @@ public class EditPreferences extends TodorooPreferenceActivity { super.onStop(); } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/activity/ExpandableListFragment.java b/astrid/src/com/todoroo/astrid/activity/ExpandableListFragment.java index c8b823c99..dc296bd71 100644 --- a/astrid/src/com/todoroo/astrid/activity/ExpandableListFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/ExpandableListFragment.java @@ -351,4 +351,4 @@ public class ExpandableListFragment extends Fragment int groupPosition, int childPosition, long id) { return false; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/activity/FilterListFragment.java b/astrid/src/com/todoroo/astrid/activity/FilterListFragment.java index 4bc3a6eb4..3ff039fce 100644 --- a/astrid/src/com/todoroo/astrid/activity/FilterListFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/FilterListFragment.java @@ -497,12 +497,15 @@ public class FilterListFragment extends ListFragment { if(intent == null || !AstridApiConstants.BROADCAST_EVENT_REFRESH.equals(intent.getAction())) return; - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - refresh(); - } - }); + Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + refresh(); + } + }); + } } } } diff --git a/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java b/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java index bf98505ac..fc6b8a5df 100755 --- a/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskEditFragment.java @@ -655,28 +655,30 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { public void onUiThread() { // prepare and set listener for voice-button - if (addOnService.hasPowerPack()) { - voiceAddNoteButton = (ImageButton) notesControlSet.getView().findViewById( - R.id.voiceAddNoteButton); - voiceAddNoteButton.setVisibility(View.VISIBLE); - int prompt = R.string.voice_edit_note_prompt; - voiceNoteAssistant = new VoiceInputAssistant(TaskEditFragment.this, - voiceAddNoteButton, notesEditText, REQUEST_VOICE_RECOG); - voiceNoteAssistant.setAppend(true); - voiceNoteAssistant.setLanguageModel(RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); - voiceNoteAssistant.configureMicrophoneButton(prompt); - } + if (getActivity() != null) { + if (addOnService.hasPowerPack()) { + voiceAddNoteButton = (ImageButton) notesControlSet.getView().findViewById( + R.id.voiceAddNoteButton); + voiceAddNoteButton.setVisibility(View.VISIBLE); + int prompt = R.string.voice_edit_note_prompt; + voiceNoteAssistant = new VoiceInputAssistant(TaskEditFragment.this, + voiceAddNoteButton, notesEditText, REQUEST_VOICE_RECOG); + voiceNoteAssistant.setAppend(true); + voiceNoteAssistant.setLanguageModel(RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); + voiceNoteAssistant.configureMicrophoneButton(prompt); + } - // re-read all - synchronized (controls) { - for (TaskEditControlSet controlSet : controls) - controlSet.readFromTask(model); - if (isNewTask) { - hideUntilControls.setDefaults(); + // re-read all + synchronized (controls) { + for (TaskEditControlSet controlSet : controls) + controlSet.readFromTask(model); + if (isNewTask) { + hideUntilControls.setDefaults(); + } } - } - loadMoreContainer(); + loadMoreContainer(); + } } @Override @@ -719,10 +721,9 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { if (idParam > -1L) { model = taskService.fetchById(idParam, Task.PROPERTIES); - if (model != null) { + if (model != null && model.containsNonNullValue(Task.REMOTE_ID)) { remoteId = model.getValue(Task.REMOTE_ID); - model.clearValue(Task.REMOTE_ID); // Having this can screw up - // autosync + model.clearValue(Task.REMOTE_ID); // Having this can screw up autosync } } @@ -738,6 +739,7 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { } model = TaskService.createWithValues(values, null, taskService, metadataService); + getActivity().getIntent().putExtra(TOKEN_ID, model.getId()); } if (model.getValue(Task.TITLE).length() == 0) { @@ -874,7 +876,8 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { R.anim.slide_right_in, R.anim.slide_right_out); } - if (title.getText().length() == 0 && isNewTask && model.isSaved()) { + if (title.getText().length() == 0 && isNewTask + && model != null && model.isSaved()) { taskService.delete(model); } } @@ -959,12 +962,6 @@ ViewPager.OnPageChangeListener, EditNoteActivity.UpdatesChangedListener { Toast.LENGTH_SHORT).show(); } - protected void commentsButtonClick() { - Intent launchIntent = new Intent(getActivity(), EditNoteActivity.class); - launchIntent.putExtra(EditNoteActivity.EXTRA_TASK_ID, model.getId()); - startActivity(launchIntent); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/astrid/src/com/todoroo/astrid/activity/TaskEditViewPager.java b/astrid/src/com/todoroo/astrid/activity/TaskEditViewPager.java index 80b6ec5ef..61fe75b78 100644 --- a/astrid/src/com/todoroo/astrid/activity/TaskEditViewPager.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskEditViewPager.java @@ -74,4 +74,4 @@ public class TaskEditViewPager extends PagerAdapter implements TitleProvider { return null; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java b/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java index a34d5ae51..9bd12dc91 100644 --- a/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskListFragment.java @@ -923,17 +923,20 @@ public class TaskListFragment extends ListFragment implements OnScrollListener, return; if (!Preferences.getBoolean( R.string.p_showed_lists_help, false)) { - if (AndroidUtilities.isTabletSized(getActivity())) { - ((AstridActivity) getActivity()).getFilterListFragment().showAddListPopover(); - } else { - ActionBar ab = ((AstridActivity) getActivity()).getSupportActionBar(); - View anchor = ab.getCustomView().findViewById(R.id.lists_nav); - HelpInfoPopover.showPopover(getActivity(), - anchor, R.string.help_popover_switch_lists, null); + AstridActivity activity = (AstridActivity) getActivity(); + if (activity != null) { + if (AndroidUtilities.isTabletSized(activity)) { + activity.getFilterListFragment().showAddListPopover(); + } else { + ActionBar ab = activity.getSupportActionBar(); + View anchor = ab.getCustomView().findViewById(R.id.lists_nav); + HelpInfoPopover.showPopover(activity, + anchor, R.string.help_popover_switch_lists, null); + } + Preferences.setBoolean( + R.string.p_showed_lists_help, + true); } - Preferences.setBoolean( - R.string.p_showed_lists_help, - true); } } diff --git a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java index bc20a9e52..7947c3d2a 100644 --- a/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java +++ b/astrid/src/com/todoroo/astrid/adapter/TaskAdapter.java @@ -157,6 +157,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { public static int APPLY_LISTENERS_NONE = 2; protected final TaskListFragment fragment; + protected final Resources resources; protected final HashMap completedItems = new HashMap(0); protected OnCompletedTaskListener onCompletedTaskListener = null; public boolean isFling = false; @@ -206,6 +207,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { this.query = query; this.resource = resource; this.fragment = fragment; + this.resources = fragment.getResources(); this.onCompletedTaskListener = onCompletedTaskListener; fontSize = Preferences.getIntegerFromString(R.string.p_fontSize, 18); @@ -213,7 +215,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { displayMetrics = new DisplayMetrics(); fragment.getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - this.minRowHeight = (int) (4 * displayMetrics.density); + this.minRowHeight = (int) (45 * displayMetrics.density); startDetailThread(); startTaskActionsThread(); @@ -352,7 +354,6 @@ public class TaskAdapter extends CursorAdapter implements Filterable { /** Helper method to set the contents and visibility of each field */ public synchronized void setFieldContentsAndVisibility(View view) { - Resources r = fragment.getResources(); ViewHolder viewHolder = (ViewHolder)view.getTag(); Task task = viewHolder.task; @@ -368,9 +369,9 @@ public class TaskAdapter extends CursorAdapter implements Filterable { long hiddenUntil = task.getValue(Task.HIDE_UNTIL); if(task.getValue(Task.DELETION_DATE) > 0) - nameValue = r.getString(R.string.TAd_deletedFormat, nameValue); + nameValue = resources.getString(R.string.TAd_deletedFormat, nameValue); if(hiddenUntil > DateUtilities.now()) - nameValue = r.getString(R.string.TAd_hiddenFormat, nameValue); + nameValue = resources.getString(R.string.TAd_hiddenFormat, nameValue); nameView.setText(nameValue); } @@ -389,7 +390,7 @@ public class TaskAdapter extends CursorAdapter implements Filterable { setVisibility(dueDateView); } else if(task.isCompleted()) { String dateValue = formatDate(task.getValue(Task.COMPLETION_DATE)); - dueDateView.setText(r.getString(R.string.TAd_completed, dateValue)); + dueDateView.setText(resources.getString(R.string.TAd_completed, dateValue)); dueDateView.setTextAppearance(fragment.getActivity(), R.style.TextAppearance_TAd_ItemDueDate_Completed); dueDateTextWidth = paint.measureText(dateValue); setVisibility(dueDateView); @@ -802,8 +803,6 @@ public class TaskAdapter extends CursorAdapter implements Filterable { new HashMap(3); @SuppressWarnings("nls") public Drawable getDrawable(String source) { - Resources r = fragment.getResources(); - if(source.equals("silk_clock")) source = "details_alarm"; else if(source.equals("silk_tag_pink")) @@ -813,12 +812,12 @@ public class TaskAdapter extends CursorAdapter implements Filterable { else if(source.equals("silk_note")) source = "details_note"; - int drawable = r.getIdentifier("drawable/" + source, null, Constants.PACKAGE); + int drawable = resources.getIdentifier("drawable/" + source, null, Constants.PACKAGE); if(drawable == 0) return null; Drawable d; if(!cache.containsKey(drawable)) { - d = r.getDrawable(drawable); + d = resources.getDrawable(drawable); d.setBounds(0,0,d.getIntrinsicWidth(),d.getIntrinsicHeight()); cache.put(drawable, d); } else diff --git a/astrid/src/com/todoroo/astrid/dao/Database.java b/astrid/src/com/todoroo/astrid/dao/Database.java index c9ac8470b..15884005c 100644 --- a/astrid/src/com/todoroo/astrid/dao/Database.java +++ b/astrid/src/com/todoroo/astrid/dao/Database.java @@ -37,7 +37,7 @@ public class Database extends AbstractDatabase { * Database version number. This variable must be updated when database * tables are updated, as it determines whether a database needs updating. */ - public static final int VERSION = 20; + public static final int VERSION = 21; /** * Database name (must be unique) @@ -130,19 +130,26 @@ public class Database extends AbstractDatabase { database.execSQL(sql.toString()); sql.setLength(0); - sql.append("CREATE INDEX IF NOT EXISTS up_tid ON "). + sql.append("CREATE INDEX IF NOT EXISTS up_tkid ON "). append(Update.TABLE).append('('). append(Update.TASK_LOCAL.name). append(')'); database.execSQL(sql.toString()); sql.setLength(0); - sql.append("CREATE INDEX IF NOT EXISTS up_pid ON "). + sql.append("CREATE INDEX IF NOT EXISTS up_tgl ON "). append(Update.TABLE).append('('). append(Update.TAGS_LOCAL.name). append(')'); database.execSQL(sql.toString()); sql.setLength(0); + + sql.append("CREATE UNIQUE INDEX IF NOT EXISTS t_rid ON "). + append(Task.TABLE).append('('). + append(Task.REMOTE_ID.name). + append(')'); + database.execSQL(sql.toString()); + sql.setLength(0); } @Override @@ -263,6 +270,26 @@ public class Database extends AbstractDatabase { database.execSQL("CREATE INDEX IF NOT EXISTS up_tid ON " + Update.TABLE + "(" + Update.TAGS_LOCAL.name + ")"); + } catch (SQLiteException e) { + Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e); + } + case 20: try { + String tasks = Task.TABLE.name; + String id = Task.ID.name; + String remoteId = Task.REMOTE_ID.name; + + // Delete any items that have duplicate remote ids + String deleteDuplicates = String.format("DELETE FROM %s WHERE %s IN (SELECT %s.%s FROM %s, %s AS t2 WHERE %s.%s < t2.%s AND %s.%s = t2.%s AND %s.%s > 0 GROUP BY %s.%s)", + tasks, id, tasks, id, tasks, tasks, tasks, id, id, tasks, remoteId, remoteId, tasks, remoteId, tasks, id); + + // Change all items with remote id = 0 to be remote id = NULL + String changeZeroes = String.format("UPDATE %s SET %s = NULL WHERE %s = 0", tasks, remoteId, remoteId); + + database.execSQL(deleteDuplicates); + database.execSQL(changeZeroes); + + onCreateTables(); + } catch (SQLiteException e) { Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e); } diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index bf604d4ab..27326645e 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -6,13 +6,16 @@ package com.todoroo.astrid.dao; import android.content.ContentValues; +import android.database.sqlite.SQLiteConstraintException; import com.timsu.astrid.R; import com.todoroo.andlib.data.DatabaseDao; +import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Functions; +import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; @@ -166,7 +169,17 @@ public class TaskDao extends DatabaseDao { public boolean save(Task task) { boolean saveSuccessful; if (task.getId() == Task.NO_ID) { - saveSuccessful = createNew(task); + try { + saveSuccessful = createNew(task); + } catch (SQLiteConstraintException e) { // Tried to create task with remote id that already exists + saveSuccessful = false; + TodorooCursor cursor = query(Query.select(Task.ID).where(Task.REMOTE_ID.eq(task.getValue(Task.REMOTE_ID)))); + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + task.setId(cursor.get(Task.ID)); + saveSuccessful = saveExisting(task); + } + } } else { saveSuccessful = saveExisting(task); } diff --git a/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java b/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java index 4675cb1ba..3b454c34d 100644 --- a/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java +++ b/astrid/src/com/todoroo/astrid/helper/TaskAdapterAddOnManager.java @@ -144,4 +144,4 @@ abstract public class TaskAdapterAddOnManager { return cache.get(taskId).values(); } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/helper/TaskEditControlSet.java b/astrid/src/com/todoroo/astrid/helper/TaskEditControlSet.java index fe214c70b..5b3fd1e6a 100644 --- a/astrid/src/com/todoroo/astrid/helper/TaskEditControlSet.java +++ b/astrid/src/com/todoroo/astrid/helper/TaskEditControlSet.java @@ -79,4 +79,4 @@ public abstract class TaskEditControlSet { * Called when views need to be inflated */ protected abstract void afterInflate(); -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/helper/TaskListContextMenuExtensionLoader.java b/astrid/src/com/todoroo/astrid/helper/TaskListContextMenuExtensionLoader.java index 7abc7cdc5..153461b22 100644 --- a/astrid/src/com/todoroo/astrid/helper/TaskListContextMenuExtensionLoader.java +++ b/astrid/src/com/todoroo/astrid/helper/TaskListContextMenuExtensionLoader.java @@ -52,4 +52,4 @@ public class TaskListContextMenuExtensionLoader { } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/legacy/LegacyAlertModel.java b/astrid/src/com/todoroo/astrid/legacy/LegacyAlertModel.java index 97bb5373f..de6da13f3 100644 --- a/astrid/src/com/todoroo/astrid/legacy/LegacyAlertModel.java +++ b/astrid/src/com/todoroo/astrid/legacy/LegacyAlertModel.java @@ -7,4 +7,4 @@ abstract public class LegacyAlertModel { public static final String TASK = "task"; public static final String DATE = "date"; -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/legacy/LegacyRepeatInfo.java b/astrid/src/com/todoroo/astrid/legacy/LegacyRepeatInfo.java index 355746c17..211afdc84 100644 --- a/astrid/src/com/todoroo/astrid/legacy/LegacyRepeatInfo.java +++ b/astrid/src/com/todoroo/astrid/legacy/LegacyRepeatInfo.java @@ -60,4 +60,4 @@ public class LegacyRepeatInfo { return rrule; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/service/TagDataService.java b/astrid/src/com/todoroo/astrid/service/TagDataService.java index 3a11a6753..ece7bb52e 100644 --- a/astrid/src/com/todoroo/astrid/service/TagDataService.java +++ b/astrid/src/com/todoroo/astrid/service/TagDataService.java @@ -13,7 +13,6 @@ import com.todoroo.astrid.dao.TagDataDao; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.UpdateDao; import com.todoroo.astrid.data.TagData; -import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Update; /** @@ -141,10 +140,10 @@ public class TagDataService { return updateDao.query(Query.select(Update.PROPERTIES).where( criterion). orderBy(Order.desc(Update.CREATION_DATE))); - if(tagData.getValue(Task.REMOTE_ID) < 1) + if(tagData.getValue(TagData.REMOTE_ID) == 0) return updateDao.query(Query.select(Update.PROPERTIES).where(Update.TAGS_LOCAL.like("%," + tagData.getId() + ",%"))); return updateDao.query(Query.select(Update.PROPERTIES).where(Criterion.and(criterion, - Criterion.or(Update.TAGS.like("%," + tagData.getValue(Task.REMOTE_ID) + ",%"), + Criterion.or(Update.TAGS.like("%," + tagData.getValue(TagData.REMOTE_ID) + ",%"), Update.TAGS_LOCAL.like("%," + tagData.getId() + ",%")))). orderBy(Order.desc(Update.CREATION_DATE))); } @@ -155,12 +154,12 @@ public class TagDataService { * @return */ public Update getLatestUpdate(TagData tagData) { - if(tagData.getValue(Task.REMOTE_ID) < 1) + if(tagData.getValue(TagData.REMOTE_ID) == 0) return null; @SuppressWarnings("nls") TodorooCursor updates = updateDao.query(Query.select(Update.PROPERTIES).where( - Update.TAGS.like("%," + tagData.getValue(Task.REMOTE_ID) + ",%")). + Update.TAGS.like("%," + tagData.getValue(TagData.REMOTE_ID) + ",%")). orderBy(Order.desc(Update.CREATION_DATE)).limit(1)); try { if(updates.getCount() == 0) diff --git a/astrid/src/com/todoroo/astrid/ui/CalendarDialog.java b/astrid/src/com/todoroo/astrid/ui/CalendarDialog.java index db999cd36..eb2104df6 100644 --- a/astrid/src/com/todoroo/astrid/ui/CalendarDialog.java +++ b/astrid/src/com/todoroo/astrid/ui/CalendarDialog.java @@ -62,4 +62,4 @@ public class CalendarDialog extends Dialog implements OnClickListener, OnSelecte public void setCalendarDate(Date calendarDate) { this.calendarDate = calendarDate; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/ContactListAdapter.java b/astrid/src/com/todoroo/astrid/ui/ContactListAdapter.java index 3fa9a4ee2..32ee2817a 100644 --- a/astrid/src/com/todoroo/astrid/ui/ContactListAdapter.java +++ b/astrid/src/com/todoroo/astrid/ui/ContactListAdapter.java @@ -189,4 +189,4 @@ public class ContactListAdapter extends CursorAdapter { } } } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/EditTextControlSet.java b/astrid/src/com/todoroo/astrid/ui/EditTextControlSet.java index b13d7bc15..8281362f8 100644 --- a/astrid/src/com/todoroo/astrid/ui/EditTextControlSet.java +++ b/astrid/src/com/todoroo/astrid/ui/EditTextControlSet.java @@ -69,4 +69,4 @@ public class EditTextControlSet extends TaskEditControlSet { return null; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/ErrorCatchingEditText.java b/astrid/src/com/todoroo/astrid/ui/ErrorCatchingEditText.java index 3851be854..e0bbb126c 100644 --- a/astrid/src/com/todoroo/astrid/ui/ErrorCatchingEditText.java +++ b/astrid/src/com/todoroo/astrid/ui/ErrorCatchingEditText.java @@ -40,4 +40,4 @@ public class ErrorCatchingEditText extends EditText { } } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/HideUntilControlSet.java b/astrid/src/com/todoroo/astrid/ui/HideUntilControlSet.java index 7921903c9..b20e4d7c0 100644 --- a/astrid/src/com/todoroo/astrid/ui/HideUntilControlSet.java +++ b/astrid/src/com/todoroo/astrid/ui/HideUntilControlSet.java @@ -258,4 +258,4 @@ public class HideUntilControlSet extends PopupControlSet implements OnItemSelect return null; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/NestedListView.java b/astrid/src/com/todoroo/astrid/ui/NestedListView.java index dc195ce8b..bb3aae9b7 100644 --- a/astrid/src/com/todoroo/astrid/ui/NestedListView.java +++ b/astrid/src/com/todoroo/astrid/ui/NestedListView.java @@ -44,4 +44,4 @@ public class NestedListView extends ListView { setMeasuredDimension(getMeasuredWidth(), newHeight); } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/NumberPicker.java b/astrid/src/com/todoroo/astrid/ui/NumberPicker.java index 826af6317..cca91331a 100644 --- a/astrid/src/com/todoroo/astrid/ui/NumberPicker.java +++ b/astrid/src/com/todoroo/astrid/ui/NumberPicker.java @@ -313,12 +313,14 @@ public class NumberPicker extends LinearLayout implements OnClickListener, } private void validateCurrentView(CharSequence str, boolean notifyChange) { - int val = getSelectedPos(str.toString()); - if ((val >= mStart) && (val <= mEnd)) { - mPrevious = mCurrent; - mCurrent = val; - if (notifyChange) - notifyChange(mCurrent); + if (!TextUtils.isEmpty(str)) { + int val = getSelectedPos(str.toString()); + if ((val >= mStart) && (val <= mEnd)) { + mPrevious = mCurrent; + mCurrent = val; + if (notifyChange) + notifyChange(mCurrent); + } } updateView(); } @@ -489,4 +491,4 @@ public class NumberPicker extends LinearLayout implements OnClickListener, validateCurrentView(str, true); return mCurrent; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/NumberPickerButton.java b/astrid/src/com/todoroo/astrid/ui/NumberPickerButton.java index 54c6cf9bd..f3f858631 100644 --- a/astrid/src/com/todoroo/astrid/ui/NumberPickerButton.java +++ b/astrid/src/com/todoroo/astrid/ui/NumberPickerButton.java @@ -86,4 +86,4 @@ public class NumberPickerButton extends ImageButton { mNumberPicker.cancelDecrement(); } } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/PeopleContainer.java b/astrid/src/com/todoroo/astrid/ui/PeopleContainer.java index 5de4d2ce3..2c0df68a4 100644 --- a/astrid/src/com/todoroo/astrid/ui/PeopleContainer.java +++ b/astrid/src/com/todoroo/astrid/ui/PeopleContainer.java @@ -185,7 +185,7 @@ public class PeopleContainer extends LinearLayout { if(text.length() == 0) continue; - if(text.indexOf('@') == -1) + if(text.indexOf('@') == -1 && textView.isEnabled()) throw new ParseSharedException(textView, activity.getString(R.string.actfm_EPA_invalid_email, text)); if (peopleAsJSON) { diff --git a/astrid/src/com/todoroo/astrid/ui/RandomReminderControlSet.java b/astrid/src/com/todoroo/astrid/ui/RandomReminderControlSet.java index 283d3fa35..25ced0bdb 100644 --- a/astrid/src/com/todoroo/astrid/ui/RandomReminderControlSet.java +++ b/astrid/src/com/todoroo/astrid/ui/RandomReminderControlSet.java @@ -95,4 +95,4 @@ public class RandomReminderControlSet extends TaskEditControlSet { task.setValue(Task.REMINDER_PERIOD, 0L); return null; } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/ReminderControlSet.java b/astrid/src/com/todoroo/astrid/ui/ReminderControlSet.java index f95ed8f00..11322e28d 100644 --- a/astrid/src/com/todoroo/astrid/ui/ReminderControlSet.java +++ b/astrid/src/com/todoroo/astrid/ui/ReminderControlSet.java @@ -127,4 +127,4 @@ public class ReminderControlSet extends PopupControlSet { protected void refreshDisplayView() { // Nothing to do here } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/ui/TimeDurationControlSet.java b/astrid/src/com/todoroo/astrid/ui/TimeDurationControlSet.java index 919065a80..6ccab9231 100644 --- a/astrid/src/com/todoroo/astrid/ui/TimeDurationControlSet.java +++ b/astrid/src/com/todoroo/astrid/ui/TimeDurationControlSet.java @@ -122,4 +122,4 @@ public class TimeDurationControlSet implements OnNNumberPickedListener, } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/voice/VoiceInputAssistant.java b/astrid/src/com/todoroo/astrid/voice/VoiceInputAssistant.java index ec705d355..9ee75e8b7 100644 --- a/astrid/src/com/todoroo/astrid/voice/VoiceInputAssistant.java +++ b/astrid/src/com/todoroo/astrid/voice/VoiceInputAssistant.java @@ -325,4 +325,4 @@ public class VoiceInputAssistant { } } } -} \ No newline at end of file +} diff --git a/astrid/src/com/todoroo/astrid/welcome/tutorial/WelcomePagerAdapter.java b/astrid/src/com/todoroo/astrid/welcome/tutorial/WelcomePagerAdapter.java index 888d4d106..1ed122fab 100644 --- a/astrid/src/com/todoroo/astrid/welcome/tutorial/WelcomePagerAdapter.java +++ b/astrid/src/com/todoroo/astrid/welcome/tutorial/WelcomePagerAdapter.java @@ -142,4 +142,4 @@ public class WelcomePagerAdapter extends PagerAdapter implements TitleProvider return context.getString(title[position]); } -} \ No newline at end of file +}