Posible mejora en el multidispositivo

This commit is contained in:
2026-05-05 22:45:51 +02:00
parent 016333f6c0
commit cfe5d479ff
8 changed files with 1228 additions and 12 deletions

View File

@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import 'package:farolero/l10n/generated/app_localizations.dart';
import '../modelos/jugador.dart';
import '../modelos/inicio_partida_multijugador.dart';
import '../modelos/snapshot_partida_online.dart';
import '../modelos/usuario.dart';
import '../servicios/servicio_nearby.dart';
import '../servicios/servicio_permisos.dart';
@@ -14,6 +15,8 @@ import 'pantalla_palabra_cliente.dart';
import 'pantalla_palabras_cliente.dart';
import 'pantalla_debate_cliente.dart';
import 'pantalla_votacion_cliente.dart';
import 'pantalla_resultado_online.dart';
import 'pantalla_fin_partida_online.dart';
/// Pantalla para unirse a una partida multidispositivo.
/// Flujo: nombre → discovery automático (lista de salas) → fallback QR
@@ -59,6 +62,7 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
void _registrarListenerPartida() {
final nearby = context.read<ServicioNearby>();
nearby.onMensaje((endpointId, mensaje) {
if (!mounted) return;
if (mensaje.tipo == TipoMensaje.partidaInicio) {
// El host ha iniciado la partida — nos ha enviado nuestra palabra
final jugadoresData = mensaje.datos['jugadores'] as List<dynamic>?;
@@ -112,11 +116,17 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
_navegarAPalabra();
}
} else if (mensaje.tipo == TipoMensaje.fase) {
// El host cambia de fase — navegar a la pantalla correspondiente
final fase = mensaje.datos['fase'] as String?;
_actualizarSnapshotSiExiste(mensaje.datos);
if (mounted && fase != null) {
_navegarSegunFase(fase);
_navegarSegunFase(fase, mensaje.datos);
}
} else if (mensaje.tipo == TipoMensaje.votacionResultado) {
_actualizarSnapshotSiExiste(mensaje.datos);
if (mounted) _navegarResultado(mensaje.datos);
} else if (mensaje.tipo == TipoMensaje.partidaFin) {
_actualizarSnapshotSiExiste(mensaje.datos);
if (mounted) _navegarFinPartida(mensaje.datos);
}
});
}
@@ -166,10 +176,28 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
);
}
void _navegarSegunFase(String fase) {
void _actualizarSnapshotSiExiste(Map<String, dynamic> datos) {
final jugadoresTodosData = datos['jugadoresTodos'] as List<dynamic>?;
if (jugadoresTodosData == null) return;
setState(() {
_jugadores
..clear()
..addAll(
jugadoresTodosData.map(
(json) => Jugador.fromJson(json as Map<String, dynamic>),
),
);
_partidaId = (datos['roomId'] as String?) ??
_partidaId ??
context.read<ServicioNearby>().roomId;
_pistaCategoria = (datos['categoria'] as String?) ?? _pistaCategoria;
});
}
void _navegarSegunFase(String fase, [Map<String, dynamic>? datos]) {
switch (fase) {
case 'debate':
final datosFase = context.read<ServicioNearby>().datosPartida;
final datosFase = datos ?? context.read<ServicioNearby>().datosPartida;
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => PantallaDebateCliente(
@@ -227,9 +255,43 @@ class _PantallaUnirseState extends State<PantallaUnirse> {
),
);
break;
case 'resultado':
case 'adivinanza':
_navegarResultado(datos ?? context.read<ServicioNearby>().datosPartida);
break;
case 'finPartida':
_navegarFinPartida(datos ?? context.read<ServicioNearby>().datosPartida);
break;
}
}
void _navegarResultado(Map<String, dynamic>? datos) {
if (datos == null) return;
final snapshot = SnapshotPartidaOnline.fromJson(datos);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => PantallaResultadoOnline(
snapshot: snapshot,
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
pistaCategoria: _pistaCategoria,
),
),
);
}
void _navegarFinPartida(Map<String, dynamic>? datos) {
if (datos == null) return;
final snapshot = SnapshotPartidaOnline.fromJson(datos);
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => PantallaFinPartidaOnline(
snapshot: snapshot,
jugadoresControlados: List.unmodifiable(_jugadoresControlados),
pistaCategoria: _pistaCategoria,
),
),
);
}
@override
void dispose() {
_nombreController.dispose();