import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../estado/estado_busqueda.dart'; import '../l10n/gen/app_localizations.dart'; import '../modelos/pais_radio.dart'; import '../widgets/pluri_glass_surface.dart'; import '../widgets/pluri_layout.dart'; import '../widgets/pluri_push_scaffold.dart'; /// WU7, `station-discovery-browse` spec — "Países Browser Over the Verified /// Countries Contract". Pure display over `EstadoBusqueda.cargarPaises()` /// (in-memory cache guard, so re-entering this screen never re-fetches): /// a "Tus idiomas" shortlist above the full alphabetical list, both with /// live station counts already parsed from the API's `stationcount` /// **string** field (`PaisRadio.fromApi`, Engram id 2500). class PantallaPaises extends StatefulWidget { const PantallaPaises({super.key}); @override State createState() => _PantallaPaisesState(); } class _PantallaPaisesState extends State { /// One representative country per app-supported locale (the same 13 /// locales as `pantalla_ajustes_idioma.dart`'s `_idiomas` list). "Tus /// idiomas" is named by the proposal/spec but its derivation is not /// otherwise specified — this reuses the app's own existing language /// identity rather than inventing a separate curated country list. static const _paisPorIdioma = { 'en': 'US', 'es': 'ES', 'zh': 'CN', 'hi': 'IN', 'ar': 'SA', 'pt': 'PT', 'fr': 'FR', 'ru': 'RU', 'de': 'DE', 'ja': 'JP', 'id': 'ID', 'bn': 'BD', 'it': 'IT', }; @override void initState() { super.initState(); // `cargarPaises()` calls `notifyListeners()` before its first `await` // (its loading-flag flip) — doing that synchronously inside `initState` // would trigger "setState() or markNeedsBuild() called during build." // Deferred to a post-frame callback, matching the established pattern // for triggering a load from a screen's `initState`/`build` // (`pantalla_alarmas.dart`'s `_favoritosSolicitados` guard). WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) context.read().cargarPaises(); }); } @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); final estado = context.watch(); return PluriPushScaffold( title: l10n.countriesScreenTitle, body: estado.cargandoPaises && estado.paises.isEmpty ? const Center(child: CircularProgressIndicator()) : ListView( padding: PluriLayout.pageContentPadding, children: [ _seccionTusIdiomas(context, estado.paises, l10n), const SizedBox(height: 16), _seccionTodos(context, estado.paises, l10n), ], ), ); } Widget _seccionTusIdiomas( BuildContext context, List paises, AppLocalizations l10n, ) { final porCodigo = {for (final p in paises) p.codigoIso: p}; final destacados = _paisPorIdioma.values .map((codigo) => porCodigo[codigo]) .whereType() .toList(); if (destacados.isEmpty) return const SizedBox.shrink(); final theme = Theme.of(context); return PluriGlassSurface( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.countriesYourLanguagesTitle, style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w900, ), ), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 8, children: [ for (final pais in destacados) Chip( label: Text( '${pais.nombre} · ${l10n.stationsCount(pais.numeroEmisoras)}', ), ), ], ), ], ), ); } Widget _seccionTodos( BuildContext context, List paises, AppLocalizations l10n, ) { final theme = Theme.of(context); return PluriGlassSurface( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.countriesAllTitle, style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.w900, ), ), const SizedBox(height: 4), ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: paises.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, i) { final pais = paises[i]; return ListTile( contentPadding: EdgeInsets.zero, title: Text(pais.nombre), trailing: Text(l10n.stationsCount(pais.numeroEmisoras)), ); }, ), ], ), ); } }