Changes you see? To many to name them. And a splash screen for flutter web of course.

This commit is contained in:
Marco 2023-06-28 12:37:59 +02:00
parent e27f1c7c22
commit 43fca47dae
14 changed files with 157 additions and 56 deletions

View File

@ -2,6 +2,7 @@ import 'package:mchess/api/move.dart';
enum MessageType {
move,
invalidMove,
colorDetermined;
String toJson() => name;
@ -20,9 +21,13 @@ class ApiWebsocketMessage {
final MessageType type;
final ApiMove? move;
final ApiColor? color;
final String? reason;
ApiWebsocketMessage(
{required this.type, required this.move, required this.color});
{required this.type,
required this.move,
required this.color,
required this.reason});
factory ApiWebsocketMessage.fromJson(Map<String, dynamic> json) {
final type = MessageType.fromJson(json['messageType']);
@ -30,11 +35,25 @@ class ApiWebsocketMessage {
switch (type) {
case MessageType.colorDetermined:
ret = ApiWebsocketMessage(
type: type, move: null, color: ApiColor.fromJson(json['color']));
type: type,
move: null,
color: ApiColor.fromJson(json['color']),
reason: null);
break;
case MessageType.move:
ret = ApiWebsocketMessage(
type: type, move: ApiMove.fromJson(json['move']), color: null);
type: type,
move: ApiMove.fromJson(json['move']),
color: null,
reason: null);
break;
case MessageType.invalidMove:
ret = ApiWebsocketMessage(
type: type,
move: ApiMove.fromJson(json['move']),
color: null,
reason: json['reason'],
);
}
return ret;
}

View File

@ -18,7 +18,7 @@ class ChessApp extends StatelessWidget {
useMaterial3: true,
),
routerConfig: ChessAppRouter.getInstance().router,
title: 'mChess v0.1.1337',
title: 'mChess',
),
),
);

View File

@ -21,8 +21,9 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
ChessBloc._internal() : super(ChessBoardState.init()) {
on<InitBoard>(initBoard);
on<ColorDetermined>(flipBoard);
on<OpponentPieceMoved>(opponentMoveHandler);
on<ReceivedMove>(moveHandler);
on<OwnPieceMoved>(ownMoveHandler);
on<InvalidMovePlayed>(invalidMoveHandler);
}
factory ChessBloc.getInstance() {
@ -45,8 +46,7 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
emit(ChessBoardState(event.myColor, state.newTurnColor, state.position));
}
void opponentMoveHandler(
OpponentPieceMoved event, Emitter<ChessBoardState> emit) {
void moveHandler(ReceivedMove event, Emitter<ChessBoardState> emit) {
log('opponentMoveHandler()');
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
var newPosition = ChessPosition.getInstance().currentPosition;
@ -66,32 +66,37 @@ class ChessBloc extends Bloc<ChessEvent, ChessBoardState> {
void ownMoveHandler(OwnPieceMoved event, Emitter<ChessBoardState> emit) {
log('ownMoveHandler()');
ChessPosition.getInstance().recordMove(event.startSquare, event.endSquare);
var start = ApiCoordinate(
col: event.startSquare.column, row: event.startSquare.row);
var end =
ApiCoordinate(col: event.endSquare.column, row: event.endSquare.row);
var move = ApiMove(startSquare: start, endSquare: end);
var message =
ApiWebsocketMessage(type: MessageType.move, move: move, color: null);
var apiMove = ApiMove(startSquare: start, endSquare: end);
var apiMessage = ApiWebsocketMessage(
type: MessageType.move, move: apiMove, color: null, reason: null);
ServerConnection.getInstance().send(jsonEncode(message));
ServerConnection.getInstance().send(jsonEncode(apiMessage));
turnColor = state.newTurnColor == ChessColor.white
? ChessColor.black
: ChessColor.white;
var newPosition = ChessPosition.getInstance().currentPosition;
//Temporary chess position until server responds with acknoledgement
var move = ChessMove.fromApiMove(apiMove);
var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition;
tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none();
tempPosition[move.from] = const ChessPiece.none();
emit(
ChessBoardState(
state.bottomColor,
turnColor,
newPosition,
tempPosition,
),
);
}
void invalidMoveHandler(
InvalidMovePlayed event, Emitter<ChessBoardState> emit) {
emit(ChessBoardState(state.bottomColor, turnColor,
ChessPosition.getInstance().currentPosition));
}
}
class ChessBoardState {

View File

@ -2,11 +2,11 @@ import 'package:mchess/utils/chess_utils.dart';
abstract class ChessEvent {}
class OpponentPieceMoved extends ChessEvent {
class ReceivedMove extends ChessEvent {
final ChessCoordinate startSquare;
final ChessCoordinate endSquare;
OpponentPieceMoved({required this.startSquare, required this.endSquare});
ReceivedMove({required this.startSquare, required this.endSquare});
}
class OwnPieceMoved extends ChessEvent {
@ -25,3 +25,9 @@ class ColorDetermined extends ChessEvent {
ColorDetermined({required this.myColor});
}
class InvalidMovePlayed extends ChessEvent {
final ChessMove move;
InvalidMovePlayed({required this.move});
}

View File

@ -20,6 +20,7 @@ class ChessPosition {
}
ChessPositionType get currentPosition => position;
ChessPositionType get copyOfCurrentPosition => Map.from(position);
ChessMove? get lastMove {
if (history.isEmpty) return null;
return history.last;
@ -103,7 +104,7 @@ class ChessPosition {
logString = '$logString\n';
}
log(logString);
print(logString);
}
void logHistory(ChessMoveHistory hist) {

View File

@ -69,6 +69,9 @@ class ServerConnection {
case MessageType.move:
handleIncomingMoveMessage(apiMessage);
break;
case MessageType.invalidMove:
handleInvalidMoveMessage(apiMessage);
}
}
@ -79,11 +82,13 @@ class ServerConnection {
void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) {
var move = ChessMove.fromApiMove(apiMessage.move!);
if (move == ChessPosition.getInstance().lastMove) {
//This is our own move that got resent by the server. Do not process.
} else {
ChessBloc.getInstance()
.add(OpponentPieceMoved(startSquare: move.from, endSquare: move.to));
}
ChessBloc.getInstance()
.add(ReceivedMove(startSquare: move.from, endSquare: move.to));
}
void handleInvalidMoveMessage(ApiWebsocketMessage apiMessage) {
log("invalid move message received, with move: ${apiMessage.move.toString()}");
ChessBloc.getInstance()
.add(InvalidMovePlayed(move: ChessMove.fromApiMove(apiMessage.move!)));
}
}

View File

@ -144,14 +144,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lints:
dependency: transitive
description:
@ -341,6 +333,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel:
dependency: "direct main"
description:
@ -358,5 +358,5 @@ packages:
source: hosted
version: "6.3.0"
sdks:
dart: ">=3.0.0 <4.0.0"
dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.7.0-0"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -24,7 +24,7 @@
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="mchess">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<link rel="apple-touch-icon" href="web_icons/Icon-192.png">
<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>
@ -40,20 +40,85 @@
<script src="flutter.js" defer></script>
</head>
<body>
<script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
},
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
appRunner.runApp();
});
}
});
});
</script>
</script>
<!-- Loading indicator -->
<div id="loading">
<style>
body {
inset: 0;
overflow: hidden;
margin: 0;
padding: 0;
position: fixed;
}
#loading {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
width: 100%;
}
#loading img {
animation: 1s ease-in-out 0s infinite alternate breathe;
opacity: .66;
transition: opacity .4s;
}
#loading.main_done img {
opacity: 1;
}
#loading.init_done img {
animation: .33s ease-in-out 0s 1 forwards zooooom;
opacity: .05;
}
@keyframes breathe {
from {
transform: scale(1)
}
to {
transform: scale(0.95)
}
}
@keyframes zooooom {
from {
transform: scale(1)
}
to {
transform: scale(10)
}
}
</style>
<img src="web_icons/Icon-192.png" alt="Loading indicator..." />
</div>
<script>
window.addEventListener('load', function () {
var loading = document.querySelector('#loading');
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function (engineInitializer) {
loading.classList.add('main_done');
return engineInitializer.initializeEngine();
}).then(function (appRunner) {
loading.classList.add('init_done');
return appRunner.runApp();
}).then(function (app) {
// Wait a few milliseconds so users can see the "zoooom" animation
// before getting rid of the "loading" div.
window.setTimeout(function () {
loading.remove();
}, 200);
});
});
</script>
</body>
</html>

View File

@ -10,23 +10,23 @@
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"src": "web_icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"src": "web_icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icons/Icon-maskable-192.png",
"src": "web_icons/Icon-maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icons/Icon-maskable-512.png",
"src": "web_icons/Icon-maskable-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"

BIN
web/web_icons/Icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB