mchess-client/lib/pages/lobby_selector.dart
Marco 212a54612c Implement moves by tapping the squares
This adds an option to dragging-and-dropping which is slightly hard on
smaller screens.

Fix promotions when tapping and fix handling of subsequently tapping two pieces of your color

Cancel tap if a drag is started (tapped square will not stay red in case a drag is started)

Change url strategy back to the hashtag thing

Change version

Fix bug that would not allow a piece move if you tried to take an opponents piece.

Fix the coloring of the last move after an invalid move was played.

Upgrading deps
2024-01-17 20:58:13 +01:00

191 lines
5.6 KiB
Dart

import 'dart:convert';
import 'dart:developer';
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:shared_preferences/shared_preferences.dart';
class LobbySelector extends StatefulWidget {
const LobbySelector({super.key});
@override
State<LobbySelector> createState() => _LobbySelectorState();
}
class _LobbySelectorState extends State<LobbySelector> {
final buttonStyle = const ButtonStyle();
final phraseController = TextEditingController();
late Future<PlayerInfo?> joinGameFuture;
@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");
});
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => buildJoinOrHostDialog(context),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.lock),
SizedBox(
width: 10,
),
Text('Private game')
],
),
),
],
),
),
);
}
Future<void> buildJoinOrHostDialog(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return Scaffold(
body: AlertDialog(
title: const Text('Host or join?'),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () => context.pop(),
),
TextButton(
child: const Text('Host'),
onPressed: () {
context.pop(); //close dialog before going to host
context.goNamed('host');
}),
TextButton(
child: const Text('Join'),
onPressed: () {
context.pop(); //close dialog before going to next dialog
buildEnterPassphraseDialog(context);
},
),
],
),
);
},
);
}
Future<void> buildEnterPassphraseDialog(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Enter the passphrase here:'),
content: TextField(
controller: phraseController,
decoration: InputDecoration(
hintText: 'Enter passphrase here',
suffixIcon: IconButton(
onPressed: () {
joinGameFuture = joinPrivateGame();
joinGameFuture.then((value) {
if (value != null) {
phraseController.clear();
context.pop();
switchToGame(value);
}
});
},
icon: const Icon(Icons.check),
)),
),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
onPressed: () {
context.pop();
},
),
],
);
},
);
}
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()) {
context.goNamed('lobbySelector');
const snackBar = SnackBar(
backgroundColor: Colors.amberAccent,
content: Text("Game information is corrupted"),
);
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
context.goNamed('game', extra: chessGameArgs);
}
Future<PlayerInfo?> joinPrivateGame() async {
String addr;
http.Response response;
// server expects us to send the passphrase
var info = PlayerInfo(
playerID: null, lobbyID: null, passphrase: phraseController.text);
addr = 'https://chess.sw-gross.de:9999/api/joinPrivate';
try {
response = await http.post(Uri.parse(addr),
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"),
);
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(snackBar);
return null;
}
if (response.statusCode == 200) {
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;
}
}