diff --git a/lib/src/androidTest/kotlin/at/bitfire/ical4android/JtxICalObjectTest.kt b/lib/src/androidTest/kotlin/at/bitfire/ical4android/JtxICalObjectTest.kt index 4dcb3122..885c7ea1 100644 --- a/lib/src/androidTest/kotlin/at/bitfire/ical4android/JtxICalObjectTest.kt +++ b/lib/src/androidTest/kotlin/at/bitfire/ical4android/JtxICalObjectTest.kt @@ -844,6 +844,12 @@ class JtxICalObjectTest { if(inProp.name == "DTSTAMP" || exceptions?.contains(inProp.name) == true) return@forEach val outProp = iCalOut.components[i].properties.getProperty(inProp.name) + + if(inProp.name == "PRIORITY" && inProp.value == "0") { + assertNull(outProp) + return@forEach + } + assertEquals(inProp, outProp) } } diff --git a/lib/src/main/kotlin/at/bitfire/ical4android/JtxICalObject.kt b/lib/src/main/kotlin/at/bitfire/ical4android/JtxICalObject.kt index 545aace4..49107ce9 100644 --- a/lib/src/main/kotlin/at/bitfire/ical4android/JtxICalObject.kt +++ b/lib/src/main/kotlin/at/bitfire/ical4android/JtxICalObject.kt @@ -36,6 +36,7 @@ import net.fortuna.ical4j.model.TextList import net.fortuna.ical4j.model.TimeZoneRegistryFactory import net.fortuna.ical4j.model.component.VAlarm import net.fortuna.ical4j.model.component.VJournal +import net.fortuna.ical4j.model.component.VTimeZone import net.fortuna.ical4j.model.component.VToDo import net.fortuna.ical4j.model.parameter.AltRep import net.fortuna.ical4j.model.parameter.Cn @@ -649,6 +650,9 @@ open class JtxICalObject( ical.components += calComponent addProperties(calComponent.properties) + for (vTimeZone in getVTimeZones(calComponent.properties)) + ical.components += vTimeZone + alarms.forEach { alarm -> val vAlarm = VAlarm() @@ -825,7 +829,12 @@ open class JtxICalObject( attendees.forEach { attendee -> val attendeeProp = net.fortuna.ical4j.model.property.Attendee().apply { - this.calAddress = URI(attendee.caladdress) + this.calAddress = try { + URI(attendee.caladdress) + } catch (_: Exception) { + logger.warning("Ignoring invalid attendee URI: ${attendee.caladdress}") + return@forEach + } attendee.cn?.let { this.parameters.add(Cn(it)) @@ -1082,17 +1091,9 @@ open class JtxICalObject( props += dur } - - /* -// remember used time zones -val usedTimeZones = HashSet() -duration?.let(props::add) -*/ - - if(component == JtxContract.JtxICalObject.Component.VTODO.name) { completed?.let { - //Completed is defines as always DateTime! And is always UTC! But the X_PROP_COMPLETEDTIMEZONE can still define a timezone + //Completed is defined as always DateTime! And is always UTC! But the X_PROP_COMPLETEDTIMEZONE can still define a timezone props += Completed(DateTime(it)) // only take completedTimezone if there was the completed time set @@ -1110,9 +1111,6 @@ duration?.let(props::add) priority?.let { props += Priority(it) } - else { - props += Priority(Priority.UNDEFINED.level) - } due?.let { when { @@ -1133,19 +1131,25 @@ duration?.let(props::add) } } } + } - /* - - // determine earliest referenced date - val earliest = arrayOf( - dtStart?.date, - due?.date, - completedAt?.date - ).filterNotNull().min() - // add VTIMEZONE components - for (tz in usedTimeZones) - ical.components += ICalendar.minifyVTimeZone(tz.vTimeZone, earliest) -*/ + + /** + * This function maps the date-time properties DtStart, Due and Completed to VTimeZone + */ + private fun getVTimeZones(props: PropertyList): List { + + val dates = listOfNotNull( + props.getProperty(Property.DTSTART), + props.getProperty(Property.DUE), + props.getProperty(Property.COMPLETED) + ).filter { it.timeZone != null } + + val earliest = dates.mapNotNull { it.date }.minOrNull() + + return dates.mapNotNull { date -> + date.timeZone?.vTimeZone?.let { ICalendar.minifyVTimeZone(it, earliest) } + } }