Reintentos de ejecución de partidas online!

This commit is contained in:
2026-05-05 20:38:13 +02:00
parent 2dbe505d77
commit 5c9e8b2b9c
3 changed files with 24 additions and 91 deletions

View File

@@ -125,7 +125,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
return;
}
// 2. Seleccionar o crear usuario del pool
// 2. Usar el perfil principal del dispositivo como usuario del host.
final nombre = await _seleccionarUsuarioHost();
if (nombre == null || nombre.trim().isEmpty) return;
@@ -244,90 +244,9 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
}
}
/// Muestra diálogo para seleccionar usuario del pool o crear nuevo
/// Devuelve el perfil principal del dispositivo para crear la sala.
Future<String?> _seleccionarUsuarioHost() async {
final l10n = AppLocalizations.of(context)!;
final nearby = context.read<ServicioNearby>();
final usuarios = nearby.usuarios;
// Si hay usuarios en el pool, mostrar selección
if (usuarios.isNotEmpty) {
String? seleccionado;
return showDialog<String>(
context: context,
builder: (ctx) => StatefulBuilder(
builder: (ctx, setDialogState) => AlertDialog(
title: Text(l10n.selectYourProfile),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
DropdownButtonFormField<String>(
initialValue: seleccionado,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.person),
hintText: l10n.selectProfile,
border: const OutlineInputBorder(),
),
items: [
// Opción para crear nuevo usuario
DropdownMenuItem<String>(
value: '_new_',
child: Row(
children: [
const Icon(Icons.add, size: 18),
const SizedBox(width: 8),
Text(l10n.createNewUser),
],
),
),
// Usuarios existentes
...usuarios.map((usuario) {
return DropdownMenuItem<String>(
value: usuario.nombre,
child: Row(
children: [
AvatarFarolero(
texto: usuario.nombre.substring(0, 1),
assetPath: usuario.avatar,
size: 28,
),
const SizedBox(width: 8),
Text(usuario.nombre),
],
),
);
}),
],
onChanged: (valor) {
setDialogState(() => seleccionado = valor);
},
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: Text(l10n.cancel),
),
TextButton(
onPressed: () {
if (seleccionado == '_new_') {
Navigator.pop(ctx);
_crearNuevoUsuarioHost();
} else if (seleccionado != null) {
Navigator.pop(ctx, seleccionado);
}
},
child: Text(l10n.accept),
),
],
),
),
);
}
// Pool vacío, pedir nombre nuevo
return _pedirNombreHost();
return context.read<ServicioPerfilUsuario>().perfil.nombre;
}
/// Crea un nuevo usuario y lo agrega al pool
@@ -378,7 +297,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
return null;
}
/// Método original para pedir nombre (usado cuando pool vacío)
/// Método original para pedir nombre (usado cuando pool vacío)
Future<String?> _pedirNombreHost() async {
final controller = TextEditingController();
controller.text = context.read<ServicioPerfilUsuario>().perfil.nombre;
@@ -443,7 +362,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'¿Cómo quieres jugar?',
'¿Cómo quieres jugar?',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 3),
@@ -494,7 +413,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
),
const SizedBox(height: 12),
// Categoría
// Categoría
Card(
child: Padding(
padding: const EdgeInsets.all(16),
@@ -598,7 +517,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
),
const SizedBox(height: 12),
// Configuración de partida
// Configuración de partida
Card(
child: Padding(
padding: const EdgeInsets.all(16),
@@ -611,7 +530,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
),
const SizedBox(height: 12),
// Número de impostores
// Número de impostores
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -672,7 +591,7 @@ class _PantallaCrearPartidaState extends State<PantallaCrearPartida> {
),
const SizedBox(height: 24),
// Botón iniciar
// Botón iniciar
SizedBox(
width: double.infinity,
height: 56,

View File

@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
import '../estado/estado_juego.dart';
import '../modelos/palabra.dart';
import '../servicios/servicio_historial_partidas.dart';
import '../servicios/servicio_nearby.dart';
import '../tema/tema_app.dart';
import 'pantalla_principal.dart';
import 'pantalla_ver_palabra.dart';
@@ -236,8 +237,10 @@ class _PantallaFinPartidaState extends State<PantallaFinPartida> {
width: double.infinity,
height: 56,
child: OutlinedButton.icon(
onPressed: () {
onPressed: () async {
await context.read<ServicioNearby>().desconectar();
estado.limpiar();
if (!context.mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(

View File

@@ -210,6 +210,15 @@ class ServicioNearby extends ChangeNotifier {
String? miNick,
String? miAvatar,
}) async {
if (_conectado ||
_anunciando ||
_buscando ||
_estadoSala != null ||
_jugadores.isNotEmpty) {
await desconectar();
await Future<void>.delayed(const Duration(milliseconds: 250));
}
_nombreSala = nombreSala;
_miNombre = miNombre;
_roomId = DateTime.now().microsecondsSinceEpoch.toString();
@@ -253,9 +262,11 @@ class ServicioNearby extends ChangeNotifier {
notifyListeners();
return true;
}
await desconectar();
return false;
} catch (e) {
debugPrint('Error iniciando host: $e');
await desconectar();
return false;
}
}