feat(tokens): add design tokens, type scale, push scaffold, and root nav state

This commit is contained in:
2026-07-28 20:01:23 +02:00
parent 6dba89432e
commit 172b2a42ac
17 changed files with 856 additions and 30 deletions
+13 -8
View File
@@ -8,6 +8,7 @@ import 'estado/estado_grabacion.dart';
import 'estado/estado_radio.dart';
import 'estado/estado_alarmas.dart';
import 'estado/estado_idioma.dart';
import 'estado/estado_navegacion.dart';
import 'l10n/display_names.dart';
import 'l10n/gen/app_localizations.dart';
import 'modelos/alarma_musical.dart';
@@ -70,6 +71,9 @@ class PluriWaveApp extends StatelessWidget {
ChangeNotifierProvider(
create: (_) => EstadoIdioma(sharedPreferences: prefs),
),
// Design ADR-8: root-to-root navigation state. `_PaginaPrincipal`
// watches this instead of owning `_indice` locally.
ChangeNotifierProvider(create: (_) => EstadoNavegacionRaiz()),
],
child: Consumer<EstadoIdioma>(
builder:
@@ -98,7 +102,6 @@ class _PaginaPrincipal extends StatefulWidget {
class _PaginaPrincipalState extends State<_PaginaPrincipal>
with WidgetsBindingObserver {
int _indice = 0;
StreamSubscription<String>? _errorSubscription;
StreamSubscription<EventoAlarmaAndroid>? _alarmaSubscription;
StreamSubscription<AlarmaMusical>? _alarmaVencidaSubscription;
@@ -206,6 +209,8 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final navegacion = context.watch<EstadoNavegacionRaiz>();
final indice = navegacion.indice;
return PluriWaveScaffold(
appBar: AppBar(
@@ -236,8 +241,8 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
),
),
child: KeyedSubtree(
key: ValueKey<int>(_indice),
child: _paginas[_indice],
key: ValueKey<int>(indice),
child: _paginas[indice],
),
),
),
@@ -252,8 +257,8 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
const MiniReproductor(),
PluriBottomNavigation(
items: _navItems(l10n),
selectedIndex: _indice,
onSelected: (i) => setState(() => _indice = i),
selectedIndex: indice,
onSelected: (i) => navegacion.irA(RaizPluriWave.values[i]),
),
],
),
@@ -307,7 +312,7 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
if (evento.accion.endsWith('.SKIP_NEXT')) {
await estado.saltarProxima(alarma.id);
if (!mounted) return;
setState(() => _indice = 3);
context.read<EstadoNavegacionRaiz>().irA(RaizPluriWave.alarmas);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
@@ -330,7 +335,7 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
ejecucion,
);
if (!mounted) return;
setState(() => _indice = 3);
context.read<EstadoNavegacionRaiz>().irA(RaizPluriWave.alarmas);
// posponerProximaDesdePreaviso no longer throws on a native scheduling
// failure — it records the failure into EstadoAlarmas.error instead.
// Branch on it here so the user sees the real outcome instead of an
@@ -347,7 +352,7 @@ class _PaginaPrincipalState extends State<_PaginaPrincipal>
return;
}
if (evento.accion.endsWith('.PRE_NOTICE')) {
setState(() => _indice = 3);
context.read<EstadoNavegacionRaiz>().irA(RaizPluriWave.alarmas);
return;
}
await _mostrarAlarmaSonando(alarma);