feat(audio): audio session integration and runtime robustness
- Integrate audio_session (new servicio_audio_session.dart): incoming calls pause the radio and resume on end, headphone unplug pauses without auto-resume, permanent focus loss never auto-resumes, duck lowers volume - Add play-intent flag to ServicioAudio so interruption handling and future reconnect logic can distinguish user pause from system-driven stops - Eliminate read-modify-write race in ServicioAlarmas with an in-memory cache and single-writer queue across all mutations; recalcularTodas persists only when state actually changed - Convert ServicioAlarmasAndroid static StreamController/handler to injectable instance fields, restoring test isolation - Inject a single cached SharedPreferences from main.dart across services and state (removes 23 inline getInstance() calls) - Move configurarLocalizaciones out of MiniReproductor.build() (was running on every rebuild during playback) - Bound the alarm fire-dedup set (cap 200 entries, 24h pruning) - 12 new tests (89 total green), flutter analyze clean
This commit is contained in:
+21
-4
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'estado/estado_radio.dart';
|
||||
import 'estado/estado_alarmas.dart';
|
||||
import 'estado/estado_idioma.dart';
|
||||
@@ -23,15 +24,21 @@ import 'package:pluriwave/widgets/mini_reproductor.dart';
|
||||
import 'servicios/servicio_alarmas_android.dart';
|
||||
|
||||
class PluriWaveApp extends StatelessWidget {
|
||||
const PluriWaveApp({super.key});
|
||||
const PluriWaveApp({super.key, this.prefs});
|
||||
|
||||
/// Single SharedPreferences instance resolved in main() (S3-R4) and
|
||||
/// injected into every state/service.
|
||||
final SharedPreferences? prefs;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => EstadoRadio()),
|
||||
ChangeNotifierProvider(create: (_) => EstadoAlarmas()),
|
||||
ChangeNotifierProvider(create: (_) => EstadoIdioma()),
|
||||
ChangeNotifierProvider(create: (_) => EstadoRadio(prefs: prefs)),
|
||||
ChangeNotifierProvider(create: (_) => EstadoAlarmas(prefs: prefs)),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => EstadoIdioma(sharedPreferences: prefs),
|
||||
),
|
||||
],
|
||||
child: Consumer<EstadoIdioma>(
|
||||
builder:
|
||||
@@ -69,6 +76,7 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
bool _alarmaSonandoActiva = false;
|
||||
bool _onboardingInicialSolicitado = false;
|
||||
String? _alarmaSonandoId;
|
||||
Locale? _localeAlarmasConfigurado;
|
||||
|
||||
static const _paginas = [
|
||||
PantallaInicio(),
|
||||
@@ -89,6 +97,15 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
// S3-R3 / Decision 3.2: keep the alarm bridge l10n in sync, once per
|
||||
// locale change (this hook re-runs when Localizations changes).
|
||||
final locale = Localizations.localeOf(context);
|
||||
if (_localeAlarmasConfigurado != locale) {
|
||||
_localeAlarmasConfigurado = locale;
|
||||
context.read<EstadoAlarmas>().configurarLocalizaciones(
|
||||
AppLocalizations.of(context),
|
||||
);
|
||||
}
|
||||
final estado = context.read<EstadoRadio>();
|
||||
if (identical(_estadoSuscrito, estado) && _errorSubscription != null) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user