Files
farolero/lib/pantallas/pantalla_palabras_cliente.dart
Javier Bautista Fernández a8d5b0f002
Some checks failed
Build & Deploy Farolero / Análisis de código (push) Has been cancelled
Build & Deploy Farolero / Build APK + AAB release (push) Has been cancelled
feat: Implement multiplayer game session management
- Add models for managing player assignments and game session initialization in `inicio_partida_multijugador.dart`.
- Create a multiplayer room state management system in `sala_multijugador.dart`, including user registration, selection, and session validation.
- Develop a UI screen for displaying player words sequentially in `pantalla_palabras_cliente.dart`.
- Implement unit tests for the multiplayer session management and player assignment logic in `inicio_partida_multijugador_test.dart` and `sala_multijugador_test.dart`.
2026-04-27 14:02:33 +02:00

129 lines
4.3 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/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;
JugadorInicioPartida get _actual => widget.jugadores[_indice];
bool get _esUltimo => _indice == widget.jugadores.length - 1;
void _continuar() {
if (_esUltimo) {
widget.onTodosVistos();
return;
}
setState(() {
_indice++;
_visible = false;
});
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final actual = _actual;
return Scaffold(
backgroundColor: TemaApp.colorFondo,
body: 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),
child: AnimatedContainer(
duration: const Duration(milliseconds: 250),
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 48,
horizontal: 24,
),
decoration: BoxDecoration(
color: _visible ? TemaApp.colorAcento : TemaApp.colorTarjeta,
borderRadius: BorderRadius.circular(24),
),
child: Column(
children: [
Icon(
_visible ? Icons.visibility : Icons.visibility_off,
color: _visible ? Colors.white : TemaApp.colorTextoSecundario,
size: 32,
),
const SizedBox(height: 16),
Text(
_visible
? (actual.esImpostor
? l10n.youAreImpostor
: actual.palabra ?? '')
: '???',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: _visible
? Colors.white
: 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 Spacer(),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: _continuar,
icon: Icon(_esUltimo ? Icons.check : Icons.arrow_forward),
label: Text(_esUltimo ? l10n.iveSeenIt : 'Siguiente jugador'),
),
),
],
),
),
),
);
}
}