@@ -10,7 +10,7 @@ import {
1010 Square ,
1111} from "react-chessboard/dist/chessboard/types" ;
1212import { useChessActions } from "@/hooks/useChessActions" ;
13- import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
13+ import { useCallback , useMemo , useRef , useState } from "react" ;
1414import { Color , MoveClassification } from "@/types/enums" ;
1515import { Chess } from "chess.js" ;
1616import { getSquareRenderer } from "./squareRenderer" ;
@@ -64,10 +64,11 @@ export default function Board({
6464 const boardHue = useAtomValue ( boardHueAtom ) ;
6565
6666 const gameFen = game . fen ( ) ;
67-
68- useEffect ( ( ) => {
67+ const [ previousFen , setPreviousFen ] = useState ( gameFen ) ;
68+ if ( gameFen !== previousFen ) {
69+ setPreviousFen ( gameFen ) ;
6970 setClickedSquares ( [ ] ) ;
70- } , [ gameFen , setClickedSquares ] ) ;
71+ }
7172
7273 const isPiecePlayable = useCallback (
7374 ( { piece } : { piece : string } ) : boolean => {
@@ -78,117 +79,134 @@ export default function Board({
7879 [ canPlay , game ]
7980 ) ;
8081
81- const onPieceDrop = (
82- source : Square ,
83- target : Square ,
84- piece : string
85- ) : boolean => {
86- if ( ! isPiecePlayable ( { piece } ) ) return false ;
87-
88- const result = playMove ( {
89- from : source ,
90- to : target ,
91- promotion : piece [ 1 ] ?. toLowerCase ( ) ?? "q" ,
92- } ) ;
93-
94- return ! ! result ;
95- } ;
96-
97- const resetMoveClick = ( square ?: Square | null ) => {
98- setMoveClickFrom ( square ?? null ) ;
99- setMoveClickTo ( null ) ;
100- setShowPromotionDialog ( false ) ;
101- if ( square ) {
102- const moves = game . moves ( { square, verbose : true } ) ;
103- setPlayableSquares ( moves . map ( ( m ) => m . to ) ) ;
104- } else {
105- setPlayableSquares ( [ ] ) ;
106- }
107- } ;
108-
109- const handleSquareLeftClick = ( square : Square , piece ?: string ) => {
110- setClickedSquares ( [ ] ) ;
111-
112- if ( ! moveClickFrom ) {
113- if ( piece && ! isPiecePlayable ( { piece } ) ) return ;
114- resetMoveClick ( square ) ;
115- return ;
116- }
117-
118- const validMoves = game . moves ( { square : moveClickFrom , verbose : true } ) ;
119- const move = validMoves . find ( ( m ) => m . to === square ) ;
82+ const onPieceDrop = useCallback (
83+ ( source : Square , target : Square , piece : string ) : boolean => {
84+ if ( ! isPiecePlayable ( { piece } ) ) return false ;
12085
121- if ( ! move ) {
122- resetMoveClick ( square ) ;
123- return ;
124- }
86+ const result = playMove ( {
87+ from : source ,
88+ to : target ,
89+ promotion : piece [ 1 ] ?. toLowerCase ( ) ?? "q" ,
90+ } ) ;
12591
126- setMoveClickTo ( square ) ;
92+ return ! ! result ;
93+ } ,
94+ [ isPiecePlayable , playMove ]
95+ ) ;
12796
128- if (
129- move . piece === "p" &&
130- ( ( move . color === "w" && square [ 1 ] === "8" ) ||
131- ( move . color === "b" && square [ 1 ] === "1" ) )
132- ) {
133- setShowPromotionDialog ( true ) ;
134- return ;
135- }
97+ const resetMoveClick = useCallback (
98+ ( square ?: Square | null ) => {
99+ setMoveClickFrom ( square ?? null ) ;
100+ setMoveClickTo ( null ) ;
101+ setShowPromotionDialog ( false ) ;
102+ if ( square ) {
103+ const moves = game . moves ( { square, verbose : true } ) ;
104+ setPlayableSquares ( moves . map ( ( m ) => m . to ) ) ;
105+ } else {
106+ setPlayableSquares ( [ ] ) ;
107+ }
108+ } ,
109+ [ setMoveClickFrom , setMoveClickTo , setPlayableSquares , game ]
110+ ) ;
136111
137- const result = playMove ( {
138- from : moveClickFrom ,
139- to : square ,
140- } ) ;
112+ const handleSquareLeftClick = useCallback (
113+ ( square : Square , piece ?: string ) => {
114+ setClickedSquares ( [ ] ) ;
141115
142- resetMoveClick ( result ? undefined : square ) ;
143- } ;
116+ if ( ! moveClickFrom ) {
117+ if ( piece && ! isPiecePlayable ( { piece } ) ) return ;
118+ resetMoveClick ( square ) ;
119+ return ;
120+ }
144121
145- const handleSquareRightClick = ( square : Square ) => {
146- setClickedSquares ( ( prev ) =>
147- prev . includes ( square )
148- ? prev . filter ( ( s ) => s !== square )
149- : [ ...prev , square ]
150- ) ;
151- } ;
122+ const validMoves = game . moves ( { square : moveClickFrom , verbose : true } ) ;
123+ const move = validMoves . find ( ( m ) => m . to === square ) ;
152124
153- const handlePieceDragBegin = ( _ : string , square : Square ) => {
154- resetMoveClick ( square ) ;
155- } ;
125+ if ( ! move ) {
126+ resetMoveClick ( square ) ;
127+ return ;
128+ }
156129
157- const handlePieceDragEnd = ( ) => {
158- resetMoveClick ( ) ;
159- } ;
130+ setMoveClickTo ( square ) ;
160131
161- const onPromotionPieceSelect = (
162- piece ?: PromotionPieceOption ,
163- from ?: Square ,
164- to ?: Square
165- ) => {
166- if ( ! piece ) return false ;
167- const promotionPiece = piece [ 1 ] ?. toLowerCase ( ) ?? "q" ;
132+ if (
133+ move . piece === "p" &&
134+ ( ( move . color === "w" && square [ 1 ] === "8" ) ||
135+ ( move . color === "b" && square [ 1 ] === "1" ) )
136+ ) {
137+ setShowPromotionDialog ( true ) ;
138+ return ;
139+ }
168140
169- if ( moveClickFrom && moveClickTo ) {
170141 const result = playMove ( {
171142 from : moveClickFrom ,
172- to : moveClickTo ,
173- promotion : promotionPiece ,
143+ to : square ,
174144 } ) ;
175- resetMoveClick ( ) ;
176- return ! ! result ;
177- }
178145
179- if ( from && to ) {
180- const result = playMove ( {
181- from,
182- to,
183- promotion : promotionPiece ,
184- } ) ;
185- resetMoveClick ( ) ;
186- return ! ! result ;
187- }
146+ resetMoveClick ( result ? undefined : square ) ;
147+ } ,
148+ [
149+ game ,
150+ isPiecePlayable ,
151+ moveClickFrom ,
152+ playMove ,
153+ resetMoveClick ,
154+ setClickedSquares ,
155+ ]
156+ ) ;
188157
189- resetMoveClick ( moveClickFrom ) ;
190- return false ;
191- } ;
158+ const handleSquareRightClick = useCallback (
159+ ( square : Square ) => {
160+ setClickedSquares ( ( prev ) =>
161+ prev . includes ( square )
162+ ? prev . filter ( ( s ) => s !== square )
163+ : [ ...prev , square ]
164+ ) ;
165+ } ,
166+ [ setClickedSquares ]
167+ ) ;
168+
169+ const handlePieceDragBegin = useCallback (
170+ ( _ : string , square : Square ) => {
171+ resetMoveClick ( square ) ;
172+ } ,
173+ [ resetMoveClick ]
174+ ) ;
175+
176+ const handlePieceDragEnd = useCallback ( ( ) => {
177+ resetMoveClick ( ) ;
178+ } , [ resetMoveClick ] ) ;
179+
180+ const onPromotionPieceSelect = useCallback (
181+ ( piece ?: PromotionPieceOption , from ?: Square , to ?: Square ) => {
182+ if ( ! piece ) return false ;
183+ const promotionPiece = piece [ 1 ] ?. toLowerCase ( ) ?? "q" ;
184+
185+ if ( moveClickFrom && moveClickTo ) {
186+ const result = playMove ( {
187+ from : moveClickFrom ,
188+ to : moveClickTo ,
189+ promotion : promotionPiece ,
190+ } ) ;
191+ resetMoveClick ( ) ;
192+ return ! ! result ;
193+ }
194+
195+ if ( from && to ) {
196+ const result = playMove ( {
197+ from,
198+ to,
199+ promotion : promotionPiece ,
200+ } ) ;
201+ resetMoveClick ( ) ;
202+ return ! ! result ;
203+ }
204+
205+ resetMoveClick ( moveClickFrom ) ;
206+ return false ;
207+ } ,
208+ [ moveClickFrom , moveClickTo , playMove , resetMoveClick ]
209+ ) ;
192210
193211 const customArrows : Arrow [ ] = useMemo ( ( ) => {
194212 const bestMove = position ?. lastEval ?. bestMove ;
@@ -249,6 +267,22 @@ export default function Board({
249267 [ pieceSet ]
250268 ) ;
251269
270+ const customBoardStyle = useMemo ( ( ) => {
271+ const commonBoardStyle = {
272+ borderRadius : "5px" ,
273+ boxShadow : "0 2px 10px rgba(0, 0, 0, 0.5)" ,
274+ } ;
275+
276+ if ( boardHue ) {
277+ return {
278+ ...commonBoardStyle ,
279+ filter : `hue-rotate(${ boardHue } deg)` ,
280+ } ;
281+ }
282+
283+ return commonBoardStyle ;
284+ } , [ boardHue ] ) ;
285+
252286 return (
253287 < Grid
254288 container
@@ -293,11 +327,7 @@ export default function Board({
293327 boardOrientation = {
294328 boardOrientation === Color . White ? "white" : "black"
295329 }
296- customBoardStyle = { {
297- borderRadius : "5px" ,
298- boxShadow : "0 2px 10px rgba(0, 0, 0, 0.5)" ,
299- filter : `hue-rotate(${ boardHue } deg)` ,
300- } }
330+ customBoardStyle = { customBoardStyle }
301331 customArrows = { customArrows }
302332 isDraggablePiece = { isPiecePlayable }
303333 customSquare = { SquareRenderer }
0 commit comments