Skip to content

Commit

Permalink
Merge pull request #37 from lichess-org/event_listener
Browse files Browse the repository at this point in the history
Improve board interactions with a custom gesture detector
  • Loading branch information
veloce authored Jul 5, 2024
2 parents 1f4e26c + bed668b commit a22b868
Show file tree
Hide file tree
Showing 10 changed files with 640 additions and 433 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## 3.0.0

Improve board interaction and add support for drawing shapes while playing.

### Playing:
- pieces are now moved with pointer down events, instead of a tap events
(pointer down followed by a pointer up event): this allows to move a piece
faster
- premoves are not anymore cleared when selecting another piece: this matches lichess website behaviour and allow to prepare another move along with the premove that is currently set

### Drawing shapes (experimental)
- drawing shapes is now possible while keeping the normal board play interaction (before it was either one or another mode)
- one can draw a shape by holding a finger to an empty square while using a second finger to draw a shape anywhere in the board
- a double tap on an empty square will clear all shapes at once
- to clear a single shape is still supported: draw the same shape again

## 2.6.4

- Fix coordinates and board display on devices with RightToLeft Directionality.
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ chess logic so you can use it with different chess variants.
- board themes
- piece sets from lichess
- promotion selector
- draw shapes on board
- draw shapes on board while playing using 2 fingers
- move annotations
- opponent's pieces can be displayed upside down

Expand Down Expand Up @@ -70,5 +70,6 @@ class _MyHomePageState extends State<MyHomePage> {
See the example app for:
- Random Bot: an interactable board for one player playing against a random bot,
- Free Play: an interactable board for two players sitting opposite to each other,
- Draw Shapes: activate the draw shapes feature and draw on the board using 2
- Board Thumbnails: a demo screen showing over hundred different boards in a grid,
- Draw Shapes: a demo screen where the user can highlight squares and draw arrows on a board.
fingers.
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
146 changes: 0 additions & 146 deletions example/lib/draw_shapes.dart

This file was deleted.

115 changes: 78 additions & 37 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:chessground/chessground.dart' hide BoardTheme;
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:dartchess/dartchess.dart' as dc;

import 'board_theme.dart';
import 'board_thumbnails.dart';
import 'draw_shapes.dart';

void main() {
runApp(const MyApp());
Expand Down Expand Up @@ -54,9 +52,12 @@ class _HomePageState extends State<HomePage> {
Side sideToMove = Side.white;
PieceSet pieceSet = PieceSet.merida;
BoardTheme boardTheme = BoardTheme.blue;
bool immersiveMode = false;
bool drawMode = true;
bool pieceAnimation = true;
bool dragMagnify = true;
Mode playMode = Mode.botPlay;
dc.Position<dc.Chess>? lastPos;
ISet<Shape> shapes = ISet();

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -103,17 +104,6 @@ class _HomePageState extends State<HomePage> {
);
},
),
ListTile(
title: const Text('Draw Shapes'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DrawShapesPage(),
),
);
},
),
],
)),
body: Center(
Expand All @@ -126,6 +116,19 @@ class _HomePageState extends State<HomePage> {
pieceAssets: pieceSet.assets,
colorScheme: boardTheme.colors,
enableCoordinates: true,
animationDuration: pieceAnimation
? const Duration(milliseconds: 200)
: Duration.zero,
dragFeedbackSize: dragMagnify ? 2.0 : 1.0,
drawShape: DrawShapeOptions(
enable: drawMode,
onCompleteShape: _onCompleteShape,
onClearShapes: () {
setState(() {
shapes = ISet();
});
},
),
),
data: BoardData(
interactableSide: playMode == Mode.botPlay
Expand All @@ -142,6 +145,7 @@ class _HomePageState extends State<HomePage> {
position.turn == dc.Side.white ? Side.white : Side.black,
isCheck: position.isCheck,
premove: premove,
shapes: shapes.isNotEmpty ? shapes : null,
),
onMove: playMode == Mode.botPlay
? _onUserMoveAgainstBot
Expand All @@ -151,29 +155,53 @@ class _HomePageState extends State<HomePage> {
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
child:
Text("Immersive mode: ${immersiveMode ? 'ON' : 'OFF'}"),
onPressed: () {
setState(() {
immersiveMode = !immersiveMode;
});
if (immersiveMode) {
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.immersiveSticky);
} else {
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.edgeToEdge);
}
},
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
ElevatedButton(
child: Text('Orientation: ${orientation.name}'),
onPressed: () {
setState(() {
orientation = orientation.opposite;
});
},
),
const SizedBox(width: 8),
ElevatedButton(
child:
Text("Magnify drag: ${dragMagnify ? 'ON' : 'OFF'}"),
onPressed: () {
setState(() {
dragMagnify = !dragMagnify;
});
},
),
],
),
ElevatedButton(
child: Text('Orientation: ${orientation.name}'),
onPressed: () {
setState(() {
orientation = orientation.opposite;
});
},
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
ElevatedButton(
child: Text("Drawing mode: ${drawMode ? 'ON' : 'OFF'}"),
onPressed: () {
setState(() {
drawMode = !drawMode;
});
},
),
const SizedBox(width: 8),
ElevatedButton(
child: Text(
"Piece animation: ${pieceAnimation ? 'ON' : 'OFF'}"),
onPressed: () {
setState(() {
pieceAnimation = !pieceAnimation;
});
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
Expand Down Expand Up @@ -235,6 +263,19 @@ class _HomePageState extends State<HomePage> {
);
}

void _onCompleteShape(Shape shape) {
if (shapes.any((element) => element == shape)) {
setState(() {
shapes = shapes.remove(shape);
});
return;
} else {
setState(() {
shapes = shapes.add(shape);
});
}
}

void _showChoicesPicker<T extends Enum>(
BuildContext context, {
required List<T> choices,
Expand Down Expand Up @@ -314,7 +355,7 @@ class _HomePageState extends State<HomePage> {
});
if (!position.isGameOver) {
final random = Random();
await Future.delayed(Duration(milliseconds: random.nextInt(5500) + 500));
await Future.delayed(Duration(milliseconds: random.nextInt(1000) + 500));
final allMoves = [
for (final entry in position.legalMoves.entries)
for (final dest in entry.value.squares)
Expand Down
Loading

0 comments on commit a22b868

Please sign in to comment.