Files
pluriwave/lib/widgets/pluri_onboarding_dialog.dart
T
FreeTLab 089b8b4227
Build & Deploy PluriWave / Análisis de código (push) Successful in 38s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 2m34s
fix(i18n): normalize translations and fallbacks
2026-06-03 21:20:08 +02:00

145 lines
4.8 KiB
Dart

import 'package:flutter/material.dart';
import '../l10n/gen/app_localizations.dart';
import '../servicios/servicio_contenido_app.dart';
import 'pluri_glass_surface.dart';
import 'pluri_markdown.dart';
class PluriOnboardingDialog {
PluriOnboardingDialog._();
static final _servicio = ServicioContenidoApp();
static Future<void> mostrarSiProcede(BuildContext context) async {
if (!await _servicio.debeMostrarInicio()) return;
if (!context.mounted) return;
await mostrar(context, soloPendientes: true);
await _servicio.marcarVisto();
}
static Future<void> mostrar(
BuildContext context, {
bool soloPendientes = false,
}) async {
final idioma = Localizations.localeOf(context).languageCode;
final contenido = await _servicio.cargar(
idioma,
soloPendientes: soloPendientes,
);
if (!context.mounted) return;
await showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) => _PluriOnboardingContent(contenido: contenido),
);
}
}
class _PluriOnboardingContent extends StatelessWidget {
const _PluriOnboardingContent({required this.contenido});
final ContenidoAyudaPluri contenido;
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
final size = MediaQuery.sizeOf(context);
return Dialog(
insetPadding: const EdgeInsets.all(16),
backgroundColor: Colors.transparent,
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 720,
maxHeight: size.height * 0.86,
),
child: PluriGlassSurface(
borderRadius: BorderRadius.circular(32),
glowColor: Theme.of(
context,
).colorScheme.primary.withValues(alpha: 0.28),
child: Column(
children: [
Row(
children: [
Container(
width: 54,
height: 54,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.tertiary,
],
),
),
child: const Icon(
Icons.graphic_eq_rounded,
color: Colors.white,
),
),
const SizedBox(width: 14),
Expanded(
child: Text(
l10n.onboardingTitle,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w900,
),
),
),
IconButton(
tooltip: l10n.onboardingCloseTooltip,
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(Icons.close_rounded),
),
],
),
const SizedBox(height: 12),
Expanded(
child: ListView(
children: [
if (contenido.onboarding.trim().isNotEmpty)
PluriMarkdown(contenido.onboarding),
if (contenido.notas.isNotEmpty) ...[
const SizedBox(height: 18),
Text(
l10n.onboardingNewsTitle,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 8),
for (final nota in contenido.notas)
ExpansionTile(
tilePadding: EdgeInsets.zero,
title: Text('v${nota.version}'),
subtitle:
nota.resumen.isEmpty ? null : Text(nota.resumen),
children: [
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: PluriMarkdown(nota.markdown),
),
],
),
],
],
),
),
const SizedBox(height: 12),
Align(
alignment: Alignment.centerRight,
child: FilledButton.icon(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(Icons.check_rounded),
label: Text(l10n.onboardingStartAction),
),
),
],
),
),
),
);
}
}