No se puede marcar “vista” sin revelar la palabra antes. Se puede volver a ver la palabra durante debate/votación/resultado. Notas online privadas por partida y jugador. Tests añadidos para notas scoped. Ajusté roomId en el payload de inicio para que las notas no se mezclen entre partidas.
152 lines
5.2 KiB
Dart
152 lines
5.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:farolero/l10n/generated/app_localizations.dart';
|
|
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
|
|
import 'package:farolero/tema/componentes_farolero.dart';
|
|
import 'package:farolero/tema/tema_app.dart';
|
|
|
|
/// Reveal secuencial para clientes que manejan uno o varios jugadores.
|
|
class PantallaPalabrasCliente extends StatefulWidget {
|
|
final List<JugadorInicioPartida> jugadores;
|
|
final String? pistaCategoria;
|
|
final VoidCallback onTodosVistos;
|
|
|
|
const PantallaPalabrasCliente({
|
|
super.key,
|
|
required this.jugadores,
|
|
this.pistaCategoria,
|
|
required this.onTodosVistos,
|
|
});
|
|
|
|
@override
|
|
State<PantallaPalabrasCliente> createState() => _PantallaPalabrasClienteState();
|
|
}
|
|
|
|
class _PantallaPalabrasClienteState extends State<PantallaPalabrasCliente> {
|
|
int _indice = 0;
|
|
bool _visible = false;
|
|
final Set<String> _jugadoresRevelados = {};
|
|
|
|
JugadorInicioPartida get _actual => widget.jugadores[_indice];
|
|
bool get _esUltimo => _indice == widget.jugadores.length - 1;
|
|
bool get _actualRevelado => _jugadoresRevelados.contains(_actual.jugadorId);
|
|
|
|
void _continuar() {
|
|
if (!_actualRevelado) return;
|
|
if (_esUltimo) {
|
|
widget.onTodosVistos();
|
|
return;
|
|
}
|
|
setState(() {
|
|
_indice++;
|
|
_visible = false;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = AppLocalizations.of(context)!;
|
|
final actual = _actual;
|
|
|
|
return Scaffold(
|
|
body: FondoFarolero(
|
|
intenso: true,
|
|
child: SafeArea(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(24),
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
'Jugador ${_indice + 1} de ${widget.jugadores.length}',
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
const Spacer(),
|
|
Text(
|
|
actual.nombre,
|
|
style: Theme.of(context).textTheme.headlineMedium,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
const SizedBox(height: 24),
|
|
GestureDetector(
|
|
onTap: () => setState(() {
|
|
_visible = !_visible;
|
|
if (_visible) _jugadoresRevelados.add(actual.jugadorId);
|
|
}),
|
|
child: AnimatedContainer(
|
|
duration: const Duration(milliseconds: 250),
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 48,
|
|
horizontal: 24,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: _visible ? TemaApp.colorSuperficie : TemaApp.colorTarjeta,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(
|
|
color: _visible ? TemaApp.colorNaranja : TemaApp.colorBorde,
|
|
),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Icon(
|
|
_visible ? Icons.visibility : Icons.visibility_off,
|
|
color: _visible ? Colors.white : TemaApp.colorTextoSecundario,
|
|
size: 32,
|
|
),
|
|
const SizedBox(height: 16),
|
|
if (_visible && !actual.esImpostor)
|
|
TarjetaPalabraFarolero(palabra: actual.palabra ?? '')
|
|
else
|
|
Text(
|
|
_visible ? l10n.youAreImpostor : '???',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
fontSize: 32,
|
|
fontWeight: FontWeight.bold,
|
|
color: _visible
|
|
? TemaApp.colorDorado
|
|
: TemaApp.colorTextoSecundario,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
if (_visible && actual.esImpostor && widget.pistaCategoria != null) ...[
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
l10n.clueIs(widget.pistaCategoria!),
|
|
style: const TextStyle(color: TemaApp.colorNaranja),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
const SizedBox(height: 12),
|
|
Text(
|
|
_actualRevelado
|
|
? l10n.seeYourWord
|
|
: l10n.tapToSee,
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(color: TemaApp.colorTextoSecundario),
|
|
),
|
|
const Spacer(),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
height: 56,
|
|
child: ElevatedButton.icon(
|
|
onPressed: _actualRevelado ? _continuar : null,
|
|
icon: Icon(_esUltimo ? Icons.check : Icons.arrow_forward),
|
|
label: Text(
|
|
_actualRevelado
|
|
? (_esUltimo ? l10n.iveSeenIt : l10n.next)
|
|
: l10n.tapToSee,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|