feat(favoritos): replace stacked group panels with chip-filtered reorderable list
Replaces the stacked per-group panel layout with a single
chip-filtered flat list. Chips read "{name} · {count}" (new ARB keys
favoriteGroupsChipLabel/favoritesFilterAllLabel), one per group plus
an "All" chip. Rows drag-reorder via a leading handle
(ReorderableDragStartListener, buildDefaultDragHandles: false) using
the modern onReorderItem callback rather than the now-@Deprecated
onReorder (Flutter 3.44 marks it obsolete).
EstadoRadio additions: listaFavoritosManual (a new memoized getter
returning the stored order untouched by the global ordenListas
setting - listaFavoritos itself always re-sorts by
name/quality on every read, which would silently discard any
drag-to-reorder), reordenarFavorito (thin wrapper over the
already-existing ServicioFavoritos.reordenar, previously unused
outside its own service test), and ordenarFavoritos (applies an
existing OrdenEmisoras criterion via ordenarEmisoras() and persists
the result as the new manual order, so the swap_vert sort action's
result also survives a restart). listaFavoritos itself is untouched,
so Android Auto's tree and the future Escuchar grid (WU5) are
unaffected by Favoritos' own manual order.
Group management: an "Manage lists" action chip pushes the existing
PantallaAjustesGruposFavoritos screen (Settings' own screen, reused
rather than duplicated) - a second entry point to the same screen.
Custom-station CTA: a new dashed-bordered card opens the add-station
form directly; that form was renamed from private _FormularioEmisora
to public FormularioEmisoraPersonalizada in
pantalla_ajustes_emisoras_personalizadas.dart so both screens share
one implementation. New ARB keys: favoriteGroupsManage,
customStationsAddCta.
Tests: pantalla_favoritos_plural_test.dart (the file tasks.md named)
never imported PantallaFavoritos - it only covers stationCount's ARB
plural formatting, unrelated to this screen. Left it untouched and
added test/pantallas/pantalla_favoritos_test.dart instead: 3
state-layer tests for the new EstadoRadio surface plus 6 widget
scenarios (empty-state CTA, chip filter, drag-reorder persistence,
sort action, group management + chip reactivity, custom-station
CTA). 604 -> 614 tests (2 skipped, unchanged). flutter analyze
unchanged at 1 pre-existing info.
Recorded in tasks.md with the test-file correction and the
design decisions this WU had to make on its own (no ADR covers
Favoritos' manual-order persistence).
This commit is contained in:
@@ -164,6 +164,7 @@ class EstadoRadio extends ChangeNotifier {
|
||||
final _memoPopulares = MemoLista<Emisora>();
|
||||
final _memoTendencias = MemoLista<Emisora>();
|
||||
final _memoFavoritos = MemoLista<Emisora>();
|
||||
final _memoFavoritosManual = MemoLista<Emisora>();
|
||||
final _memoGrupos = MemoLista<GrupoFavoritos>();
|
||||
final _memoCustom = MemoLista<Emisora>();
|
||||
final _memoInicio = MemoLista<Emisora>();
|
||||
@@ -200,6 +201,17 @@ class EstadoRadio extends ChangeNotifier {
|
||||
_listaFavoritos,
|
||||
_ordenListas,
|
||||
], () => ordenarEmisoras(_listaFavoritos, _ordenListas));
|
||||
|
||||
/// WU4, `favorites-organization` spec: Favoritos' own manual order —
|
||||
/// unlike [listaFavoritos], this is NOT re-sorted by the global
|
||||
/// [ordenListas] setting on every read. It reflects exactly the order
|
||||
/// stored via the `orden` column (`ServicioFavoritos.obtenerTodos()`),
|
||||
/// which [reordenarFavorito] and [ordenarFavoritos] mutate. Other
|
||||
/// consumers of `listaFavoritos` (Android Auto, the Escuchar grid) are
|
||||
/// unaffected by drag-reordering Favoritos.
|
||||
List<Emisora> get listaFavoritosManual => _memoFavoritosManual.obtener([
|
||||
_listaFavoritos,
|
||||
], () => List<Emisora>.unmodifiable(_listaFavoritos));
|
||||
List<GrupoFavoritos> get gruposFavoritos => _memoGrupos.obtener([
|
||||
_gruposFavoritos,
|
||||
], () => List<GrupoFavoritos>.unmodifiable(_gruposFavoritos));
|
||||
@@ -371,6 +383,30 @@ class EstadoRadio extends ChangeNotifier {
|
||||
await cargarFavoritos();
|
||||
}
|
||||
|
||||
/// WU4: persists a single drag-to-reorder move within [listaFavoritosManual].
|
||||
/// [nuevoIndice] is the absolute target position among ALL favorites (not
|
||||
/// scoped to any chip filter) — the screen translates a filtered-list drag
|
||||
/// into this global index before calling this method.
|
||||
Future<void> reordenarFavorito(String uuid, int nuevoIndice) async {
|
||||
await favoritos.reordenar(uuid, nuevoIndice);
|
||||
await cargarFavoritos();
|
||||
}
|
||||
|
||||
/// WU4: the Favoritos `swap_vert` sort action. Reuses the existing
|
||||
/// [OrdenEmisoras] criteria and [ordenarEmisoras] function — "It MUST NOT
|
||||
/// introduce a sort criterion with no backing implementation"
|
||||
/// (favorites-organization spec). Unlike [ordenListas] (a GLOBAL setting
|
||||
/// affecting favorites/searches/nearby/quick-lists), this sorts ONLY the
|
||||
/// favorites list once and PERSISTS the result as the new manual order —
|
||||
/// consistent with [reordenarFavorito]'s "the order MUST persist" contract.
|
||||
Future<void> ordenarFavoritos(OrdenEmisoras criterio) async {
|
||||
final ordenados = ordenarEmisoras(_listaFavoritos, criterio);
|
||||
for (var i = 0; i < ordenados.length; i++) {
|
||||
await favoritos.reordenar(ordenados[i].uuid, i);
|
||||
}
|
||||
await cargarFavoritos();
|
||||
}
|
||||
|
||||
Future<void> cambiarEmisoraPreferida(Emisora? emisora) async {
|
||||
_emisoraPreferidaUuid = emisora?.uuid;
|
||||
final prefs = await _resolverPrefs();
|
||||
|
||||
Reference in New Issue
Block a user