Introduce checkmate screen #6

Merged
marco merged 1 commits from checkmate-screen into master 2024-01-18 16:03:30 +00:00
6 changed files with 103 additions and 16 deletions

View File

@ -4,7 +4,8 @@ enum MessageType {
boardState, boardState,
move, move,
invalidMove, invalidMove,
colorDetermined; colorDetermined,
gameEnded;
String toJson() => name; String toJson() => name;
static MessageType fromJson(String json) => values.byName(json); static MessageType fromJson(String json) => values.byName(json);
@ -82,6 +83,16 @@ class ApiWebsocketMessage {
squareInCheck: json['squareInCheck'], squareInCheck: json['squareInCheck'],
playerColor: null, playerColor: null,
); );
case MessageType.gameEnded:
ret = ApiWebsocketMessage(
type: type,
move: null,
turnColor: null,
reason: json['reason'],
position: null,
squareInCheck: null,
playerColor: null,
);
} }
return ret; return ret;
} }

View File

@ -1,5 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mchess/api/move.dart'; import 'package:mchess/api/move.dart';
import 'package:mchess/api/websocket_message.dart'; import 'package:mchess/api/websocket_message.dart';
import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'package:mchess/chess_bloc/chess_bloc.dart';
@ -7,7 +9,9 @@ import 'package:mchess/chess_bloc/chess_events.dart';
import 'package:mchess/api/register.dart'; import 'package:mchess/api/register.dart';
import 'package:mchess/chess_bloc/chess_position.dart'; import 'package:mchess/chess_bloc/chess_position.dart';
import 'package:mchess/connection_cubit/connection_cubit.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart';
import 'package:mchess/utils/chess_router.dart';
import 'package:mchess/utils/chess_utils.dart'; import 'package:mchess/utils/chess_utils.dart';
import 'package:mchess/utils/config.dart' as config;
import 'package:web_socket_channel/web_socket_channel.dart'; import 'package:web_socket_channel/web_socket_channel.dart';
class ServerConnection { class ServerConnection {
@ -38,9 +42,7 @@ class ServerConnection {
} }
void connect(String playerID, lobbyID, String? passphrase) { void connect(String playerID, lobbyID, String? passphrase) {
String url; channel = WebSocketChannel.connect(Uri.parse(config.getWebsocketURL()));
url = 'wss://chess.sw-gross.de:9999/api/ws';
channel = WebSocketChannel.connect(Uri.parse(url));
send( send(
jsonEncode( jsonEncode(
@ -82,6 +84,8 @@ class ServerConnection {
case MessageType.invalidMove: case MessageType.invalidMove:
handleInvalidMoveMessage(apiMessage); handleInvalidMoveMessage(apiMessage);
case MessageType.gameEnded:
handleGameEndedMessage(apiMessage);
} }
} }
@ -125,4 +129,29 @@ class ServerConnection {
), ),
); );
} }
void handleGameEndedMessage(ApiWebsocketMessage apiMessage) {
showDialog(
context: navigatorKey.currentContext!,
builder: (context) {
String msg = '';
if (apiMessage.reason == 'whiteIsCheckmated') {
msg = 'Black won! White is checkmated';
} else if (apiMessage.reason == 'blackIsCheckmated') {
msg = 'White won! Black is checkmated';
}
return AlertDialog(
title: const Text('Game ended'),
content: Text(msg),
actions: <Widget>[
TextButton(
child: const Text('Home'),
onPressed: () {
navigatorKey.currentContext!.goNamed('lobbySelector');
},
),
]);
},
);
}
} }

View File

@ -1,6 +1,7 @@
import 'dart:developer'; import 'dart:developer';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
@ -10,6 +11,7 @@ import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import 'package:mchess/pages/chess_game.dart'; import 'package:mchess/pages/chess_game.dart';
import 'package:mchess/utils/config.dart' as config;
class HostGameWidget extends StatefulWidget { class HostGameWidget extends StatefulWidget {
const HostGameWidget({super.key}); const HostGameWidget({super.key});
@ -80,9 +82,21 @@ class _HostGameWidgetState extends State<HostGameWidget> {
color: Theme.of(context).colorScheme.primary), color: Theme.of(context).colorScheme.primary),
), ),
const SizedBox(height: 25), const SizedBox(height: 25),
SelectableText( Row(
passphrase, mainAxisAlignment: MainAxisAlignment.center,
style: const TextStyle(fontWeight: FontWeight.bold), children: [
SelectableText(
passphrase,
style: const TextStyle(fontWeight: FontWeight.bold),
),
IconButton(
icon: const Icon(Icons.copy),
onPressed: () async {
await Clipboard.setData(
ClipboardData(text: passphrase));
},
)
],
), ),
const SizedBox(height: 25), const SizedBox(height: 25),
const CircularProgressIndicator() const CircularProgressIndicator()
@ -97,14 +111,11 @@ class _HostGameWidgetState extends State<HostGameWidget> {
} }
Future<PlayerInfo?> hostPrivateGame() async { Future<PlayerInfo?> hostPrivateGame() async {
String addr;
Response response; Response response;
addr = 'https://chess.sw-gross.de:9999/api/hostPrivate';
try { try {
response = await http response = await http.get(Uri.parse(config.getHostURL()),
.get(Uri.parse(addr), headers: {"Accept": "application/json"}); headers: {"Accept": "application/json"});
} catch (e) { } catch (e) {
log(e.toString()); log(e.toString());

View File

@ -7,6 +7,7 @@ import 'package:http/http.dart' as http;
import 'package:mchess/api/register.dart'; import 'package:mchess/api/register.dart';
import 'package:mchess/connection_cubit/connection_cubit.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart';
import 'package:mchess/pages/chess_game.dart'; import 'package:mchess/pages/chess_game.dart';
import 'package:mchess/utils/config.dart' as config;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class LobbySelector extends StatefulWidget { class LobbySelector extends StatefulWidget {
@ -149,17 +150,14 @@ class _LobbySelectorState extends State<LobbySelector> {
} }
Future<PlayerInfo?> joinPrivateGame() async { Future<PlayerInfo?> joinPrivateGame() async {
String addr;
http.Response response; http.Response response;
// server expects us to send the passphrase // server expects us to send the passphrase
var info = PlayerInfo( var info = PlayerInfo(
playerID: null, lobbyID: null, passphrase: phraseController.text); playerID: null, lobbyID: null, passphrase: phraseController.text);
addr = 'https://chess.sw-gross.de:9999/api/joinPrivate';
try { try {
response = await http.post(Uri.parse(addr), response = await http.post(Uri.parse(config.getJoinURL()),
body: jsonEncode(info), headers: {"Accept": "application/json"}); body: jsonEncode(info), headers: {"Accept": "application/json"});
} catch (e) { } catch (e) {
log(e.toString()); log(e.toString());

View File

@ -1,8 +1,11 @@
import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:mchess/pages/chess_game.dart'; import 'package:mchess/pages/chess_game.dart';
import 'package:mchess/pages/lobby_selector.dart'; import 'package:mchess/pages/lobby_selector.dart';
import 'package:mchess/pages/host_game.dart'; import 'package:mchess/pages/host_game.dart';
final navigatorKey = GlobalKey<NavigatorState>();
class ChessAppRouter { class ChessAppRouter {
static final ChessAppRouter _instance = ChessAppRouter._internal(); static final ChessAppRouter _instance = ChessAppRouter._internal();
@ -13,6 +16,7 @@ class ChessAppRouter {
} }
final router = GoRouter( final router = GoRouter(
navigatorKey: navigatorKey,
debugLogDiagnostics: true, debugLogDiagnostics: true,
routes: [ routes: [
GoRoute( GoRoute(

34
lib/utils/config.dart Normal file
View File

@ -0,0 +1,34 @@
const prodURL = 'chess.sw-gross.de:9999';
const debugURL = 'localhost:8080';
const dbgUrl = false;
String getHostURL() {
var prot = 'https';
var domain = prodURL;
if (dbgUrl) {
prot = 'http';
domain = debugURL;
}
return '$prot://$domain/api/hostPrivate';
}
String getJoinURL() {
var prot = 'https';
var domain = prodURL;
if (dbgUrl) {
prot = 'http';
domain = debugURL;
}
return '$prot://$domain/api/joinPrivate';
}
String getWebsocketURL() {
var prot = 'wss';
var domain = prodURL;
if (dbgUrl) {
prot = 'ws';
domain = debugURL;
}
return '$prot://$domain/api/ws';
}