Detect remote caldav deletions

pull/645/head
Alex Baker 6 years ago
parent 4f300a8f37
commit 3bb93f1ad0

@ -0,0 +1,815 @@
{
"formatVersion": 1,
"database": {
"version": 56,
"identityHash": "dcac47adc6c2df5755061388ec3a1248",
"entities": [
{
"tableName": "notification",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `type` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "taskId",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "timestamp",
"columnName": "timestamp",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"uid"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_notification_task",
"unique": true,
"columnNames": [
"task"
],
"createSql": "CREATE UNIQUE INDEX `index_notification_task` ON `${TABLE_NAME}` (`task`)"
}
],
"foreignKeys": []
},
{
"tableName": "tagdata",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `name` TEXT, `color` INTEGER, `tagOrdering` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "tagOrdering",
"columnName": "tagOrdering",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "userActivity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `message` TEXT, `picture` TEXT, `target_id` TEXT, `created_at` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "message",
"columnName": "message",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "picture",
"columnName": "picture",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "targetId",
"columnName": "target_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "created",
"columnName": "created_at",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "task_attachments",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `task_id` TEXT, `name` TEXT, `path` TEXT, `content_type` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "taskId",
"columnName": "task_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "path",
"columnName": "path",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "contentType",
"columnName": "content_type",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "task_list_metadata",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `remoteId` TEXT, `tag_uuid` TEXT, `filter` TEXT, `task_ids` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "tagUuid",
"columnName": "tag_uuid",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "filter",
"columnName": "filter",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "taskIds",
"columnName": "task_ids",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT, `importance` INTEGER, `dueDate` INTEGER, `hideUntil` INTEGER, `created` INTEGER, `modified` INTEGER, `completed` INTEGER, `deleted` INTEGER, `notes` TEXT, `estimatedSeconds` INTEGER, `elapsedSeconds` INTEGER, `timerStart` INTEGER, `notificationFlags` INTEGER, `notifications` INTEGER, `lastNotified` INTEGER, `snoozeTime` INTEGER, `recurrence` TEXT, `repeatUntil` INTEGER, `calendarUri` TEXT, `remoteId` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "importance",
"columnName": "importance",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "dueDate",
"columnName": "dueDate",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "hideUntil",
"columnName": "hideUntil",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "created",
"columnName": "created",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "modified",
"columnName": "modified",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "completed",
"columnName": "completed",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "deleted",
"columnName": "deleted",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "notes",
"columnName": "notes",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "estimatedSeconds",
"columnName": "estimatedSeconds",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "elapsedSeconds",
"columnName": "elapsedSeconds",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "timerStart",
"columnName": "timerStart",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "notificationFlags",
"columnName": "notificationFlags",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "notifications",
"columnName": "notifications",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lastNotified",
"columnName": "lastNotified",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "snoozeTime",
"columnName": "snoozeTime",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "recurrence",
"columnName": "recurrence",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "repeatUntil",
"columnName": "repeatUntil",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "calendarUri",
"columnName": "calendarUri",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remoteId",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [
{
"name": "t_rid",
"unique": true,
"columnNames": [
"remoteId"
],
"createSql": "CREATE UNIQUE INDEX `t_rid` ON `${TABLE_NAME}` (`remoteId`)"
}
],
"foreignKeys": []
},
{
"tableName": "alarms",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `time` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "locations",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `name` TEXT, `latitude` REAL NOT NULL, `longitude` REAL NOT NULL, `radius` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "latitude",
"columnName": "latitude",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "longitude",
"columnName": "longitude",
"affinity": "REAL",
"notNull": true
},
{
"fieldPath": "radius",
"columnName": "radius",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "tags",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `name` TEXT, `tag_uid` TEXT, `task_uid` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "tagUid",
"columnName": "tag_uid",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "taskUid",
"columnName": "task_uid",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "google_tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `remote_id` TEXT, `list_id` TEXT, `parent` INTEGER NOT NULL, `indent` INTEGER NOT NULL, `order` INTEGER NOT NULL, `remote_order` INTEGER NOT NULL, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "listId",
"columnName": "list_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "parent",
"columnName": "parent",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "indent",
"columnName": "indent",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteOrder",
"columnName": "remote_order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lastSync",
"columnName": "last_sync",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "deleted",
"columnName": "deleted",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "filters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT, `sql` TEXT, `values` TEXT, `criterion` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sql",
"columnName": "sql",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "values",
"columnName": "values",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "criterion",
"columnName": "criterion",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "google_task_lists",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `remote_id` TEXT, `title` TEXT, `remote_order` INTEGER NOT NULL, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL, `color` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "remoteOrder",
"columnName": "remote_order",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lastSync",
"columnName": "last_sync",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "deleted",
"columnName": "deleted",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "caldav_account",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `uuid` TEXT, `name` TEXT, `color` INTEGER NOT NULL, `ctag` TEXT, `url` TEXT, `username` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "uuid",
"columnName": "uuid",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "color",
"columnName": "color",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "ctag",
"columnName": "ctag",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "caldav_tasks",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task` INTEGER NOT NULL, `account` TEXT, `object` TEXT, `remote_id` TEXT, `etag` TEXT, `last_sync` INTEGER NOT NULL, `deleted` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "task",
"columnName": "task",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "account",
"columnName": "account",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "object",
"columnName": "object",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "remoteId",
"columnName": "remote_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "etag",
"columnName": "etag",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastSync",
"columnName": "last_sync",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "deleted",
"columnName": "deleted",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"_id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"dcac47adc6c2df5755061388ec3a1248\")"
]
}
}

@ -13,6 +13,7 @@ import com.todoroo.astrid.api.GtasksFilter;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.gtasks.GtasksListService;
import com.todoroo.astrid.helper.UUIDHelper;
import org.tasks.R;
import org.tasks.analytics.Tracker;
@ -140,7 +141,7 @@ public class RemoteListFragment extends TaskEditControlFragment {
if (selectedList instanceof GtasksFilter) {
googleTaskDao.insert(new GoogleTask(task.getId(), ((GtasksFilter) selectedList).getRemoteId()));
} else if (selectedList instanceof CaldavFilter) {
caldavDao.insert(new CaldavTask(task.getId(), ((CaldavFilter) selectedList).getUuid()));
caldavDao.insert(new CaldavTask(task.getId(), ((CaldavFilter) selectedList).getUuid(), UUIDHelper.newUUID()));
}
}

@ -66,7 +66,7 @@ import timber.log.Timber;
CaldavAccount.class,
CaldavTask.class
},
version = 55)
version = 56)
public abstract class Database extends RoomDatabase {
public abstract NotificationDao notificationDao();

@ -86,7 +86,7 @@ public class TaskCreator {
if (task.hasTransitory(GoogleTask.KEY)) {
googleTaskDao.insert(new GoogleTask(task.getId(), task.getTransitory(GoogleTask.KEY)));
} else if (task.hasTransitory(CaldavTask.KEY)) {
caldavDao.insert(new CaldavTask(task.getId(), task.getTransitory(CaldavTask.KEY)));
caldavDao.insert(new CaldavTask(task.getId(), task.getTransitory(CaldavTask.KEY), UUIDHelper.newUUID()));
} else {
Filter remoteList = defaultFilterProvider.getDefaultRemoteList();
if (remoteList != null && remoteList instanceof GtasksFilter) {

@ -7,12 +7,14 @@ import android.content.SyncResult;
import android.os.Bundle;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.UUIDHelper;
import com.todoroo.astrid.service.TaskCreator;
import com.todoroo.astrid.service.TaskDeleter;
import org.apache.commons.codec.Charsets;
import org.tasks.AccountManager;
@ -30,6 +32,7 @@ import java.io.InputStreamReader;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
@ -51,7 +54,13 @@ import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import timber.log.Timber;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.filter;
import static com.google.common.collect.Sets.newHashSet;
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
@ -62,6 +71,7 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
@Inject TaskDao taskDao;
@Inject LocalBroadcastManager localBroadcastManager;
@Inject TaskCreator taskCreator;
@Inject TaskDeleter taskDeleter;
CalDAVSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
@ -115,27 +125,22 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
String remoteCtag = properties.get(GetCTag.class).getCTag();
String localCtag = caldavAccount.getCtag();
if (localCtag != null && localCtag.equals(remoteCtag)) {
Timber.d("%s up to date", caldavAccount.getName());
return;
}
// fetch etags
// check for deleted tasks
// multiget updated tasks
davCalendar.calendarQuery("VTODO", null, null);
// fetch and apply remote changes
// TODO: multi-get new and modified objects
// TODO: delete this loop
for (DavResource vCard : davCalendar.getMembers()) {
ResponseBody responseBody = vCard.get("text/calendar");
GetETag eTag = (GetETag) vCard.getProperties().get(GetETag.NAME);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException("Received CalDAV GET response without ETag for " + vCard.getLocation());
}
ResponseBody responseBody = vCard.get("text/calendar");
MediaType contentType = responseBody.contentType();
Charset charset = contentType == null ? Charsets.UTF_8 : contentType.charset(Charsets.UTF_8);
InputStream stream = responseBody.byteStream();
@ -148,6 +153,13 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
}
}
Sets.SetView<String> deleted = difference(
newHashSet(caldavDao.getObjects(caldavAccount.getUuid())),
newHashSet(transform(davCalendar.getMembers(), DavResource::fileName)));
List<String> toDelete = newArrayList(deleted);
taskDeleter.markDeleted(caldavDao.getTasks(caldavAccount.getUuid(), toDelete));
caldavDao.deleteObjects(caldavAccount.getUuid(), toDelete);
caldavAccount.setCtag(remoteCtag);
caldavDao.update(caldavAccount);
} catch (IOException | HttpException | DavException | CalendarStorageException e) {
@ -172,8 +184,8 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
private boolean deleteRemoteResource(OkHttpClient httpClient, HttpUrl httpUrl, CaldavTask caldavTask) {
try {
if (!Strings.isNullOrEmpty(caldavTask.getRemoteId())) {
DavResource remote = new DavResource(httpClient, httpUrl.newBuilder().addPathSegment(caldavTask.getRemoteId() + ".ics").build());
if (!Strings.isNullOrEmpty(caldavTask.getObject())) {
DavResource remote = new DavResource(httpClient, httpUrl.newBuilder().addPathSegment(caldavTask.getObject()).build());
remote.delete(null);
}
} catch (HttpException e) {
@ -228,7 +240,7 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
DavCalendar.MIME_ICALENDAR,
os.toByteArray());
try {
DavResource remote = new DavResource(httpClient, httpUrl.newBuilder().addPathSegment(caldavMetadata.getRemoteId() + ".ics").build());
DavResource remote = new DavResource(httpClient, httpUrl.newBuilder().addPathSegment(caldavMetadata.getObject()).build());
remote.put(requestBody, null, false);
} catch (HttpException e) {
Timber.e(e.getMessage(), e);
@ -261,12 +273,11 @@ public class CalDAVSyncAdapter extends InjectingAbstractThreadedSyncAdapter {
if (tasks.size() == 1) {
at.bitfire.ical4android.Task remote = tasks.get(0);
Task task;
CaldavTask caldavTask = caldavDao.getTask(caldavAccount.getUuid(), remote.getUid());
CaldavTask caldavTask = caldavDao.getTask(caldavAccount.getUuid(), fileName);
if (caldavTask == null) {
task = taskCreator.createWithValues(null, "");
taskDao.createNew(task);
caldavTask = new CaldavTask(task.getId(), caldavAccount.getUuid());
caldavTask.setRemoteId(remote.getUid());
caldavTask = new CaldavTask(task.getId(), caldavAccount.getUuid(), remote.getUid(), fileName);
Timber.d("NEW %s", remote);
} else {
task = taskDao.fetch(caldavTask.getTask());

@ -7,6 +7,7 @@ import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
import java.util.List;
import java.util.Set;
@Dao
public interface CaldavDao {
@ -38,8 +39,8 @@ public interface CaldavDao {
@Query("SELECT * FROM caldav_tasks WHERE task = :taskId AND deleted = 0 LIMIT 1")
CaldavTask getTask(long taskId);
@Query("SELECT * FROM caldav_tasks WHERE account = :account AND remote_id = :remoteId LIMIT 1")
CaldavTask getTask(String account, String remoteId);
@Query("SELECT * FROM caldav_tasks WHERE account = :account AND object = :object LIMIT 1")
CaldavTask getTask(String account, String object);
@Query("DELETE FROM caldav_tasks WHERE task = :taskId")
void deleteById(long taskId);
@ -58,4 +59,13 @@ public interface CaldavDao {
@Query("DELETE FROM caldav_tasks WHERE account = :uuid")
void deleteTasksForAccount(String uuid);
@Query("SELECT object FROM caldav_tasks WHERE account = :account")
List<String> getObjects(String account);
@Query("SELECT task FROM caldav_tasks WHERE account = :account AND object IN (:objects)")
List<Long> getTasks(String account, List<String> objects);
@Query("DELETE FROM caldav_tasks WHERE account = :account AND object IN (:objects)")
void deleteObjects(String account, List<String> objects);
}

@ -25,6 +25,9 @@ public class CaldavTask {
@ColumnInfo(name = "account")
private String account;
@ColumnInfo(name = "object")
private String object;
@ColumnInfo(name = "remote_id")
private String remoteId;
@ -42,9 +45,16 @@ public class CaldavTask {
}
@Ignore
public CaldavTask(long task, String account) {
public CaldavTask(long task, String account, String remoteId) {
this(task, account, remoteId, remoteId + ".ics");
}
@Ignore
public CaldavTask(long task, String account, String remoteId, String object) {
this.task = task;
this.account = account;
this.remoteId = remoteId;
this.object = object;
}
public long getId() {
@ -63,6 +73,22 @@ public class CaldavTask {
this.task = task;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
public String getRemoteId() {
return remoteId;
}
@ -95,20 +121,13 @@ public class CaldavTask {
this.deleted = deleted;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
@Override
public String toString() {
return "CaldavTask{" +
"id=" + id +
", task=" + task +
", account='" + account + '\'' +
", object='" + object + '\'' +
", remoteId='" + remoteId + '\'' +
", etag='" + etag + '\'' +
", lastSync=" + lastSync +

@ -151,6 +151,13 @@ public class Migrations {
}
};
private static final Migration MIGRATION_55_56 = new Migration(55, 56) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `caldav_tasks` ADD COLUMN `object` TEXT");
}
};
private static Migration NOOP(int from, int to) {
return new Migration(from, to) {
@Override
@ -174,6 +181,7 @@ public class Migrations {
MIGRATION_51_52,
MIGRATION_52_53,
MIGRATION_53_54,
MIGRATION_54_55
MIGRATION_54_55,
MIGRATION_55_56
};
}

Loading…
Cancel
Save