Files
pluriwave/lib/pantallas/ajustes/pantalla_ajustes_idioma.dart
T
FreeTLab e0164f68b5 fix(ajustes): show each settings row's current value
The prototype puts a trailing current-value string on nearly every
settings row (t4 lines 512-539, 625 -- "3 guardados", "Alfabetico",
"Espanol", "7 . 84 MB"). FilaAjuste only accepted icon/titulo/onTap,
so every row was value-blind.

Add an optional `valor` slot to FilaAjuste (13px, rgba(242,247,250,.55),
rendered before the chevron). Wire 8 of the 12 built rows to state
already available at the settings root: equalizer on/off, sleep-timer
active, favourite-group count, preferred station name, custom-station
count, sort order, recordings count-and-size (FutureBuilder over
EstadoGrabacion.listarGrabaciones), and the current language (hoisted
pantalla_ajustes_idioma.dart's native-name list to module level so the
root can read it without duplicating it). Salida de audio, Musica
local, Backup and Info's version are left without a value -- each
lacks a low-risk, deterministically-testable data source (see the
apply-progress note for the reason per row).

Reading EstadoRadio for these values through a root `context.watch`
would rebuild the whole settings list -- including the Grabaciones
FutureBuilder's disk read -- on every unrelated audio notification;
this follows the codebase's existing S4-R5 convention of narrow
`context.select` per field instead.

Ajustes' own PluriRootHeader/PluriScreenHeader edit (S2 in this same
pass) landed in this commit too, since both touched the same header
block in pantalla_ajustes.dart at the same time.

S8, Tier 1 visual-fidelity pass (audit id 2521).
2026-07-29 21:26:48 +02:00

152 lines
5.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../estado/estado_idioma.dart';
import '../../l10n/gen/app_localizations.dart';
import '../../widgets/pluri_glass_surface.dart';
import '../../widgets/pluri_layout.dart';
import '../../widgets/pluri_push_scaffold.dart';
/// APLICACIÓN group · "Idioma" (design ADR-3). Body moved verbatim from the
/// former `_SeccionIdioma` (+ `_IdiomaDisponible`) in `pantalla_ajustes.dart`
/// — only the panel header's icon and title were removed (the pushed
/// screen's title now carries them); every method and the language list
/// below is unchanged.
class PantallaAjustesIdioma extends StatelessWidget {
const PantallaAjustesIdioma({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return PluriPushScaffold(
title: l10n.languageSectionTitle,
body: ListView(
padding: PluriLayout.pageContentPadding,
children: const [_CuerpoIdioma()],
),
);
}
}
/// S8 (Tier 1 visual fidelity): the "system" pseudo-code, the native-name
/// list and the locale<->code mapping used to be private to this file's
/// `_CuerpoIdioma`. Hoisted to module level (unchanged values/logic) so
/// `pantalla_ajustes.dart`'s Idioma row can show the CURRENT language's
/// native name as its trailing value (t4's own example, line 526:
/// "Español") without duplicating this list.
const codigoIdiomaSistema = 'system';
const idiomasDisponibles = [
IdiomaDisponible(Locale('en'), 'English'),
IdiomaDisponible(Locale('es'), 'Español'),
IdiomaDisponible(Locale('zh'), '中文'),
IdiomaDisponible(Locale('hi'), 'हिन्दी'),
IdiomaDisponible(Locale('ar'), 'العربية'),
IdiomaDisponible(Locale('pt'), 'Português'),
IdiomaDisponible(Locale('fr'), 'Français'),
IdiomaDisponible(Locale('ru'), 'Русский'),
IdiomaDisponible(Locale('de'), 'Deutsch'),
IdiomaDisponible(Locale('ja'), '日本語'),
IdiomaDisponible(Locale('id'), 'Bahasa Indonesia'),
IdiomaDisponible(Locale('bn'), 'বাংলা'),
IdiomaDisponible(Locale('it'), 'Italiano'),
];
String codigoLocaleIdioma(Locale locale) {
final countryCode = locale.countryCode;
if (countryCode == null || countryCode.isEmpty) {
return locale.languageCode;
}
return '${locale.languageCode}_$countryCode';
}
/// The current language's own native name (e.g. "Español"), or the
/// localized "system default" label when [locale] is null.
String nombreIdiomaActual(Locale? locale, AppLocalizations l10n) {
if (locale == null) return l10n.languageSystemDefault;
final codigo = codigoLocaleIdioma(locale);
final idioma = idiomasDisponibles.firstWhere(
(item) => codigoLocaleIdioma(item.locale) == codigo,
orElse: () => idiomasDisponibles.first,
);
return idioma.nombreNativo;
}
class _CuerpoIdioma extends StatelessWidget {
const _CuerpoIdioma();
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final estadoIdioma = context.watch<EstadoIdioma>();
final locale = estadoIdioma.localeSeleccionado;
final valorActual =
locale == null ? codigoIdiomaSistema : codigoLocaleIdioma(locale);
return PluriGlassSurface(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
Text(
l10n.languageSectionDescription,
style: Theme.of(context).textTheme.bodySmall,
),
const SizedBox(height: 12),
DropdownButtonFormField<String>(
initialValue: valorActual,
decoration: InputDecoration(
labelText: l10n.languageSectionTitle,
border: const OutlineInputBorder(),
),
items: [
DropdownMenuItem(
value: codigoIdiomaSistema,
child: Text(l10n.languageSystemDefault),
),
for (final idioma in idiomasDisponibles)
DropdownMenuItem(
value: codigoLocaleIdioma(idioma.locale),
child: Text(idioma.nombreNativo),
),
],
onChanged: (codigo) async {
if (codigo == null) return;
if (codigo == codigoIdiomaSistema) {
await context.read<EstadoIdioma>().seleccionarSistema();
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(l10n.languageUpdatedSystem)),
);
return;
}
final idioma = idiomasDisponibles.firstWhere(
(item) => codigoLocaleIdioma(item.locale) == codigo,
orElse: () => idiomasDisponibles.first,
);
await context.read<EstadoIdioma>().seleccionarLocale(
idioma.locale,
);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(l10n.languageUpdated(idioma.nombreNativo)),
),
);
},
),
],
),
);
}
}
class IdiomaDisponible {
const IdiomaDisponible(this.locale, this.nombreNativo);
final Locale locale;
final String nombreNativo;
}