Files
calendula/app
Jean-Luc Makiola a1f091a88b feat(reminders): schedule and fire reminders in-house (#75)
Delivery no longer waits to be told. The scan reads `Instances` and `Reminders`,
plans every reminder, posts what has come due and arms one exact alarm for the
next — replacing both halves of what the provider used to do for us.

Reacting to `EVENT_REMINDER` could not be made reliable, only more hopeful. An
app that reacts cannot distinguish "nothing was due" from "the broadcast never
came", and AOSP's own unbundled calendar carries three workarounds for OEM
providers that retarget it or write the alert row late. Etar's fallback was not
the answer either: it replaces the alarm but still reads `CalendarAlerts` for
what to show, and it disables itself the moment one real broadcast arrives —
useless against a broadcast that arrives with no row behind it.

Keeping the old receiver alongside was rejected for the same reason it looks
attractive: on a healthy device both paths fire, and there is no honest way to
suppress one without the latch we just ruled out. So the provider path goes —
`EventReminderReceiver`, `ReminderAlertStore`, `ReminderRecovery` and the
`CalendarAlerts` writes with it. Reminder delivery no longer needs WRITE_CALENDAR.

One alarm exists at a time, re-planned on every firing, so an edit needs no alarm
bookkeeping to stay in sync. Every trigger runs the same idempotent scan: the
alarm, boot and package-replace (both wipe pending alarms), clock and timezone
changes, a provider change while the app is up, launch, and a daily worker for a
device that drops the alarm with nothing to announce it. RECEIVE_BOOT_COMPLETED
is new and load-bearing — without it reminders stop dead after a restart.

`ReminderAlert.alertId` becomes `key`, derived from the reminder rather than a
row id that no longer exists, and the notification tag and PendingIntent request
codes ride on it, so a re-posted reminder still replaces itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 15:24:45 +02:00
..