fix(favoritos,grabaciones): replace glass cards with flat rows

Item 23 / audit 4.3, 12.4 (t4:226-232, 616-619): Favoritos and
Grabaciones rows were full glass cards / ListTiles with two stacked
buttons and no artwork slot. Replace with flat, background-less rows
via a new shared FilaEmisoraPlana widget (square art, name+meta, a
circular play affordance) plus a bespoke Grabaciones row (44x12
placeholder art -- recordings carry no per-station favicon, so this
is a themed fallback, not invented artwork).

Favoritos keeps "Move to list" / "Remove from favorites" behind an
overflow menu (same underlying methods, unchanged) instead of two
always-visible buttons, since dropping either would be a functional
regression the prototype's own row doesn't have to solve for.

Also 12.1 (t4:610): the Grabaciones header action is folder_open, not
a generic gear.
This commit is contained in:
2026-07-30 11:46:55 +02:00
parent 4537497e83
commit 955682271c
6 changed files with 727 additions and 92 deletions
+59 -39
View File
@@ -6,13 +6,13 @@ import '../l10n/display_names.dart';
import '../l10n/gen/app_localizations.dart';
import '../modelos/emisora.dart';
import '../modelos/grupo_favoritos.dart';
import '../widgets/fila_emisora_plana.dart';
import '../widgets/pluri_icon.dart';
import '../widgets/pluri_layout.dart';
import '../widgets/pluri_premium_widgets.dart';
import '../widgets/pluri_push_scaffold.dart';
import '../widgets/pluri_root_header.dart';
import '../widgets/pluri_sleep_timer_sheet.dart';
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
import 'ajustes/pantalla_ajustes_emisoras_personalizadas.dart';
import 'ajustes/pantalla_ajustes_grupos_favoritos.dart';
@@ -399,45 +399,65 @@ class _FilaFavorito extends StatelessWidget {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
ReorderableDragStartListener(
index: index,
child: const Padding(
padding: EdgeInsets.only(right: 4),
child: Icon(Icons.drag_handle_rounded),
),
),
Expanded(
child: TarjetaEmisora(
key: Key(emisora.uuid),
emisora: emisora,
esCompacta: true,
onTap: () => reproducirMinimizado(context, emisora),
),
),
const SizedBox(width: 6),
Column(
mainAxisSize: MainAxisSize.min,
children: [
IconButton.filledTonal(
tooltip: l10n.favoriteGroupsAssignSubtitle(
_nombreVisible(l10n, grupoActual),
),
icon: const Icon(Icons.drive_file_move_rounded),
onPressed: () => _asignar(context),
),
IconButton.filledTonal(
tooltip: l10n.favoritesRemoveTooltip,
icon: const Icon(Icons.delete_outline_rounded),
onPressed: () => _eliminar(context),
),
],
),
],
final meta = [
emisora.pais,
emisora.idioma,
].where((s) => s != null && s.isNotEmpty).join(' · ');
// Item 23 / audit 4.3 (t4:226-232): a flat, background-less row --
// drag handle, square art, name+meta, and a circular play affordance --
// replacing the full glass TarjetaEmisora card and its two stacked
// filledTonal buttons. "Move to list"/"Remove from favorites" keep their
// EXACT prior logic (`_asignar`/`_eliminar`, untouched), now reachable
// from an overflow menu instead of two always-visible buttons -- the
// prototype's row has no such menu, but dropping either capability
// entirely would be a functional regression, not a fidelity fix.
return FilaEmisoraPlana(
key: Key(emisora.uuid),
emisora: emisora,
meta: meta,
onTap: () => reproducirMinimizado(context, emisora),
leading: ReorderableDragStartListener(
index: index,
child: Icon(
// t4:227: drag_indicator, not drag_handle, at 22px/28%.
Icons.drag_indicator_rounded,
size: 22,
color: Theme.of(
context,
).colorScheme.onSurface.withValues(alpha: 0.28),
),
),
trailing: [
BotonReproducirCircular(
onPressed: () => reproducirMinimizado(context, emisora),
),
PopupMenuButton<String>(
icon: Icon(
Icons.more_vert_rounded,
size: 20,
color: Theme.of(
context,
).colorScheme.onSurface.withValues(alpha: 0.45),
),
constraints: const BoxConstraints.tightFor(width: 38, height: 42),
onSelected: (accion) {
if (accion == 'assign') _asignar(context);
if (accion == 'remove') _eliminar(context);
},
itemBuilder:
(context) => [
PopupMenuItem(
value: 'assign',
child: Text(l10n.favoriteGroupsAssign),
),
PopupMenuItem(
value: 'remove',
child: Text(l10n.favoritesRemoveTooltip),
),
],
),
],
);
}
}