Add calendar local-only name override - #2143
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for a per-device (local-only) calendar display name override that is shown in the app and propagated to Android’s CalendarProvider, without changing the server-side DAV collection name.
Changes:
- Added
localDisplayNameto theCollectionRoom entity and preserved it across collection refreshes. - Updated title/display name resolution so UI and CalendarProvider prefer
localDisplayNamewhen present. - Added collection-screen UI (switch + dialog) and repository/DAO plumbing to set/clear the local override.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| core/src/main/res/values/strings.xml | Adds new UI strings for the local rename flow and a generic “Save” label. |
| core/src/main/kotlin/at/bitfire/davdroid/ui/account/CollectionScreenModel.kt | Adds setLocalDisplayName() to update DB and trigger a delayed refresh. |
| core/src/main/kotlin/at/bitfire/davdroid/ui/account/CollectionScreen.kt | Adds local rename entry + dialog; makes entries optionally clickable. |
| core/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt | Writes CALENDAR_DISPLAY_NAME from localDisplayName (fallback to server/URL name). |
| core/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt | Preserves localDisplayName on refresh; adds setter that trims blanks to null. |
| core/src/main/kotlin/at/bitfire/davdroid/db/CollectionDao.kt | Adds updateLocalDisplayName() query. |
| core/src/main/kotlin/at/bitfire/davdroid/db/Collection.kt | Adds localDisplayName field and prefers it in title(). |
| core/src/main/kotlin/at/bitfire/davdroid/db/AppDatabase.kt | Bumps Room DB version to 19 and adds auto-migration 18→19. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ], exportSchema = true, version = 19, autoMigrations = [ | ||
| AutoMigration(from = 18, to = 19), // collection: add localDisplayName | ||
| AutoMigration(from = 17, to = 18, spec = AutoMigration18::class), |
There was a problem hiding this comment.
Room schema was bumped to v19 with an AutoMigration (18→19) adding collection.localDisplayName, but there is no corresponding migration test in core/src/androidTest/kotlin/at/bitfire/davdroid/db/migration/ like the existing AutoMigration18Test. Adding an AutoMigration19Test (or equivalent) that opens a v18 schema DB and validates the new nullable column exists (and that existing collection rows migrate without data loss) would help catch migration regressions.
| private fun valuesFromCollectionInfo(info: Collection, withColor: Boolean): ContentValues { | ||
| val serverDisplayName = if (info.displayName.isNullOrBlank()) info.url.lastSegment else info.displayName | ||
| val values = contentValuesOf( | ||
| Calendars._SYNC_ID to info.id, | ||
| Calendars.CALENDAR_DISPLAY_NAME to | ||
| if (info.displayName.isNullOrBlank()) info.url.lastSegment else info.displayName, | ||
| Calendars.CALENDAR_DISPLAY_NAME to (info.localDisplayName ?: serverDisplayName), |
There was a problem hiding this comment.
valuesFromCollectionInfo() now prefers info.localDisplayName for Calendars.CALENDAR_DISPLAY_NAME, but there’s no test exercising this new behavior. Since LocalCalendarStoreTest exists, consider adding a test case that creates a Collection with localDisplayName set and verifies the resulting calendar row in the CalendarProvider gets that value (and falls back to the server/url name when the override is null).

Purpose
Let users give calendars a local-only display name that differs from the server-side one. The override is shown in DAVx5 and used as
CALENDAR_DISPLAY_NAMEin the Android CalendarProvider, while the DAV collection on the server remains unchanged. This is useful when the server-provided name is generic, duplicated across accounts, or just not how the user wants to see the calendar on their device.Short description
localDisplayNamecolumn to theCollectionentity (auto-migration 18 → 19).Collection.title()now preferslocalDisplayNameover the serverdisplayName.LocalCalendarStorewriteslocalDisplayName(if set) toCalendars.CALENDAR_DISPLAY_NAME, so renames are picked up by the CalendarProvider on the next update.DavCollectionRepository.setLocalDisplayName()(trims blanks →null) and wired it throughCollectionScreenModel.Switchand a rename dialog. Entry is gated toTYPE_CALENDARandTYPE_WEBCAL— address books are excluded for now.insertOrUpdateByUrlRememberSyncpreserveslocalDisplayNamein addition tosyncandforceReadOnly, so a "Refresh list" dose not wipe the override.Not included: local rename for address books (requires a separate decision because Android Contacts shows the raw account name, not a per-account-local name).
Checklist