Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 6c2cb6dd authored by Ricki Hirner's avatar Ricki Hirner
Browse files

Create fake main event for exceptions of recurring events where the main event is missing

* fixes bitfireAT/icsx5#27
* fixes bitfireAT/davx5#58
parent 9bca5fac
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -573,10 +573,10 @@ abstract class AndroidEvent(
               (it checks for RRULE and aborts if no RRULE is found).
               So I have chosen the method of inserting the exception event manually.

               It's also noteworthy that the link between the main event and the exception is not
               between ID and ORIGINAL_ID (as one could assume), but between _SYNC_ID and ORIGINAL_SYNC_ID.
               So, if you don't set _SYNC_ID in the master event and ORIGINAL_SYNC_ID in the exception,
               the exception will appear additionally (and not *instead* of the instance).
               It's also noteworthy that linking the main event to the exception only works using _SYNC_ID
               and ORIGINAL_SYNC_ID (and not ID and ORIGINAL_ID, as one could assume). So, if you don't
               set _SYNC_ID in the main event and ORIGINAL_SYNC_ID in the exception, the exception will
               appear additionally (and not *instead* of the instance).
             */

            val recurrenceId = exception.recurrenceId
+18 −3
Original line number Diff line number Diff line
@@ -94,7 +94,6 @@ class Event: ICalendar() {
            Ical4Android.log.fine("Assigning exceptions to main events")
            val mainEvents = mutableMapOf<String /* UID */,VEvent>()
            val exceptions = mutableMapOf<String /* UID */,MutableMap<String /* RECURRENCE-ID */,VEvent>>()

            for (vEvent in vEvents) {
                val uid = vEvent.uid.value
                val sequence = vEvent.sequence?.sequenceNo ?: 0
@@ -124,11 +123,17 @@ class Event: ICalendar() {
                }
            }

            /* There may be UIDs which have only RECURRENCE-ID entries and not a main entry (for instance, a recurring
            event with an exception where the current user has been invited only to this exception. In this case,
            the UID will not appear in mainEvents but only in exceptions. */

            val events = mutableListOf<Event>()
            for ((uid, vEvent) in mainEvents) {
                val event = fromVEvent(vEvent)
                exceptions[uid]?.let { eventExceptions ->
                    event.exceptions.addAll(eventExceptions.map { (_,it) -> fromVEvent(it) })

                // assign exceptions to main event and then remove them from exceptions array
                exceptions.remove(uid)?.let { eventExceptions ->
                    event.exceptions.addAll(eventExceptions.values.map { fromVEvent(it) })
                }

                // make sure that exceptions have at least a SUMMARY
@@ -137,6 +142,16 @@ class Event: ICalendar() {
                events += event
            }

            for ((uid, onlyExceptions) in exceptions) {
                Ical4Android.log.info("UID $uid doesn't have a main event but only exceptions: $onlyExceptions")

                // create a fake main event from the first exception
                val fakeEvent = fromVEvent(onlyExceptions.values.first())
                fakeEvent.exceptions.addAll(onlyExceptions.values.map { fromVEvent(it) })

                events += fakeEvent
            }

            return events
        }

+15 −0
Original line number Diff line number Diff line
@@ -157,6 +157,21 @@ class EventTest {
        assertEquals("Another summary for the third day", exception.summary)
    }

    @Test
    fun testRecurringOnlyException() {
        val event = parseCalendar("recurring-only-exception.ics").first()

        assertEquals(1, event.exceptions.size)
        val exception = event.exceptions.first
        assertEquals("20150503T010203Z", exception.recurrenceId!!.value)
        assertEquals("This is an exception", exception.summary)

        // fake main event
        assertEquals(event.summary, exception.summary)
        assertEquals(event.dtStart, exception.dtStart)
        assertEquals(event.dtEnd, exception.dtEnd)
    }

    @Test
    fun testStartEndTimes() {
        // event with start+end date-time
+11 −0
Original line number Diff line number Diff line
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:fcb42e4d-bc6e-4499-97f0-6616a02da7bc
RECURRENCE-ID:20150503T010203Z
DTSTART:20150503T010203Z
DTEND:20150504T010203Z
SUMMARY:This is an exception
DESCRIPTION:The main event is not visible for us.
END:VEVENT
END:VCALENDAR