refactorización de pantallas

This commit is contained in:
2026-05-11 23:16:38 +02:00
parent 1929d86689
commit 4599678e77
48 changed files with 1446 additions and 1463 deletions
+217 -545
View File
@@ -7,12 +7,14 @@ import '../estado/estado_juego.dart';
import '../modelos/gamificacion_usuario.dart';
import '../modelos/inicio_partida_multijugador.dart';
import '../modelos/jugador.dart';
import '../modelos/palabra.dart';
import '../modelos/partida.dart';
import '../modelos/snapshot_partida_online.dart';
import '../servicios/servicio_historial_partidas.dart';
import '../servicios/servicio_nearby.dart';
import '../servicios/servicio_perfil_usuario.dart';
import '../tema/componentes_farolero.dart';
import '../tema/componentes_resultado_farolero.dart';
import '../tema/tema_app.dart';
import 'pantalla_notas_online.dart';
import 'pantalla_revision_palabra.dart';
@@ -279,10 +281,13 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
const SizedBox(height: 8),
Align(
alignment: Alignment.centerRight,
child: OutlinedButton.icon(
onPressed: () => nearby.asumirUsuariosDesconectados(),
icon: const Icon(Icons.person_add_alt_1),
label: Text(AppLocalizations.of(context)!.assumeOnThisPhone),
child: SizedBox(
width: 260,
child: BotonFarolero.oscuro(
texto: AppLocalizations.of(context)!.assumeOnThisPhone,
icono: Icons.person_add_alt_1,
onPressed: () => nearby.asumirUsuariosDesconectados(),
),
),
),
],
@@ -404,67 +409,35 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
bool todosListos,
ServicioNearby nearby,
) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.waitingPlayersSeeWord,
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 16),
Text(
l10n.connectedPlayers,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
_buildJugadorTile(nearby.miNombre ?? 'Host', true, _hostListo),
...nearby.jugadores.map(
(j) => _buildJugadorTile(
j.nombre,
false,
_clientesListos[j.endpointId] ?? false,
),
),
const Spacer(),
// Botón para que el host vea su palabra
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _mostrarPalabraHost(context),
icon: const Icon(Icons.visibility),
label: Text(l10n.seeYourWord),
style: ElevatedButton.styleFrom(
backgroundColor: TemaApp.colorNaranja,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
),
),
return TarjetaFaseFarolero(
icono: Icons.visibility,
titulo: l10n.waitingPlayersSeeWord,
subtitulo: l10n.connectedPlayers,
child: Column(
children: [
_buildJugadorTile(nearby.miNombre ?? 'Host', true, _hostListo),
...nearby.jugadores.map(
(jugador) => _buildJugadorTile(
jugador.nombre,
false,
_clientesListos[jugador.endpointId] ?? false,
),
),
const SizedBox(height: 12),
BotonFarolero(
texto: l10n.seeYourWord,
icono: Icons.visibility,
onPressed: () => _mostrarPalabraHost(context),
),
if (todosListos) ...[
const SizedBox(height: 12),
if (todosListos)
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: TemaApp.colorVerde.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.check_circle, color: TemaApp.colorVerde),
const SizedBox(width: 8),
Text(
l10n.allSeenStartDebate,
style: const TextStyle(color: TemaApp.colorVerde),
),
],
),
),
EstadoJugadorFarolero(
nombre: l10n.allSeenStartDebate,
completado: true,
icono: Icons.check_circle,
),
],
),
],
),
);
}
@@ -563,66 +536,32 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
final estado = context.read<EstadoJuego>();
final tiempo = estado.partida?.config.tiempoDebateSegundos;
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (tiempo != null) ...[
Text(l10n.debate, style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 16),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: _segundosRestantes == 0
? TemaApp.colorAcento.withValues(alpha: 0.3)
: TemaApp.colorTarjeta,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Text(
_segundosRestantes == 0
? l10n.timeUp
: l10n.timeRemaining,
style: Theme.of(context).textTheme.bodyMedium,
),
Text(
_formatearTiempo(_segundosRestantes),
style: Theme.of(context).textTheme.headlineLarge,
),
],
),
),
const SizedBox(height: 16),
],
_buildPrimerTurno(context),
return TarjetaFaseFarolero(
icono: Icons.forum,
titulo: l10n.debate,
subtitulo: l10n.debateInstructions,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (tiempo != null) ...[
TemporizadorFarolero(
etiqueta: _segundosRestantes == 0
? l10n.timeUp
: l10n.timeRemaining,
tiempo: _formatearTiempo(_segundosRestantes),
agotado: _segundosRestantes == 0,
),
const SizedBox(height: 16),
Text(
l10n.activePlayers,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Expanded(
child: ListView.builder(
itemCount: nearby.jugadores.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
return _buildJugadorTile(
nearby.miNombre ?? 'Host',
true,
true,
);
}
final j = nearby.jugadores[index - 1];
return _buildJugadorTile(j.nombre, false, true);
},
),
),
],
),
_buildPrimerTurno(context),
const SizedBox(height: 16),
Text(l10n.activePlayers, style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
_buildJugadorTile(nearby.miNombre ?? 'Host', true, true),
...nearby.jugadores.map(
(jugador) => _buildJugadorTile(jugador.nombre, false, true),
),
],
),
);
}
@@ -644,7 +583,7 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
const SizedBox(width: 12),
Expanded(
child: Text(
'Empieza $nombre diciendo su palabra.',
AppLocalizations.of(context)!.firstTurnInstruction(nombre),
style: Theme.of(context).textTheme.titleMedium,
),
),
@@ -664,89 +603,42 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
final votosEmitidos = estado.votos.length;
final progreso = totalVotos == 0 ? 0.0 : votosEmitidos / totalVotos;
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.voting, style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 16),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: TemaApp.colorTarjeta,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Text(l10n.votesProgress(votosEmitidos, totalVotos)),
const SizedBox(height: 8),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: progreso.clamp(0.0, 1.0).toDouble(),
backgroundColor: TemaApp.colorSuperficie,
valueColor: const AlwaysStoppedAnimation(
TemaApp.colorAcento,
),
minHeight: 8,
),
),
],
),
return TarjetaFaseFarolero(
icono: Icons.how_to_vote,
titulo: l10n.voting,
subtitulo: l10n.votesProgress(votosEmitidos, totalVotos),
color: TemaApp.colorAcento,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(999),
child: LinearProgressIndicator(
value: progreso.clamp(0.0, 1.0).toDouble(),
minHeight: 14,
backgroundColor: Colors.black.withValues(alpha: 0.35),
valueColor: const AlwaysStoppedAnimation(TemaApp.colorAcento),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: _hostYaVoto(context) ? null : () => _abrirVotacionHost(context),
icon: const Icon(Icons.how_to_vote),
label: Text(
_hostYaVoto(context)
? l10n.playersVoted
: l10n.confirmVote,
),
),
),
const SizedBox(height: 16),
if (!_hostYaVoto(context))
BotonFarolero.secundario(
texto: l10n.votar,
icono: Icons.how_to_vote,
onPressed: () => _abrirVotacionHost(context),
),
const SizedBox(height: 16),
Text(
l10n.playersVoted,
style: Theme.of(context).textTheme.titleMedium,
if (!_hostYaVoto(context)) const SizedBox(height: 16),
...partida.jugadoresActivos.map((jugador) {
final haVotado = estado.votos.containsKey(jugador.id);
return _buildJugadorTile(jugador.nombre, false, haVotado);
}),
if (todosVotaron)
EstadoJugadorFarolero(
nombre: l10n.allVoted,
completado: true,
icono: Icons.check_circle,
),
const SizedBox(height: 8),
Expanded(
child: ListView.builder(
itemCount: partida.jugadoresActivos.length,
itemBuilder: (context, index) {
final jugador = partida.jugadoresActivos[index];
final haVotado = estado.votos.containsKey(jugador.id);
return _buildJugadorTile(jugador.nombre, false, haVotado);
},
),
),
if (todosVotaron)
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: TemaApp.colorVerde.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.check_circle, color: TemaApp.colorVerde),
const SizedBox(width: 8),
Text(
l10n.allVoted,
style: const TextStyle(color: TemaApp.colorVerde),
),
],
),
),
],
),
],
),
);
}
@@ -760,132 +652,11 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
return Center(child: Text(l10n.noResult));
}
final conteo = <String, int>{};
for (final votadoId in resultado.votos.values) {
conteo[votadoId] = (conteo[votadoId] ?? 0) + 1;
}
final maxVotos = conteo.values.isEmpty
? 1
: conteo.values.reduce((a, b) => a > b ? a : b);
final ranking = conteo.entries.toList()
..sort((a, b) => b.value.compareTo(a.value));
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(l10n.result, style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 12),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: TemaApp.decoracionPanel(
color: resultado.eraImpostor
? TemaApp.colorVerde.withValues(alpha: 0.18)
: TemaApp.colorAcento.withValues(alpha: 0.18),
borderColor: resultado.eraImpostor
? TemaApp.colorVerde
: TemaApp.colorAcento,
),
child: Column(
children: [
Text(
resultado.eliminadoNombre,
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 6),
Text(
resultado.eraImpostor
? l10n.wasImpostor
: l10n.wasInnocent,
style: TextStyle(
color: resultado.eraImpostor
? TemaApp.colorVerde
: TemaApp.colorAcento,
fontWeight: FontWeight.bold,
),
),
],
),
),
const SizedBox(height: 16),
Text(l10n.votesThisRound,
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 12),
Expanded(
child: ListView(
children: [
...ranking.map((entry) {
final jugador = partida.jugadores.firstWhere(
(j) => j.id == entry.key,
orElse: () => partida.jugadores.first,
);
return _buildBarraResultado(
context,
nombre: jugador.nombre,
votos: entry.value,
maxVotos: maxVotos,
destacado: entry.key == resultado.eliminadoId,
);
}),
const Divider(height: 24),
...resultado.votos.entries.map((entry) {
final votante = partida.jugadores.firstWhere(
(j) => j.id == entry.key,
orElse: () => partida.jugadores.first,
);
final votado = partida.jugadores.firstWhere(
(j) => j.id == entry.value,
orElse: () => partida.jugadores.first,
);
return ListTile(
dense: true,
leading: const Icon(Icons.how_to_vote),
title: Text('${votante.nombre}${votado.nombre}'),
);
}),
],
),
),
],
),
),
);
}
Widget _buildBarraResultado(
BuildContext context, {
required String nombre,
required int votos,
required int maxVotos,
required bool destacado,
}) {
final color = destacado ? TemaApp.colorAcento : TemaApp.colorNaranja;
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(child: Text(nombre)),
Text('$votos',
style: TextStyle(color: color, fontWeight: FontWeight.bold)),
],
),
const SizedBox(height: 6),
ClipRRect(
borderRadius: BorderRadius.circular(999),
child: LinearProgressIndicator(
value: (votos / maxVotos).clamp(0.0, 1.0).toDouble(),
minHeight: 10,
backgroundColor: TemaApp.colorSuperficie,
valueColor: AlwaysStoppedAnimation(color),
),
),
],
return SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 8),
child: ResultadoRondaFarolero(
resultado: resultado,
jugadores: partida.jugadores,
),
);
}
@@ -895,102 +666,63 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
final ultimo = partida?.historialVotaciones.isNotEmpty == true
? partida!.historialVotaciones.last
: null;
return Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.psychology, size: 56, color: TemaApp.colorNaranja),
const SizedBox(height: 16),
Text(
l10n.impostorGuessTitle,
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
ultimo == null
? l10n.impostorCanGuess
: '${ultimo.eliminadoNombre}: ${l10n.impostorCanGuess}',
textAlign: TextAlign.center,
),
],
),
),
return TarjetaFaseFarolero(
icono: Icons.psychology,
titulo: l10n.impostorGuessTitle,
subtitulo: ultimo == null
? l10n.impostorCanGuess
: '${ultimo.eliminadoNombre}: ${l10n.impostorCanGuess}',
color: TemaApp.colorNaranja,
child: const ArteGameplayFarolero.resultado(height: 132),
);
}
Widget _buildFaseFinOnline(BuildContext context, AppLocalizations l10n) {
final partida = context.watch<EstadoJuego>().partida;
final ganaronJugadores = partida?.ganador == 'jugadores';
return Card(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
ganaronJugadores ? '🎉' : '🎭',
style: const TextStyle(fontSize: 64),
),
const SizedBox(height: 16),
Text(
ganaronJugadores ? l10n.playersWin : l10n.impostorsWin,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 12),
Text(
partida == null ? '' : l10n.theWordWas(partida.palabraSecreta),
textAlign: TextAlign.center,
),
if (_progresoGamificacion != null) ...[
const SizedBox(height: 16),
_buildProgresoGamificacion(context, _progresoGamificacion!),
],
],
),
),
);
}
if (partida == null) return Center(child: Text(l10n.noResult));
Widget _buildProgresoGamificacion(
BuildContext context,
ProgresoGamificacionUsuario progreso,
) {
final nuevas = progreso.nuevasMedallas;
return PanelFarolero(
padding: const EdgeInsets.all(14),
color: TemaApp.colorSuperficie.withValues(alpha: 0.82),
final ganaronJugadores = partida.ganador == 'jugadores';
final color = ganaronJugadores ? TemaApp.colorVerde : TemaApp.colorAcento;
final impostores = partida.jugadores.where((j) => j.esImpostor).toList();
return SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Tu progreso', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 10),
Row(
children: [
const Text('🔥', style: TextStyle(fontSize: 22)),
const SizedBox(width: 8),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(6),
child: LinearProgressIndicator(
value: progreso.despues.fuego / 100,
minHeight: 8,
color: TemaApp.colorNaranja,
backgroundColor: Colors.black.withValues(alpha: 0.35),
),
),
),
const SizedBox(width: 8),
Text('${progreso.despues.fuego}%'),
],
HeroFinalPartidaFarolero(
encabezado: l10n.gameOver,
titulo: ganaronJugadores ? l10n.playersWin : l10n.impostorsWin,
icono: ganaronJugadores ? Icons.emoji_events : Icons.theater_comedy,
color: color,
),
if (nuevas.isNotEmpty) ...[
const SizedBox(height: 10),
MedallasCompactasFarolero(ids: nuevas, max: nuevas.length),
],
const SizedBox(height: 12),
if (_progresoGamificacion == null)
const TarjetaRecompensaCargandoPremium()
else
TarjetaProgresoGamificacionPremium(
progreso: _progresoGamificacion!,
),
const SizedBox(height: 18),
TarjetaSecretoPremium(
palabra: partida.palabraSecreta,
categoria: BancoPalabras.nombreBonitoCategoria(
partida.categoriaReal,
l10n,
),
),
const SizedBox(height: 18),
TarjetaImpostoresPremium(
titulo: impostores.length == 1
? l10n.theImpostorWas
: l10n.theImpostorsWere,
impostores: impostores,
),
const SizedBox(height: 18),
if (partida.historialVotaciones.isNotEmpty)
TarjetaHistorialVotosPremium(
historial: partida.historialVotaciones,
jugadores: partida.jugadores,
),
],
),
);
@@ -1046,28 +778,11 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
}
Widget _buildJugadorTile(String nombre, bool esHost, bool listo) {
return Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: listo
? TemaApp.colorVerde.withValues(alpha: 0.2)
: TemaApp.colorTarjeta,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
esHost ? Icons.phone_android : Icons.devices,
color: esHost ? TemaApp.colorDorado : TemaApp.colorNaranja,
size: 22,
),
const SizedBox(width: 8),
Expanded(child: Text(nombre)),
if (listo)
const Icon(Icons.check_circle, color: TemaApp.colorVerde, size: 20),
],
),
return EstadoJugadorFarolero(
nombre: nombre,
destacado: esHost,
completado: listo,
icono: esHost ? Icons.phone_android : Icons.devices,
);
}
@@ -1080,60 +795,36 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
) {
switch (fase) {
case FaseJuego.verPalabra:
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: todosListos
? () => _avanzarAFase(FaseJuego.debate)
: null,
icon: const Icon(Icons.forum),
label: Text(
todosListos
? l10n.allSeenStartDebate
: l10n.waitingPlayersSeeWord,
),
),
return BotonFarolero(
texto: todosListos ? l10n.allSeenStartDebate : l10n.waitingPlayersSeeWord,
icono: Icons.forum,
onPressed: todosListos ? () => _avanzarAFase(FaseJuego.debate) : null,
);
case FaseJuego.debate:
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () => _avanzarAFase(FaseJuego.votacion),
icon: const Icon(Icons.how_to_vote),
label: Text(l10n.goToVoting),
),
return BotonFarolero.secundario(
texto: l10n.goToVoting,
icono: Icons.how_to_vote,
onPressed: () => _avanzarAFase(FaseJuego.votacion),
);
case FaseJuego.votacion:
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: todosVotaron
? () => _avanzarAFase(FaseJuego.resultado)
: null,
icon: const Icon(Icons.visibility),
label: Text(todosVotaron ? l10n.revealResult : l10n.waitingVoting),
),
return BotonFarolero(
texto: todosVotaron ? l10n.revealResult : l10n.waitingVoting,
icono: Icons.visibility,
onPressed: todosVotaron ? () => _avanzarAFase(FaseJuego.resultado) : null,
);
case FaseJuego.resultado:
return _buildAccionesResultado(context, l10n);
case FaseJuego.adivinanza:
return _buildAccionesAdivinanza(context, l10n);
case FaseJuego.finPartida:
return SizedBox(
width: double.infinity,
height: 56,
child: OutlinedButton.icon(
onPressed: () async {
final nearby = context.read<ServicioNearby>();
await nearby.desconectar();
widget.onPartidaFin();
},
icon: const Icon(Icons.home),
label: Text(l10n.mainMenu),
),
return BotonFarolero.oscuro(
texto: l10n.mainMenu,
icono: Icons.home,
onPressed: () async {
final nearby = context.read<ServicioNearby>();
await nearby.desconectar();
widget.onPartidaFin();
},
);
default:
return const SizedBox.shrink();
@@ -1149,80 +840,58 @@ class _PantallaGestorHostState extends State<PantallaGestorHost> {
if (partida == null || resultado == null) return const SizedBox.shrink();
if (_hayFinTrasVotacion(partida)) {
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () => _finalizarPartidaOnline(context),
icon: const Icon(Icons.emoji_events),
label: Text(l10n.seeEndResult),
),
return BotonFarolero(
texto: l10n.seeEndResult,
icono: Icons.emoji_events,
onPressed: () => _finalizarPartidaOnline(context),
);
}
if (resultado.eraImpostor) {
return Column(
children: [
SizedBox(
width: double.infinity,
height: 56,
child: OutlinedButton.icon(
onPressed: () => _iniciarAdivinanzaOnline(context),
icon: const Icon(Icons.psychology),
label: Text(l10n.impostorGuessWord),
),
BotonFarolero.oscuro(
texto: l10n.impostorGuessWord,
icono: Icons.psychology,
onPressed: () => _iniciarAdivinanzaOnline(context),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () => _siguienteRondaOnline(context),
icon: const Icon(Icons.skip_next),
label: Text(l10n.nextRound),
),
BotonFarolero(
texto: l10n.nextRound,
icono: Icons.skip_next,
onPressed: () => _siguienteRondaOnline(context),
),
],
);
}
return SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () => _siguienteRondaOnline(context),
icon: const Icon(Icons.skip_next),
label: Text(l10n.nextRound),
),
return BotonFarolero(
texto: l10n.nextRound,
icono: Icons.skip_next,
onPressed: () => _siguienteRondaOnline(context),
);
}
Widget _buildAccionesAdivinanza(BuildContext context, AppLocalizations l10n) {
return Column(
children: [
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: () => _resolverAdivinanzaOnline(context),
icon: const Icon(Icons.check_circle),
label: Text(l10n.guess),
),
BotonFarolero(
texto: l10n.guess,
icono: Icons.check_circle,
onPressed: () => _resolverAdivinanzaOnline(context),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
height: 56,
child: OutlinedButton.icon(
onPressed: () => _siguienteRondaOnline(context),
icon: const Icon(Icons.skip_next),
label: Text(l10n.dontGuess),
),
BotonFarolero.oscuro(
texto: l10n.dontGuess,
icono: Icons.skip_next,
onPressed: () => _siguienteRondaOnline(context),
),
],
);
}
Future<void> _finalizarPartidaOnline
Future<void> _finalizarPartidaOnline(BuildContext context) async {
final estado = context.read<EstadoJuego>();
final nearby = context.read<ServicioNearby>();
@@ -1441,7 +1110,12 @@ class _PantallaRevelarPalabraHostState
if (widget.esImpostor && widget.pistaActiva) ...[
const SizedBox(height: 12),
Text(
'Categoría: ${widget.categoria}',
l10n.clueCategory(
BancoPalabras.nombreBonitoCategoria(
widget.categoria,
l10n,
),
),
style: Theme.of(context).textTheme.bodyLarge
?.copyWith(color: TemaApp.colorNaranja),
),
@@ -1450,7 +1124,11 @@ class _PantallaRevelarPalabraHostState
)
: Column(
children: [
const Text('🔒', style: TextStyle(fontSize: 48)),
const Icon(
Icons.lock,
color: TemaApp.colorDorado,
size: 48,
),
const SizedBox(height: 16),
Text(
l10n.holdToSeeWord,
@@ -1496,21 +1174,15 @@ class _PantallaRevelarPalabraHostState
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: _haRevelado
? () {
widget.onVisto();
Navigator.of(context).pop();
}
: null,
icon: const Icon(Icons.check),
label: Text(
_haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
),
),
BotonFarolero(
texto: _haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
icono: Icons.check,
onPressed: _haRevelado
? () {
widget.onVisto();
Navigator.of(context).pop();
}
: null,
),
],
),