Files
farolero/lib/pantallas/pantalla_debate_cliente.dart
ShanaiaBot eb2662f561
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
fix: multidispositivo - Random seguro + gestor host + reacción clientes
- Random.secure() para selección de impostores (no predecible)
- Random.secure() también en desempate de votación
- Nueva PantallaGestorHost para coordinación multi-device
- Navegación: host va a gestor tras iniciar, no a pantalla de palabra
- PantallaPalabraCliente: cada jugador ve su palabra en su móvil
- PantallaDebateCliente: debate con timer y botón solicitar votación
- PantallaVotacionCliente: voto desde el móvil del cliente
- PantallaUnirse: listener que reacciona a partidaInicio y cambia de fase
- Protocolo: listo/voto/solicitoVotacion via Nearby hacia el host
- Nuevas cadenas l10n ES
2026-04-15 02:09:05 +02:00

157 lines
4.9 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:farolero/tema/tema_app.dart';
/// Pantalla que ve el jugador durante la fase de debate (multidispositivo).
/// El cliente recibe el cambio de fase via Nearby y se navega aquí.
class PantallaDebateCliente extends StatefulWidget {
final int? tiempoDebateSegundos;
final VoidCallback onSolicitarVotacion;
const PantallaDebateCliente({
super.key,
this.tiempoDebateSegundos,
required this.onSolicitarVotacion,
});
@override
State<PantallaDebateCliente> createState() => _PantallaDebateClienteState();
}
class _PantallaDebateClienteState extends State<PantallaDebateCliente> {
Timer? _timer;
int _segundosRestantes = 0;
bool _votacionSolicitada = false;
@override
void initState() {
super.initState();
if (widget.tiempoDebateSegundos != null) {
_segundosRestantes = widget.tiempoDebateSegundos!;
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_segundosRestantes > 0) {
setState(() => _segundosRestantes--);
} else {
timer.cancel();
}
});
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
String _formatearTiempo(int segundos) {
final min = segundos ~/ 60;
final seg = segundos % 60;
return '${min.toString().padLeft(2, '0')}:${seg.toString().padLeft(2, '0')}';
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
backgroundColor: TemaApp.colorFondo,
appBar: AppBar(
title: Text(l10n.debate),
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
const Spacer(),
// Timer
if (widget.tiempoDebateSegundos != null) ...[
Container(
padding: const EdgeInsets.all(32),
decoration: BoxDecoration(
color: _segundosRestantes == 0
? TemaApp.colorAcento.withValues(alpha: 0.3)
: TemaApp.colorTarjeta,
borderRadius: BorderRadius.circular(24),
),
child: Column(
children: [
Text(
_segundosRestantes == 0
? l10n.timeUp
: l10n.timeRemaining,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
Text(
_formatearTiempo(_segundosRestantes),
style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontWeight: FontWeight.bold,
color: _segundosRestantes == 0
? TemaApp.colorAcento
: TemaApp.colorTexto,
),
),
],
),
),
const SizedBox(height: 32),
] else ...[
Text(
l10n.debatePhaseActive,
style: Theme.of(context).textTheme.headlineMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
],
// Instrucciones
Text(
l10n.debateInstructions,
textAlign: TextAlign.center,
style: TextStyle(
color: TemaApp.colorTextoSecundario,
fontSize: 16,
),
),
const Spacer(),
// Botón solicitar votación
SizedBox(
width: double.infinity,
height: 56,
child: ElevatedButton.icon(
onPressed: _votacionSolicitada
? null
: () {
setState(() => _votacionSolicitada = true);
widget.onSolicitarVotacion();
},
icon: Icon(_votacionSolicitada ? Icons.hourglass_empty : Icons.how_to_vote),
label: Text(
_votacionSolicitada
? l10n.votacionSolicitada
: l10n.solicitarVotacion,
),
style: ElevatedButton.styleFrom(
backgroundColor: _votacionSolicitada
? TemaApp.colorTarjeta
: TemaApp.colorAcento,
foregroundColor: Colors.white,
textStyle: const TextStyle(fontSize: 16),
),
),
),
],
),
),
);
}
}