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.
193 lines
6.5 KiB
Dart
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),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|