Files
farolero/lib/pantallas/pantalla_adivinanza.dart
ShanaiaBot 1bca50af1d v0.2.0: i18n 18 idiomas + pantalla ajustes + bancos multiidioma
Internacionalización completa:
- 18 ficheros .arb: es, en, fr, pt, de, it, ru, ja, ko, zh, zh_TW, ar, hi, tr, pl, nl, ca, eu
- Todos los strings extraídos de todas las pantallas
- Detección automática de idioma del sistema
- Selector manual en pantalla de ajustes

Pantalla de ajustes nueva:
- Selector de idioma con banderas emoji
- Vibración ON/OFF
- Acerca de (versión, desarrollador)

Bancos de palabras multiidioma:
- palabras.json (castellano, 1000 palabras)
- palabras_en.json (inglés, 1000 palabras)
- palabras_fr.json (francés, 1000 palabras)
- Fallback a castellano si no hay banco del idioma

13138 líneas Dart, 39 ficheros, 0 issues en flutter analyze
2026-04-04 01:18:09 +02:00

239 lines
8.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:el_impostor/l10n/generated/app_localizations.dart';
import 'package:provider/provider.dart';
import '../estado/estado_juego.dart';
import '../tema/tema_app.dart';
import 'pantalla_debate.dart';
import 'pantalla_fin_partida.dart';
class PantallaAdivinanza extends StatefulWidget {
const PantallaAdivinanza({super.key});
@override
State<PantallaAdivinanza> createState() => _PantallaAdivinanzaState();
}
class _PantallaAdivinanzaState extends State<PantallaAdivinanza> {
final _controlador = TextEditingController();
bool? _acierto;
@override
void dispose() {
_controlador.dispose();
super.dispose();
}
void _intentarAdivinar() {
final estado = context.read<EstadoJuego>();
final resultado = estado.intentarAdivinar(_controlador.text);
setState(() => _acierto = resultado);
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final estado = context.watch<EstadoJuego>();
final partida = estado.partida;
if (partida == null) return const SizedBox.shrink();
return Scaffold(
appBar: AppBar(
title: Text(l10n.impostorGuessTitle),
automaticallyImplyLeading: false,
),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('🎭', style: TextStyle(fontSize: 64)),
const SizedBox(height: 16),
Text(
l10n.impostorCanGuess,
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
l10n.ifCorrectImpostorsWin,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: TemaApp.colorNaranja,
),
),
const SizedBox(height: 32),
if (_acierto == null) ...[
TextField(
controller: _controlador,
decoration: InputDecoration(
hintText: l10n.guessWordHint,
prefixIcon: const Icon(Icons.search),
),
textCapitalization: TextCapitalization.sentences,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20),
onSubmitted: (_) => _intentarAdivinar(),
),
const SizedBox(height: 24),
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {
// No intenta adivinar, siguiente ronda
final fin = estado.comprobarFinPartida();
if (fin) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const PantallaFinPartida(),
),
);
} else {
estado.siguienteRonda();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const PantallaDebate(),
),
);
}
},
child: Text(l10n.dontGuess),
),
),
const SizedBox(width: 12),
Expanded(
flex: 2,
child: ElevatedButton.icon(
onPressed: _controlador.text.trim().isNotEmpty
? _intentarAdivinar
: null,
icon: const Icon(Icons.send),
label: Text(l10n.guess),
),
),
],
),
],
if (_acierto == true) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: TemaApp.colorAcento.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: TemaApp.colorAcento),
),
child: Column(
children: [
const Text('🎭🎉', style: TextStyle(fontSize: 48)),
const SizedBox(height: 12),
Text(
l10n.correctGuess,
style: Theme.of(context)
.textTheme
.headlineMedium
?.copyWith(color: TemaApp.colorAcento),
),
const SizedBox(height: 8),
Text(
l10n.theWordWas(partida.palabraSecreta),
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 8),
Text(
l10n.impostorsWin,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: TemaApp.colorNaranja,
),
),
],
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const PantallaFinPartida(),
),
);
},
icon: const Icon(Icons.emoji_events),
label: Text(l10n.seeEndResult),
),
),
],
if (_acierto == false) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: TemaApp.colorVerde.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: TemaApp.colorVerde),
),
child: Column(
children: [
const Text('', style: TextStyle(fontSize: 48)),
const SizedBox(height: 12),
Text(
l10n.wrongGuess,
style: Theme.of(context)
.textTheme
.headlineMedium
?.copyWith(color: TemaApp.colorVerde),
),
const SizedBox(height: 8),
Text(
l10n.gameContinues,
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () {
final fin = estado.comprobarFinPartida();
if (fin) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const PantallaFinPartida(),
),
);
} else {
estado.siguienteRonda();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => const PantallaDebate(),
),
);
}
},
icon: const Icon(Icons.skip_next),
label: Text(l10n.nextRound),
),
),
],
],
),
),
),
);
}
}