feat(favorites): add group persistence foundation
Build & Deploy Pluriwave / Análisis de código (push) Successful in 25s
Build & Deploy Pluriwave / Build APK + AAB release (push) Successful in 1m50s

This commit is contained in:
2026-05-22 16:09:52 +02:00
parent c347ce9d8e
commit 9bd973b327
7 changed files with 301 additions and 15 deletions
+32
View File
@@ -367,6 +367,38 @@ void main() {
await estado.toggleFavorito(emisora);
expect(estado.listaFavoritos.any((e) => e.uuid == emisora.uuid), isFalse);
});
test('crea y asigna grupos de favoritos sin tocar Sin asignar', () async {
final favoritos = FakeServicioFavoritos();
final emisora = emisoraDemo(uuid: 'fav-group', nombre: 'Grupo');
await favoritos.agregar(emisora);
final estado = EstadoRadio(
audio: FakeServicioAudio(),
favoritos: favoritos,
radio: FakeServicioRadio(populares: [emisora]),
servicioEcualizador: FakeServicioEcualizador(),
resolverArchivoCustom: _archivoCustomVacio,
iniciarAutomaticamente: false,
);
await estado.inicializar();
expect(estado.gruposFavoritos.first.protegido, isTrue);
await estado.crearGrupoFavoritos('Noticias');
final grupo = estado.gruposFavoritos.last;
await estado.asignarGrupoFavorito(emisora.uuid, grupo.id);
expect(
estado.listaFavoritos.first.grupoFavoritosId,
grupo.id,
);
await estado.eliminarGrupoFavoritos(grupo.id);
expect(
estado.listaFavoritos.first.grupoFavoritosId,
'sin_asignar',
);
});
});
}
+54
View File
@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:pluriwave/modelos/emisora.dart';
import 'package:pluriwave/modelos/grupo_favoritos.dart';
import 'package:pluriwave/modelos/preset_ecualizador.dart';
import 'package:pluriwave/servicios/servicio_audio.dart';
import 'package:pluriwave/servicios/servicio_ecualizador.dart';
@@ -71,6 +72,14 @@ class FakeServicioAudio extends ServicioAudio {
class FakeServicioFavoritos extends ServicioFavoritos {
final List<Emisora> _favoritos = [];
final List<GrupoFavoritos> _grupos = [
const GrupoFavoritos(
id: GrupoFavoritos.sinAsignarId,
nombre: 'Sin asignar',
orden: 0,
protegido: true,
),
];
int toggleCalls = 0;
@override
@@ -106,6 +115,51 @@ class FakeServicioFavoritos extends ServicioFavoritos {
return true;
}
@override
Future<List<GrupoFavoritos>> obtenerGrupos() async => List.unmodifiable(_grupos);
@override
Future<GrupoFavoritos> crearGrupo(String nombre) async {
final grupo = GrupoFavoritos(
id: 'grupo_${_grupos.length}',
nombre: nombre.trim(),
orden: _grupos.length,
);
_grupos.add(grupo);
return grupo;
}
@override
Future<void> renombrarGrupo(String id, String nombre) async {
final index = _grupos.indexWhere((g) => g.id == id && !g.protegido);
if (index == -1) return;
_grupos[index] = _grupos[index].copyWith(nombre: nombre.trim());
}
@override
Future<void> eliminarGrupo(String id) async {
if (id == GrupoFavoritos.sinAsignarId) return;
_grupos.removeWhere((g) => g.id == id && !g.protegido);
for (var i = 0; i < _favoritos.length; i++) {
if (_favoritos[i].grupoFavoritosId == id) {
_favoritos[i] = _favoritos[i].copyWith(
grupoFavoritosId: GrupoFavoritos.sinAsignarId,
);
}
}
}
@override
Future<void> asignarGrupo(String uuid, String grupoId) async {
final destino = _grupos.any((g) => g.id == grupoId)
? grupoId
: GrupoFavoritos.sinAsignarId;
final index = _favoritos.indexWhere((e) => e.uuid == uuid);
if (index != -1) {
_favoritos[index] = _favoritos[index].copyWith(grupoFavoritosId: destino);
}
}
@override
Future<void> reordenar(String uuid, int nuevoOrden) async {
final oldIndex = _favoritos.indexWhere((e) => e.uuid == uuid);