2024-05-19 19:18:47 +00:00
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:developer';
|
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
2024-05-21 16:48:06 +00:00
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
2024-06-27 19:55:54 +00:00
|
|
|
import 'package:go_router/go_router.dart';
|
2024-05-19 19:18:47 +00:00
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'package:mchess/api/game_info.dart';
|
|
|
|
import 'package:mchess/connection_cubit/connection_cubit.dart';
|
|
|
|
import 'package:mchess/pages/chess_game.dart';
|
|
|
|
import 'package:mchess/utils/config.dart' as config;
|
2024-06-27 19:55:54 +00:00
|
|
|
import 'package:universal_platform/universal_platform.dart';
|
2024-05-19 19:18:47 +00:00
|
|
|
|
|
|
|
class JoinGameHandleWidget extends StatefulWidget {
|
|
|
|
final String passphrase;
|
|
|
|
const JoinGameHandleWidget({required this.passphrase, super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<JoinGameHandleWidget> createState() => _JoinGameHandleWidgetState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _JoinGameHandleWidgetState extends State<JoinGameHandleWidget> {
|
|
|
|
late Future<GameInfo?> joinGameFuture;
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
2024-05-21 16:48:06 +00:00
|
|
|
joinGameFuture = joinPrivateGame(widget.passphrase);
|
|
|
|
joinGameFuture.then((val) {
|
2024-06-27 19:55:54 +00:00
|
|
|
if (val == null) return;
|
|
|
|
|
2024-05-21 16:48:06 +00:00
|
|
|
ConnectionCubit.getInstance().connectIfNotConnected(
|
2024-06-27 19:55:54 +00:00
|
|
|
val.playerID!.uuid,
|
2024-05-21 16:48:06 +00:00
|
|
|
val.passphrase,
|
|
|
|
);
|
2024-05-20 15:21:25 +00:00
|
|
|
});
|
2024-05-19 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-06-27 19:55:54 +00:00
|
|
|
FloatingActionButton? fltnBtn;
|
|
|
|
if (UniversalPlatform.isLinux ||
|
|
|
|
UniversalPlatform.isMacOS ||
|
|
|
|
UniversalPlatform.isWindows) {
|
|
|
|
fltnBtn = FloatingActionButton(
|
|
|
|
child: const Icon(Icons.cancel),
|
|
|
|
onPressed: () {
|
|
|
|
context.pop();
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-05-21 16:48:06 +00:00
|
|
|
var loadingIndicator = const SizedBox(
|
|
|
|
height: 100,
|
|
|
|
width: 100,
|
|
|
|
child: CircularProgressIndicator(),
|
|
|
|
);
|
|
|
|
|
|
|
|
return Scaffold(
|
2024-06-27 19:55:54 +00:00
|
|
|
floatingActionButton: fltnBtn,
|
2024-05-21 16:48:06 +00:00
|
|
|
body: Center(
|
|
|
|
child: FutureBuilder(
|
|
|
|
future: joinGameFuture,
|
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (snapshot.connectionState != ConnectionState.done) {
|
|
|
|
return loadingIndicator;
|
|
|
|
} else {
|
|
|
|
return BlocBuilder<ConnectionCubit, ConnectionCubitState>(
|
|
|
|
builder: (context, state) {
|
|
|
|
if (state.iAmConnected) {
|
2024-05-20 15:21:25 +00:00
|
|
|
return const ChessGame();
|
2024-05-21 16:48:06 +00:00
|
|
|
} else {
|
|
|
|
return loadingIndicator;
|
2024-05-20 15:21:25 +00:00
|
|
|
}
|
|
|
|
});
|
2024-05-21 16:48:06 +00:00
|
|
|
}
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
);
|
2024-05-19 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<GameInfo?> joinPrivateGame(String phrase) async {
|
|
|
|
http.Response response;
|
2024-05-20 13:34:20 +00:00
|
|
|
|
|
|
|
var existingInfo = await GameInfo.get(phrase);
|
|
|
|
log('playerID: ${existingInfo?.playerID} and passphrase: "${existingInfo?.passphrase}"');
|
2024-05-19 19:18:47 +00:00
|
|
|
|
|
|
|
GameInfo info;
|
|
|
|
if (existingInfo?.passphrase == phrase) {
|
|
|
|
// We have player info for this exact passphrase
|
2024-05-20 13:34:20 +00:00
|
|
|
info = GameInfo(playerID: existingInfo?.playerID, passphrase: phrase);
|
2024-05-19 19:18:47 +00:00
|
|
|
} else {
|
2024-05-20 13:34:20 +00:00
|
|
|
info = GameInfo(playerID: null, passphrase: phrase);
|
2024-05-19 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2024-05-20 13:34:20 +00:00
|
|
|
response = await http.post(Uri.parse(config.getJoinGameURL()),
|
2024-05-19 19:18:47 +00:00
|
|
|
body: jsonEncode(info), headers: {"Accept": "application/json"});
|
|
|
|
} catch (e) {
|
|
|
|
log(e.toString());
|
|
|
|
|
|
|
|
if (!context.mounted) return null;
|
|
|
|
|
|
|
|
const snackBar = SnackBar(
|
|
|
|
backgroundColor: Colors.amberAccent,
|
|
|
|
content: Text("mChess server is not responding. Try again or give up"),
|
|
|
|
);
|
2024-06-27 19:55:54 +00:00
|
|
|
|
|
|
|
Future.delayed(const Duration(seconds: 1), () {
|
|
|
|
if (!mounted) return null;
|
|
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
|
|
|
context.goNamed('lobbySelector'); // We go back to the lobby selector
|
|
|
|
});
|
2024-05-19 19:18:47 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (response.statusCode == HttpStatus.notFound) {
|
|
|
|
const snackBar = SnackBar(
|
|
|
|
backgroundColor: Colors.amberAccent,
|
|
|
|
content: Text("Passphrase could not be found."),
|
|
|
|
);
|
|
|
|
|
2024-06-27 19:55:54 +00:00
|
|
|
if (!mounted) return null;
|
2024-05-19 19:18:47 +00:00
|
|
|
|
|
|
|
ScaffoldMessenger.of(context).clearSnackBars();
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
2024-06-27 19:55:54 +00:00
|
|
|
context.goNamed('lobbySelector');
|
|
|
|
|
2024-05-19 19:18:47 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (response.statusCode == HttpStatus.ok) {
|
|
|
|
var info = GameInfo.fromJson(jsonDecode(response.body));
|
|
|
|
info.store();
|
|
|
|
log('Player info received from server: ');
|
|
|
|
log('playerID: ${info.playerID}');
|
|
|
|
log('passphrase: ${info.passphrase}');
|
|
|
|
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|