diff --git a/api/src/com/todoroo/andlib/utility/AndroidUtilities.java b/api/src/com/todoroo/andlib/utility/AndroidUtilities.java index 09b2bf05d..1f0a9fb53 100644 --- a/api/src/com/todoroo/andlib/utility/AndroidUtilities.java +++ b/api/src/com/todoroo/andlib/utility/AndroidUtilities.java @@ -10,6 +10,7 @@ import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -153,6 +154,32 @@ public class AndroidUtilities { return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length); } + + private static final int BUFFER_SIZE = 4096; + public static String encodeBase64File(File file) { + try { + FileInputStream in = new FileInputStream(file); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + byte[] buffer = new byte[BUFFER_SIZE]; + int len = 0; + while ((len = in.read(buffer)) > 0) { + baos.write(buffer, 0, len); + } + + byte[] bytes = baos.toByteArray(); + return Base64.encodeToString(bytes, Base64.DEFAULT); + } finally { + in.close(); + } + } catch (FileNotFoundException e) { + return null; + } catch (IOException e) { + return null; + } + } + /** * Start the given intent, handling security exceptions if they arise * diff --git a/api/src/com/todoroo/astrid/data/TaskAttachment.java b/api/src/com/todoroo/astrid/data/TaskAttachment.java index 1941eb565..784d5f247 100644 --- a/api/src/com/todoroo/astrid/data/TaskAttachment.java +++ b/api/src/com/todoroo/astrid/data/TaskAttachment.java @@ -144,6 +144,7 @@ public final class TaskAttachment extends RemoteModel { TaskAttachment attachment = new TaskAttachment(); attachment.setValue(TaskAttachment.TASK_UUID, taskUuid); attachment.setValue(NAME, fileName); + attachment.setValue(USER_UUID, Task.USER_ID_SELF); attachment.setValue(FILE_PATH, filePath); attachment.setValue(CONTENT_TYPE, fileType); attachment.setValue(DELETED_AT, 0L); diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ChangesHappened.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ChangesHappened.java index 4c8662146..e3d6e4199 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ChangesHappened.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ChangesHappened.java @@ -1,5 +1,6 @@ package com.todoroo.astrid.actfm.sync.messages; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -7,6 +8,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.text.TextUtils; import android.util.Log; import com.todoroo.andlib.data.Property; @@ -14,6 +16,7 @@ import com.todoroo.andlib.data.Property.PropertyVisitor; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Query; +import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.actfm.sync.ActFmSyncThread.ModelType; @@ -110,6 +113,15 @@ public class ChangesHappened localProperty = NameMaps.localColumnNameToProperty(table, localColumn); if (localProperty == null) @@ -155,6 +167,28 @@ public class ChangesHappened { private String getAsString(OE data) { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/NameMaps.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/NameMaps.java index ccd635afc..db3c054ee 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/NameMaps.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/NameMaps.java @@ -255,6 +255,8 @@ public class NameMaps { private static final Map> TASK_ATTACHMENT_PROPERTIES_SERVER_TO_LOCAL; private static final Set TASK_ATTACHMENT_PROPERTIES_EXCLUDED; + public static final String ATTACHMENT_ADDED_COLUMN = "file"; + private static void putTaskAttachmentPropertyToServerName(Property property, String serverName, boolean writeable) { putPropertyToServerName(property, serverName, TASK_ATTACHMENT_PROPERTIES_LOCAL_TO_SERVER, TASK_ATTACHMENT_COLUMN_NAMES_TO_PROPERTIES, TASK_ATTACHMENT_COLUMNS_LOCAL_TO_SERVER, TASK_ATTACHMENT_PROPERTIES_EXCLUDED, writeable); diff --git a/astrid/plugin-src/com/todoroo/astrid/files/FilesControlSet.java b/astrid/plugin-src/com/todoroo/astrid/files/FilesControlSet.java index 578e211ca..b63689cd1 100644 --- a/astrid/plugin-src/com/todoroo/astrid/files/FilesControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/files/FilesControlSet.java @@ -46,6 +46,7 @@ import com.todoroo.andlib.utility.DialogUtilities; import com.todoroo.astrid.actfm.sync.ActFmPreferenceService; import com.todoroo.astrid.dao.TaskAttachmentDao; import com.todoroo.astrid.data.RemoteModel; +import com.todoroo.astrid.data.SyncFlags; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.TaskAttachment; import com.todoroo.astrid.ui.PopupControlSet; @@ -256,6 +257,7 @@ public class FilesControlSet extends PopupControlSet { useType = guessedType; if (useType != guessedType) { m.setValue(TaskAttachment.CONTENT_TYPE, useType); + m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); taskAttachmentDao.saveExisting(m); } } diff --git a/astrid/src/com/todoroo/astrid/dao/TaskAttachmentDao.java b/astrid/src/com/todoroo/astrid/dao/TaskAttachmentDao.java index 1499c570a..684f1dbc3 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskAttachmentDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskAttachmentDao.java @@ -5,14 +5,23 @@ */ package com.todoroo.astrid.dao; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.ContentValues; +import android.text.TextUtils; + 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.Query; +import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.actfm.sync.messages.NameMaps; +import com.todoroo.astrid.data.OutstandingEntry; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.TaskAttachment; +import com.todoroo.astrid.data.TaskAttachmentOutstanding; /** * Data Access layer for {@link TagData}-related operations. @@ -36,6 +45,34 @@ public class TaskAttachmentDao extends RemoteModelDao { return NameMaps.shouldRecordOutstandingColumnForTable(NameMaps.TABLE_ID_ATTACHMENTS, columnName); } + @Override + protected int createOutstandingEntries(long modelId, ContentValues modelSetValues) { + // new attachment case -- only set by us when creating new attachments; when setting during sync outstanding entries suppressed + if (modelSetValues.containsKey(TaskAttachment.CONTENT_TYPE.name)) { + TaskAttachmentOutstanding m = new TaskAttachmentOutstanding(); + String path = modelSetValues.getAsString(TaskAttachment.FILE_PATH.name); + if (TextUtils.isEmpty(path)) + return -1; + try { + JSONObject newFileHash = new JSONObject(); + newFileHash.put("name", modelSetValues.getAsString(TaskAttachment.NAME.name)); //$NON-NLS-1$ + newFileHash.put("type", modelSetValues.getAsString(TaskAttachment.CONTENT_TYPE.name)); //$NON-NLS-1$ + newFileHash.put("path", modelSetValues.getAsString(path)); //$NON-NLS-1$ + + m.setValue(OutstandingEntry.ENTITY_ID_PROPERTY, modelId); + m.setValue(OutstandingEntry.COLUMN_STRING_PROPERTY, NameMaps.ATTACHMENT_ADDED_COLUMN); + m.setValue(OutstandingEntry.VALUE_STRING_PROPERTY, newFileHash.toString()); + m.setValue(OutstandingEntry.CREATED_AT_PROPERTY, DateUtilities.now()); + } catch (JSONException e) { + return -1; + } + } + int result = super.createOutstandingEntries(modelId, modelSetValues); + if (result < 0) // Error + return result; + return 1 + result; + } + public boolean taskHasAttachments(String taskUuid) { TodorooCursor files = query(Query.select(TaskAttachment.TASK_UUID).where( Criterion.and(TaskAttachment.TASK_UUID.eq(taskUuid),