From 823622d43a5bc4c6fdd6a4aedccff09e29f6ee8b Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Thu, 25 Sep 2025 16:28:11 +0200 Subject: [PATCH] [WIP] Generate VEvent directly --- .../bitfire/davdroid/resource/LocalEvent.kt | 64 +++++++++---------- .../davdroid/sync/CalendarSyncManager.kt | 6 +- gradle/libs.versions.toml | 2 +- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalEvent.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalEvent.kt index 327747805..75a286ef5 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalEvent.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalEvent.kt @@ -7,8 +7,9 @@ package at.bitfire.davdroid.resource import android.provider.CalendarContract.Events import androidx.core.content.contentValuesOf import at.bitfire.ical4android.Event -import at.bitfire.ical4android.LegacyAndroidCalendar +import at.bitfire.synctools.icalendar.AssociatedEvents import at.bitfire.synctools.mapping.calendar.LegacyAndroidEventBuilder2 +import at.bitfire.synctools.mapping.calendar.LegacyAndroidEventProcessor import at.bitfire.synctools.storage.LocalStorageException import at.bitfire.synctools.storage.calendar.AndroidEvent2 import at.bitfire.synctools.storage.calendar.AndroidRecurringCalendar @@ -48,53 +49,32 @@ class LocalEvent( recurringCalendar.updateEventAndExceptions(id, eventAndExceptions) } - - private var _event: Event? = null - /** - * Retrieves the event from the content provider and converts it to a legacy data object. - * - * Caches the result: the content provider is only queried at the first call and then - * this method always returns the same object. - * - * @throws LocalStorageException if there is no local event with the ID from [androidEvent] - */ - @Synchronized - fun getCachedEvent(): Event { - _event?.let { return it } - - val legacyCalendar = LegacyAndroidCalendar(androidEvent.calendar) - val event = legacyCalendar.getEvent(androidEvent.id) - ?: throw LocalStorageException("Event ${androidEvent.id} not found") - - _event = event - return event - } - /** * Generates the [Event] that should actually be uploaded: * - * 1. Takes the [getCachedEvent]. + * 1. Takes the event from the calendar provider. * 2. Calculates the new SEQUENCE. * - * _Note: This method currently modifies the object returned by [getCachedEvent], but - * this may change in the future._ - * * @return data object that should be used for uploading + * + * @throws LocalStorageException if there is no local event with the given [id] */ - fun eventToUpload(): Event { - val event = getCachedEvent() + fun eventToUpload(): AssociatedEvents { + val eventAndExceptions = recurringCalendar.getById(id) ?: throw LocalStorageException("Event $id not found") - val nonGroupScheduled = event.attendees.isEmpty() - val weAreOrganizer = event.isOrganizer == true + // map local event to iCalendar + val processor = LegacyAndroidEventProcessor(recurringCalendar.calendar.account.name) + val associatedEvents = processor.process(eventAndExceptions) // Increase sequence (event.sequence null/non-null behavior is defined by the Event, see KDoc of event.sequence): // - If it's null, the event has just been created in the database, so we can start with SEQUENCE:0 (default). // - If it's non-null, the event already exists on the server, so increase by one. - val sequence = event.sequence + /*val sequence = event.sequence if (sequence != null && (nonGroupScheduled || weAreOrganizer)) - event.sequence = sequence + 1 + event.sequence = sequence + 1*/ + // TODO - return event + return associatedEvents } /** @@ -117,7 +97,10 @@ class LocalEvent( */ override fun prepareForUpload(): String { // make sure that UID is set - val uid: String = getCachedEvent().uid ?: run { + + // TODO iCalendar UID + + /*val uid: String = getCachedEvent().uid ?: run { // generate new UID val newUid = UUID.randomUUID().toString() @@ -128,6 +111,17 @@ class LocalEvent( // update in cached event data object getCachedEvent().uid = newUid + newUid + }*/ + + val event = recurringCalendar.calendar.getEventRow(id) ?: throw LocalStorageException("Event $id not found") + val uid = event.getAsString(Events.UID_2445) ?: run { + val newUid = UUID.randomUUID().toString() + + // persist to calendar provider + val values = contentValuesOf(Events.UID_2445 to newUid) + androidEvent.update(values) + newUid } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/sync/CalendarSyncManager.kt b/app/src/main/kotlin/at/bitfire/davdroid/sync/CalendarSyncManager.kt index 118ab7186..3ad97f232 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/sync/CalendarSyncManager.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/sync/CalendarSyncManager.kt @@ -33,6 +33,7 @@ import at.bitfire.ical4android.EventReader import at.bitfire.ical4android.EventWriter import at.bitfire.ical4android.util.DateUtils import at.bitfire.synctools.exception.InvalidRemoteResourceException +import at.bitfire.synctools.icalendar.ICalendarWriter import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -182,7 +183,8 @@ class CalendarSyncManager @AssistedInject constructor( super.onSuccessfulUpload(local, newFileName, eTag, scheduleTag) // update local SEQUENCE to new value after successful upload - local.updateSequence(local.getCachedEvent().sequence) + //local.updateSequence(local.getCachedEvent().sequence) + // TODO } override fun generateUpload(resource: LocalEvent): RequestBody = @@ -192,7 +194,7 @@ class CalendarSyncManager @AssistedInject constructor( // write iCalendar to string and convert to request body val iCalWriter = StringWriter() - EventWriter(Constants.iCalProdId).write(event, iCalWriter) + ICalendarWriter(Constants.iCalProdId).write(event, iCalWriter) iCalWriter.toString().toRequestBody(DavCalendar.MIME_ICALENDAR_UTF8) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3e82271a7..108b45cbf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ androidx-test-junit = "1.3.0" androidx-work = "2.10.4" bitfire-cert4android = "41009d48ed" bitfire-dav4jvm = "f11523619b" -bitfire-synctools = "095f96005b" +bitfire-synctools = "9ba6966ab0" compose-accompanist = "0.37.3" compose-bom = "2025.09.00" dnsjava = "3.6.3"