-
-
Notifications
You must be signed in to change notification settings - Fork 223
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
base: main
Are you sure you want to change the base?
Changes from all commits
92ec7b8
a3a4dd0
af02c69
ab1df72
cd26a45
c8348c0
5e4a995
bd116aa
b303806
647e37e
1d901c6
981d0d3
5064c88
cce8762
23cf849
82ffcc0
1eb5432
e876e05
b48e8a2
da320a7
8797ee1
0a0d44b
a7fb84b
41b71d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import 'package:lichess_mobile/l10n/l10n.dart'; | |
import 'package:lichess_mobile/src/model/settings/preferences_storage.dart'; | ||
import 'package:lichess_mobile/src/styles/styles.dart'; | ||
import 'package:lichess_mobile/src/utils/color_palette.dart'; | ||
import 'package:lichess_mobile/src/utils/l10n_context.dart'; | ||
import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||
|
||
part 'board_preferences.freezed.dart'; | ||
|
@@ -43,6 +44,10 @@ class BoardPreferences extends _$BoardPreferences with PreferencesStorage<BoardP | |
await save(state.copyWith(pieceShiftMethod: pieceShiftMethod)); | ||
} | ||
|
||
Future<void> setCastlingMethod(CastlingMethod castlingMethod) { | ||
return save(state.copyWith(castlingMethod: castlingMethod)); | ||
} | ||
|
||
Future<void> toggleHapticFeedback() { | ||
return save(state.copyWith(hapticFeedback: !state.hapticFeedback)); | ||
} | ||
|
@@ -125,6 +130,7 @@ class BoardPrefs with _$BoardPrefs implements Serializable { | |
required ClockPosition clockPosition, | ||
@JsonKey(defaultValue: PieceShiftMethod.either, unknownEnumValue: PieceShiftMethod.either) | ||
required PieceShiftMethod pieceShiftMethod, | ||
required CastlingMethod castlingMethod, | ||
|
||
/// Whether to enable shape drawings on the board for games and puzzles. | ||
@JsonKey(defaultValue: true) required bool enableShapeDrawings, | ||
|
@@ -150,6 +156,7 @@ class BoardPrefs with _$BoardPrefs implements Serializable { | |
materialDifferenceFormat: MaterialDifferenceFormat.materialDifference, | ||
clockPosition: ClockPosition.right, | ||
pieceShiftMethod: PieceShiftMethod.either, | ||
castlingMethod: CastlingMethod.either, | ||
enableShapeDrawings: true, | ||
magnifyDraggedPiece: true, | ||
dragTargetKind: DragTargetKind.circle, | ||
|
@@ -347,6 +354,19 @@ enum ClockPosition { | |
}; | ||
} | ||
|
||
enum CastlingMethod { | ||
kingOverRook, | ||
kingTwoSquares, | ||
either; | ||
|
||
String castlingMethodl10n(BuildContext context, CastlingMethod castlingMethod) => | ||
switch (castlingMethod) { | ||
CastlingMethod.kingOverRook => context.l10n.preferencesCastleByMovingOntoTheRook, | ||
CastlingMethod.kingTwoSquares => context.l10n.preferencesCastleByMovingTwoSquares, | ||
CastlingMethod.either => context.l10n.preferencesBothClicksAndDrag, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be using There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah just hardcode it for now and leave a |
||
}; | ||
} | ||
|
||
String dragTargetKindLabel(DragTargetKind kind) => switch (kind) { | ||
DragTargetKind.circle => 'Circle', | ||
DragTargetKind.square => 'Square', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,30 @@ class _Body extends ConsumerWidget { | |
} | ||
}, | ||
), | ||
SettingsListTile( | ||
settingsLabel: Text( | ||
context.l10n.preferencesCastleByMovingTheKingTwoSquaresOrOntoTheRook, | ||
), | ||
settingsValue: boardPrefs.castlingMethod.name, | ||
showCupertinoTrailingValue: false, | ||
onTap: () { | ||
if (Theme.of(context).platform == TargetPlatform.android) { | ||
showChoicePicker( | ||
context, | ||
choices: CastlingMethod.values, | ||
selectedItem: boardPrefs.castlingMethod, | ||
labelBuilder: (t) => Text(t.castlingMethodl10n(context, t)), | ||
onSelectedItemChanged: (CastlingMethod? value) { | ||
ref | ||
.read(boardPreferencesProvider.notifier) | ||
.setCastlingMethod(value ?? CastlingMethod.either); | ||
}, | ||
); | ||
} else { | ||
Navigator.of(context).push(CastlingMethodSettingsScreen.buildRoute(context)); | ||
} | ||
}, | ||
), | ||
SwitchSettingTile( | ||
title: Text(context.l10n.mobilePrefMagnifyDraggedPiece), | ||
value: boardPrefs.magnifyDraggedPiece, | ||
|
@@ -263,6 +287,46 @@ class PieceShiftMethodSettingsScreen extends ConsumerWidget { | |
} | ||
} | ||
|
||
class CastlingMethodSettingsScreen extends ConsumerWidget { | ||
const CastlingMethodSettingsScreen({super.key}); | ||
|
||
static Route<dynamic> buildRoute(BuildContext context) { | ||
return buildScreenRoute( | ||
context, | ||
screen: const BoardClockPositionScreen(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong screen here. |
||
title: 'Clock position', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong title. |
||
); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final castlingMethod = ref.watch( | ||
boardPreferencesProvider.select((state) => state.castlingMethod), | ||
); | ||
|
||
void onChanged(CastlingMethod? value) { | ||
ref.read(boardPreferencesProvider.notifier).setCastlingMethod(value ?? CastlingMethod.either); | ||
} | ||
|
||
return CupertinoPageScaffold( | ||
navigationBar: const CupertinoNavigationBar(), | ||
child: SafeArea( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to have a SafeArea around |
||
child: ListView( | ||
children: [ | ||
ChoicePicker( | ||
notchedTile: true, | ||
choices: CastlingMethod.values, | ||
selectedItem: castlingMethod, | ||
titleBuilder: (t) => Text(t.castlingMethodl10n(context, t)), | ||
onSelectedItemChanged: onChanged, | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
class BoardClockPositionScreen extends ConsumerWidget { | ||
const BoardClockPositionScreen({super.key}); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import 'package:chessground/chessground.dart'; | ||
import 'package:dartchess/dartchess.dart'; | ||
import 'package:fast_immutable_collections/fast_immutable_collections.dart'; | ||
import 'package:flutter/cupertino.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:lichess_mobile/src/model/settings/board_preferences.dart'; | ||
|
||
class BoardWidget extends StatelessWidget { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A doc comment indicating the purpose of this widget would be welcome. |
||
BoardWidget({ | ||
required this.size, | ||
required this.boardPrefs, | ||
required this.fen, | ||
required this.orientation, | ||
required this.gameData, | ||
this.lastMove, | ||
this.shapes, | ||
required this.settings, | ||
this.boardOverlay, | ||
this.error, | ||
this.annotations, | ||
this.boardKey, | ||
}) : setup = Setup.parseFen(fen); | ||
|
||
final double size; | ||
final BoardPrefs boardPrefs; | ||
final String fen; | ||
final Side orientation; | ||
final GameData? gameData; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here I don't think Perhaps renaming it to |
||
final Move? lastMove; | ||
final ISet<Shape>? shapes; | ||
final ChessboardSettings settings; | ||
final String? error; | ||
final Widget? boardOverlay; | ||
final IMap<Square, Annotation>? annotations; | ||
final GlobalKey? boardKey; | ||
final Setup setup; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final Map<Square, Square> castlingMap = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be a static const. |
||
Square.a1: Square.c1, | ||
Square.a8: Square.c8, | ||
Square.h1: Square.g1, | ||
Square.h8: Square.g8, | ||
}; | ||
|
||
GameData? modifiedGameData; | ||
|
||
MapEntry<Square, ISet<Square>> mapper(Square sq, ISet<Square> moves) { | ||
return MapEntry( | ||
sq, | ||
setup.board.kings.squares.contains(sq) && //king move | ||
setup.castlingRights.squares.intersectsWith( | ||
moves, //king can castle | ||
) | ||
? (switch (boardPrefs.castlingMethod) { | ||
CastlingMethod.kingOverRook => moves.removeAll(castlingMap.values), | ||
CastlingMethod.kingTwoSquares => moves.removeAll(castlingMap.keys), | ||
_ => moves, | ||
}) | ||
: moves, | ||
); | ||
} | ||
|
||
if (gameData != null) { | ||
modifiedGameData = GameData( | ||
playerSide: gameData!.playerSide, | ||
sideToMove: gameData!.sideToMove, | ||
validMoves: gameData!.validMoves.map(mapper), | ||
promotionMove: gameData!.promotionMove, | ||
onMove: gameData!.onMove, | ||
onPromotionSelection: gameData!.onPromotionSelection, | ||
premovable: gameData?.premovable, | ||
isCheck: gameData?.isCheck, | ||
); | ||
} | ||
|
||
final board = Chessboard( | ||
key: boardKey, | ||
size: size, | ||
fen: fen, | ||
orientation: orientation, | ||
game: modifiedGameData ?? gameData, | ||
lastMove: lastMove, | ||
shapes: shapes, | ||
settings: settings, | ||
annotations: annotations, | ||
); | ||
|
||
if (boardOverlay != null) { | ||
return SizedBox.square( | ||
dimension: size, | ||
child: Stack( | ||
children: [ | ||
board, | ||
SizedBox.square( | ||
dimension: size, | ||
child: Center( | ||
child: SizedBox( | ||
width: (size / 8) * 6.6, | ||
height: (size / 8) * 4.6, | ||
child: boardOverlay, | ||
), | ||
), | ||
), | ||
], | ||
), | ||
); | ||
} else if (error != null) { | ||
return SizedBox.square( | ||
dimension: size, | ||
child: Stack(children: [board, _ErrorWidget(errorMessage: error!, boardSize: size)]), | ||
); | ||
} | ||
|
||
return board; | ||
} | ||
} | ||
|
||
class _ErrorWidget extends StatelessWidget { | ||
const _ErrorWidget({required this.errorMessage, required this.boardSize}); | ||
final double boardSize; | ||
final String errorMessage; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return SizedBox.square( | ||
dimension: boardSize, | ||
child: Center( | ||
child: Padding( | ||
padding: const EdgeInsets.all(16.0), | ||
child: Container( | ||
decoration: BoxDecoration( | ||
color: | ||
Theme.of(context).platform == TargetPlatform.iOS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 I should have changed it in the new theme PR, but let's do it here. |
||
? CupertinoColors.secondarySystemBackground.resolveFrom(context) | ||
: Theme.of(context).colorScheme.surface, | ||
borderRadius: const BorderRadius.all(Radius.circular(10.0)), | ||
), | ||
child: Padding(padding: const EdgeInsets.all(10.0), child: Text(errorMessage)), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.