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:
parent
aca0839e0f
commit
8c3cd0c965
3 changed files with 15 additions and 2 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ class DoseAlarmReceiver : BroadcastReceiver() {
|
|||
// Only unresolved doses nag. TAKEN/SKIPPED here means the cancel raced us.
|
||||
if (log.status != DoseStatus.PENDING && log.status != DoseStatus.SNOOZED) return
|
||||
if (log.nagCount >= AlarmScheduler.NAG_CAP) return
|
||||
// A future dose can't be overdue — drop stray escalations (defense in
|
||||
// depth against any path that arms one too early).
|
||||
if (log.scheduledAtMillis > System.currentTimeMillis()) return
|
||||
|
||||
val med = db.medicationDao().getById(log.medId) ?: return
|
||||
val nagged = log.copy(nagCount = log.nagCount + 1)
|
||||
|
|
|
|||
|
|
@ -67,5 +67,9 @@ class DoseActions(private val context: Context) {
|
|||
}
|
||||
}
|
||||
db.doseLogDao().setStatus(logId, DoseStatus.PENDING, null)
|
||||
// Fresh start: stale nag counts would otherwise eat into the real
|
||||
// escalation quota when the dose actually falls due.
|
||||
db.doseLogDao().setNagCount(logId, 0)
|
||||
scheduler.cancelEscalation(logId)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue