fix(calendars): make the Settings toggle the one visibility model (#75)
Reminders never fired for a calendar hidden at system level and nothing hinted at it: the provider only schedules reminder alarms for Calendars.VISIBLE=1, while Calendula filtered with its own disabledCalendarIds pref and parsed isVisibleInSystem without ever using it — two models that could disagree indefinitely. Settings → Calendars now writes Calendars.VISIBLE, one calendar per update (CalendarProvider2 skips its own checkNextAlarm() reschedule for any selection that isn't _id=), and every display predicate reads isVisibleInSystem. The drawer's filter sheet stays a purely in-app declutter and still leaves reminders alone. With VISIBLE=0 the provider creates no alert rows, so there is nothing left to suppress: the disabled-calendar gates, SuppressedReminderStore and the re-enable recovery are gone. A one-shot migration reconciles the retired set with the app's state winning — enabled in-app and syncing gets shown, disabled gets hidden, everything else untouched — so the upgrade changes nothing the user sees. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -157,6 +157,15 @@ sequenceDiagram
|
||||
Posting happens before marking: a crash in between re-posts silently (same
|
||||
tag + `setOnlyAlertOnce`) rather than losing a reminder. Swiped
|
||||
notifications never return because `FIRED` rows are never re-queried.
|
||||
|
||||
**One visibility model.** The provider only schedules alarms for calendars with
|
||||
`Calendars.VISIBLE = 1`, so that flag *is* the app's on/off switch: Settings →
|
||||
Calendars writes it (one calendar per update — `CalendarProvider2` skips its own
|
||||
`checkNextAlarm()` reschedule for any selection that isn't `_id=`), and every
|
||||
display predicate reads `CalendarSource.isVisibleInSystem`. There is deliberately
|
||||
no second, app-local model and therefore nothing to suppress here. The drawer's
|
||||
filter sheet (`CalendarPrefs.hiddenCalendarIds`) is a separate in-app declutter
|
||||
that never touches reminders. See `docs/design/calendar-visibility-model.md`.
|
||||
Deliberately absent until real devices prove it necessary: own alarm
|
||||
scheduling, `BOOT_COMPLETED`, snooze/dismiss actions, battery-exemption
|
||||
prompts.
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
# Design: One calendar-visibility model (reminders silently never fire)
|
||||
|
||||
Status: **planned** on `fix/calendar-visibility-model`
|
||||
Status: **implemented** on `fix/calendar-visibility-model` (on-device review owed)
|
||||
Date: 2026-07-25
|
||||
|
||||
Built as specified, with three notes: `CalendarSource` gained a `syncsEvents`
|
||||
flag (the migration's `sync_events = 1` condition needs it, and #76 will label
|
||||
those rows); the migration runs from `CalendulaApp.onCreate` *and* from
|
||||
`PermissionViewModel.onGranted`, so a launch that starts without the calendar
|
||||
permissions still migrates the moment they are granted; and the Settings hint
|
||||
string was reworded rather than dropped — it described the retired app-only
|
||||
behaviour, so leaving it would have been the one piece of false text on screen.
|
||||
Tracking: Codeberg #75. Split out of this work: #76 (read-only / not-synced
|
||||
communication), #77 (accounts merged by name).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user