fix: address code-review findings on the 2.16.0 branch #87
Reference in New Issue
Block a user
Delete Branch "fix/code-review-2.16.0"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Code review of
main...release/v2.16.0(the per-event time zones, toolbar today-button, multi-day agenda and app-name work) surfaced ten findings. This fixes all of them.Correctness
Recurring series anchor drifted by an hour (the significant one).
buildEventUpdateValuesmoved a recurring event's seriesDTSTARTby a millisecond delta measured at the edited occurrence. That delta bakes in whichever UTC offset applied on the occurrence's date — a different offset from the series anchor's whenever a DST boundary sits between them, and an entirely wrong one when the zone itself changed. Pinning a recurring event to another zone shifted the whole series.Now the anchor moves by the wall-clock shift the user applied and is re-resolved in the event's (possibly new) zone, so "09:00" keeps meaning 09:00 at both ends. Three new tests pin it: a Berlin→Tokyo pin with a January anchor and a July occurrence, a time edit across a DST boundary, and a whole-day move. The pre-existing delta tests pass unchanged.
Zone abbreviations resolved at the wrong instant. The detail card and the edit form both resolved a pinned zone's abbreviation and offset at
Instant.now()and printed them next to the event's time — a July event readCET · 10:00 AMwhen opened in January. Both now resolve at the event's own start.Agenda labelling could disagree with grouping.
agendaTimeSummaryread a file-levelprivate val zonefixed for the process lifetime, while grouping used the ViewModel's. After a device time-zone change the two diverge and a row can read "Starts …" under a day it doesn't start on. The zone now travels onAgendaUiState.Success; the constant is gone.Week title hid the year across New Year. A week running Dec 28 – Jan 3 showed a bare "December" with four visible columns in the new year. Added a
forceYearflag toformatCalendarTitle.Performance
produceState+Dispatchers.Default; the device row's summary resolves on its own so it still renders complete on the first frame.filterTimeZonesre-normalized four strings per option per call — ~2400 NFD normalizations and regex passes per keystroke. Search keys are now normalized once atTimeZoneOptionconstruction (in the class body, so they stay out ofequals/copy), and the combining-markRegexis hoisted out of the hot path.timesInon every recomposition — i.e. every keystroke in the title field. Now keyed on the fields it reads.LauncherNameManager'sgetComponentEnabledSetting/setComponentEnabledSettingare binder round-trips that ran on the main thread (one of them in theSettingsViewModelinitializer, while Settings was opening). Both moved off-thread; the app-name card highlights optimistically and settles on the real component state.Cleanup
Icons.Default.Publicimport inEventEditScreen.event_edit_timezone_clearstring — it was being shipped to Weblate for translators to translate a string that can never render.Beyond the ten findings
While rewriting the series-anchor logic I hit an adjacent pre-existing wart in the code I was touching: switching a recurring event to all-day shifts by a time-of-day and can land the anchor off a UTC midnight. Snapped it, with a test. Happy to split this out if you'd rather keep the PR strictly to the review findings.
Not addressed, deliberately:
AgendaViewModelstill caches its ownzoneat construction. It's recreated far more often than the process lives, so the window is much smaller than the file-level constant this removes, and fixing it properly means observingACTION_TIMEZONE_CHANGED— bigger than this PR's scope.Verification
./gradlew lint test assembleDebuggreen;scripts/check_translations.pyclean.Not verified on device. The time-zone and agenda changes in particular want an on-device look before 2.16.0 goes to main.
🤖 Generated with Claude Code