Files
farolero/lib/pantallas/pantalla_palabra_cliente.dart
freetlab 6e5e423ab4 Implementado:
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.
2026-05-05 21:49:40 +02:00

193 lines
6.5 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:farolero/tema/componentes_farolero.dart';
import 'package:farolero/tema/tema_app.dart';
/// Pantalla que ve cada jugador cuando recibe su palabra (modo multidispositivo).
/// El cliente recibe la palabra via ServicioNearby y se navega aquí.
/// NO es la pantalla del host.
class PantallaPalabraCliente extends StatefulWidget {
final String palabra;
final bool esImpostor;
final String? pistaCategoria;
final VoidCallback onVisto;
const PantallaPalabraCliente({
super.key,
required this.palabra,
required this.esImpostor,
this.pistaCategoria,
required this.onVisto,
});
@override
State<PantallaPalabraCliente> createState() => _PantallaPalabraClienteState();
}
class _PantallaPalabraClienteState extends State<PantallaPalabraCliente> {
bool _palabraVisible = false;
bool _haRevelado = false;
Timer? _timer;
void _togglePalabra() {
setState(() {
_palabraVisible = !_palabraVisible;
if (_palabraVisible) _haRevelado = true;
});
_timer?.cancel();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
body: FondoFarolero(
intenso: true,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
const Spacer(),
// Tarjeta de palabra
GestureDetector(
onTap: _togglePalabra,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 48, horizontal: 24),
decoration: TemaApp.decoracionPanel(
color: _palabraVisible
? TemaApp.colorSuperficie
: TemaApp.colorTarjeta,
borderColor: _palabraVisible
? TemaApp.colorNaranja
: TemaApp.colorBorde,
).copyWith(
boxShadow: _palabraVisible
? [
BoxShadow(
color: TemaApp.colorNaranja.withValues(alpha: 0.32),
blurRadius: 24,
spreadRadius: 2,
),
]
: null,
),
child: Column(
children: [
Icon(
_palabraVisible ? Icons.visibility : Icons.visibility_off,
color: _palabraVisible
? Colors.white
: TemaApp.colorTextoSecundario,
size: 32,
),
const SizedBox(height: 16),
if (_palabraVisible && widget.esImpostor)
Text(
l10n.youAreImpostor,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: TemaApp.colorDorado,
),
)
else if (_palabraVisible)
TarjetaPalabraFarolero(palabra: widget.palabra)
else
const Text(
'???',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: TemaApp.colorTextoSecundario,
),
),
],
),
),
),
const SizedBox(height: 16),
// Pista para impostores
if (widget.esImpostor && widget.pistaCategoria != null) ...[
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: TemaApp.colorAcento.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.lightbulb, color: TemaApp.colorAcento),
const SizedBox(width: 8),
Flexible(
child: Text(
'🎭 ${l10n.clueIs(widget.pistaCategoria!)}',
style: const TextStyle(color: TemaApp.colorAcento),
),
),
],
),
),
const SizedBox(height: 8),
],
// Instrucciones
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
_palabraVisible
? 'Mantén la pantalla oculta. No la enseñes a nadie.'
: _haRevelado
? l10n.seeYourWord
: l10n.tapToSee,
textAlign: TextAlign.center,
style: TextStyle(
color: TemaApp.colorTextoSecundario,
fontSize: 14,
),
),
),
const Spacer(),
// Botón confirmar
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: _haRevelado ? widget.onVisto : null,
icon: const Icon(Icons.check),
label: Text(
_haRevelado ? l10n.iveSeenIt : l10n.tapToSee,
),
style: ElevatedButton.styleFrom(
backgroundColor: TemaApp.colorAcento,
foregroundColor: Colors.white,
textStyle: const TextStyle(fontSize: 16),
),
),
),
],
),
),
),
),
);
}
}