Loading app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt +5 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.Event import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import net.fortuna.ical4j.model.property.RecurrenceId Loading Loading @@ -94,7 +95,7 @@ class LocalCalendarTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -103,7 +104,7 @@ class LocalCalendarTest { // verify that event is now marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading @@ -123,7 +124,7 @@ class LocalCalendarTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -132,7 +133,7 @@ class LocalCalendarTest { // verify that event is not marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt +6 −6 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ import android.provider.CalendarContract.Events import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendar.Companion.syncAdapterURI import at.bitfire.ical4android.Event import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat import at.techbee.jtx.JtxContract.asSyncAdapter import net.fortuna.ical4j.model.Date import net.fortuna.ical4j.model.DateList import net.fortuna.ical4j.model.parameter.Value Loading Loading @@ -293,7 +293,7 @@ class LocalEventTest { // Get the status of whether the event is deleted provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!), account), ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!).asSyncAdapter(account), arrayOf(Events.DELETED), null, null, null Loading Loading @@ -340,7 +340,7 @@ class LocalEventTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -349,7 +349,7 @@ class LocalEventTest { // verify that event is now marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading @@ -369,7 +369,7 @@ class LocalEventTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -378,7 +378,7 @@ class LocalEventTest { // verify that event is not marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.kt +13 −12 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendarFactory import at.bitfire.ical4android.BatchOperation import at.bitfire.ical4android.DateUtils import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import java.util.* import java.util.logging.Level Loading Loading @@ -149,7 +150,7 @@ class LocalCalendar private constructor( override fun markNotDirty(flags: Int): Int { val values = ContentValues(1) values.put(LocalEvent.COLUMN_FLAGS, flags) return provider.update(eventsSyncURI(), values, return provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL", arrayOf(id.toString())) } Loading @@ -157,7 +158,7 @@ class LocalCalendar private constructor( override fun removeNotDirtyMarked(flags: Int): Int { var deleted = 0 // list all non-dirty events with the given flags and delete every row + its exceptions provider.query(eventsSyncURI(), arrayOf(Events._ID), provider.query(Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL AND ${LocalEvent.COLUMN_FLAGS}=?", arrayOf(id.toString(), flags.toString()), null)?.use { cursor -> val batch = BatchOperation(provider) Loading @@ -165,7 +166,7 @@ class LocalCalendar private constructor( val id = cursor.getLong(0) // delete event and possible exceptions (content provider doesn't delete exceptions itself) batch.enqueue(BatchOperation.CpoBuilder .newDelete(eventsSyncURI()) .newDelete(Events.CONTENT_URI.asSyncAdapter(account)) .withSelection("${Events._ID}=? OR ${Events.ORIGINAL_ID}=?", arrayOf(id.toString(), id.toString()))) } deleted = batch.commit() Loading @@ -176,7 +177,7 @@ class LocalCalendar private constructor( override fun forgetETags() { val values = ContentValues(1) values.putNull(LocalEvent.COLUMN_ETAG) provider.update(eventsSyncURI(), values, "${Events.CALENDAR_ID}=?", provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.CALENDAR_ID}=?", arrayOf(id.toString())) } Loading @@ -185,7 +186,7 @@ class LocalCalendar private constructor( // process deleted exceptions Logger.log.info("Processing deleted exceptions") provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE), "${Events.CALENDAR_ID}=? AND ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NOT NULL", arrayOf(id.toString()), null)?.use { cursor -> Loading @@ -198,7 +199,7 @@ class LocalCalendar private constructor( // get original event's SEQUENCE provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)), ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account), arrayOf(LocalEvent.COLUMN_SEQUENCE), null, null, null)?.use { cursor2 -> if (cursor2.moveToNext()) { Loading @@ -207,14 +208,14 @@ class LocalCalendar private constructor( // re-schedule original event and set it to DIRTY batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account)) .withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence + 1) .withValue(Events.DIRTY, 1)) } } // completely remove deleted exception batch.enqueue(BatchOperation.CpoBuilder.newDelete(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))) batch.enqueue(BatchOperation.CpoBuilder.newDelete(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account))) batch.commit() } } Loading @@ -222,7 +223,7 @@ class LocalCalendar private constructor( // process dirty exceptions Logger.log.info("Processing dirty exceptions") provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE), "${Events.CALENDAR_ID}=? AND ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NOT NULL", arrayOf(id.toString()), null)?.use { cursor -> Loading @@ -235,11 +236,11 @@ class LocalCalendar private constructor( val batch = BatchOperation(provider) // original event to DIRTY batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account)) .withValue(Events.DIRTY, 1)) // increase SEQUENCE and set DIRTY to 0 batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account)) .withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1) .withValue(Events.DIRTY, 0)) batch.commit() Loading @@ -254,7 +255,7 @@ class LocalCalendar private constructor( */ fun deleteDirtyEventsWithoutInstances() { provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.DIRTY} AND NOT ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NULL", // Get dirty main events (and no exception events) null, null Loading app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.kt +11 −14 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.provider.CalendarContract import android.provider.CalendarContract.Events import at.bitfire.davdroid.BuildConfig import at.bitfire.ical4android.* import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import net.fortuna.ical4j.model.property.ProdId import org.apache.commons.lang3.StringUtils import java.util.* Loading @@ -34,12 +35,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { */ fun markAsDeleted(provider: ContentProviderClient, account: Account, eventID: Long) { provider.update( AndroidCalendar.syncAdapterURI( ContentUris.withAppendedId( Events.CONTENT_URI, eventID ), account ), ).asSyncAdapter(account), ContentValues(1).apply { put(Events.DELETED, 1) }, Loading @@ -61,12 +60,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { var first: Long? = null var last: Long? = null provider.query( AndroidCalendar.syncAdapterURI( ContentUris.withAppendedId( Events.CONTENT_URI, eventID ), account ), ).asSyncAdapter(account), arrayOf(Events.DTSTART, Events.LAST_DATE), null, null, null )?.use { cursor -> cursor.moveToNext() Loading @@ -82,7 +79,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { /* We can't use Long.MIN_VALUE and Long.MAX_VALUE because Android generates the instances on the fly and it doesn't accept those values. So we use the first/last actual occurence of the event (calculated by Android). */ val instancesUri = AndroidCalendar.syncAdapterURI(CalendarContract.Instances.CONTENT_URI, account) val instancesUri = CalendarContract.Instances.CONTENT_URI.asSyncAdapter(account) .buildUpon() .appendPath(first.toString()) // begin timestamp .appendPath(last.toString()) // end timestamp Loading Loading @@ -113,7 +110,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { // add the number of instances of every main event's exception provider.query( AndroidCalendar.syncAdapterURI(Events.CONTENT_URI, account), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.ORIGINAL_ID}=?", // get exception events of the main event arrayOf("$eventID"), null Loading app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt +7 −6 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.UnknownProperty import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.GroupMethod import at.techbee.jtx.JtxContract.asSyncAdapter import net.fortuna.ical4j.model.Property import net.fortuna.ical4j.model.property.Url import okhttp3.HttpUrl.Companion.toHttpUrlOrNull Loading Loading @@ -438,7 +439,7 @@ class AccountSettings( context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider -> // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query // to the given account! So all extended properties will be processed number-of-accounts times. val extUri = AndroidCalendar.syncAdapterURI(ExtendedProperties.CONTENT_URI, account) val extUri = ExtendedProperties.CONTENT_URI.asSyncAdapter(account) provider.query(extUri, arrayOf( ExtendedProperties._ID, // idx 0 Loading @@ -450,7 +451,7 @@ class AccountSettings( val rawValue = cursor.getString(2) val uri by lazy { AndroidCalendar.syncAdapterURI(ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id), account) ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id).asSyncAdapter(account) } when (cursor.getString(1)) { Loading Loading @@ -519,7 +520,7 @@ class AccountSettings( **/ private fun update_9_10() { TaskProvider.acquire(context, OpenTasks)?.use { provider -> val tasksUri = TaskProvider.syncAdapterUri(provider.tasksUri(), account) val tasksUri = provider.tasksUri().asSyncAdapter(account) val emptyETag = ContentValues(1) emptyETag.putNull(LocalTask.COLUMN_ETAG) provider.client.update(tasksUri, emptyETag, "${TaskContract.Tasks._DIRTY}=0 AND ${TaskContract.Tasks._DELETED}=0", null) Loading @@ -528,7 +529,7 @@ class AccountSettings( @SuppressLint("Recycle") if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.let { provider -> provider.update(AndroidCalendar.syncAdapterURI(CalendarContract.Calendars.CONTENT_URI, account), provider.update(CalendarContract.Calendars.CONTENT_URI.asSyncAdapter(account), AndroidCalendar.calendarBaseValues, null, null) provider.closeCompat() } Loading Loading @@ -558,7 +559,7 @@ class AccountSettings( TaskProvider.acquire(context, OpenTasks)?.use { provider -> // ETag is now in sync_version instead of sync1 // UID is now in _uid instead of sync2 provider.client.query(TaskProvider.syncAdapterUri(provider.tasksUri(), account), provider.client.query(provider.tasksUri().asSyncAdapter(account), arrayOf(TaskContract.Tasks._ID, TaskContract.Tasks.SYNC1, TaskContract.Tasks.SYNC2), "${TaskContract.Tasks.ACCOUNT_TYPE}=? AND ${TaskContract.Tasks.ACCOUNT_NAME}=?", arrayOf(account.type, account.name), null)!!.use { cursor -> Loading @@ -573,7 +574,7 @@ class AccountSettings( values.putNull(TaskContract.Tasks.SYNC2) Logger.log.log(Level.FINER, "Updating task $id", values) provider.client.update( TaskProvider.syncAdapterUri(ContentUris.withAppendedId(provider.tasksUri(), id), account), ContentUris.withAppendedId(provider.tasksUri(), id).asSyncAdapter(account), values, null, null) } } Loading Loading
app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt +5 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.Event import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import net.fortuna.ical4j.model.property.RecurrenceId Loading Loading @@ -94,7 +95,7 @@ class LocalCalendarTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -103,7 +104,7 @@ class LocalCalendarTest { // verify that event is now marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading @@ -123,7 +124,7 @@ class LocalCalendarTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -132,7 +133,7 @@ class LocalCalendarTest { // verify that event is not marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading
app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt +6 −6 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ import android.provider.CalendarContract.Events import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendar.Companion.syncAdapterURI import at.bitfire.ical4android.Event import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat import at.techbee.jtx.JtxContract.asSyncAdapter import net.fortuna.ical4j.model.Date import net.fortuna.ical4j.model.DateList import net.fortuna.ical4j.model.parameter.Value Loading Loading @@ -293,7 +293,7 @@ class LocalEventTest { // Get the status of whether the event is deleted provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!), account), ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!).asSyncAdapter(account), arrayOf(Events.DELETED), null, null, null Loading Loading @@ -340,7 +340,7 @@ class LocalEventTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -349,7 +349,7 @@ class LocalEventTest { // verify that event is now marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading @@ -369,7 +369,7 @@ class LocalEventTest { val eventId = localEvent.id!! // set event as dirty provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply { provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply { put(Events.DIRTY, 1) }, null, null) Loading @@ -378,7 +378,7 @@ class LocalEventTest { // verify that event is not marked as deleted provider.query( ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), arrayOf(Events.DELETED), null, null, null )!!.use { cursor -> cursor.moveToNext() Loading
app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.kt +13 −12 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.AndroidCalendarFactory import at.bitfire.ical4android.BatchOperation import at.bitfire.ical4android.DateUtils import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import java.util.* import java.util.logging.Level Loading Loading @@ -149,7 +150,7 @@ class LocalCalendar private constructor( override fun markNotDirty(flags: Int): Int { val values = ContentValues(1) values.put(LocalEvent.COLUMN_FLAGS, flags) return provider.update(eventsSyncURI(), values, return provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL", arrayOf(id.toString())) } Loading @@ -157,7 +158,7 @@ class LocalCalendar private constructor( override fun removeNotDirtyMarked(flags: Int): Int { var deleted = 0 // list all non-dirty events with the given flags and delete every row + its exceptions provider.query(eventsSyncURI(), arrayOf(Events._ID), provider.query(Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL AND ${LocalEvent.COLUMN_FLAGS}=?", arrayOf(id.toString(), flags.toString()), null)?.use { cursor -> val batch = BatchOperation(provider) Loading @@ -165,7 +166,7 @@ class LocalCalendar private constructor( val id = cursor.getLong(0) // delete event and possible exceptions (content provider doesn't delete exceptions itself) batch.enqueue(BatchOperation.CpoBuilder .newDelete(eventsSyncURI()) .newDelete(Events.CONTENT_URI.asSyncAdapter(account)) .withSelection("${Events._ID}=? OR ${Events.ORIGINAL_ID}=?", arrayOf(id.toString(), id.toString()))) } deleted = batch.commit() Loading @@ -176,7 +177,7 @@ class LocalCalendar private constructor( override fun forgetETags() { val values = ContentValues(1) values.putNull(LocalEvent.COLUMN_ETAG) provider.update(eventsSyncURI(), values, "${Events.CALENDAR_ID}=?", provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.CALENDAR_ID}=?", arrayOf(id.toString())) } Loading @@ -185,7 +186,7 @@ class LocalCalendar private constructor( // process deleted exceptions Logger.log.info("Processing deleted exceptions") provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE), "${Events.CALENDAR_ID}=? AND ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NOT NULL", arrayOf(id.toString()), null)?.use { cursor -> Loading @@ -198,7 +199,7 @@ class LocalCalendar private constructor( // get original event's SEQUENCE provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)), ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account), arrayOf(LocalEvent.COLUMN_SEQUENCE), null, null, null)?.use { cursor2 -> if (cursor2.moveToNext()) { Loading @@ -207,14 +208,14 @@ class LocalCalendar private constructor( // re-schedule original event and set it to DIRTY batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account)) .withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence + 1) .withValue(Events.DIRTY, 1)) } } // completely remove deleted exception batch.enqueue(BatchOperation.CpoBuilder.newDelete(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))) batch.enqueue(BatchOperation.CpoBuilder.newDelete(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account))) batch.commit() } } Loading @@ -222,7 +223,7 @@ class LocalCalendar private constructor( // process dirty exceptions Logger.log.info("Processing dirty exceptions") provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE), "${Events.CALENDAR_ID}=? AND ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NOT NULL", arrayOf(id.toString()), null)?.use { cursor -> Loading @@ -235,11 +236,11 @@ class LocalCalendar private constructor( val batch = BatchOperation(provider) // original event to DIRTY batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account)) .withValue(Events.DIRTY, 1)) // increase SEQUENCE and set DIRTY to 0 batch.enqueue(BatchOperation.CpoBuilder .newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))) .newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account)) .withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1) .withValue(Events.DIRTY, 0)) batch.commit() Loading @@ -254,7 +255,7 @@ class LocalCalendar private constructor( */ fun deleteDirtyEventsWithoutInstances() { provider.query( syncAdapterURI(Events.CONTENT_URI), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.DIRTY} AND NOT ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NULL", // Get dirty main events (and no exception events) null, null Loading
app/src/main/java/at/bitfire/davdroid/resource/LocalEvent.kt +11 −14 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.provider.CalendarContract import android.provider.CalendarContract.Events import at.bitfire.davdroid.BuildConfig import at.bitfire.ical4android.* import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import net.fortuna.ical4j.model.property.ProdId import org.apache.commons.lang3.StringUtils import java.util.* Loading @@ -34,12 +35,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { */ fun markAsDeleted(provider: ContentProviderClient, account: Account, eventID: Long) { provider.update( AndroidCalendar.syncAdapterURI( ContentUris.withAppendedId( Events.CONTENT_URI, eventID ), account ), ).asSyncAdapter(account), ContentValues(1).apply { put(Events.DELETED, 1) }, Loading @@ -61,12 +60,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { var first: Long? = null var last: Long? = null provider.query( AndroidCalendar.syncAdapterURI( ContentUris.withAppendedId( Events.CONTENT_URI, eventID ), account ), ).asSyncAdapter(account), arrayOf(Events.DTSTART, Events.LAST_DATE), null, null, null )?.use { cursor -> cursor.moveToNext() Loading @@ -82,7 +79,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { /* We can't use Long.MIN_VALUE and Long.MAX_VALUE because Android generates the instances on the fly and it doesn't accept those values. So we use the first/last actual occurence of the event (calculated by Android). */ val instancesUri = AndroidCalendar.syncAdapterURI(CalendarContract.Instances.CONTENT_URI, account) val instancesUri = CalendarContract.Instances.CONTENT_URI.asSyncAdapter(account) .buildUpon() .appendPath(first.toString()) // begin timestamp .appendPath(last.toString()) // end timestamp Loading Loading @@ -113,7 +110,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> { // add the number of instances of every main event's exception provider.query( AndroidCalendar.syncAdapterURI(Events.CONTENT_URI, account), Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID), "${Events.ORIGINAL_ID}=?", // get exception events of the main event arrayOf("$eventID"), null Loading
app/src/main/java/at/bitfire/davdroid/settings/AccountSettings.kt +7 −6 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks import at.bitfire.ical4android.UnknownProperty import at.bitfire.vcard4android.ContactsStorageException import at.bitfire.vcard4android.GroupMethod import at.techbee.jtx.JtxContract.asSyncAdapter import net.fortuna.ical4j.model.Property import net.fortuna.ical4j.model.property.Url import okhttp3.HttpUrl.Companion.toHttpUrlOrNull Loading Loading @@ -438,7 +439,7 @@ class AccountSettings( context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider -> // Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query // to the given account! So all extended properties will be processed number-of-accounts times. val extUri = AndroidCalendar.syncAdapterURI(ExtendedProperties.CONTENT_URI, account) val extUri = ExtendedProperties.CONTENT_URI.asSyncAdapter(account) provider.query(extUri, arrayOf( ExtendedProperties._ID, // idx 0 Loading @@ -450,7 +451,7 @@ class AccountSettings( val rawValue = cursor.getString(2) val uri by lazy { AndroidCalendar.syncAdapterURI(ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id), account) ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id).asSyncAdapter(account) } when (cursor.getString(1)) { Loading Loading @@ -519,7 +520,7 @@ class AccountSettings( **/ private fun update_9_10() { TaskProvider.acquire(context, OpenTasks)?.use { provider -> val tasksUri = TaskProvider.syncAdapterUri(provider.tasksUri(), account) val tasksUri = provider.tasksUri().asSyncAdapter(account) val emptyETag = ContentValues(1) emptyETag.putNull(LocalTask.COLUMN_ETAG) provider.client.update(tasksUri, emptyETag, "${TaskContract.Tasks._DIRTY}=0 AND ${TaskContract.Tasks._DELETED}=0", null) Loading @@ -528,7 +529,7 @@ class AccountSettings( @SuppressLint("Recycle") if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED) context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.let { provider -> provider.update(AndroidCalendar.syncAdapterURI(CalendarContract.Calendars.CONTENT_URI, account), provider.update(CalendarContract.Calendars.CONTENT_URI.asSyncAdapter(account), AndroidCalendar.calendarBaseValues, null, null) provider.closeCompat() } Loading Loading @@ -558,7 +559,7 @@ class AccountSettings( TaskProvider.acquire(context, OpenTasks)?.use { provider -> // ETag is now in sync_version instead of sync1 // UID is now in _uid instead of sync2 provider.client.query(TaskProvider.syncAdapterUri(provider.tasksUri(), account), provider.client.query(provider.tasksUri().asSyncAdapter(account), arrayOf(TaskContract.Tasks._ID, TaskContract.Tasks.SYNC1, TaskContract.Tasks.SYNC2), "${TaskContract.Tasks.ACCOUNT_TYPE}=? AND ${TaskContract.Tasks.ACCOUNT_NAME}=?", arrayOf(account.type, account.name), null)!!.use { cursor -> Loading @@ -573,7 +574,7 @@ class AccountSettings( values.putNull(TaskContract.Tasks.SYNC2) Logger.log.log(Level.FINER, "Updating task $id", values) provider.client.update( TaskProvider.syncAdapterUri(ContentUris.withAppendedId(provider.tasksUri(), id), account), ContentUris.withAppendedId(provider.tasksUri(), id).asSyncAdapter(account), values, null, null) } } Loading