fix(alarm): improve firing and preferred station
This commit is contained in:
@@ -54,6 +54,8 @@ class _AjustesContent extends StatelessWidget {
|
||||
SizedBox(height: 12),
|
||||
_SeccionGrabaciones(),
|
||||
SizedBox(height: 12),
|
||||
_SeccionEmisoraPreferida(),
|
||||
SizedBox(height: 12),
|
||||
_SeccionEmisoras(),
|
||||
SizedBox(height: 12),
|
||||
_SeccionBackup(),
|
||||
@@ -238,6 +240,107 @@ class _SeccionEcualizador extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _SeccionEmisoraPreferida extends StatelessWidget {
|
||||
const _SeccionEmisoraPreferida();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final estado = context.watch<EstadoRadio>();
|
||||
final favoritas = estado.listaFavoritos;
|
||||
final preferida = estado.emisoraPreferida;
|
||||
final opciones = _opciones(estado, preferida);
|
||||
|
||||
return PluriGlassSurface(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.radio_rounded),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
'Emisora preferida',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Se preselecciona al crear alarmas y puede iniciarse como reproducción rápida.',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
if (opciones.isEmpty)
|
||||
const ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Icon(Icons.info_outline_rounded),
|
||||
title: Text('Todavía no hay emisoras disponibles'),
|
||||
subtitle: Text(
|
||||
'Guardá favoritas o cargá emisoras para elegir una preferida.',
|
||||
),
|
||||
)
|
||||
else
|
||||
DropdownButtonFormField<String>(
|
||||
initialValue: preferida?.uuid,
|
||||
decoration: InputDecoration(
|
||||
labelText:
|
||||
favoritas.isEmpty
|
||||
? 'Fallback automático'
|
||||
: 'Favorita por defecto',
|
||||
),
|
||||
items: [
|
||||
for (final emisora in opciones)
|
||||
DropdownMenuItem<String>(
|
||||
value: emisora.uuid,
|
||||
child: Text(
|
||||
emisora.nombre,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: (uuid) async {
|
||||
final seleccion = opciones.firstWhere((e) => e.uuid == uuid);
|
||||
await context.read<EstadoRadio>().cambiarEmisoraPreferida(
|
||||
seleccion,
|
||||
);
|
||||
},
|
||||
),
|
||||
if (preferida != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
favoritas.any((e) => e.uuid == preferida.uuid)
|
||||
? 'Preferida actual: ${preferida.nombre}'
|
||||
: 'Sin favoritas: usando automáticamente ${preferida.nombre}',
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: FilledButton.tonalIcon(
|
||||
icon: const Icon(Icons.play_arrow_rounded),
|
||||
label: const Text('Reproducir preferida'),
|
||||
onPressed:
|
||||
() => context.read<EstadoRadio>().reproducirEmisoraPreferida(),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Emisora> _opciones(EstadoRadio estado, Emisora? preferida) {
|
||||
final base =
|
||||
estado.listaFavoritos.isNotEmpty
|
||||
? estado.listaFavoritos
|
||||
: estado.emisorasDisponiblesPreferencia;
|
||||
final mapa = <String, Emisora>{for (final emisora in base) emisora.uuid: emisora};
|
||||
if (preferida != null) {
|
||||
mapa[preferida.uuid] = preferida;
|
||||
}
|
||||
return mapa.values.toList();
|
||||
}
|
||||
}
|
||||
|
||||
class _SeccionEmisoras extends StatelessWidget {
|
||||
const _SeccionEmisoras();
|
||||
|
||||
|
||||
@@ -294,6 +294,7 @@ class _EditorAlarmaSheetState extends State<_EditorAlarmaSheet> {
|
||||
late bool _sonarEnVacaciones;
|
||||
late SonidoInternoAlarma _sonidoInterno;
|
||||
Emisora? _emisora;
|
||||
bool _favoritosSolicitados = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -311,7 +312,7 @@ class _EditorAlarmaSheetState extends State<_EditorAlarmaSheet> {
|
||||
_volumen = alarma?.volumen ?? 0.85;
|
||||
_sonarEnVacaciones = alarma?.sonarEnVacaciones ?? true;
|
||||
_sonidoInterno = alarma?.sonidoInterno ?? SonidoInternoAlarma.amanecer;
|
||||
_emisora = alarma?.emisora;
|
||||
_emisora = alarma?.emisora ?? context.read<EstadoRadio>().emisoraPreferida;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -324,6 +325,20 @@ class _EditorAlarmaSheetState extends State<_EditorAlarmaSheet> {
|
||||
Widget build(BuildContext context) {
|
||||
final radio = context.watch<EstadoRadio>();
|
||||
final bottom = MediaQuery.of(context).viewInsets.bottom;
|
||||
if (!_favoritosSolicitados) {
|
||||
_favoritosSolicitados = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) context.read<EstadoRadio>().cargarFavoritos();
|
||||
});
|
||||
}
|
||||
if (_emisora == null && widget.alarma == null && radio.emisoraPreferida != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted && _emisora == null) {
|
||||
setState(() => _emisora = radio.emisoraPreferida);
|
||||
}
|
||||
});
|
||||
}
|
||||
final favoritas = _favoritasConSeleccion(radio.listaFavoritos);
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(12, 12, 12, bottom + 12),
|
||||
child: PluriGlassSurface(
|
||||
@@ -437,22 +452,52 @@ class _EditorAlarmaSheetState extends State<_EditorAlarmaSheet> {
|
||||
onChanged: (value) => setState(() => _sonidoInterno = value ?? _sonidoInterno),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const Icon(Icons.radio_rounded),
|
||||
title: Text(_emisora?.nombre ?? 'Sin emisora principal'),
|
||||
subtitle: Text(
|
||||
radio.emisoraActual == null
|
||||
? 'Se usará el sonido interno si la radio falla.'
|
||||
: 'Podés usar la emisora que está seleccionada ahora.',
|
||||
),
|
||||
trailing: FilledButton.tonal(
|
||||
onPressed: radio.emisoraActual == null
|
||||
? null
|
||||
: () => setState(() => _emisora = radio.emisoraActual),
|
||||
child: const Text('Usar actual'),
|
||||
DropdownButtonFormField<String>(
|
||||
key: ValueKey(_emisora?.uuid ?? 'sin-emisora'),
|
||||
initialValue: _emisora?.uuid,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Emisora favorita',
|
||||
prefixIcon: Icon(Icons.radio_rounded),
|
||||
),
|
||||
items: [
|
||||
const DropdownMenuItem<String>(
|
||||
value: '',
|
||||
child: Text('Sin emisora: usar sonido interno'),
|
||||
),
|
||||
for (final emisora in favoritas)
|
||||
DropdownMenuItem<String>(
|
||||
value: emisora.uuid,
|
||||
child: Text(
|
||||
emisora.nombre,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: (uuid) => setState(() {
|
||||
if (uuid == null || uuid.isEmpty) {
|
||||
_emisora = null;
|
||||
return;
|
||||
}
|
||||
_emisora = favoritas.firstWhere((e) => e.uuid == uuid);
|
||||
}),
|
||||
),
|
||||
if (favoritas.isEmpty) ...[
|
||||
const SizedBox(height: 6),
|
||||
const Text(
|
||||
'Guardá emisoras en Favoritos para usarlas como alarma musical.',
|
||||
),
|
||||
],
|
||||
if (radio.emisoraActual != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: FilledButton.tonalIcon(
|
||||
onPressed: () => setState(() => _emisora = radio.emisoraActual),
|
||||
icon: const Icon(Icons.add_task_rounded),
|
||||
label: const Text('Usar emisora actual'),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
SwitchListTile.adaptive(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
@@ -531,6 +576,18 @@ class _EditorAlarmaSheetState extends State<_EditorAlarmaSheet> {
|
||||
await estado.guardarAlarma(alarma);
|
||||
if (mounted) Navigator.pop(context);
|
||||
}
|
||||
|
||||
List<Emisora> _favoritasConSeleccion(List<Emisora> favoritas) {
|
||||
final mapa = <String, Emisora>{};
|
||||
for (final emisora in favoritas) {
|
||||
mapa[emisora.uuid] = emisora;
|
||||
}
|
||||
final seleccionada = _emisora;
|
||||
if (seleccionada != null) {
|
||||
mapa[seleccionada.uuid] = seleccionada;
|
||||
}
|
||||
return mapa.values.toList();
|
||||
}
|
||||
}
|
||||
|
||||
class _AccesoDiagnostico extends StatelessWidget {
|
||||
|
||||
Reference in New Issue
Block a user