fix: match sync errors to calendars by id, not name suffix

The server now includes calendar_id in per-calendar sync-error entries.
Match CalendarFilterSheet's warning icon on (source, calendarId) like
calendarKey() already does everywhere else, instead of a fragile
name-suffix comparison that could false-positive across accounts whose
calendar names happen to overlap.
This commit is contained in:
Guido Schmit
2026-07-02 19:00:49 +02:00
parent a3568fb6f3
commit 382cb717a4
2 changed files with 8 additions and 5 deletions

View File

@@ -35,8 +35,9 @@ data class LoginResult(val token: String, val username: String, val isAdmin: Boo
data class TotpSetup(val secret: String, val qrUrl: String)
/** A single calendar's sync failure, surfaced alongside a (still-successful) events fetch. */
data class SyncError(val source: String, val name: String, val message: String)
/** A single calendar's sync failure, surfaced alongside a (still-successful) events fetch.
* [calendarId] is null for account-wide failures (no single calendar is at fault). */
data class SyncError(val source: String, val name: String, val calendarId: Int?, val message: String)
/** Result of [CalendarRepository.fetchEvents]: the merged events plus any per-calendar sync failures. */
data class EventsResult(val events: List<CalEvent>, val errors: List<SyncError>)
@@ -322,6 +323,7 @@ class CalendarRepository @Inject constructor(
add(SyncError(
source = obj.optString("source"),
name = obj.optString("name"),
calendarId = if (obj.has("calendar_id")) obj.optInt("calendar_id") else null,
message = obj.optString("message"),
))
}

View File

@@ -84,10 +84,11 @@ fun CalendarFilterSheet(
}
rows.forEach { entry ->
val visible = entry.key !in hiddenSet
// Best-effort match: server error `name` is "<account> <calendar name>",
// so a suffix match on this calendar's own name is reliable enough.
// entry.key is "source:id" (see calendarKey()); match sync errors on the
// same (source, calendarId) pair the server already attaches to events.
val entryId = entry.key.substringAfter(":")
val hasSyncError = !groupMode && state.syncErrors.any { err ->
err.source == entry.source && err.name.endsWith(entry.name)
err.source == entry.source && err.calendarId?.toString() == entryId
}
Row(
Modifier.fillMaxWidth().padding(vertical = 8.dp),