276 lines
8.2 KiB
Dart
276 lines
8.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../estado/estado_radio.dart';
|
|
import '../l10n/display_names.dart';
|
|
import '../l10n/gen/app_localizations.dart';
|
|
import '../modelos/emisora.dart';
|
|
import '../modelos/grupo_favoritos.dart';
|
|
import '../widgets/pluri_glass_surface.dart';
|
|
import '../widgets/pluri_icon.dart';
|
|
import '../widgets/pluri_layout.dart';
|
|
import '../widgets/pluri_premium_widgets.dart';
|
|
import 'package:pluriwave/widgets/tarjeta_emisora.dart';
|
|
|
|
import 'reproducir_minimizado.dart';
|
|
|
|
class PantallaFavoritos extends StatelessWidget {
|
|
const PantallaFavoritos({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final estado = context.watch<EstadoRadio>();
|
|
final favoritos = estado.listaFavoritos;
|
|
final grupos = estado.gruposFavoritos;
|
|
final l10n = AppLocalizations.of(context);
|
|
|
|
if (favoritos.isEmpty) {
|
|
return ListView(
|
|
padding: PluriLayout.pageListPadding,
|
|
children: [
|
|
PluriScreenHeader(
|
|
title: l10n.favoritesTitle,
|
|
subtitle: l10n.favoritesHeaderSubtitle,
|
|
glyph: PluriIconGlyph.favorites,
|
|
trailing: PluriStatusPill(
|
|
icon: Icons.favorite_rounded,
|
|
label: l10n.favoritesCollection,
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: 320,
|
|
child: PluriEmptyState(
|
|
glyph: PluriIconGlyph.favorites,
|
|
title: l10n.favoritesEmptyTitle,
|
|
subtitle: l10n.favoritesEmptySubtitle,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
final gruposVisibles = grupos.isEmpty
|
|
? [
|
|
GrupoFavoritos(
|
|
id: GrupoFavoritos.sinAsignarId,
|
|
nombre: l10n.favoriteGroupsUnassigned,
|
|
orden: 0,
|
|
protegido: true,
|
|
),
|
|
]
|
|
: grupos;
|
|
|
|
return CustomScrollView(
|
|
slivers: [
|
|
SliverToBoxAdapter(
|
|
child: PluriScreenHeader(
|
|
title: l10n.favoritesTitle,
|
|
subtitle: l10n.favoritesHeaderSubtitle,
|
|
glyph: PluriIconGlyph.favorites,
|
|
trailing: PluriStatusPill(
|
|
icon: Icons.library_music_rounded,
|
|
label: l10n.favoritesSavedCount(favoritos.length),
|
|
),
|
|
),
|
|
),
|
|
SliverPadding(
|
|
padding: const EdgeInsets.fromLTRB(
|
|
PluriLayout.horizontal,
|
|
4,
|
|
PluriLayout.horizontal,
|
|
PluriLayout.bottomChromeInset,
|
|
),
|
|
sliver: SliverList(
|
|
delegate: SliverChildListDelegate([
|
|
for (final grupo in gruposVisibles) ...[
|
|
_GrupoFavoritosPanel(
|
|
grupo: grupo,
|
|
grupos: gruposVisibles,
|
|
emisoras: favoritos
|
|
.where((e) => e.grupoFavoritosId == grupo.id)
|
|
.toList(),
|
|
),
|
|
const SizedBox(height: 12),
|
|
],
|
|
]),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _GrupoFavoritosPanel extends StatelessWidget {
|
|
const _GrupoFavoritosPanel({
|
|
required this.grupo,
|
|
required this.grupos,
|
|
required this.emisoras,
|
|
});
|
|
|
|
final GrupoFavoritos grupo;
|
|
final List<GrupoFavoritos> grupos;
|
|
final List<Emisora> emisoras;
|
|
|
|
String _nombreVisible(AppLocalizations l10n, GrupoFavoritos grupo) =>
|
|
grupo.esSinAsignar ? l10n.favoriteGroupsUnassigned : grupo.nombre;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = AppLocalizations.of(context);
|
|
final theme = Theme.of(context);
|
|
return PluriGlassSurface(
|
|
padding: const EdgeInsets.all(10),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(grupo.esSinAsignar ? Icons.lock_rounded : Icons.folder_rounded),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
_nombreVisible(l10n, grupo),
|
|
style: theme.textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w900,
|
|
),
|
|
),
|
|
),
|
|
Text('${emisoras.length}'),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
if (emisoras.isEmpty)
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 4),
|
|
child: Text(
|
|
l10n.favoritesEmptyTitle,
|
|
style: theme.textTheme.bodySmall,
|
|
),
|
|
)
|
|
else
|
|
for (var i = 0; i < emisoras.length; i++) ...[
|
|
_FavoritoItem(
|
|
emisora: emisoras[i],
|
|
grupos: grupos,
|
|
grupoActual: grupo,
|
|
),
|
|
if (i < emisoras.length - 1) const SizedBox(height: 8),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _FavoritoItem extends StatelessWidget {
|
|
const _FavoritoItem({
|
|
required this.emisora,
|
|
required this.grupos,
|
|
required this.grupoActual,
|
|
});
|
|
|
|
final Emisora emisora;
|
|
final List<GrupoFavoritos> grupos;
|
|
final GrupoFavoritos grupoActual;
|
|
|
|
String _nombreVisible(AppLocalizations l10n, GrupoFavoritos grupo) =>
|
|
grupo.esSinAsignar ? l10n.favoriteGroupsUnassigned : grupo.nombre;
|
|
|
|
Future<void> _asignar(BuildContext context) async {
|
|
final l10n = AppLocalizations.of(context);
|
|
final seleccionado = await showModalBottomSheet<String>(
|
|
context: context,
|
|
showDragHandle: true,
|
|
builder: (ctx) => SafeArea(
|
|
child: ListView(
|
|
shrinkWrap: true,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(20, 4, 20, 12),
|
|
child: Text(
|
|
l10n.favoriteGroupsAssign,
|
|
style: Theme.of(ctx).textTheme.titleLarge,
|
|
),
|
|
),
|
|
for (final grupo in grupos)
|
|
ListTile(
|
|
leading: Icon(
|
|
grupo.id == emisora.grupoFavoritosId
|
|
? Icons.radio_button_checked_rounded
|
|
: Icons.radio_button_off_rounded,
|
|
),
|
|
title: Text(_nombreVisible(l10n, grupo)),
|
|
onTap: () => Navigator.pop(ctx, grupo.id),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
if (seleccionado == null || !context.mounted) return;
|
|
await context.read<EstadoRadio>().asignarGrupoFavorito(
|
|
emisora.uuid,
|
|
seleccionado,
|
|
);
|
|
if (!context.mounted) return;
|
|
final destino = grupos.firstWhere((g) => g.id == seleccionado);
|
|
final stationName = localizedStationName(l10n, emisora.nombre);
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
l10n.favoriteGroupsAssigned(
|
|
stationName,
|
|
_nombreVisible(l10n, destino),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _eliminar(BuildContext context) async {
|
|
final l10n = AppLocalizations.of(context);
|
|
final estado = context.read<EstadoRadio>();
|
|
final stationName = localizedStationName(l10n, emisora.nombre);
|
|
await estado.favoritos.eliminar(emisora.uuid);
|
|
await estado.cargarFavoritos();
|
|
if (!context.mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text(l10n.favoritesRemovedMessage(stationName))),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = AppLocalizations.of(context);
|
|
return Row(
|
|
children: [
|
|
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),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|