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

1043 add castling method option v2 #1347

Open
wants to merge 28 commits into
base: main
Choose a base branch
from

Conversation

Jimima
Copy link
Contributor

@Jimima Jimima commented Jan 8, 2025

Adds an option to change castling method. Still needs some work to tidy up but the approach is implemented. Note that it only really works for Standard variants as chess960 always uses king over rook. I think this is okay but maybe the UI could make this clearer.

@veloce
Copy link
Contributor

veloce commented Jan 9, 2025

Just for my understanding, why the v1 was closed? thanks :)

@Jimima
Copy link
Contributor Author

Jimima commented Jan 9, 2025

Sure, I had attempted an implementation that modified dartchess and chessground which maybe was not the correct approach. I didn't have a great deal of time to look at it at that point so I just closed the PRs for hygeine. See here for reference lichess-org/dartchess#44

This change is limited to only the mobile app with no changes elsewhere. Not sure if this is the right approach still, happy to be told if you think there is an alternative way to come at it

@Jimima Jimima force-pushed the 1043-add-castling-method-option-v2 branch from c97a375 to b2a2c28 Compare January 17, 2025 10:52
@Jimima Jimima force-pushed the 1043-add-castling-method-option-v2 branch from b2a2c28 to c8348c0 Compare January 17, 2025 10:54
@Jimima Jimima marked this pull request as ready for review January 17, 2025 11:12
@Jimima
Copy link
Contributor Author

Jimima commented Jan 17, 2025

I think this is ready to be looked at @veloce. Not sure what's going on with the tests but maybe an issue unrelated to this PR?

@julien4215
Copy link
Contributor

A fix was pushed on the main branch. The tests need to be rerun manually.

@veloce
Copy link
Contributor

veloce commented Jan 20, 2025

@Jimima can you rebase your branch on top of main so the tests pass? thank.

@Jimima
Copy link
Contributor Author

Jimima commented Jan 20, 2025

@veloce done!

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.

Thanks for this. This is looking good but there are a couple of issues to address on top of the comments I've made:

  • for now this settings applies only to online games, but it should also apply to puzzles, analysis, study, etc.
  • the logic you added to game_controller.dart must be refactored so it can work everywhere.
  • this is the time for a refactoring: we need a global board wrapper so we can apply settings to the whole app
  • a good starting point for this refactoring imo, is the private _BoardWidget which should be extracted to a public widget in another file. It should be modified to take only BoardPrefs and BoardSettingsOverride (and not directly the ChessboardSettings from chessground which should be constructed inside the widget from the prefs and the optional override).
  • the new castling logic should be tested


// TODO: l10n
String get label => switch (this) {
CastlingMethod.kingOverRook => 'Move king over rook',
Copy link
Contributor

Choose a reason for hiding this comment

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

translation keys already exist: look at app_en.arb: preferencesCastleByMovingOntoTheRook.

enum CastlingMethod {
kingOverRook,
kingTwoSquares,
either;
Copy link
Contributor

Choose a reason for hiding this comment

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

We should not support either because it is not supported on website.

The default is kingOverRook

Copy link
Contributor

Choose a reason for hiding this comment

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

Default is now either since we'll support all three castling methods which is correctly set on line 159.

@@ -369,3 +429,11 @@ String pieceShiftMethodl10n(BuildContext context, PieceShiftMethod pieceShiftMet
PieceShiftMethod.drag => context.l10n.preferencesDragPiece,
PieceShiftMethod.tapTwoSquares => 'Tap two squares',
};

String castlingMethodl10n(BuildContext context, CastlingMethod castlingMethod) =>
Copy link
Contributor

Choose a reason for hiding this comment

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

Duplicated l10n logic; must be defined directly in the enum to be consistent with rest of code.

@Jimima
Copy link
Contributor Author

Jimima commented Jan 21, 2025

Thanks for the feedback, that all makes sense. I also wonder if we are worried about premoves respecting the preference as right now they do not. I think the main site does not either but I would need to check this.

@Jimima Jimima marked this pull request as draft January 21, 2025 09:13
@Jimima
Copy link
Contributor Author

Jimima commented Jan 29, 2025

@veloce I would appreciate another review if possible, I have made a few changes:

Created a new BoardWidget component and use this in place of Chessboard where possible
Used translation strings for labels etc.

Some questions:

I wonder if we can support either castling method in the app as it seems like an improvement over the web site. I have left it in for now but can easily remove it if you prefer.

Right now I kept the refactoring light and boardPrefs is passed in as a parameter. Should the board widget be fetching the boardPrefs directly from the shared state rather than taking it as a parameter?

Is there further refactoring to be done? You mentioned taking only BoardPrefs and BoardSettingsOverride but I was a bit unsure about how to make this work. Any further guidance would be gratefully received 🙂

@Jimima Jimima marked this pull request as ready for review January 29, 2025 10:27
@Jimima
Copy link
Contributor Author

Jimima commented Jan 29, 2025

Oh yes, also I will add some tests in the meantime

@veloce
Copy link
Contributor

veloce commented Jan 30, 2025

Will review asap.

I wonder if we can support either castling method in the app as it seems like an improvement over the web site. I have left it in for now but can easily remove it if you prefer.

No here I think we should stick to what the website does. It would be less error prone and easier to maintain.

@CloudyDino
Copy link
Contributor

@veloce The website only gives two castling options, but the second castling option (move king onto rook) still allows you to move the king two spaces to castle. So in reality the two options on the website are

  • Move king two squares
  • Either (move king two squares or move king onto rook)

If we're going to stick to what the website does, we should make sure to do it this way or include all three options since the website options aren't explicit enough.

Lichess.Website.-.Move.king.onto.rook.mov

@veloce
Copy link
Contributor

veloce commented Feb 10, 2025

I wish the website would have more explicit options indeed.

@veloce
Copy link
Contributor

veloce commented Feb 10, 2025

Sorry @Jimima for the delay I was focused on fixing the new theme. Could you fix the conflicts and I look at this asap. Thanks!

@veloce
Copy link
Contributor

veloce commented Feb 10, 2025

Oh, by the way if we have to support the "either" as the website I'd rather have an "either" choice in the settings as you did initially and asked you to remove... sorry about that.

Comment on lines 94 to 99
Navigator.of(context).push(CastlingMethodSettingsScreen.buildRoute(context));
// pushPlatformRoute(
// context,
// title: context.l10n.preferencesCastleByMovingTheKingTwoSquaresOrOntoTheRook,
// builder: (context) => const CastlingMethodSettingsScreen(),
// );
Copy link
Contributor

Choose a reason for hiding this comment

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

Quick question, should this be commented out or deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will remove

enum CastlingMethod {
kingOverRook,
kingTwoSquares,
either;
Copy link
Contributor

Choose a reason for hiding this comment

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

Default is now either since we'll support all three castling methods which is correctly set on line 159.

switch (castlingMethod) {
CastlingMethod.kingOverRook => context.l10n.preferencesCastleByMovingOntoTheRook,
CastlingMethod.kingTwoSquares => context.l10n.preferencesCastleByMovingTwoSquares,
CastlingMethod.either => context.l10n.preferencesBothClicksAndDrag,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be using preferencesBothClicksAndDrag here? If the string gets changed in the future from "Either" to "Either click or drag", then we wouldn't want the castling method string to change to that as well. I'm unsure when new strings should be created or if maybe we should rename preferencesBothClicksAndDrag to something like preferencesEither

Copy link
Contributor Author

@Jimima Jimima Feb 10, 2025

Choose a reason for hiding this comment

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

Yeah good point, not sure how to correctly handle this as there is no string currently for this. Maybe I just hard code an english string and add a comment?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah just hardcode it for now and leave a // TODO translate

@@ -88,6 +90,7 @@ class AnalysisBoardState extends ConsumerState<AnalysisBoard> {
.onUserMove(move, shouldReplace: widget.shouldReplaceChildOnUserMove),
onPromotionSelection: (role) => ref.read(ctrlProvider.notifier).onPromotionSelection(role),
),

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: extra line I think?

@@ -354,6 +355,7 @@ class _BroadcastBoardState extends ConsumerState<_BroadcastBoard> {
newShapeColor: boardPrefs.shapeColor.color,
),
),
boardPrefs: boardPrefs,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: maybe we add this new line right under the size argument to keep argument order the same

@@ -568,6 +569,7 @@ class _StudyBoardState extends ConsumerState<_StudyBoard> {
},
)
: null,
boardPrefs: boardPrefs,
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: same here, maybe we add this new line right under the size argument to keep argument order the same

@Jimima
Copy link
Contributor Author

Jimima commented Feb 10, 2025

@veloce thanks, and no problem at all. I am still not sure of the correct approach here, as I said, happy to take a steer from you if you think there is more to do with refactoring or whatever. I might need some guidance, however :-)

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.

Good job, I think it's taking the right direction. Made a couple of small comments.

Now, this touches crucial part of the app (board for games and analysis) so this change should be tested.

It should be a widget test for the new BoardWidget that test at least the correct behaviour of castling according to all possible settings.

You can look at existing puzzle_screen_test.dart, game_screen_test.dart or flutter-chessground tests for inspiration.

switch (castlingMethod) {
CastlingMethod.kingOverRook => context.l10n.preferencesCastleByMovingOntoTheRook,
CastlingMethod.kingTwoSquares => context.l10n.preferencesCastleByMovingTwoSquares,
CastlingMethod.either => context.l10n.preferencesBothClicksAndDrag,
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah just hardcode it for now and leave a // TODO translate

static Route<dynamic> buildRoute(BuildContext context) {
return buildScreenRoute(
context,
screen: const BoardClockPositionScreen(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrong screen here.

return buildScreenRoute(
context,
screen: const BoardClockPositionScreen(),
title: 'Clock position',
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrong title.


return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(),
child: SafeArea(
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to have a SafeArea around ListView.


@override
Widget build(BuildContext context) {
final Map<Square, Square> castlingMap = {
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be a static const.

import 'package:flutter/material.dart';
import 'package:lichess_mobile/src/model/settings/board_preferences.dart';

class BoardWidget extends StatelessWidget {
Copy link
Contributor

Choose a reason for hiding this comment

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

A doc comment indicating the purpose of this widget would be welcome.

final BoardPrefs boardPrefs;
final String fen;
final Side orientation;
final GameData? gameData;
Copy link
Contributor

Choose a reason for hiding this comment

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

Here I don't think GameData should be nullable. This board widget purpose is to wrap interactive boards only.

Perhaps renaming it to InteractiveBoardWidget would make it even clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a holdover from boardTable where this was refactored out from. boardTable can take a null value which is then passed in here. I can change this but I'm not totally clear on how to handle the case where boardTable does not have gameData. Happy to take a steer here as I can see a few solutions but not sure which is best.

child: Container(
decoration: BoxDecoration(
color:
Theme.of(context).platform == TargetPlatform.iOS
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 new theme we can remove these distinctions between iOS and android. So use colorScheme.surface on both platforms.

I should have changed it in the new theme PR, but let's do it here.

@Jimima
Copy link
Contributor Author

Jimima commented Feb 12, 2025

Thanks for the comments I'll get to work on this

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.

4 participants