feat(radio): add nearby discovery and paged search
Build & Deploy Pluriwave / Build APK + AAB release (push) Successful in 1m34s
Build & Deploy Pluriwave / Análisis de código (push) Successful in 11s

This commit is contained in:
2026-05-20 23:22:15 +02:00
parent f888153aa9
commit 7fcd0f544e
13 changed files with 428 additions and 40 deletions
+10 -1
View File
@@ -106,6 +106,7 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
PresetEcualizador _presetActual = PresetEcualizador.flat;
PresetEcualizador get presetActual => _presetActual;
Future<void> _colaReproduccion = Future<void>.value();
PluriWaveAudioHandler() {
_setupStreams();
@@ -213,12 +214,20 @@ class PluriWaveAudioHandler extends BaseAudioHandler with SeekHandler {
}
@override
Future<void> playMediaItem(MediaItem mediaItem) async {
Future<void> playMediaItem(MediaItem mediaItem) {
_colaReproduccion = _colaReproduccion
.catchError((_) {})
.then((_) => _playMediaItemSerializado(mediaItem));
return _colaReproduccion;
}
Future<void> _playMediaItemSerializado(MediaItem mediaItem) async {
this.mediaItem.add(mediaItem);
emisoraActual = _emisoraDesdeMediaItem(mediaItem);
playbackState.add(playbackState.value.copyWith(
processingState: AudioProcessingState.loading,
playing: false,
errorMessage: null,
));
try {
await _player.stop();
+17 -6
View File
@@ -105,8 +105,13 @@ class ServicioRadio {
}
/// Emisoras más votadas globalmente.
Future<List<Emisora>> obtenerPopulares({int limit = 30}) async {
return _get('/json/stations/topvote/$limit', {});
Future<List<Emisora>> obtenerPopulares({int limit = 30, int offset = 0}) async {
return _get('/json/stations/search', {
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});
}
/// Emisoras más escuchadas (por clicks) globalmente.
@@ -115,37 +120,41 @@ class ServicioRadio {
}
/// Buscar por nombre de emisora.
Future<List<Emisora>> buscarPorNombre(String query, {int limit = 30}) async {
Future<List<Emisora>> buscarPorNombre(String query, {int limit = 30, int offset = 0}) async {
return _get('/json/stations/search', {
'name': query,
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});
}
/// Buscar por código de país (ISO 3166-1 alpha-2, e.g. 'ES', 'US').
Future<List<Emisora>> buscarPorPais(String codigoPais, {int limit = 50}) async {
Future<List<Emisora>> buscarPorPais(String codigoPais, {int limit = 50, int offset = 0}) async {
return _get('/json/stations/bycountrycodeexact/$codigoPais', {
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});
}
/// Buscar por idioma (e.g. 'spanish', 'english').
Future<List<Emisora>> buscarPorIdioma(String idioma, {int limit = 30}) async {
Future<List<Emisora>> buscarPorIdioma(String idioma, {int limit = 30, int offset = 0}) async {
return _get('/json/stations/bylanguageexact/$idioma', {
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});
}
/// Buscar por tag/género (e.g. 'rock', 'jazz', 'pop').
Future<List<Emisora>> buscarPorTag(String tag, {int limit = 30}) async {
Future<List<Emisora>> buscarPorTag(String tag, {int limit = 30, int offset = 0}) async {
return _get('/json/stations/bytagexact/$tag', {
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});
@@ -158,6 +167,7 @@ class ServicioRadio {
String? idioma,
String? tag,
int limit = 30,
int offset = 0,
}) async {
return _get('/json/stations/search', {
if (nombre != null && nombre.isNotEmpty) 'name': nombre,
@@ -165,6 +175,7 @@ class ServicioRadio {
if (idioma != null && idioma.isNotEmpty) 'language': idioma,
if (tag != null && tag.isNotEmpty) 'tag': tag,
'limit': limit.toString(),
'offset': offset.toString(),
'order': 'votes',
'reverse': 'true',
});