fix(alarm): unfreeze snooze modal and add per-minute snooze countdown
The snooze button was fire-and-forget without error handling: if
posponerAlarma threw (e.g. native scheduleAlarm returns false on a
device without exact-alarm permission), _dismissScreen never ran. The
stuck modal also kept _alarmaSonandoActiva true, which made the next
ring get ignored. _posponer/_detener now dismiss in a finally and stop
audio defensively.
Add a native, AlarmManager-driven snooze countdown notification that
re-posts every minute ("Rings in N min", 3->2->1) while the engine is
dead. scheduleSpec drives scheduleSnoozeCountdown for snoozes (instead
of the 30-min pre-notice). Localized text and button labels travel
Dart->Kotlin as {minutes} templates, same pattern as preNoticeTemplate.
Notification actions: "snooze again" (snoozeAgain, anchored to now)
reports back via the existing snoozed event; "stop" (cancelSnooze)
records a handled occurrence for cold-start reconciliation and emits a
new snoozeCancelled event handled in EstadoAlarmas.
Adds snoozeCountdown/snoozeAgainAction keys across all 13 locales and a
test for the snoozeCancelled event. Kotlin changes are static-reviewed
only; no Android build environment available here.
This commit is contained in:
@@ -23,6 +23,10 @@ class EventoAlarmaAndroid {
|
||||
/// (notification "Posponer" while the app may be backgrounded/killed).
|
||||
static const accionSnoozed = 'snoozed';
|
||||
|
||||
/// Action reported when a pending snooze was cancelled natively from the
|
||||
/// countdown notification ("Detener" while the app may be killed).
|
||||
static const accionSnoozeCancelled = 'snoozeCancelled';
|
||||
|
||||
final String alarmaId;
|
||||
final String titulo;
|
||||
final String accion;
|
||||
@@ -183,6 +187,16 @@ class ServicioAlarmasAndroid implements PuertoAlarmasAndroid {
|
||||
);
|
||||
}
|
||||
|
||||
/// Same sentinel strategy as [_preNoticeTemplate], but for the snooze
|
||||
/// countdown notification re-posted every minute while an alarm is snoozed.
|
||||
static String _snoozeCountdownTemplate(AppLocalizations l10n) {
|
||||
const sentinel = 42424242;
|
||||
return l10n.snoozeCountdown(sentinel).replaceFirst(
|
||||
sentinel.toString(),
|
||||
'{minutes}',
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<EventoAlarmaAndroid> get eventosAlarma => _eventosController.stream;
|
||||
|
||||
@@ -203,6 +217,9 @@ class ServicioAlarmasAndroid implements PuertoAlarmasAndroid {
|
||||
'id': alarma.id,
|
||||
'title': localizedAlarmName(_textos, alarma.nombre),
|
||||
'preNoticeTemplate': _preNoticeTemplate(_textos),
|
||||
'snoozeCountdownTemplate': _snoozeCountdownTemplate(_textos),
|
||||
'snoozeAgainLabel': _textos.snoozeAgainAction,
|
||||
'snoozeStopLabel': _textos.stopAlarmAction,
|
||||
'triggerAtMillis': proxima.millisecondsSinceEpoch,
|
||||
'preNoticeAtMillis':
|
||||
alarma.snoozeHasta == null
|
||||
|
||||
Reference in New Issue
Block a user