From bd3c92aa864157f63e8458e848b0a641fadd3617 Mon Sep 17 00:00:00 2001 From: Guido Schmit Date: Mon, 6 Jul 2026 20:49:29 +0200 Subject: [PATCH] feat(sharing): let share recipients recolour a shared calendar The colour dot for a shared (non-owned) local calendar was disabled, and the colour write hit the owner-only PUT /calendars/{id} (404 for recipients). Now the dot is always editable and colour changes go through the dedicated PUT /calendars/{id}/color endpoint, which stores a recipient's own per-user colour server-side (synced across devices) without granting write or rename. Renaming stays owner-only (no rename UI for shared calendars). Co-Authored-By: Claude Opus 4.8 --- .../com/scarriffle/calendarr/data/CalendarRepository.kt | 6 ++++-- .../com/scarriffle/calendarr/data/remote/CalendarrApi.kt | 5 +++++ .../com/scarriffle/calendarr/ui/accounts/AccountsScreen.kt | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/scarriffle/calendarr/data/CalendarRepository.kt b/app/src/main/java/com/scarriffle/calendarr/data/CalendarRepository.kt index fcaa574..59d6a8f 100644 --- a/app/src/main/java/com/scarriffle/calendarr/data/CalendarRepository.kt +++ b/app/src/main/java/com/scarriffle/calendarr/data/CalendarRepository.kt @@ -222,9 +222,11 @@ class CalendarRepository @Inject constructor( suspend fun deleteHomeAssistantAccount(id: Int) = guarded { api.deleteHomeAssistantAccount(id).ensureSuccess() } - /** Change a local calendar's colour. */ + /** Change a local calendar's colour. Uses the colour-only endpoint so share + * recipients can recolour their view (own per-user colour) without needing + * write access or being able to rename the calendar. */ suspend fun updateLocalCalendarColor(id: Int, color: String) = guarded { - api.updateLocalCalendar(id, jsonBody("color" to color)).ensureSuccess() + api.setLocalCalendarColor(id, jsonBody("color" to color)).ensureSuccess() } /** Change an iCal subscription's colour. */ diff --git a/app/src/main/java/com/scarriffle/calendarr/data/remote/CalendarrApi.kt b/app/src/main/java/com/scarriffle/calendarr/data/remote/CalendarrApi.kt index d246d47..c39c00d 100644 --- a/app/src/main/java/com/scarriffle/calendarr/data/remote/CalendarrApi.kt +++ b/app/src/main/java/com/scarriffle/calendarr/data/remote/CalendarrApi.kt @@ -155,6 +155,11 @@ interface CalendarrApi { @PUT("api/local/calendars/{id}") suspend fun updateLocalCalendar(@Path("id") id: Int, @Body body: RequestBody): Response + // Colour-only update that works for owners AND share recipients (recipients + // get their own per-user colour; owners change the calendar's colour). + @PUT("api/local/calendars/{id}/color") + suspend fun setLocalCalendarColor(@Path("id") id: Int, @Body body: RequestBody): Response + @DELETE("api/local/calendars/{id}") suspend fun deleteLocalCalendar(@Path("id") id: Int): Response diff --git a/app/src/main/java/com/scarriffle/calendarr/ui/accounts/AccountsScreen.kt b/app/src/main/java/com/scarriffle/calendarr/ui/accounts/AccountsScreen.kt index bb0b1e6..554ddbb 100644 --- a/app/src/main/java/com/scarriffle/calendarr/ui/accounts/AccountsScreen.kt +++ b/app/src/main/java/com/scarriffle/calendarr/ui/accounts/AccountsScreen.kt @@ -380,7 +380,9 @@ private fun LocalCalendarRow( ) { var menu by remember { mutableStateOf(false) } Row(Modifier.fillMaxWidth().padding(vertical = 6.dp), verticalAlignment = Alignment.CenterVertically) { - ColorDot(cal.color, editable = cal.owned, onClick = onColor) + // Recipients of a shared calendar may recolour it (their own per-user + // colour); only renaming/other management stays owner-only. + ColorDot(cal.color, editable = true, onClick = onColor) Column(Modifier.weight(1f).padding(start = 12.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { Text(cal.name, style = MaterialTheme.typography.bodyLarge)