Don't nag for future doses: time-guard escalation resume

'Ta nå' + 'Angre' on a not-yet-due dose leaves a PENDING log with a
future scheduledAt; armAll() (every app start/update) then resumed
'escalation' for it as if it were overdue — nagging hours early. Three
layers: armAll only resumes escalation for past-due logs, the
escalation receiver drops anything scheduled in the future (defense
in depth), and undo resets nagCount + cancels any escalation so stale
counts can't eat the real quota when the dose actually falls due.

Emulator-verified with both cases side by side: past-due PENDING nags
within the minute, future PENDING stays silent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-06-11 18:26:46 +02:00
commit 8c3cd0c965
3 changed files with 15 additions and 2 deletions

View file

@ -87,9 +87,15 @@ class AlarmScheduler(private val context: Context) {
val db = MedDatabase.get(context)
db.doseTimeDao().getAllForActiveMeds().forEach { armDoseTime(it.id) }
armSupplyCheck()
// Resume nagging for doses that were unresolved when the device died.
// Resume nagging for doses that were unresolved when the device died —
// but only PAST-DUE ones. An unresolved log can also be a future dose
// (e.g. "Ta nå" + "Angre" before its time); its own occurrence alarm
// handles it when it actually falls due.
val now = System.currentTimeMillis()
db.doseLogDao().getUnresolved().forEach { log ->
if (log.nagCount < NAG_CAP) armEscalation(log.id, delayMinutes = 1)
if (log.nagCount < NAG_CAP && log.scheduledAtMillis <= now) {
armEscalation(log.id, delayMinutes = 1)
}
}
}