Persist the exploration, proposal, spec, design, tasks, and verify/archive reports produced during the multi-device EQ, alarm-countdown, and notification-visual-polish SDD cycles.
3.5 KiB
Alarm Snooze Reschedule Specification
Purpose
Snoozing an alarm (from the ringing screen or from a pre-notice) MUST reliably re-arm the native Android alarm, refresh the in-app UI, and inform the user when scheduling fails. This spec covers EstadoAlarmas.posponerAlarma(), EstadoAlarmas.posponerProximaDesdePreaviso(), and the user-facing failure feedback in _posponer().
Requirements
Requirement: Permission Pre-Check Before Snooze Scheduling
The system MUST call _solicitarPermisosNecesariosParaAlarma() before invoking android.programar() in both posponerAlarma() and posponerProximaDesdePreaviso(), mirroring guardarAlarma().
Scenario: Exact-alarm permission was revoked since the alarm was created
- GIVEN the exact-alarm permission was previously granted but has since been revoked (OEM battery manager or Android 14 auto-revoke)
- WHEN the user snoozes the ringing alarm
- THEN the system re-requests the exact-alarm permission before calling
android.programar()
Scenario: Permission already granted
- GIVEN the exact-alarm permission is currently granted
- WHEN the user snoozes the alarm
- THEN the permission pre-check is a no-op and scheduling proceeds immediately
Requirement: Native Scheduling Failure Must Not Corrupt UI State
posponerAlarma() and posponerProximaDesdePreaviso() MUST wrap the call to android.programar() in try/catch and MUST call notifyListeners() regardless of whether scheduling succeeds or fails.
Scenario: Native scheduling succeeds (happy path)
- GIVEN the user snoozes an alarm from the ringing screen
- WHEN
android.programar()completes successfully - THEN the in-memory alarm state reflects the new
snoozeHasta - AND
notifyListeners()is called - AND the "next alarm" panel updates to show the snoozed time
- AND a per-minute countdown notification appears
- AND the native alarm re-fires at the snoozed time
Scenario: Native scheduling throws (failure path)
- GIVEN the user snoozes an alarm from the ringing screen
- WHEN
android.programar()throws (e.g.StateErrorfrom a failedscheduleAlarmplatform call) - THEN the exception is caught inside
posponerAlarma()(orposponerProximaDesdePreaviso()) - AND
notifyListeners()is still called - AND no real alarm is left silently un-scheduled without the UI knowing
- AND the failure is recorded (e.g. into an error field) instead of propagating uncaught
Scenario: Pre-notice snooze failure (variant path)
- GIVEN the user snoozes from a pre-notice (not the ringing screen)
- WHEN
android.programar()throws insideposponerProximaDesdePreaviso() - THEN the same catch +
notifyListeners()guarantee applies as inposponerAlarma()
Requirement: User-Facing Failure Feedback
_posponer() in pantalla_alarma_sonando.dart MUST surface a scheduling failure to the user (e.g. via SnackBar) instead of only debugPrint.
Scenario: Snooze fails and ringing screen dismisses
- GIVEN
posponerAlarma()reports a failure (via thrown/caught error or returned failure state) - WHEN
_posponer()handles the result - THEN the ringing screen still dismisses (existing dismiss-by-design behavior is preserved)
- AND the user sees an explicit failure message (e.g. SnackBar) before or immediately after dismissal
- AND no failure is silently swallowed with only a debug log
Scenario: Snooze succeeds
- GIVEN
posponerAlarma()completes successfully - WHEN
_posponer()handles the result - THEN the ringing screen dismisses
- AND no failure message is shown