Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add board editor #865

Merged
merged 2 commits into from
Aug 5, 2024
Merged

feat: add board editor #865

merged 2 commits into from
Aug 5, 2024

Conversation

tom-anders
Copy link
Contributor

@tom-anders tom-anders commented Jul 14, 2024

Closes #458

Opening an early draft PR to let people know I'm working on this.

Functionality that should definitely be part of this PR IMO:

  • Move around pieces freely on the board.
  • Add a bottom bar to add pieces similar to the old app and lichess.org, selecting a piece in this bar and then tapping a square will add a piece to that square, selecting the bin will remove tapped pieces from the board.
    Screenshot_2024-07-14_16-29-33
  • Button to flip the board
  • Buttons for castling rights and for side to play
  • Buttons to open position in analysis screen

Functionality that we could add later:

  • Drag-and-drop pieces from the bottom bar (see above) onto the board - I'm not sure if this needs adjustments in flutter-chessground as well...? Edit: yes, most definitely
  • Discard pieces by dragging them off-screen
  • Load a specific opening as starting position
  • Add button to challenge from built position
  • Export position as FEN

@veloce Feedback would be welcome, if you find the time :)

@tom-anders
Copy link
Contributor Author

tom-anders commented Jul 14, 2024

Okay, so after playing around a bit already, it looks to me like most of the board editor logic needs to be added directly to flutter-chessground. Not sure about the "piece-menu" for adding pieces (see above). But if we want to support adding pieces by dragging them from the menu to the board, we probably have to implement this in chessground as well...?

@veloce
Copy link
Contributor

veloce commented Jul 15, 2024

Quick feedback: if we have to modify chessground to support this, the changes should be the simplest and the lightest possible.

Like we should only add "generic" (optional) handlers. Something like:

class BoardEditorOptions {
  /// Enable board editor mode
  final bool enable;

  /// Callback to add or remove a piece on this square id.
  final void Function(SquareId squareId)? onTogglePiece;

  final void Function(SquareId squareId)? onRemovePiece;
  ...
}

This is already a significant change because we have to implement the "board editor" logic in the pointer event listener handlers.

Don't know if we can handle drag to board feature like that, but I'd say it is not mandatory to support this so we can figure it out later.

Anyway, changes in chessground shouldn't be more than that.

@tom-anders
Copy link
Contributor Author

tom-anders commented Jul 15, 2024

Quick feedback: if we have to modify chessground to support this, the changes should be the simplest and the lightest possible.

Like we should only add "generic" (optional) handlers. Something like:

class BoardEditorOptions {
  /// Enable board editor mode
  final bool enable;

  /// Callback to add or remove a piece on this square id.
  final void Function(SquareId squareId)? onTogglePiece;

  final void Function(SquareId squareId)? onRemovePiece;
  ...
}

This is already a significant change because we have to implement the "board editor" logic in the pointer event listener handlers.

Don't know if we can handle drag to board feature like that, but I'd say it is not mandatory to support this so we can figure it out later.

Anyway, changes in chessground shouldn't be more than that.

Thanks for the quick reply! However, after playing around with the code a bit yesterday, I'm not a 100% sure if it's really the best idea to modify the Board class for this:

  1. The Board has a lot of parameters and logic related to them which are not relevant in board editor mode, such as drawing shapes, premoves, highlighting squares, the sideToMove variable, ... I tried to add a editorMode flag (similar to the BoardEditorSettings you described above), and it quickly got messy, with a lof of if (!editorMode) at various places.

  2. Even if we get this to work, we still have to take care of disabling some rules, like castling. Currently, the Board does not modify itself, but rather calls the onMove callback, which then will call something like position.playUnchecked() - There's currently no way to disable castling for this method, so we'd need to modify dartchess as well probably. If we had a dedicated BoardEditor widget that could simply modify the position by itself when a move is played, we wouldn't have these problems.

So maybe adding a separate BoardEditor widget makes sense? Or do you think we'd have too much code duplication in this case?

@tom-anders
Copy link
Contributor Author

@veloce I added a quick proof of concept implementing a basic board editor (minus adding new pieces) by adding a new BoardEditor widget: lichess-org/flutter-chessground#40

@veloce
Copy link
Contributor

veloce commented Jul 15, 2024

Yeah totally, a separate BoardEditor is the way to go. Thanks for tackling this!

Now there is still the question of the chessground API. I haven't had much time to think about it, but I still think the chessground package should only expose a lightweight API that would allows package users to build a full-fledged board editor.
Meaning we shouldn't build the full-fledged board editor inside chessground, but rather provide ways to do it through the BoardEditor widget and its callbacks.

The reason behind this is that we don't want to maintain a full-fledged editor in an external package. Because there is no limit in terms of what a board editor can be in terms of feature, the majority of the UI should be implemented in the app and chessground should just take care of what is going on inside the board.

@tom-anders
Copy link
Contributor Author

Thanks for taking a look, I really appreciate the quick feedback!

Yeah I agree with that, the BoardEditor widget in the chessground PR really should be minimal, with the rest (e.g. the piece menu) being implemented by library consumers. I think the draft in the PR is a good start, the only things it's missing are (off the top of my head) addPiece() and removePiece() methods, and also callbacks like clickedSquare and draggedOntoSquare. Probably also a getter that calculates the current FEN.

I'd suggest that I add the missing API described above and clean up and document the code a bit more (maybe reduce some more duplication). Then when I mark it as "Ready To Review", you can take a closer look and we can continue the discussion over at flutter-chessground.

@veloce
Copy link
Contributor

veloce commented Jul 24, 2024

@tom-anders I think you can start working on this using a local chessground plugin based on current main, if you don't mind?

I'll publish the 4.0.0 version later when I had the chance to test this.

@tom-anders
Copy link
Contributor Author

@tom-anders I think you can start working on this using a local chessground plugin based on current main, if you don't mind?

I'll publish the 4.0.0 version later when I had the chance to test this.

Sure!

@tom-anders
Copy link
Contributor Author

@veloce There are a lot of API breaks to be fixed when updating to the main branch, so I'll think for now I'll stick with a commit before those breaks. Let me know when the API breaks are fixed in the mobile repo (or even if you just have a branch ready that I can rebase onto).

@tom-anders
Copy link
Contributor Author

tom-anders commented Jul 24, 2024

Okay, so here's what I got so far. The code is not cleaned up yet, but I think it has all the basic feature we need. Right now, I'm mainly looking for design feedback:

board_editor.webm

@veloce
Copy link
Contributor

veloce commented Jul 25, 2024

@veloce There are a lot of API breaks to be fixed when updating to the main branch, so I'll think for now I'll stick with a commit before those breaks. Let me know when the API breaks are fixed in the mobile repo (or even if you just have a branch ready that I can rebase onto).

I'm ok if you fix the API breaks in this PR. These are only name changes so it should be straightforward to fix.

@veloce
Copy link
Contributor

veloce commented Jul 25, 2024

Thanks for your work @tom-anders , it looks great already!

Here's my feedback:

  • I think we should use the material color palette for the piece menu, trying to find a contrasting color that looks good
  • I don't understand the bottom left button; is it to reverse the board? then we should use the existing button from the TV screen
  • I don't think we need the same trash and pointer icons as lichess website.
  • Not sure the settings button is the best placed here at the top right:
    • it's not a real settings button, it is more the settings of the position; a real settings button would be for settings controlling the editor itself
    • I'd try to find another icon more appropriate
    • and put it in the bottom bar instead

@tom-anders tom-anders marked this pull request as ready for review July 28, 2024 21:52
@tom-anders
Copy link
Contributor Author

Thanks for the feedback, ready for code review now!

* I think we should use the material color palette for the piece menu, trying to find a contrasting color that looks good

Yeah I'm using plain Color.grey, Color.green, Color.blue and Color.red for now. I saw on Discord that someone wanted to help with the app's design, so maybe they can take a look at what colors we should use?

* I don't understand the bottom left button; is it to reverse the board? then we should use the existing button from the TV screen

Yep, wrong icon, fixed now

* I don't think we need the same trash and pointer icons as lichess website.
  
  * I agree they don't look that good right now but we can improve that I think:
  * You can try the Cupertino hand icon: https://api.flutter.dev/flutter/cupertino/CupertinoIcons/hand_draw-constant.html
  * and delete: https://api.flutter.dev/flutter/cupertino/CupertinoIcons/delete-constant.html
  * which kind of look better

Done, I scaled down the icons a bit so that they match the piece size.

* Not sure the settings button is the best placed here at the top right:
  
  * it's not a real settings button, it is more the settings of the position; a real settings button would be for settings controlling the editor itself
  * I'd try to find another icon more appropriate
  * and put it in the bottom bar instead

It uses the "menu" icon now and has been moved to the bottom bar.

@veloce
Copy link
Contributor

veloce commented Jul 29, 2024

Yeah I'm using plain Color.grey, Color.green, Color.blue and Color.red for now.

That is not the material color palette I meant, sorry for the confusion. What you want to use is the ColorScheme.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand all these changes in analysis_controller. The board editor isn't supposed to make a difference in analysis screen.

Copy link
Contributor Author

@tom-anders tom-anders Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, not sure what went wrong here. There are some changes expected due to the chessground API breaks, but maybe I messed up during the rebase. I'll take a look

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely some kind of merge mistake, the changes are only part of the first commit that fixes the chessground API breaks. Sorry about that! Will fix later this evening.

In the meantime, the second commit (feat: add board editor) seems fine, so I think you can already review that one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, sorry again for the confusion!

@veloce
Copy link
Contributor

veloce commented Aug 2, 2024

I just published chessground 4.0.0 to pub.dev @tom-anders .

I think you want to update your PR with that version. There are other breaking changes, sorry for that, but it should not be too hard to fix them.
Here's a summary:

  • dartchess Square is now an extension type so we gain convenient methods at no cost
  • chessground now uses all the dartchess types, including Square. There is no more need for chessground_compat.dart
  • importing dartchess and chessground with prefixes is no more useful and should be avoided.

@tom-anders
Copy link
Contributor Author

Nice work!

Uses chessground 4.0.0 now, fixing all API breaks. Also rebased against main

Copy link
Contributor

@veloce veloce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outstanding work, thank you very much.

@override
Widget build(BuildContext context, WidgetRef ref) {
final pgn = ref.watch(boardEditorControllerProvider).pgn;
final orientation = ref.read(boardEditorControllerProvider).orientation;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be ref.watch


String get fen => _setup.fen;

String? get pgn {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be made clear in a doc comment that only valid position PGN is returned, and it returns null if not valid.

@@ -37,7 +37,7 @@ class UciCharPair with _$UciCharPair {
String.fromCharCode(35 + f),
String.fromCharCode(
p != null
? 35 + 64 + 8 * _promotionRoles.indexOf(p) + squareFile(t)
? 35 + 64 + 8 * _promotionRoles.indexOf(p) + t.file.value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the File extension type implements int, unwrapping .value is not necessary.

),
pointerMode: ref.watch(boardEditorControllerProvider).editorPointerMode,
onDiscardedPiece:
ref.read(boardEditorControllerProvider.notifier).discardPiece,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One should not use ref.read in build() methods. Also it is better to put it at the beginning of build() so that we know the provider dependencies of a widget.

}

Future<BoardEditorController> setupBoardEditor(WidgetTester tester) async {
final boardEditorController = BoardEditorController();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not ideal to construct directly a notifier instance. Testing providers should be done according to Riverpod's doc:
https://riverpod.dev/docs/essentials/testing

Creating/reading providers should always go through a Container.

Copy link
Contributor

@veloce veloce Aug 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done here: 86dd3fb

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will keep that in mind for the next time

@veloce veloce merged commit 4246037 into lichess-org:main Aug 5, 2024
1 check passed
@tom-anders
Copy link
Contributor Author

Thanks again for the quick and valuable feedback! Implementing this was really fun

@ijm8710
Copy link

ijm8710 commented Sep 6, 2024

Hey @tom-anders great work on this again.

  1. Would it make sense to have a "clear board" option similar to how web has one? If there was a menu that would be easy but if you are trying to avoid a menu, perhaps holding down the trash-can?
  2. Out of curiosity, how seamless easy would it be to have an option if you're in the analysis board tool to have it become editable? On web, that option exists. Technically you can just grab the fen/pgn and then load position and choose board editor option but just curious if you could simply but easily enter board editor mode directly from analysis board without much configuration

@tom-anders
Copy link
Contributor Author

1. Would it make sense to have a "clear board" option similar to how web has one? If there was a menu that would be easy but if you are trying to avoid a menu, perhaps holding down the trash-can?

Yeah, what's still missing is a "Load Position" menu, where you can set the board to a specific opening or endgame position. We could also have a "Clear Board" entry in that list (I think the old app does as well).

2. Out of curiosity, how seamless easy would it be to have an option if you're in the analysis board tool to have it become editable? On web, that option exists. Technically you can just grab the fen/pgn and then load position and choose board editor option but just curious if you could simply but easily enter board editor mode directly from analysis board without much configuration

Yeah sounds useful, shouldn't be too hard to implement.

I'll open Github issues for both of these features, I think these are "Good first issue" candidates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Board editor
3 participants