From adf8c86692badbe274cb86cc018a7e5ce8d155dd Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 20 May 2024 15:34:20 +0200 Subject: [PATCH 1/5] Make many changes 1. A game is only identified by a passphrase (not a lobby id) 2. We can store multiple passphrase/playerID combinations --- lib/api/game_info.dart | 48 +++------------ lib/connection/ws_connection.dart | 9 +-- lib/connection_cubit/connection_cubit.dart | 8 ++- lib/pages/create_game_widget.dart | 44 +++++--------- lib/pages/join_game_handle_widget.dart | 69 ++++++++-------------- lib/pages/lobby_selector.dart | 8 ++- lib/utils/chess_router.dart | 6 +- lib/utils/config.dart | 6 +- 8 files changed, 68 insertions(+), 130 deletions(-) diff --git a/lib/api/game_info.dart b/lib/api/game_info.dart index c34adc7..9247df4 100644 --- a/lib/api/game_info.dart +++ b/lib/api/game_info.dart @@ -3,43 +3,33 @@ import 'package:uuid/uuid.dart'; class GameInfo { final UuidValue? playerID; - final UuidValue? lobbyID; final String? passphrase; const GameInfo({ required this.playerID, - required this.lobbyID, required this.passphrase, }); factory GameInfo.empty() { - return const GameInfo(playerID: null, lobbyID: null, passphrase: null); + return const GameInfo(playerID: null, passphrase: null); } factory GameInfo.fromJson(Map json) { final playerid = UuidValue.fromString(json['playerID']); - final lobbyid = UuidValue.fromString(json['lobbyID']); final passphrase = json['passphrase']; - return GameInfo( - playerID: playerid, lobbyID: lobbyid, passphrase: passphrase); + return GameInfo(playerID: playerid, passphrase: passphrase); } Map toJson() { String? pid; - String? lid; if (playerID != null) { pid = playerID.toString(); } - if (lobbyID != null) { - lid = lobbyID.toString(); - } - return { 'playerID': pid, - 'lobbyID': lid, 'passphrase': passphrase, }; } @@ -47,51 +37,29 @@ class GameInfo { void store() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); - await prefs.setBool("contains", true); - await prefs.setString("playerID", playerID.toString()); - await prefs.setString("lobbyID", lobbyID.toString()); - await prefs.setString("passphrase", passphrase.toString()); + await prefs.setString(passphrase!, playerID.toString()); } - void delete() async { + static Future get(String phrase) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); + var playerID = prefs.getString(phrase); - await prefs.setBool("contains", false); - } - - static Future get() async { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - var contains = prefs.getBool("contains"); - var playerID = prefs.getString("playerID"); - var lobbyID = prefs.getString("lobbyID"); - var passphrase = prefs.getString("passphrase"); - - if (contains == null || - !contains || - playerID == null || - lobbyID == null || - passphrase == null) { - return null; - } + if (playerID == null) return null; return GameInfo( - playerID: UuidValue.fromString(playerID), - lobbyID: UuidValue.fromString(lobbyID), - passphrase: passphrase); + playerID: UuidValue.fromString(playerID!), passphrase: phrase); } } class WebsocketMessageIdentifyPlayer { final String playerID; - final String lobbyID; final String? passphrase; const WebsocketMessageIdentifyPlayer({ required this.playerID, - required this.lobbyID, required this.passphrase, }); Map toJson() => - {'lobbyID': lobbyID, 'playerID': playerID, 'passphrase': passphrase}; + {'playerID': playerID, 'passphrase': passphrase}; } diff --git a/lib/connection/ws_connection.dart b/lib/connection/ws_connection.dart index 33eaac8..85dcd99 100644 --- a/lib/connection/ws_connection.dart +++ b/lib/connection/ws_connection.dart @@ -40,15 +40,15 @@ class ServerConnection { channel!.sink.add(message); } - void connect(String playerID, lobbyID, String? passphrase) { - disconnectExistingConnection(); + void connect(String playerID, String? passphrase) { + if (channel != null) return; + channel = WebSocketChannel.connect(Uri.parse(config.getWebsocketURL())); send( jsonEncode( WebsocketMessageIdentifyPlayer( playerID: (playerID), - lobbyID: (lobbyID), passphrase: (passphrase), ), ), @@ -61,8 +61,9 @@ class ServerConnection { void disconnectExistingConnection() { if (channel == null) return; - channel!.sink.close(); + channel!.sink.close(); + channel = null; broadcast = const Stream.empty(); } diff --git a/lib/connection_cubit/connection_cubit.dart b/lib/connection_cubit/connection_cubit.dart index 9c9c3e2..3ef0c5e 100644 --- a/lib/connection_cubit/connection_cubit.dart +++ b/lib/connection_cubit/connection_cubit.dart @@ -15,8 +15,12 @@ class ConnectionCubit extends Cubit { return _instance; } - void connect(String playerID, lobbyID, String? passphrase) { - ServerConnection.getInstance().connect(playerID, lobbyID, passphrase); + void connect(String playerID, String? passphrase) { + ServerConnection.getInstance().connect(playerID, passphrase); + } + + void disonnect() { + ServerConnection.getInstance().disconnectExistingConnection(); } void opponentConnected() { diff --git a/lib/pages/create_game_widget.dart b/lib/pages/create_game_widget.dart index 5db7430..d005bba 100644 --- a/lib/pages/create_game_widget.dart +++ b/lib/pages/create_game_widget.dart @@ -28,31 +28,9 @@ class _CreateGameWidgetState extends State { @override void initState() { - registerResponse = hostPrivateGame(); - - registerResponse.then((args) { - if (args == null) return; - - chessGameArgs = ChessGameArguments( - lobbyID: args.lobbyID!, - playerID: args.playerID!, - passphrase: args.passphrase); - }); - - connectToWebsocket(registerResponse); super.initState(); - } - - void connectToWebsocket(Future resp) { - resp.then((value) { - if (value == null) return; - - ConnectionCubit.getInstance().connect( - value.playerID!.uuid, - value.lobbyID!.uuid, - value.passphrase, - ); - }); + ConnectionCubit().disonnect(); + registerResponse = createPrivateGame(); } @override @@ -82,15 +60,21 @@ class _CreateGameWidgetState extends State { child: CircularProgressIndicator(), ); } else { - String passphrase = snapshot.data?.passphrase ?? "no passphrase"; + var passphrase = snapshot.data?.passphrase ?? "no passphrase"; + + ConnectionCubit().connect( + snapshot.data!.playerID.toString(), + snapshot.data!.passphrase, + ); + return BlocListener( listener: (context, state) { // We wait for our opponent to connect if (state.opponentConnected) { //TODO: is goNamed the correct way to navigate? - context.goNamed('game', - pathParameters: {'phrase': passphrase.toURL()}, - extra: chessGameArgs); + context.goNamed('game', pathParameters: { + 'phrase': passphrase.toURL(), + }); } }, child: Column( @@ -130,11 +114,11 @@ class _CreateGameWidgetState extends State { ); } - Future hostPrivateGame() async { + Future createPrivateGame() async { Response response; try { - response = await http.get(Uri.parse(config.getHostURL()), + response = await http.get(Uri.parse(config.getCreateGameURL()), headers: {"Accept": "application/json"}); } catch (e) { log('Exception: ${e.toString()}'); diff --git a/lib/pages/join_game_handle_widget.dart b/lib/pages/join_game_handle_widget.dart index 4d865c5..9c0dfbc 100644 --- a/lib/pages/join_game_handle_widget.dart +++ b/lib/pages/join_game_handle_widget.dart @@ -3,7 +3,6 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:mchess/api/game_info.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart'; @@ -23,65 +22,48 @@ class _JoinGameHandleWidgetState extends State { @override void initState() { - joinGameFuture = joinPrivateGame(widget.passphrase); - joinGameFuture.then( - (value) { - if (value != null) { - switchToGame(value); - } - }, - ); super.initState(); + ConnectionCubit().disonnect(); + joinGameFuture = joinPrivateGame(widget.passphrase); } @override Widget build(BuildContext context) { - return const ChessGame(); - } - - void switchToGame(GameInfo 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); - - return; - } + return FutureBuilder( + future: joinGameFuture, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ); + } else { + ConnectionCubit.getInstance().connect( + snapshot.data!.playerID!.uuid, + snapshot.data!.passphrase, + ); + return const ChessGame(); + } + }); } Future joinPrivateGame(String phrase) async { http.Response response; - var existingInfo = await GameInfo.get(); - log('lobbyID: ${existingInfo?.lobbyID} and playerID: ${existingInfo?.playerID} and passphrase: "${existingInfo?.passphrase}"'); + + var existingInfo = await GameInfo.get(phrase); + log('playerID: ${existingInfo?.playerID} and passphrase: "${existingInfo?.passphrase}"'); GameInfo info; if (existingInfo?.passphrase == phrase) { // We have player info for this exact passphrase - info = GameInfo( - playerID: existingInfo?.playerID, - lobbyID: existingInfo?.lobbyID, - passphrase: phrase); + info = GameInfo(playerID: existingInfo?.playerID, passphrase: phrase); } else { - info = GameInfo(playerID: null, lobbyID: null, passphrase: phrase); + info = GameInfo(playerID: null, passphrase: phrase); } try { - response = await http.post(Uri.parse(config.getJoinURL()), + response = await http.post(Uri.parse(config.getJoinGameURL()), body: jsonEncode(info), headers: {"Accept": "application/json"}); } catch (e) { log(e.toString()); @@ -114,7 +96,6 @@ class _JoinGameHandleWidgetState extends State { var info = GameInfo.fromJson(jsonDecode(response.body)); info.store(); log('Player info received from server: '); - log('lobbyID: ${info.lobbyID}'); log('playerID: ${info.playerID}'); log('passphrase: ${info.passphrase}'); diff --git a/lib/pages/lobby_selector.dart b/lib/pages/lobby_selector.dart index 353d73b..c6e10b2 100644 --- a/lib/pages/lobby_selector.dart +++ b/lib/pages/lobby_selector.dart @@ -20,7 +20,9 @@ class _LobbySelectorState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( - onPressed: () => context.goNamed('createGame'), + onPressed: () { + context.goNamed('createGame'); + }, child: const Row( mainAxisSize: MainAxisSize.min, children: [ @@ -34,7 +36,9 @@ class _LobbySelectorState extends State { ), const SizedBox(height: 20), ElevatedButton( - onPressed: () => buildEnterPassphraseDialog(context), + onPressed: () { + buildEnterPassphraseDialog(context); + }, child: const Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/lib/utils/chess_router.dart b/lib/utils/chess_router.dart index aab6974..6507b9a 100644 --- a/lib/utils/chess_router.dart +++ b/lib/utils/chess_router.dart @@ -2,7 +2,6 @@ import 'dart:developer'; import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; -import 'package:mchess/connection/ws_connection.dart'; import 'package:mchess/pages/join_game_handle_widget.dart'; import 'package:mchess/pages/lobby_selector.dart'; import 'package:mchess/pages/create_game_widget.dart'; @@ -40,8 +39,6 @@ class ChessAppRouter { path: 'game/:phrase', name: 'game', builder: (context, state) { - ServerConnection.getInstance().disconnectExistingConnection(); - var urlPhrase = state.pathParameters['phrase']; if (urlPhrase == null) { log('in /game route builder: url phrase null'); @@ -49,8 +46,7 @@ class ChessAppRouter { } return JoinGameHandleWidget( - passphrase: urlPhrase.toPhraseWithSpaces(), - ); + passphrase: urlPhrase.toPhraseWithSpaces()); }, ) ], diff --git a/lib/utils/config.dart b/lib/utils/config.dart index 863dedb..c80f6ae 100644 --- a/lib/utils/config.dart +++ b/lib/utils/config.dart @@ -1,9 +1,9 @@ const prodURL = 'chess.sw-gross.de:9999'; const debugURL = 'localhost:8080'; -const useDbgUrl = false; +const useDbgUrl = true; -String getHostURL() { +String getCreateGameURL() { var prot = 'https'; var domain = prodURL; if (useDbgUrl) { @@ -13,7 +13,7 @@ String getHostURL() { return '$prot://$domain/api/hostPrivate'; } -String getJoinURL() { +String getJoinGameURL() { var prot = 'https'; var domain = prodURL; if (useDbgUrl) { From 2a2e219c80c88be574b07845d7a76f9a24317995 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 20 May 2024 17:21:25 +0200 Subject: [PATCH 2/5] Wait for websocket to be disconnected before continuing --- lib/connection/ws_connection.dart | 5 +- lib/connection_cubit/connection_cubit.dart | 4 +- lib/pages/create_game_widget.dart | 132 ++++++++++++--------- lib/pages/join_game_handle_widget.dart | 37 ++++-- 4 files changed, 102 insertions(+), 76 deletions(-) diff --git a/lib/connection/ws_connection.dart b/lib/connection/ws_connection.dart index 85dcd99..0e5f10c 100644 --- a/lib/connection/ws_connection.dart +++ b/lib/connection/ws_connection.dart @@ -59,10 +59,11 @@ class ServerConnection { broadcast.listen(handleIncomingData); } - void disconnectExistingConnection() { + Future disconnectExistingConnection() async { if (channel == null) return; - channel!.sink.close(); + await channel!.sink.close(); + channel = null; broadcast = const Stream.empty(); } diff --git a/lib/connection_cubit/connection_cubit.dart b/lib/connection_cubit/connection_cubit.dart index 3ef0c5e..2f877b8 100644 --- a/lib/connection_cubit/connection_cubit.dart +++ b/lib/connection_cubit/connection_cubit.dart @@ -19,8 +19,8 @@ class ConnectionCubit extends Cubit { ServerConnection.getInstance().connect(playerID, passphrase); } - void disonnect() { - ServerConnection.getInstance().disconnectExistingConnection(); + Future disonnect() async { + return ServerConnection.getInstance().disconnectExistingConnection(); } void opponentConnected() { diff --git a/lib/pages/create_game_widget.dart b/lib/pages/create_game_widget.dart index d005bba..e31f723 100644 --- a/lib/pages/create_game_widget.dart +++ b/lib/pages/create_game_widget.dart @@ -24,13 +24,16 @@ class CreateGameWidget extends StatefulWidget { class _CreateGameWidgetState extends State { late Future registerResponse; + late Future disconnectFuture; late ChessGameArguments chessGameArgs; @override void initState() { super.initState(); - ConnectionCubit().disonnect(); - registerResponse = createPrivateGame(); + disconnectFuture = ConnectionCubit().disonnect(); + disconnectFuture.then((val) { + registerResponse = createPrivateGame(); + }); } @override @@ -50,66 +53,77 @@ class _CreateGameWidgetState extends State { return Scaffold( floatingActionButton: fltnBtn, body: Center( - child: FutureBuilder( - future: registerResponse, - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done) { - return const SizedBox( - height: 100, - width: 100, - child: CircularProgressIndicator(), - ); - } else { - var passphrase = snapshot.data?.passphrase ?? "no passphrase"; + child: FutureBuilder( + future: disconnectFuture, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return Container(); + } else { + return FutureBuilder( + future: registerResponse, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ); + } else { + var passphrase = + snapshot.data?.passphrase ?? "no passphrase"; - ConnectionCubit().connect( - snapshot.data!.playerID.toString(), - snapshot.data!.passphrase, - ); + ConnectionCubit().connect( + snapshot.data!.playerID.toString(), + snapshot.data!.passphrase, + ); - return BlocListener( - listener: (context, state) { - // We wait for our opponent to connect - if (state.opponentConnected) { - //TODO: is goNamed the correct way to navigate? - context.goNamed('game', pathParameters: { - 'phrase': passphrase.toURL(), - }); - } - }, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Give this phrase to your friend and sit tight:', - style: TextStyle( - color: Theme.of(context).colorScheme.primary), - ), - const SizedBox(height: 25), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SelectableText( - passphrase, - style: const TextStyle(fontWeight: FontWeight.bold), + return BlocListener( + listener: (context, state) { + // We wait for our opponent to connect + if (state.opponentConnected) { + //TODO: is goNamed the correct way to navigate? + context.goNamed('game', pathParameters: { + 'phrase': passphrase.toURL(), + }); + } + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Give this phrase to your friend and sit tight:', + style: TextStyle( + color: Theme.of(context).colorScheme.primary), + ), + const SizedBox(height: 25), + Row( + mainAxisAlignment: MainAxisAlignment.center, + 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 CircularProgressIndicator() + ], ), - IconButton( - icon: const Icon(Icons.copy), - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: passphrase)); - }, - ) - ], - ), - const SizedBox(height: 25), - const CircularProgressIndicator() - ], - ), - ); - } - }, - ), + ); + } + }, + ); + } + }), ), ); } diff --git a/lib/pages/join_game_handle_widget.dart b/lib/pages/join_game_handle_widget.dart index 9c0dfbc..28f3c66 100644 --- a/lib/pages/join_game_handle_widget.dart +++ b/lib/pages/join_game_handle_widget.dart @@ -19,31 +19,42 @@ class JoinGameHandleWidget extends StatefulWidget { class _JoinGameHandleWidgetState extends State { late Future joinGameFuture; + late Future disconnectFuture; @override void initState() { super.initState(); - ConnectionCubit().disonnect(); - joinGameFuture = joinPrivateGame(widget.passphrase); + disconnectFuture = ConnectionCubit().disonnect(); + disconnectFuture.then((val) { + joinGameFuture = joinPrivateGame(widget.passphrase); + }); } @override Widget build(BuildContext context) { return FutureBuilder( - future: joinGameFuture, + future: disconnectFuture, builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.done) { - return const SizedBox( - height: 100, - width: 100, - child: CircularProgressIndicator(), - ); + return Container(); } else { - ConnectionCubit.getInstance().connect( - snapshot.data!.playerID!.uuid, - snapshot.data!.passphrase, - ); - return const ChessGame(); + return FutureBuilder( + future: joinGameFuture, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ); + } else { + ConnectionCubit.getInstance().connect( + snapshot.data!.playerID!.uuid, + snapshot.data!.passphrase, + ); + return const ChessGame(); + } + }); } }); } From 358e8a6041fe640a9a9283680eaa273d54848fb5 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 21 May 2024 18:48:06 +0200 Subject: [PATCH 3/5] more changes because it's fun --- lib/api/game_info.dart | 2 +- lib/connection/ws_connection.dart | 28 ++++++----- lib/connection_cubit/connection_cubit.dart | 49 +++++++++++++++++-- lib/pages/create_game_widget.dart | 12 ++--- lib/pages/join_game_handle_widget.dart | 56 ++++++++++++---------- 5 files changed, 97 insertions(+), 50 deletions(-) diff --git a/lib/api/game_info.dart b/lib/api/game_info.dart index 9247df4..5b10048 100644 --- a/lib/api/game_info.dart +++ b/lib/api/game_info.dart @@ -47,7 +47,7 @@ class GameInfo { if (playerID == null) return null; return GameInfo( - playerID: UuidValue.fromString(playerID!), passphrase: phrase); + playerID: UuidValue.fromString(playerID), passphrase: phrase); } } diff --git a/lib/connection/ws_connection.dart b/lib/connection/ws_connection.dart index 0e5f10c..ceaed3e 100644 --- a/lib/connection/ws_connection.dart +++ b/lib/connection/ws_connection.dart @@ -40,23 +40,27 @@ class ServerConnection { channel!.sink.add(message); } - void connect(String playerID, String? passphrase) { - if (channel != null) return; + Future? connect(String playerID, String? passphrase) { + if (channel != null) return null; channel = WebSocketChannel.connect(Uri.parse(config.getWebsocketURL())); - send( - jsonEncode( - WebsocketMessageIdentifyPlayer( - playerID: (playerID), - passphrase: (passphrase), + channel!.ready.then((val) { + send( + jsonEncode( + WebsocketMessageIdentifyPlayer( + playerID: (playerID), + passphrase: (passphrase), + ), ), - ), - ); + ); - log(channel!.closeCode.toString()); - broadcast = channel!.stream.asBroadcastStream(); - broadcast.listen(handleIncomingData); + log(channel!.closeCode.toString()); + broadcast = channel!.stream.asBroadcastStream(); + broadcast.listen(handleIncomingData); + }); + + return channel!.ready; } Future disconnectExistingConnection() async { diff --git a/lib/connection_cubit/connection_cubit.dart b/lib/connection_cubit/connection_cubit.dart index 2f877b8..10babd6 100644 --- a/lib/connection_cubit/connection_cubit.dart +++ b/lib/connection_cubit/connection_cubit.dart @@ -16,24 +16,63 @@ class ConnectionCubit extends Cubit { } void connect(String playerID, String? passphrase) { - ServerConnection.getInstance().connect(playerID, passphrase); + var connectedFuture = + ServerConnection.getInstance().connect(playerID, passphrase); + + connectedFuture?.then((val) { + emit(ConnectionCubitState( + iAmConnected: true, + connectedToPhrase: passphrase, + opponentConnected: false)); + }); + } + + void connectIfNotConnected(String playerID, String? passphrase) { + if (state.iAmConnected && state.connectedToPhrase == passphrase) { + return; + } + if (state.iAmConnected && state.connectedToPhrase != passphrase) { + disonnect().then((val) { + connect(playerID, passphrase); + }); + } + + connect(playerID, passphrase); } Future disonnect() async { - return ServerConnection.getInstance().disconnectExistingConnection(); + var disconnectFuture = + ServerConnection.getInstance().disconnectExistingConnection(); + + disconnectFuture.then( + (val) { + emit(ConnectionCubitState.init()); + }, + ); + + return disconnectFuture; } void opponentConnected() { - emit(ConnectionCubitState(true)); + emit(ConnectionCubitState( + iAmConnected: state.iAmConnected, + connectedToPhrase: state.connectedToPhrase, + opponentConnected: true)); } } class ConnectionCubitState { + final bool iAmConnected; + final String? connectedToPhrase; final bool opponentConnected; - ConnectionCubitState(this.opponentConnected); + ConnectionCubitState( + {required this.iAmConnected, + required this.connectedToPhrase, + required this.opponentConnected}); factory ConnectionCubitState.init() { - return ConnectionCubitState(false); + return ConnectionCubitState( + iAmConnected: false, connectedToPhrase: null, opponentConnected: false); } } diff --git a/lib/pages/create_game_widget.dart b/lib/pages/create_game_widget.dart index e31f723..199e149 100644 --- a/lib/pages/create_game_widget.dart +++ b/lib/pages/create_game_widget.dart @@ -33,6 +33,12 @@ class _CreateGameWidgetState extends State { disconnectFuture = ConnectionCubit().disonnect(); disconnectFuture.then((val) { registerResponse = createPrivateGame(); + registerResponse.then((val) { + ConnectionCubit().connectIfNotConnected( + val!.playerID.toString(), + val.passphrase, + ); + }); }); } @@ -71,12 +77,6 @@ class _CreateGameWidgetState extends State { } else { var passphrase = snapshot.data?.passphrase ?? "no passphrase"; - - ConnectionCubit().connect( - snapshot.data!.playerID.toString(), - snapshot.data!.passphrase, - ); - return BlocListener( listener: (context, state) { diff --git a/lib/pages/join_game_handle_widget.dart b/lib/pages/join_game_handle_widget.dart index 28f3c66..7cd0724 100644 --- a/lib/pages/join_game_handle_widget.dart +++ b/lib/pages/join_game_handle_widget.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:http/http.dart' as http; import 'package:mchess/api/game_info.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart'; @@ -19,44 +20,47 @@ class JoinGameHandleWidget extends StatefulWidget { class _JoinGameHandleWidgetState extends State { late Future joinGameFuture; - late Future disconnectFuture; @override void initState() { super.initState(); - disconnectFuture = ConnectionCubit().disonnect(); - disconnectFuture.then((val) { - joinGameFuture = joinPrivateGame(widget.passphrase); + joinGameFuture = joinPrivateGame(widget.passphrase); + joinGameFuture.then((val) { + ConnectionCubit.getInstance().connectIfNotConnected( + val!.playerID!.uuid, + val.passphrase, + ); }); } @override Widget build(BuildContext context) { - return FutureBuilder( - future: disconnectFuture, - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done) { - return Container(); - } else { - return FutureBuilder( - future: joinGameFuture, - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done) { - return const SizedBox( - height: 100, - width: 100, - child: CircularProgressIndicator(), - ); - } else { - ConnectionCubit.getInstance().connect( - snapshot.data!.playerID!.uuid, - snapshot.data!.passphrase, - ); + var loadingIndicator = const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ); + + return Scaffold( + body: Center( + child: FutureBuilder( + future: joinGameFuture, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return loadingIndicator; + } else { + return BlocBuilder( + builder: (context, state) { + if (state.iAmConnected) { return const ChessGame(); + } else { + return loadingIndicator; } }); - } - }); + } + }), + ), + ); } Future joinPrivateGame(String phrase) async { From bde3d3e35880d3834832bce1475a8cfb7ed9908d Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 21 May 2024 23:47:11 +0200 Subject: [PATCH 4/5] url --- lib/utils/config.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/config.dart b/lib/utils/config.dart index c80f6ae..89d1b6a 100644 --- a/lib/utils/config.dart +++ b/lib/utils/config.dart @@ -1,7 +1,7 @@ const prodURL = 'chess.sw-gross.de:9999'; const debugURL = 'localhost:8080'; -const useDbgUrl = true; +const useDbgUrl = false; String getCreateGameURL() { var prot = 'https'; From fa525c244279a73684a89fc653a77daa1fc86416 Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 21 May 2024 23:47:50 +0200 Subject: [PATCH 5/5] bump version --- lib/chess/chess_app.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chess/chess_app.dart b/lib/chess/chess_app.dart index c25efeb..da3a3fa 100644 --- a/lib/chess/chess_app.dart +++ b/lib/chess/chess_app.dart @@ -31,7 +31,7 @@ class ChessApp extends StatelessWidget { useMaterial3: true, ), routerConfig: ChessAppRouter.getInstance().router, - title: 'mChess 1.0.6', + title: 'mChess 1.0.7', ), ); }