mchess-client/lib/pages/lobby_selector.dart

213 lines
6.5 KiB
Dart
Raw Normal View History

import 'dart:convert';
import 'dart:developer';
2024-02-05 09:35:28 +00:00
import 'dart:io';
2022-12-25 15:16:23 +00:00
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:mchess/api/register.dart';
import 'package:mchess/connection_cubit/connection_cubit.dart';
import 'package:mchess/pages/chess_game.dart';
import 'package:mchess/utils/config.dart' as config;
import 'package:shared_preferences/shared_preferences.dart';
2022-12-25 15:16:23 +00:00
class LobbySelector extends StatefulWidget {
2022-12-25 15:16:23 +00:00
const LobbySelector({super.key});
@override
State<LobbySelector> createState() => _LobbySelectorState();
}
class _LobbySelectorState extends State<LobbySelector> {
2023-06-29 23:49:18 +00:00
final buttonStyle = const ButtonStyle();
2023-12-27 14:46:15 +00:00
final phraseController = TextEditingController();
late Future<PlayerInfo?> joinGameFuture;
2023-06-29 23:49:18 +00:00
2022-12-25 15:16:23 +00:00
@override
Widget build(BuildContext context) {
SharedPreferences.getInstance().then((prefs) {
final playerID = prefs.getString("playerID");
final lobbyID = prefs.getString("lobbyID");
final passphrase = prefs.getString("passphrase");
log("lobbyID: $lobbyID and playerID: $playerID and passphrase: $passphrase");
});
2022-12-25 19:18:50 +00:00
return Scaffold(
2023-06-08 15:10:48 +00:00
body: Center(
2023-06-29 23:49:18 +00:00
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
2023-12-27 14:46:15 +00:00
onPressed: () => buildJoinOrHostDialog(context),
2023-06-29 23:49:18 +00:00
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.lock),
SizedBox(
width: 10,
),
Text('Private game')
2023-06-29 23:49:18 +00:00
],
),
),
],
2023-06-08 15:10:48 +00:00
),
2022-12-25 19:18:50 +00:00
),
2022-12-25 15:16:23 +00:00
);
}
2023-06-29 23:49:18 +00:00
Future<void> buildJoinOrHostDialog(BuildContext context) {
return showDialog<void>(
context: context,
2024-02-05 09:35:28 +00:00
builder: (BuildContext builderContext) {
return Scaffold(
body: AlertDialog(
title: const Text('Host or join?'),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
2024-02-05 09:35:28 +00:00
onPressed: () => builderContext.pop(),
),
TextButton(
2023-12-27 14:46:15 +00:00
child: const Text('Host'),
onPressed: () {
2024-02-05 09:35:28 +00:00
builderContext.pop(); //close dialog before going to host
builderContext.goNamed('host');
2023-12-27 14:46:15 +00:00
}),
TextButton(
child: const Text('Join'),
onPressed: () {
2024-02-05 09:35:28 +00:00
builderContext
.pop(); //close dialog before going to next dialog
buildEnterPassphraseDialog(builderContext);
},
),
],
),
);
},
);
}
Future<void> buildEnterPassphraseDialog(BuildContext context) {
2023-06-29 23:49:18 +00:00
return showDialog<void>(
context: context,
builder: (BuildContext context) {
2024-02-05 09:35:28 +00:00
return ScaffoldMessenger(
child: Builder(builder: (builderContext) {
return Scaffold(
backgroundColor: Colors.transparent,
body: AlertDialog(
title: const Text('Enter the passphrase here:'),
content: TextField(
controller: phraseController,
decoration: InputDecoration(
hintText: 'Enter passphrase here',
suffixIcon: IconButton(
onPressed: () {
joinGameFuture = joinPrivateGame(builderContext);
joinGameFuture.then((value) {
if (value != null) {
phraseController.clear();
builderContext.pop();
switchToGame(value);
}
});
},
icon: const Icon(Icons.check),
)),
),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () {
builderContext.pop();
},
),
],
),
);
}),
2023-06-29 23:49:18 +00:00
);
},
);
}
void switchToGame(PlayerInfo info) {
var chessGameArgs = ChessGameArguments(
lobbyID: info.lobbyID!,
playerID: info.playerID!,
passphrase: info.passphrase);
ConnectionCubit.getInstance().connect(
info.playerID!.uuid,
info.lobbyID!.uuid,
info.passphrase,
);
if (!chessGameArgs.isValid()) {
2023-12-25 16:50:58 +00:00
context.goNamed('lobbySelector');
const snackBar = SnackBar(
backgroundColor: Colors.amberAccent,
content: Text("Game information is corrupted"),
);
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
2024-02-05 09:35:28 +00:00
return;
}
2023-12-27 14:46:15 +00:00
context.goNamed('game', extra: chessGameArgs);
}
2024-02-05 09:35:28 +00:00
Future<PlayerInfo?> joinPrivateGame(BuildContext context) async {
http.Response response;
// server expects us to send the passphrase
var info = PlayerInfo(
2023-12-27 14:46:15 +00:00
playerID: null, lobbyID: null, passphrase: phraseController.text);
try {
response = await http.post(Uri.parse(config.getJoinURL()),
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-02-05 09:35:28 +00:00
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
return null;
}
if (response.statusCode == HttpStatus.notFound) {
const snackBar = SnackBar(
backgroundColor: Colors.amberAccent,
content: Text("Passphrase could not be found."),
);
if (!context.mounted) return null;
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
return null;
}
2024-02-05 09:35:28 +00:00
if (response.statusCode == HttpStatus.ok) {
var info = PlayerInfo.fromJson(jsonDecode(response.body));
log('Player info received from server: ');
log('lobbyID: ${info.lobbyID}');
log('playerID: ${info.playerID}');
log('passphrase: ${info.passphrase}');
return info;
}
return null;
}
2022-12-25 15:16:23 +00:00
}