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.
5.4 KiB
Proposal: Snooze Reschedule Reliability Fix
Intent
Snoozing an alarm silently fails: the alarm never re-fires, no countdown notification appears, and the "Next alarm" panel keeps showing the already-fired alarm. Confirmed structural defect (exploration sdd/snooze-reschedule-fix/explore): posponerAlarma() and posponerProximaDesdePreaviso() await android.programar() with NO try/catch, so a native scheduling failure (most likely exact-alarm permission revoked — these methods never re-request it) throws past notifyListeners(), leaving in-memory state mutated but UI stale and no real alarm armed. guardarAlarma() already handles this correctly; the snooze paths regressed. Snooze is core alarm functionality — silent failure is critical.
Scope
In Scope
- Wrap
android.programar()in try/catch inposponerAlarma()andposponerProximaDesdePreaviso(), always reachingnotifyListeners()(mirrorguardarAlarma()). - Add
_solicitarPermisosNecesariosParaAlarma()pre-check before scheduling in both snooze methods. - Surface failure to the user in
_posponer()(SnackBar/feedback) instead of silentdebugPrint. - Regression tests (Strict TDD) for both snooze paths: success reschedules + notifies; failure still notifies + reports error.
Out of Scope
- Notification visual improvements (custom small icon, color theming, action-button icons, BigTextStyle, fallback artwork, channel groups) — split into a separate change
notification-visual-polish(see Approach for rationale). - Changing the Kotlin
scheduleMainAlarm()inexact-fallback policy (intentional behavior; out of this fix). - iOS snooze path (this defect is Android-specific).
Capabilities
New Capabilities
alarm-snooze-reschedule: snoozing an alarm MUST reliably re-arm the native alarm, refresh the UI, and report any scheduling failure to the user — covering both ringing-screen snooze and pre-notice snooze.
Modified Capabilities
- None. (
alarm-pre-notice-countdownbehavior is unchanged; only its scheduling reliability is hardened, which the new capability covers.)
Approach
Mirror the proven guardarAlarma() pattern in both snooze methods: permission pre-check → try/schedule/catch-into-_error → notifyListeners() in a finally so the widget tree always rebuilds. Propagate a failure signal to _posponer() for user-visible feedback (the ringing screen dismisses by design, so feedback must survive dismissal). Dart-only change — fully testable under Strict TDD with a mocked ServicioAlarmasAndroid.
Split decision (one of the two questions this proposal answers): Bug fix and notification visuals are SEPARATE changes. Justification: (1) Risk isolation — a critical, fast, Dart-only, fully-testable fix must not be blocked or complicated by cosmetic Kotlin work that has no test infra. (2) File overlap is shallow — the bug fix barely touches Kotlin (only optionally a signal in scheduleSpec); visuals are Kotlin-heavy. Coupling them would force the critical fix through a larger, riskier review. (3) Delivery — this fix is small (well under the 400-line budget), ships as a single PR with no size:exception; visuals ship later as their own change.
Affected Areas
| Area | Impact | Description |
|---|---|---|
lib/estado/estado_alarmas.dart |
Modified | try/catch + permission pre-check + guaranteed notifyListeners() in both snooze methods |
lib/pantallas/pantalla_alarma_sonando.dart |
Modified | _posponer() surfaces snooze failure to user |
test/ (Dart) |
New | Regression tests for both snooze paths (success + failure) |
android/.../AlarmScheduler.kt |
Modified (optional) | Optionally distinguish "main fire failed" so caller can react — only if needed by tests |
Risks
| Risk | Likelihood | Mitigation |
|---|---|---|
| Root cause is permission-dependent; unconfirmed without device logcat | Med | Fix targets the confirmed structural defect (missing try/catch + notify), valid regardless of which native call failed |
| Different unfound bug if permission was actually granted | Low | Request adb logcat (tag PluriWave) for a snooze attempt before/alongside implementation |
| Re-requesting permission at snooze time disrupts the ringing UX | Low | Pre-check mirrors guardarAlarma(); if already granted it's a no-op |
Rollback Plan
Single-PR, Dart-focused change. Revert by reverting the PR commit(s) — estado_alarmas.dart and pantalla_alarma_sonando.dart return to current behavior; new tests removed with the revert. No data migration, no schema change, no persisted-state format change, so rollback is clean with zero residual state.
Dependencies
- Optional but recommended: device
adb logcat(tagPluriWave) confirmingscheduleMainAlarm/setAlarmClockfailure, to upgrade the hypothesis to a confirmed reproduction.
Success Criteria
- Snoozing from the ringing screen re-arms the native alarm; it rings again at the snooze time.
- The per-minute countdown notification appears after snoozing.
- The "Next alarm" panel updates immediately to the snoozed time (UI rebuilds via
notifyListeners()). - On scheduling failure, the user sees explicit feedback (no silent failure) and the UI still rebuilds.
- Pre-notice snooze (
posponerProximaDesdePreaviso) has identical reliability. - Dart regression tests cover success and failure for both paths and pass under
flutter test.