mchess-client/lib/pages/create_game_widget.dart

164 lines
5.0 KiB
Dart

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<CreateGameWidget> createState() => _CreateGameWidgetState();
}
class _CreateGameWidgetState extends State<CreateGameWidget> {
late Future<GameInfo?> 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<GameInfo?> 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<GameInfo?>(
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<ConnectionCubit, ConnectionCubitState>(
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<GameInfo?> 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;
}
}