Files
pluriwave/openspec/changes/snooze-reschedule-fix/specs/alarm-snooze-reschedule/spec.md
T
FreeTLab bccc5c48b8
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m30s
docs(openspec): add SDD artifact trail for recent alarm and EQ changes
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.
2026-07-04 12:42:11 +02:00

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. StateError from a failed scheduleAlarm platform call)
  • THEN the exception is caught inside posponerAlarma() (or posponerProximaDesdePreaviso())
  • 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 inside posponerProximaDesdePreaviso()
  • THEN the same catch + notifyListeners() guarantee applies as in posponerAlarma()

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