import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart'; import 'package:mchess/api/game_info.dart'; import 'package:mchess/connection_cubit/connection_cubit.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:mchess/pages/chess_game.dart'; import 'package:mchess/utils/config.dart' as config; import 'package:mchess/utils/passphrase.dart'; import 'package:universal_platform/universal_platform.dart'; class CreateGameWidget extends StatefulWidget { const CreateGameWidget({super.key}); @override State createState() => _CreateGameWidgetState(); } class _CreateGameWidgetState extends State { late Future registerResponse; late ChessGameArguments chessGameArgs; @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, ); }); } @override Widget build(BuildContext context) { FloatingActionButton? fltnBtn; if (UniversalPlatform.isLinux || UniversalPlatform.isMacOS || UniversalPlatform.isWindows) { fltnBtn = FloatingActionButton( child: const Icon(Icons.cancel), onPressed: () { context.pop(); }, ); } 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 { String passphrase = snapshot.data?.passphrase ?? "no 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); } }, 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() ], ), ); } }, ), ), ); } Future hostPrivateGame() async { Response response; try { response = await http.get(Uri.parse(config.getHostURL()), headers: {"Accept": "application/json"}); } catch (e) { log('Exception: ${e.toString()}'); const snackBar = SnackBar( backgroundColor: Colors.amberAccent, content: Text("mChess server is not responding. Try again or give up"), ); Future.delayed(const Duration(seconds: 2), () { if (!context.mounted) return null; ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).showSnackBar(snackBar); context.goNamed('lobbySelector'); // We go back to the lobby selector }); return null; } if (response.statusCode == 200) { var info = GameInfo.fromJson(jsonDecode(response.body)); info.store(); return info; } return null; } }