Auto-sync: 20260324_150000
This commit is contained in:
parent
027c41a75c
commit
88f1520b5b
4 changed files with 64 additions and 21 deletions
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
BIN
ios/.DS_Store
vendored
BIN
ios/.DS_Store
vendored
Binary file not shown.
|
|
@ -57,8 +57,11 @@ class _GameScreenState extends State<GameScreen> with TickerProviderStateMixin {
|
|||
@override
|
||||
void dispose() { _blinkController.dispose(); super.dispose(); }
|
||||
|
||||
// --- NUOVO DIALOG: CONFERMA USCITA (ANTI-FUGA) ---
|
||||
// --- DIALOG: CONFERMA USCITA (ANTI-FUGA) AGGIORNATO ---
|
||||
void _showExitConfirmationDialog(BuildContext context, GameController gameController, ThemeColors theme, AppThemeType themeType) {
|
||||
// Determiniamo se è una partita locale (no CPU e no Online)
|
||||
bool isLocalMatch = !gameController.isOnline && !gameController.isVsCPU;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
|
|
@ -80,7 +83,9 @@ class _GameScreenState extends State<GameScreen> with TickerProviderStateMixin {
|
|||
],
|
||||
),
|
||||
content: Text(
|
||||
"Se esci ora, la partita verrà registrata automaticamente come una SCONFITTA.\n\nSei sicuro di voler fuggire?",
|
||||
isLocalMatch
|
||||
? "Sei sicuro di voler interrompere la partita locale in corso?" // Testo per partite in locale
|
||||
: "Se esci ora, la partita verrà registrata automaticamente come una SCONFITTA.\n\nSei sicuro di voler fuggire?", // Testo minaccioso per partite classificate
|
||||
style: _getTextStyle(themeType, TextStyle(color: theme.text, fontSize: 15, height: 1.4)),
|
||||
),
|
||||
actions: [
|
||||
|
|
@ -95,8 +100,10 @@ class _GameScreenState extends State<GameScreen> with TickerProviderStateMixin {
|
|||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
onPressed: () {
|
||||
// 1. Assegna la sconfitta!
|
||||
StorageService.instance.addLoss();
|
||||
// 1. Assegna la sconfitta SOLO se non è una partita in locale!
|
||||
if (!isLocalMatch) {
|
||||
StorageService.instance.addLoss();
|
||||
}
|
||||
// 2. Disconnette e pulisce
|
||||
gameController.disconnectOnlineGame();
|
||||
// 3. Chiude il dialog
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// ===========================================================================
|
||||
|
||||
import 'dart:ui';
|
||||
import 'dart:math'; // <--- AGGIUNTO PER IL RANDOM DELL'INVITO
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
|
|
@ -17,8 +18,9 @@ import '../../services/multiplayer_service.dart';
|
|||
import '../../services/storage_service.dart';
|
||||
import '../game/game_screen.dart';
|
||||
import '../../widgets/cyber_border.dart';
|
||||
import '../../widgets/painters.dart'; // <--- ECCO L'IMPORT MANCANTE!
|
||||
import '../../widgets/painters.dart';
|
||||
import 'lobby_widgets.dart';
|
||||
import '../home/home_modals.dart'; // <--- AGGIUNTO PER IL DIALOG DELLE IMPOSTAZIONI
|
||||
|
||||
class LobbyScreen extends StatefulWidget {
|
||||
final String? initialRoomCode;
|
||||
|
|
@ -104,27 +106,62 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _createRoomAndInvite(String targetUid, String targetName) async {
|
||||
if (_isLoading) return;
|
||||
// --- NUOVA LOGICA: FLOW PER SFIDA DIRETTA (Allineato con HomeScreen) ---
|
||||
void _startDirectChallengeFlow(String targetUid, String targetName) {
|
||||
HomeModals.showChallengeSetupDialog(
|
||||
context,
|
||||
targetName,
|
||||
(int radius, ArenaShape shape, String timeMode) {
|
||||
_executeSendChallenge(targetUid, targetName, radius, shape, timeMode);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _executeSendChallenge(String targetUid, String targetName, int radius, ArenaShape shape, String timeMode) async {
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
final rnd = Random();
|
||||
String roomCode = String.fromCharCodes(Iterable.generate(5, (_) => chars.codeUnitAt(rnd.nextInt(chars.length))));
|
||||
|
||||
try {
|
||||
String code = await _multiplayerService.createGameRoom(
|
||||
_selectedRadius, _playerName, _selectedShape.name, _timeModeSetting, isPublic: _isPublicRoom
|
||||
);
|
||||
int gameSeed = rnd.nextInt(9999999);
|
||||
|
||||
await _multiplayerService.sendInvite(targetUid, code, _playerName);
|
||||
await FirebaseFirestore.instance.collection('games').doc(roomCode).set({
|
||||
'status': 'waiting',
|
||||
'hostName': StorageService.instance.playerName,
|
||||
'hostUid': FirebaseAuth.instance.currentUser?.uid,
|
||||
'radius': radius,
|
||||
'shape': shape.name,
|
||||
'timeMode': timeMode,
|
||||
'isPublic': false,
|
||||
'createdAt': FieldValue.serverTimestamp(),
|
||||
'players': [FirebaseAuth.instance.currentUser?.uid],
|
||||
'turn': 0,
|
||||
'moves': [],
|
||||
'seed': gameSeed,
|
||||
});
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() { _myRoomCode = code; _isLoading = false; _roomStarted = false; });
|
||||
await FirebaseFirestore.instance.collection('invites').add({
|
||||
'toUid': targetUid,
|
||||
'fromName': StorageService.instance.playerName,
|
||||
'roomCode': roomCode,
|
||||
'timestamp': FieldValue.serverTimestamp(),
|
||||
});
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Sfida inviata a $targetName!"), backgroundColor: Colors.green));
|
||||
_showWaitingDialog(code);
|
||||
setState(() => _isLoading = false);
|
||||
|
||||
if (mounted) {
|
||||
_showWaitingDialog(roomCode); // Usiamo il dialog interno della lobby
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) { setState(() => _isLoading = false); _showError("Errore durante la creazione della partita."); }
|
||||
setState(() => _isLoading = false);
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Errore: $e", style: const TextStyle(color: Colors.white)), backgroundColor: Colors.red));
|
||||
}
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Future<void> _joinRoomByCode(String code) async {
|
||||
if (_isLoading) return;
|
||||
|
|
@ -193,7 +230,6 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
)
|
||||
)
|
||||
: StreamBuilder<QuerySnapshot>(
|
||||
// Interroghiamo Firebase solo per gli UID dei nostri preferiti (max 10 per limiti di Firestore)
|
||||
stream: FirebaseFirestore.instance.collection('leaderboard')
|
||||
.where(FieldPath.documentId, whereIn: favs.map((f) => f['uid']).take(10).toList())
|
||||
.snapshots(),
|
||||
|
|
@ -202,7 +238,6 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
return Center(child: CircularProgressIndicator(color: theme.playerBlue));
|
||||
}
|
||||
|
||||
// Mappiamo i risultati di Firebase per un accesso rapido
|
||||
Map<String, Map<String, dynamic>> liveData = {};
|
||||
for (var doc in snapshot.data!.docs) {
|
||||
liveData[doc.id] = doc.data() as Map<String, dynamic>;
|
||||
|
|
@ -219,7 +254,6 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
if (liveData.containsKey(uid) && liveData[uid]!['lastActive'] != null) {
|
||||
Timestamp lastActive = liveData[uid]!['lastActive'];
|
||||
int diffInSeconds = DateTime.now().difference(lastActive.toDate()).inSeconds;
|
||||
// Se ha fatto un'azione negli ultimi 3 minuti, lo consideriamo online
|
||||
if (diffInSeconds.abs() < 180) isOnline = true;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +279,8 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(ctx);
|
||||
_createRoomAndInvite(uid, name);
|
||||
// --- ORA USA IL FLUSSO SICURO CON LE IMPOSTAZIONI ---
|
||||
_startDirectChallengeFlow(uid, name);
|
||||
},
|
||||
child: Text("SFIDA", style: getLobbyTextStyle(themeType, const TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
|
||||
)
|
||||
|
|
@ -273,6 +308,7 @@ class _LobbyScreenState extends State<LobbyScreen> with WidgetsBindingObserver {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
void _showWaitingDialog(String code) {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
|
@ -804,4 +840,4 @@ class FullScreenGridPainter extends CustomPainter {
|
|||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue