fix(alarm): capture alarm state before dispose so its volume restore works
Build & Deploy PluriWave / Análisis de código (push) Successful in 43s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 1m52s

_restaurarVolumenMediaUnaVez() read the BuildContext to reach the
alarm port, but dispose() runs after the element is defunct, so the
lookup always threw (caught and logged) and the dispose safety-net
never actually restored the media volume when it was the sole exit
path. The state is now captured once in initState and the restore
helper uses the field. Adds the missing dispose-as-sole-caller
regression test.
This commit is contained in:
2026-07-11 10:16:25 +02:00
parent b9539223de
commit 79f6f8ef38
2 changed files with 22 additions and 1 deletions
+6 -1
View File
@@ -42,9 +42,14 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
bool _audioFlutterConfirmado = false;
bool _volumenMediaRestaurado = false;
// Captured while mounted: dispose() also restores the media volume, and by
// then the element is defunct, so context.read() would throw there.
late final EstadoAlarmas _estadoAlarmas;
@override
void initState() {
super.initState();
_estadoAlarmas = context.read<EstadoAlarmas>();
WidgetsBinding.instance.addPostFrameCallback((_) => _iniciarAlarma());
}
@@ -164,7 +169,7 @@ class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
if (_volumenMediaRestaurado) return;
_volumenMediaRestaurado = true;
try {
await context.read<EstadoAlarmas>().android.restaurarVolumenMedia();
await _estadoAlarmas.android.restaurarVolumenMedia();
} catch (e) {
debugPrint('[PluriWave][alarmas] restaurar volumen media fallo: $e');
}
@@ -228,4 +228,20 @@ void main() {
expect(entorno.audio.volumenesAplicados, [0.05, 0.85]);
});
});
group('restore de volumen de medios con dispose como unico llamador', () {
testWidgets('desmontar la pantalla sin detener ni posponer restaura el '
'volumen exactamente una vez', (tester) async {
final entorno = await _montarPantalla(tester);
// Teardown that bypasses _detener()/_posponer() entirely: dispose()
// must work as a restore path on its own. Reading the BuildContext
// inside dispose() throws (the element is already defunct), so the
// port reference has to be captured while the widget is mounted.
await tester.pumpWidget(const SizedBox.shrink());
await tester.pumpAndSettle();
expect(entorno.android.volumenRestaurado, 1);
});
});
}