fix(alarm): handle snooze reschedule failures instead of silently dropping them
Build & Deploy PluriWave / Análisis de código (push) Successful in 47s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m1s

posponerAlarma() and posponerProximaDesdePreaviso() called the native
scheduler with no error handling, unlike guardarAlarma(). When the
native call failed (e.g. revoked exact-alarm permission), the
exception escaped before notifyListeners() ran, leaving the alarm
list stuck on stale data with no real alarm scheduled and no snooze
countdown notification.

Both methods now mirror guardarAlarma()'s pattern: permission
pre-check, try/catch into _error, and an unconditional
notifyListeners() so the UI always reflects the outcome. Failures
surface via SnackBar in the ringing screen and in app.dart's
postpone-next handler.
This commit is contained in:
2026-07-01 00:22:58 +02:00
parent cc98f3f331
commit 6acbd7ca93
6 changed files with 263 additions and 32 deletions
+14 -4
View File
@@ -173,13 +173,23 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
Future<void> _posponer(int minutos) async {
final radio = context.read<EstadoRadio>();
final alarmas = context.read<EstadoAlarmas>();
// Captured BEFORE dismiss (Design D4): the ringing screen dismisses by
// design below, so the messenger must outlive it for the failure
// SnackBar to still be shown.
final messenger = ScaffoldMessenger.of(context);
await _silenciarAudio(radio);
// See _detener: the screen MUST close even if posponerAlarma throws
// (e.g. native scheduleAlarm returns false on a device without exact
// alarm permission). Otherwise the modal freezes and the snooze never
// re-rings because _alarmaSonandoActiva stays true.
// posponerAlarma no longer throws on a native scheduling failure (it
// records the failure into EstadoAlarmas.error and always calls
// notifyListeners instead) — the dismiss-in-finally below is now a
// structural safety net, not a workaround for an expected throw. The
// screen still closes either way (dismiss-by-design); the failure is
// reported to the user via a SnackBar, not silently swallowed.
try {
await alarmas.posponerAlarma(widget.alarma, minutos);
final error = alarmas.error;
if (error != null) {
messenger.showSnackBar(SnackBar(content: Text(error)));
}
} catch (e) {
debugPrint('[PluriWave][alarmas] posponer alarma fallo: $e');
} finally {