fix(v0.3.0): audio background + emisoras rotas + errores toast + icono
- ServicioAudio: delega a PluriWaveAudioHandler (audio_service) para mantener audio vivo en background. AudioService.init() en main.dart. onTaskRemoved() libera player. mediaItem con nombre/artista/artwork. - ServicioRadio: lastcheckok=1 en todas las peticiones — solo emisoras verificadas como funcionales por Radio Browser API. - EstadoRadio: errorStream (broadcast) para errores de reproducción y búsqueda. App.dart suscribe y muestra SnackBar flotante 3s. Los errores de carga de lista siguen como banner inline. - Icono: generado con SDXL (morado, ondas radio blancas, Material You). 5 densidades Android (48-192px), ic_launcher_round añadido.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../modelos/emisora.dart';
|
||||
import '../servicios/servicio_audio.dart';
|
||||
@@ -7,13 +8,18 @@ import '../servicios/servicio_timer.dart';
|
||||
|
||||
/// Estado global de la app con ChangeNotifier (Provider).
|
||||
///
|
||||
/// Centraliza: reproductoor, favoritos, búsqueda, timer.
|
||||
/// Errores de reproducción se emiten por [errorStream] para mostrar como
|
||||
/// SnackBar — no bloquean la UI.
|
||||
class EstadoRadio extends ChangeNotifier {
|
||||
final ServicioAudio audio = ServicioAudio();
|
||||
final ServicioFavoritos favoritos = ServicioFavoritos();
|
||||
final ServicioRadio radio = ServicioRadio();
|
||||
late final ServicioTimer timer;
|
||||
|
||||
// Errores de reproducción → SnackBar en el UI
|
||||
final _errorController = StreamController<String>.broadcast();
|
||||
Stream<String> get errorStream => _errorController.stream;
|
||||
|
||||
List<Emisora> _populares = [];
|
||||
List<Emisora> _tendencias = [];
|
||||
List<Emisora> _resultadosBusqueda = [];
|
||||
@@ -21,7 +27,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
|
||||
bool _cargandoPopulares = false;
|
||||
bool _cargandoBusqueda = false;
|
||||
String? _error;
|
||||
String? _errorCarga; // solo para errores de carga de lista (banner estático)
|
||||
|
||||
EstadoRadio() {
|
||||
timer = ServicioTimer(audio);
|
||||
@@ -34,7 +40,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
List<Emisora> get listaFavoritos => _listafavoritos;
|
||||
bool get cargandoPopulares => _cargandoPopulares;
|
||||
bool get cargandoBusqueda => _cargandoBusqueda;
|
||||
String? get error => _error;
|
||||
String? get error => _errorCarga;
|
||||
Emisora? get emisoraActual => audio.emisoraActual;
|
||||
Stream<EstadoReproduccion> get estadoStream => audio.estadoStream;
|
||||
|
||||
@@ -47,7 +53,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
|
||||
Future<void> cargarPopulares() async {
|
||||
_cargandoPopulares = true;
|
||||
_error = null;
|
||||
_errorCarga = null;
|
||||
notifyListeners();
|
||||
try {
|
||||
final results = await Future.wait([
|
||||
@@ -57,7 +63,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
_populares = results[0];
|
||||
_tendencias = results[1];
|
||||
} catch (e) {
|
||||
_error = 'Error al cargar emisoras: $e';
|
||||
_errorCarga = 'Sin conexión a la API de radio';
|
||||
} finally {
|
||||
_cargandoPopulares = false;
|
||||
notifyListeners();
|
||||
@@ -86,7 +92,8 @@ class EstadoRadio extends ChangeNotifier {
|
||||
tag: tag,
|
||||
);
|
||||
} catch (e) {
|
||||
_error = 'Error en búsqueda: $e';
|
||||
// Error de búsqueda → toast, no bloquear pantalla
|
||||
_errorController.add('Error en la búsqueda. Comprueba tu conexión.');
|
||||
} finally {
|
||||
_cargandoBusqueda = false;
|
||||
notifyListeners();
|
||||
@@ -99,8 +106,8 @@ class EstadoRadio extends ChangeNotifier {
|
||||
radio.registrarClick(emisora.uuid); // fire & forget
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
_error = 'No se puede reproducir esta emisora';
|
||||
notifyListeners();
|
||||
// Error de reproducción → SnackBar, no pintar en medio de la UI
|
||||
_errorController.add('No se puede reproducir "${emisora.nombre}"');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +136,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_errorController.close();
|
||||
audio.dispose();
|
||||
timer.dispose();
|
||||
super.dispose();
|
||||
|
||||
Reference in New Issue
Block a user