mirror of
https://github.com/bitfireAT/davx5-ose.git
synced 2025-12-23 23:17:50 -05:00
Compare commits
2 Commits
v4.5.6-ose
...
synctools-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a89483d8c7 | ||
|
|
60eba44541 |
@@ -32,7 +32,7 @@ class LocalTestResource: LocalResource<Any> {
|
||||
this.flags = flags
|
||||
}
|
||||
|
||||
override fun update(data: Any, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) = throw NotImplementedError()
|
||||
override fun updateFromRemote(data: Any, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) = throw NotImplementedError()
|
||||
override fun deleteLocal() = throw NotImplementedError()
|
||||
override fun resetDeleted() = throw NotImplementedError()
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ import android.provider.CalendarContract.Events
|
||||
import androidx.core.content.contentValuesOf
|
||||
import at.bitfire.ical4android.Event
|
||||
import at.bitfire.ical4android.util.MiscUtils.asSyncAdapter
|
||||
import at.bitfire.synctools.mapping.calendar.LegacyAndroidEventBuilder2
|
||||
import at.bitfire.synctools.icalendar.AssociatedEvents
|
||||
import at.bitfire.synctools.mapping.calendar.AndroidEventBuilder
|
||||
import at.bitfire.synctools.storage.BatchOperation
|
||||
import at.bitfire.synctools.storage.calendar.AndroidCalendar
|
||||
import at.bitfire.synctools.storage.calendar.AndroidEvent2
|
||||
@@ -63,16 +64,17 @@ class LocalCalendar @AssistedInject constructor(
|
||||
private val recurringCalendar = AndroidRecurringCalendar(androidCalendar)
|
||||
|
||||
|
||||
fun add(event: Event, fileName: String, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
val mapped = LegacyAndroidEventBuilder2(
|
||||
calendar = androidCalendar,
|
||||
event = event,
|
||||
id = null,
|
||||
fun addFromRemote(associatedEvents: AssociatedEvents, legacyEvent: Event, fileName: String, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
val mapped = AndroidEventBuilder(
|
||||
syncId = fileName,
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = flags
|
||||
).build()
|
||||
flags = flags,
|
||||
associatedEvents = associatedEvents,
|
||||
androidCalendar = androidCalendar,
|
||||
event = legacyEvent,
|
||||
id = null
|
||||
).build() ?: TODO("Handle invalid event")
|
||||
recurringCalendar.addEventAndExceptions(mapped)
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class LocalContact: AndroidContact, LocalAddress {
|
||||
addressBook.provider!!.update(rawContactSyncURI(), values, null, null)
|
||||
}
|
||||
|
||||
override fun update(data: Contact, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
override fun updateFromRemote(data: Contact, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
this.fileName = fileName
|
||||
this.eTag = eTag
|
||||
this.flags = flags
|
||||
|
||||
@@ -8,7 +8,8 @@ import android.provider.CalendarContract.Events
|
||||
import androidx.core.content.contentValuesOf
|
||||
import at.bitfire.ical4android.Event
|
||||
import at.bitfire.ical4android.LegacyAndroidCalendar
|
||||
import at.bitfire.synctools.mapping.calendar.LegacyAndroidEventBuilder2
|
||||
import at.bitfire.synctools.icalendar.AssociatedEvents
|
||||
import at.bitfire.synctools.mapping.calendar.AndroidEventBuilder
|
||||
import at.bitfire.synctools.storage.LocalStorageException
|
||||
import at.bitfire.synctools.storage.calendar.AndroidEvent2
|
||||
import at.bitfire.synctools.storage.calendar.AndroidRecurringCalendar
|
||||
@@ -18,7 +19,7 @@ import java.util.UUID
|
||||
class LocalEvent(
|
||||
val recurringCalendar: AndroidRecurringCalendar,
|
||||
val androidEvent: AndroidEvent2
|
||||
) : LocalResource<Event> {
|
||||
) : LocalResource<AssociatedEvents> {
|
||||
|
||||
override val id: Long
|
||||
get() = androidEvent.id
|
||||
@@ -36,17 +37,21 @@ class LocalEvent(
|
||||
get() = androidEvent.flags
|
||||
|
||||
|
||||
override fun update(data: Event, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
val eventAndExceptions = LegacyAndroidEventBuilder2(
|
||||
calendar = androidEvent.calendar,
|
||||
event = data,
|
||||
id = id,
|
||||
syncId = fileName,
|
||||
override fun updateFromRemote(data: AssociatedEvents, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
val eventAndExceptions = AndroidEventBuilder(
|
||||
associatedEvents = data,
|
||||
calendarId = androidEvent.calendar.id,
|
||||
syncId = fileName ?: TODO(),
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = flags
|
||||
).build()
|
||||
recurringCalendar.updateEventAndExceptions(id, eventAndExceptions)
|
||||
|
||||
if (eventAndExceptions != null)
|
||||
recurringCalendar.updateEventAndExceptions(id, eventAndExceptions)
|
||||
else {
|
||||
// TODO handle invalid event
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ class LocalGroup: AndroidGroup, LocalAddress {
|
||||
batch.commit()
|
||||
}
|
||||
|
||||
override fun update(data: Contact, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
override fun updateFromRemote(data: Contact, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
this.fileName = fileName
|
||||
this.eTag = eTag
|
||||
this.scheduleTag = scheduleTag
|
||||
|
||||
@@ -50,7 +50,7 @@ class LocalJtxICalObject(
|
||||
|
||||
}
|
||||
|
||||
override fun update(data: JtxICalObject, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
override fun updateFromRemote(data: JtxICalObject, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
this.fileName = fileName
|
||||
this.eTag = eTag
|
||||
this.scheduleTag = scheduleTag
|
||||
|
||||
@@ -81,7 +81,7 @@ interface LocalResource<in TData: Any> {
|
||||
*
|
||||
* @return content URI of the updated row (e.g. event URI)
|
||||
*/
|
||||
fun update(data: TData, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int)
|
||||
fun updateFromRemote(data: TData, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int)
|
||||
|
||||
/**
|
||||
* Deletes the data object from the content provider.
|
||||
|
||||
@@ -94,7 +94,7 @@ class LocalTask: DmfsTask, LocalResource<Task> {
|
||||
this.eTag = eTag
|
||||
}
|
||||
|
||||
override fun update(data: Task, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
override fun updateFromRemote(data: Task, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
|
||||
this.fileName = fileName
|
||||
this.eTag = eTag
|
||||
this.scheduleTag = scheduleTag
|
||||
|
||||
@@ -28,26 +28,23 @@ import at.bitfire.davdroid.resource.LocalResource
|
||||
import at.bitfire.davdroid.resource.SyncState
|
||||
import at.bitfire.davdroid.settings.AccountSettings
|
||||
import at.bitfire.davdroid.util.DavUtils.lastSegment
|
||||
import at.bitfire.ical4android.Event
|
||||
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.CalendarUidSplitter
|
||||
import at.bitfire.synctools.icalendar.ICalendarParser
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import net.fortuna.ical4j.model.Component
|
||||
import net.fortuna.ical4j.model.component.VAlarm
|
||||
import net.fortuna.ical4j.model.property.Action
|
||||
import net.fortuna.ical4j.model.component.VEvent
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.Reader
|
||||
import java.io.StringReader
|
||||
import java.io.StringWriter
|
||||
import java.time.Duration
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.Optional
|
||||
import java.util.logging.Level
|
||||
@@ -262,55 +259,63 @@ class CalendarSyncManager @AssistedInject constructor(
|
||||
// helpers
|
||||
|
||||
private fun processVEvent(fileName: String, eTag: String, scheduleTag: String?, reader: Reader) {
|
||||
val events: List<Event>
|
||||
try {
|
||||
events = EventReader().readEvents(reader)
|
||||
val vEvent = try {
|
||||
val iCalendar = ICalendarParser().parse(reader)
|
||||
val vEvents = CalendarUidSplitter<VEvent>().associateByUid(iCalendar, Component.VEVENT)
|
||||
|
||||
if (vEvents.size > 1)
|
||||
logger.warning("Received iCalendar with more than one UID; ignoring all but first one")
|
||||
|
||||
vEvents.values.firstOrNull()
|
||||
} catch (e: InvalidRemoteResourceException) {
|
||||
logger.log(Level.SEVERE, "Received invalid iCalendar, ignoring", e)
|
||||
notifyInvalidResource(e, fileName)
|
||||
return
|
||||
}
|
||||
|
||||
if (events.size == 1) {
|
||||
val event = events.first()
|
||||
if (vEvent == null) {
|
||||
logger.warning("Ignoring iCalendar without VEVENTs ($fileName)")
|
||||
return
|
||||
}
|
||||
|
||||
// set default reminder for non-full-day events, if requested
|
||||
val defaultAlarmMinBefore = accountSettings.getDefaultAlarm()
|
||||
if (defaultAlarmMinBefore != null && DateUtils.isDateTime(event.dtStart) && event.alarms.isEmpty()) {
|
||||
val alarm = VAlarm(Duration.ofMinutes(-defaultAlarmMinBefore.toLong())).apply {
|
||||
// Sets METHOD_ALERT instead of METHOD_DEFAULT in the calendar provider.
|
||||
// Needed for calendars to actually show a notification.
|
||||
properties += Action.DISPLAY
|
||||
}
|
||||
logger.log(Level.FINE, "${event.uid}: Adding default alarm", alarm)
|
||||
event.alarms += alarm
|
||||
}
|
||||
// TODO we need both the new associated event and the legacy event here,
|
||||
// then pass both to addupdateFromRemote / updateFromRemote.
|
||||
|
||||
// update local event, if it exists
|
||||
val local = localCollection.findByName(fileName)
|
||||
SyncException.wrapWithLocalResource(local) {
|
||||
if (local != null) {
|
||||
logger.log(Level.INFO, "Updating $fileName in local calendar", event)
|
||||
local.update(
|
||||
data = event,
|
||||
fileName = fileName,
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = LocalResource.FLAG_REMOTELY_PRESENT
|
||||
)
|
||||
} else {
|
||||
logger.log(Level.INFO, "Adding $fileName to local calendar", event)
|
||||
localCollection.add(
|
||||
event = event,
|
||||
fileName = fileName,
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = LocalResource.FLAG_REMOTELY_PRESENT
|
||||
)
|
||||
}
|
||||
// TODO add default reminder
|
||||
/* set default reminder for non-full-day events, if requested
|
||||
val defaultAlarmMinBefore = accountSettings.getDefaultAlarm()
|
||||
if (defaultAlarmMinBefore != null && DateUtils.isDateTime(event.dtStart) && event.alarms.isEmpty()) {
|
||||
val alarm = VAlarm(Duration.ofMinutes(-defaultAlarmMinBefore.toLong())).apply {
|
||||
// Sets METHOD_ALERT instead of METHOD_DEFAULT in the calendar provider.
|
||||
// Needed for calendars to actually show a notification.
|
||||
properties += Action.DISPLAY
|
||||
}
|
||||
} else
|
||||
logger.info("Received VCALENDAR with not exactly one VEVENT with UID and without RECURRENCE-ID; ignoring $fileName")
|
||||
logger.log(Level.FINE, "${event.uid}: Adding default alarm", alarm)
|
||||
event.alarms += alarm
|
||||
} */
|
||||
|
||||
val localEvent = localCollection.findByName(fileName)
|
||||
SyncException.wrapWithLocalResource(localEvent) {
|
||||
if (localEvent != null) {
|
||||
logger.log(Level.INFO, "Updating $fileName in local calendar", vEvent)
|
||||
localEvent.updateFromRemote(
|
||||
data = vEvent,
|
||||
fileName = fileName,
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = LocalResource.FLAG_REMOTELY_PRESENT
|
||||
)
|
||||
} else {
|
||||
logger.log(Level.INFO, "Adding $fileName to local calendar", vEvent)
|
||||
localCollection.addFromRemote(
|
||||
associatedEvents = vEvent,
|
||||
fileName = fileName,
|
||||
eTag = eTag,
|
||||
scheduleTag = scheduleTag,
|
||||
flags = LocalResource.FLAG_REMOTELY_PRESENT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun notifyInvalidResourceTitle(): String =
|
||||
|
||||
@@ -421,7 +421,7 @@ class ContactsSyncManager @AssistedInject constructor(
|
||||
if ((existing is LocalGroup && newData.group) || (existing is LocalContact && !newData.group)) {
|
||||
// update contact / group
|
||||
|
||||
existing.update(
|
||||
existing.updateFromRemote(
|
||||
data = newData,
|
||||
fileName = fileName,
|
||||
eTag = eTag,
|
||||
|
||||
@@ -20,7 +20,7 @@ androidx-test-junit = "1.3.0"
|
||||
androidx-work = "2.10.3"
|
||||
bitfire-cert4android = "41009d48ed"
|
||||
bitfire-dav4jvm = "cb6065b262"
|
||||
bitfire-synctools = "54557601b8"
|
||||
bitfire-synctools = "4d847edf27"
|
||||
compose-accompanist = "0.37.3"
|
||||
compose-bom = "2025.07.00"
|
||||
dnsjava = "3.6.3"
|
||||
|
||||
Reference in New Issue
Block a user