From 59d272814d6ce9daaabd69e870b280661e92c631 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 30 Oct 2024 13:44:33 +0100 Subject: [PATCH] AndroidEvent: update without event color correctly resets color (#180) --- .../bitfire/ical4android/AndroidEventTest.kt | 36 +++++++++++++++++-- .../at/bitfire/ical4android/AndroidEvent.kt | 36 ++++++++++++------- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/lib/src/androidTest/kotlin/at/bitfire/ical4android/AndroidEventTest.kt b/lib/src/androidTest/kotlin/at/bitfire/ical4android/AndroidEventTest.kt index 4883b0bb..6a293181 100644 --- a/lib/src/androidTest/kotlin/at/bitfire/ical4android/AndroidEventTest.kt +++ b/lib/src/androidTest/kotlin/at/bitfire/ical4android/AndroidEventTest.kt @@ -581,7 +581,6 @@ class AndroidEventTest { @Test fun testBuildEvent_Color_WhenNotAvailable() { - AndroidCalendar.removeColors(provider, testAccount) buildEvent(true) { color = Css3Color.darkseagreen }.let { result -> @@ -1700,7 +1699,7 @@ class AndroidEventTest { } @Test - fun testPopulateEvent_Color() { + fun testPopulateEvent_Color_FromIndex() { AndroidCalendar.insertColors(provider, testAccount) populateEvent(true) { put(Events.EVENT_COLOR_KEY, Css3Color.silver.name) @@ -1709,6 +1708,15 @@ class AndroidEventTest { } } + @Test + fun testPopulateEvent_Color_FromValue() { + populateEvent(true) { + put(Events.EVENT_COLOR, Css3Color.silver.argb) + }.let { result -> + assertEquals(Css3Color.silver, result.color) + } + } + @Test fun testPopulateEvent_Status_Confirmed() { populateEvent(true) { @@ -2357,6 +2365,30 @@ class AndroidEventTest { } } + @Test + fun testUpdateEvent_ResetColor() { + // add event with color + val event = Event().apply { + uid = "sample1@testAddEvent" + dtStart = DtStart(DateTime()) + color = Css3Color.silver + } + val uri = TestEvent(calendar, event).add() + val id = ContentUris.parseId(uri) + + // verify that it has color + val beforeUpdate = calendar.findById(id) + assertNotNull(beforeUpdate.event?.color) + + // update: reset color + event.color = null + beforeUpdate.update(event) + + // verify that it doesn't have color anymore + val afterUpdate = calendar.findById(id) + assertNull(afterUpdate.event!!.color) + } + @Test fun testUpdateEvent_UpdateStatusFromNull() { val event = Event() diff --git a/lib/src/main/kotlin/at/bitfire/ical4android/AndroidEvent.kt b/lib/src/main/kotlin/at/bitfire/ical4android/AndroidEvent.kt index 9905cc13..263846e2 100644 --- a/lib/src/main/kotlin/at/bitfire/ical4android/AndroidEvent.kt +++ b/lib/src/main/kotlin/at/bitfire/ical4android/AndroidEvent.kt @@ -336,13 +336,19 @@ abstract class AndroidEvent( event.location = row.getAsString(Events.EVENT_LOCATION) event.description = row.getAsString(Events.DESCRIPTION) - row.getAsString(Events.EVENT_COLOR_KEY)?.let { name -> - try { - event.color = Css3Color.valueOf(name) - } catch (e: IllegalArgumentException) { - logger.warning("Ignoring unknown color $name from Calendar Provider") + // color can be specified as RGB value and/or as index key (CSS3 color of AndroidCalendar) + event.color = + row.getAsString(Events.EVENT_COLOR_KEY)?.let { name -> // try color key first + try { + Css3Color.valueOf(name) + } catch (_: IllegalArgumentException) { + logger.warning("Ignoring unknown color name \"$name\"") + null + } + } ?: + row.getAsInteger(Events.EVENT_COLOR)?.let { color -> // otherwise, try to find the color name from the value + Css3Color.entries.firstOrNull { it.argb == color } } - } // status when (row.getAsInteger(Events.STATUS)) { @@ -928,18 +934,22 @@ abstract class AndroidEvent( builder.withValue(Events.TITLE, event.summary) builder.withValue(Events.EVENT_LOCATION, event.location) builder.withValue(Events.DESCRIPTION, event.description) - builder.withValue(Events.EVENT_COLOR_KEY, event.color?.let { color -> - val colorName = color.name + + val color = event.color + if (color != null) { // set event color (if it's available for this account) calendar.provider.query(Colors.CONTENT_URI.asSyncAdapter(calendar.account), arrayOf(Colors.COLOR_KEY), - "${Colors.COLOR_KEY}=? AND ${Colors.COLOR_TYPE}=${Colors.TYPE_EVENT}", arrayOf(colorName), null)?.use { cursor -> + "${Colors.COLOR_KEY}=? AND ${Colors.COLOR_TYPE}=${Colors.TYPE_EVENT}", arrayOf(color.name), null)?.use { cursor -> if (cursor.moveToNext()) - return@let colorName + builder.withValue(Events.EVENT_COLOR_KEY, color.name) else - logger.fine("Ignoring event color: $colorName (not available for this account)") + logger.fine("Ignoring event color \"${color.name}\" (not available for this account)") } - null - }) + } else { + // reset color index and value + builder .withValue(Events.EVENT_COLOR_KEY, null) + .withValue(Events.EVENT_COLOR, null) + } // scheduling val groupScheduled = event.attendees.isNotEmpty()