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.
This commit is contained in:
2026-05-05 21:49:40 +02:00
parent 1abdeb2f56
commit 6e5e423ab4
12 changed files with 802 additions and 75 deletions

View File

@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import 'package:farolero/modelos/inicio_partida_multijugador.dart';
import 'package:farolero/modelos/jugador.dart';
import 'package:farolero/pantallas/pantalla_notas_online.dart';
import 'package:farolero/pantallas/pantalla_revision_palabra.dart';
import 'package:farolero/servicios/servicio_nearby.dart';
import 'package:farolero/tema/tema_app.dart';
import 'package:provider/provider.dart';
@@ -12,12 +14,16 @@ import 'package:provider/provider.dart';
class PantallaVotacionCliente extends StatefulWidget {
final List<Jugador> jugadores;
final List<JugadorInicioPartida> jugadoresControlados;
final String? partidaId;
final String? pistaCategoria;
final Function(Map<String, String> votos) onVotos;
const PantallaVotacionCliente({
super.key,
required this.jugadores,
this.jugadoresControlados = const [],
this.partidaId,
this.pistaCategoria,
required this.onVotos,
});
@@ -75,6 +81,35 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(
tooltip: l10n.seeYourWord,
icon: const Icon(Icons.visibility),
onPressed: widget.jugadoresControlados.isEmpty
? null
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
),
),
IconButton(
tooltip: l10n.notesTitle,
icon: const Icon(Icons.edit_note),
onPressed: _puedeAbrirNotas
? () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PantallaNotasOnline(
partidaId: widget.partidaId!,
jugadores: widget.jugadores,
autoresControlados: widget.jugadoresControlados,
),
),
)
: null,
),
],
),
body: Padding(
padding: const EdgeInsets.all(16),
@@ -127,7 +162,14 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
);
}
bool get _puedeAbrirNotas {
return widget.partidaId != null &&
widget.jugadores.isNotEmpty &&
widget.jugadoresControlados.isNotEmpty;
}
Widget _buildResultado(BuildContext context, Map<String, dynamic> resultado) {
final l10n = AppLocalizations.of(context)!;
final eliminadoId = resultado['eliminadoId'] as String?;
final eliminadoNombre = resultado['eliminadoNombre'] as String? ?? '?';
final eraImpostor = resultado['eraImpostor'] as bool? ?? false;
@@ -153,6 +195,35 @@ class _PantallaVotacionClienteState extends State<PantallaVotacionCliente> {
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(
tooltip: l10n.seeYourWord,
icon: const Icon(Icons.visibility),
onPressed: widget.jugadoresControlados.isEmpty
? null
: () => mostrarRevisionPalabraOnline(
context: context,
jugadoresControlados: widget.jugadoresControlados,
pistaCategoria: widget.pistaCategoria,
),
),
IconButton(
tooltip: l10n.notesTitle,
icon: const Icon(Icons.edit_note),
onPressed: _puedeAbrirNotas
? () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PantallaNotasOnline(
partidaId: widget.partidaId!,
jugadores: widget.jugadores,
autoresControlados: widget.jugadoresControlados,
),
),
)
: null,
),
],
),
body: Padding(
padding: const EdgeInsets.all(24),