Squashed commit of the following:
commit dfc79cf287823383a25a650d5788ee5250b1c316
Author: GuillaumeSD <47183782+GuillaumeSD@users.noreply.github.com>
Date: Sun May 11 01:32:35 2025 +0200
fix : style
commit bccfa5a3358302c2f037cc2dcfbd0a1df5e2974e
Author: GuillaumeSD <47183782+GuillaumeSD@users.noreply.github.com>
Date: Sun May 11 01:01:12 2025 +0200
feat : players clocks v1
commit 5f65009f200686433904710d5f9ceb1ba166fa9d
Author: GuillaumeSD <47183782+GuillaumeSD@users.noreply.github.com>
Date: Sat May 10 21:58:02 2025 +0200
fix : merge issues
commit f93dc6104e2d3fbb60088f578c2d1f13bf6519e9
Merge: a9f3728 fea1f3f
Author: GuillaumeSD <47183782+GuillaumeSD@users.noreply.github.com>
Date: Sat May 10 21:53:11 2025 +0200
Merge branch 'main' into feat/add-players-clocks
commit a9f372808ef403dfb823c4cf93c837412cc55c53
Author: GuillaumeSD <gsd.lfny@gmail.com>
Date: Mon Jan 6 23:10:28 2025 +0100
fix : rename
commit aedf9c252023bebe4da4327b7526371fa75b7b3e
Author: GuillaumeSD <gsd.lfny@gmail.com>
Date: Sun Jan 5 17:30:27 2025 +0100
feat : add players clocks
This commit is contained in:
@@ -8,7 +8,7 @@ export interface Props {
|
|||||||
color: Color;
|
color: Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PIECE_SCALE = 0.6;
|
const PIECE_SCALE = 0.55;
|
||||||
|
|
||||||
export default function CapturedPieces({ fen, color }: Props) {
|
export default function CapturedPieces({ fen, color }: Props) {
|
||||||
const cssProps = useMemo(() => {
|
const cssProps = useMemo(() => {
|
||||||
@@ -22,7 +22,7 @@ export default function CapturedPieces({ fen, color }: Props) {
|
|||||||
}, [fen, color]);
|
}, [fen, color]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container alignItems="end" columnGap={0.6} size="auto">
|
<Grid container alignItems="end" columnGap={0.5} size="auto">
|
||||||
{cssProps.map((cssProp, i) => (
|
{cssProps.map((cssProp, i) => (
|
||||||
<span
|
<span
|
||||||
key={i}
|
key={i}
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ export default function Board({
|
|||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
rowGap={1}
|
rowGap={1.5}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
paddingLeft={showEvaluationBar ? 2 : 0}
|
paddingLeft={showEvaluationBar ? 2 : 0}
|
||||||
@@ -278,7 +278,7 @@ export default function Board({
|
|||||||
>
|
>
|
||||||
<PlayerHeader
|
<PlayerHeader
|
||||||
color={boardOrientation === Color.White ? Color.Black : Color.White}
|
color={boardOrientation === Color.White ? Color.Black : Color.White}
|
||||||
fen={gameFen}
|
gameAtom={gameAtom}
|
||||||
player={boardOrientation === Color.White ? blackPlayer : whitePlayer}
|
player={boardOrientation === Color.White ? blackPlayer : whitePlayer}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -318,7 +318,7 @@ export default function Board({
|
|||||||
|
|
||||||
<PlayerHeader
|
<PlayerHeader
|
||||||
color={boardOrientation}
|
color={boardOrientation}
|
||||||
fen={gameFen}
|
gameAtom={gameAtom}
|
||||||
player={boardOrientation === Color.White ? whitePlayer : blackPlayer}
|
player={boardOrientation === Color.White ? whitePlayer : blackPlayer}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,35 +1,113 @@
|
|||||||
import { Color } from "@/types/enums";
|
import { Color } from "@/types/enums";
|
||||||
import { Player } from "@/types/game";
|
import { Player } from "@/types/game";
|
||||||
import { Avatar, Grid2 as Grid, Typography } from "@mui/material";
|
import { Avatar, Grid2 as Grid, Stack, Typography } from "@mui/material";
|
||||||
import CapturedPieces from "./capturedPieces";
|
import CapturedPieces from "./capturedPieces";
|
||||||
|
import { PrimitiveAtom, useAtomValue } from "jotai";
|
||||||
|
import { Chess } from "chess.js";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { getPaddedNumber } from "@/lib/helpers";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
player: Player;
|
player: Player;
|
||||||
color: Color;
|
color: Color;
|
||||||
fen: string;
|
gameAtom: PrimitiveAtom<Chess>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PlayerHeader({ color, player, fen }: Props) {
|
export default function PlayerHeader({ color, player, gameAtom }: Props) {
|
||||||
|
const game = useAtomValue(gameAtom);
|
||||||
|
|
||||||
|
const gameFen = game.fen();
|
||||||
|
|
||||||
|
const clock = useMemo(() => {
|
||||||
|
const turn = game.turn();
|
||||||
|
|
||||||
|
if (turn === color) {
|
||||||
|
const history = game.history({ verbose: true });
|
||||||
|
const previousFen = history.at(-1)?.before;
|
||||||
|
|
||||||
|
const comment = game
|
||||||
|
.getComments()
|
||||||
|
.find(({ fen }) => fen === previousFen)?.comment;
|
||||||
|
|
||||||
|
return getClock(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const comment = game.getComment();
|
||||||
|
return getClock(comment);
|
||||||
|
}, [game, color]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
justifyContent="center"
|
justifyContent="space-between"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
columnGap={2}
|
|
||||||
size={12}
|
size={12}
|
||||||
>
|
>
|
||||||
{player.avatarUrl && (
|
<Stack direction="row">
|
||||||
<Avatar
|
<Avatar
|
||||||
src={player.avatarUrl}
|
src={player.avatarUrl}
|
||||||
|
alt={player.name}
|
||||||
variant="circular"
|
variant="circular"
|
||||||
sx={{ width: 24, height: 24 }}
|
sx={{
|
||||||
/>
|
width: 40,
|
||||||
)}
|
height: 40,
|
||||||
<Typography>
|
backgroundColor: color === Color.White ? "white" : "black",
|
||||||
{player.rating ? `${player.name} (${player.rating})` : player.name}
|
color: color === Color.White ? "black" : "white",
|
||||||
</Typography>
|
border: "1px solid black",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{player.name[0].toUpperCase()}
|
||||||
|
</Avatar>
|
||||||
|
|
||||||
<CapturedPieces fen={fen} color={color} />
|
<Stack marginLeft={1}>
|
||||||
|
<Stack direction="row">
|
||||||
|
<Typography fontSize="0.9rem">{player.name}</Typography>
|
||||||
|
|
||||||
|
{player.rating && (
|
||||||
|
<Typography marginLeft={0.5} fontSize="0.9rem" fontWeight="200">
|
||||||
|
({player.rating})
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<CapturedPieces fen={gameFen} color={color} />
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{clock && (
|
||||||
|
<Typography
|
||||||
|
align="center"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: color === Color.White ? "white" : "black",
|
||||||
|
color: color === Color.White ? "black" : "white",
|
||||||
|
}}
|
||||||
|
borderRadius="5px"
|
||||||
|
padding={0.8}
|
||||||
|
border="1px solid #424242"
|
||||||
|
width="5rem"
|
||||||
|
textAlign="right"
|
||||||
|
>
|
||||||
|
{clock.hours ? `${clock.hours}:` : ""}
|
||||||
|
{getPaddedNumber(clock.minutes)}:{getPaddedNumber(clock.seconds)}
|
||||||
|
{clock.hours || clock.minutes || clock.seconds > 20
|
||||||
|
? ""
|
||||||
|
: `.${clock.tenths}`}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getClock = (comment: string | undefined) => {
|
||||||
|
if (!comment) return undefined;
|
||||||
|
|
||||||
|
const match = comment.match(/\[%clk (\d+):(\d+):(\d+)(?:\.(\d*))?\]/);
|
||||||
|
if (!match) return undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
hours: parseInt(match[1]),
|
||||||
|
minutes: parseInt(match[2]),
|
||||||
|
seconds: parseInt(match[3]),
|
||||||
|
tenths: match[4] ? parseInt(match[4]) : 0,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { setGameHeaders } from "@/lib/chess";
|
import { getGameFromPgn, setGameHeaders } from "@/lib/chess";
|
||||||
import {
|
import {
|
||||||
playGameEndSound,
|
playGameEndSound,
|
||||||
playIllegalMoveSound,
|
playIllegalMoveSound,
|
||||||
playSoundFromMove,
|
playSoundFromMove,
|
||||||
} from "@/lib/sounds";
|
} from "@/lib/sounds";
|
||||||
import { Player } from "@/types/game";
|
import { Player } from "@/types/game";
|
||||||
import { Chess, Move } from "chess.js";
|
import { Chess, Move, DEFAULT_POSITION } from "chess.js";
|
||||||
import { PrimitiveAtom, useAtom } from "jotai";
|
import { PrimitiveAtom, useAtom } from "jotai";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
|
||||||
@@ -43,8 +43,9 @@ export const useChessActions = (chessAtom: PrimitiveAtom<Chess>) => {
|
|||||||
if (game.history().length === 0) {
|
if (game.history().length === 0) {
|
||||||
const pgnSplitted = game.pgn().split("]");
|
const pgnSplitted = game.pgn().split("]");
|
||||||
if (
|
if (
|
||||||
pgnSplitted.at(-1)?.includes("1-0") ||
|
["1-0", "0-1", "1/2-1/2", "*"].includes(
|
||||||
pgnSplitted.at(-1) === "\n *"
|
pgnSplitted.at(-1)?.trim() ?? ""
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
newGame.loadPgn(pgnSplitted.slice(0, -1).join("]") + "]");
|
newGame.loadPgn(pgnSplitted.slice(0, -1).join("]") + "]");
|
||||||
return newGame;
|
return newGame;
|
||||||
@@ -55,11 +56,31 @@ export const useChessActions = (chessAtom: PrimitiveAtom<Chess>) => {
|
|||||||
return newGame;
|
return newGame;
|
||||||
}, [game]);
|
}, [game]);
|
||||||
|
|
||||||
|
const resetToStartingPosition = useCallback(
|
||||||
|
(pgn?: string) => {
|
||||||
|
const newGame = pgn ? getGameFromPgn(pgn) : copyGame();
|
||||||
|
newGame.load(newGame.getHeaders().FEN || DEFAULT_POSITION, {
|
||||||
|
preserveHeaders: true,
|
||||||
|
});
|
||||||
|
setGame(newGame);
|
||||||
|
},
|
||||||
|
[copyGame, setGame]
|
||||||
|
);
|
||||||
|
|
||||||
const makeMove = useCallback(
|
const makeMove = useCallback(
|
||||||
(move: { from: string; to: string; promotion?: string }): Move | null => {
|
(params: {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
promotion?: string;
|
||||||
|
comment?: string;
|
||||||
|
}): Move | null => {
|
||||||
const newGame = copyGame();
|
const newGame = copyGame();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const { comment, ...move } = params;
|
||||||
const result = newGame.move(move);
|
const result = newGame.move(move);
|
||||||
|
if (comment) newGame.setComment(comment);
|
||||||
|
|
||||||
setGame(newGame);
|
setGame(newGame);
|
||||||
playSoundFromMove(result);
|
playSoundFromMove(result);
|
||||||
return result;
|
return result;
|
||||||
@@ -103,5 +124,12 @@ export const useChessActions = (chessAtom: PrimitiveAtom<Chess>) => {
|
|||||||
[setGame]
|
[setGame]
|
||||||
);
|
);
|
||||||
|
|
||||||
return { setPgn, reset, makeMove, undoMove, goToMove };
|
return {
|
||||||
|
setPgn,
|
||||||
|
reset,
|
||||||
|
makeMove,
|
||||||
|
undoMove,
|
||||||
|
goToMove,
|
||||||
|
resetToStartingPosition,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -280,17 +280,6 @@ const getPieceValue = (piece: PieceSymbol): number => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getStartingFen = (
|
|
||||||
params: { pgn: string } | { game: Chess }
|
|
||||||
): string => {
|
|
||||||
const game = "game" in params ? params.game : getGameFromPgn(params.pgn);
|
|
||||||
|
|
||||||
const history = game.history({ verbose: true });
|
|
||||||
if (!history.length) return game.fen();
|
|
||||||
|
|
||||||
return history[0].before;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const isCheck = (fen: string): boolean => {
|
export const isCheck = (fen: string): boolean => {
|
||||||
const game = new Chess(fen);
|
const game = new Chess(fen);
|
||||||
return game.inCheck();
|
return game.inCheck();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ChessComGame } from "@/types/chessCom";
|
import { ChessComGame } from "@/types/chessCom";
|
||||||
import { getPaddedMonth } from "./helpers";
|
import { getPaddedNumber } from "./helpers";
|
||||||
|
|
||||||
export const getChessComUserRecentGames = async (
|
export const getChessComUserRecentGames = async (
|
||||||
username: string
|
username: string
|
||||||
@@ -7,7 +7,7 @@ export const getChessComUserRecentGames = async (
|
|||||||
const date = new Date();
|
const date = new Date();
|
||||||
const year = date.getUTCFullYear();
|
const year = date.getUTCFullYear();
|
||||||
const month = date.getUTCMonth() + 1;
|
const month = date.getUTCMonth() + 1;
|
||||||
const paddedMonth = getPaddedMonth(month);
|
const paddedMonth = getPaddedNumber(month);
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://api.chess.com/pub/player/${username}/games/${year}/${paddedMonth}`
|
`https://api.chess.com/pub/player/${username}/games/${year}/${paddedMonth}`
|
||||||
@@ -21,7 +21,7 @@ export const getChessComUserRecentGames = async (
|
|||||||
|
|
||||||
if (games.length < 50) {
|
if (games.length < 50) {
|
||||||
const previousMonth = month === 1 ? 12 : month - 1;
|
const previousMonth = month === 1 ? 12 : month - 1;
|
||||||
const previousPaddedMonth = getPaddedMonth(previousMonth);
|
const previousPaddedMonth = getPaddedNumber(previousMonth);
|
||||||
const yearToFetch = previousMonth === 12 ? year - 1 : year;
|
const yearToFetch = previousMonth === 12 ? year - 1 : year;
|
||||||
|
|
||||||
const resPreviousMonth = await fetch(
|
const resPreviousMonth = await fetch(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export const getPaddedMonth = (month: number) => {
|
export const getPaddedNumber = (month: number) => {
|
||||||
return month < 10 ? `0${month}` : month;
|
return month < 10 ? `0${month}` : month;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const getLichessUserRecentGames = async (
|
|||||||
username: string
|
username: string
|
||||||
): Promise<LichessGame[]> => {
|
): Promise<LichessGame[]> => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://lichess.org/api/games/user/${username}?until=${Date.now()}&max=50&pgnInJson=true&sort=dateDesc`,
|
`https://lichess.org/api/games/user/${username}?until=${Date.now()}&max=50&pgnInJson=true&sort=dateDesc&clocks=true`,
|
||||||
{ method: "GET", headers: { accept: "application/x-ndjson" } }
|
{ method: "GET", headers: { accept: "application/x-ndjson" } }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default function GameReview() {
|
|||||||
maxWidth: "1200px",
|
maxWidth: "1200px",
|
||||||
}}
|
}}
|
||||||
rowGap={2}
|
rowGap={2}
|
||||||
maxHeight={{ lg: "calc(95vh - 130px)", xs: "900px" }}
|
maxHeight={{ lg: "calc(95vh - 80px)", xs: "900px" }}
|
||||||
display="grid"
|
display="grid"
|
||||||
gridTemplateRows="repeat(3, auto) fit-content(100%)"
|
gridTemplateRows="repeat(3, auto) fit-content(100%)"
|
||||||
marginTop={isLgOrGreater && window.innerHeight > 780 ? 4 : 0}
|
marginTop={isLgOrGreater && window.innerHeight > 780 ? 4 : 0}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function BoardContainer() {
|
|||||||
return Math.min(width, height - 150);
|
return Math.min(width, height - 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(width - 700, height * 0.95);
|
return Math.min(width - 700, height * 0.92);
|
||||||
}, [screenSize]);
|
}, [screenSize]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -42,9 +42,20 @@ export const useCurrentPosition = (engineName?: EngineName) => {
|
|||||||
if (gameEval) {
|
if (gameEval) {
|
||||||
const evalIndex = boardHistory.length;
|
const evalIndex = boardHistory.length;
|
||||||
|
|
||||||
position.eval = gameEval.positions[evalIndex];
|
position.eval = {
|
||||||
|
...gameEval.positions[evalIndex],
|
||||||
|
lines: gameEval.positions[evalIndex].lines.slice(0, multiPv),
|
||||||
|
};
|
||||||
position.lastEval =
|
position.lastEval =
|
||||||
evalIndex > 0 ? gameEval.positions[evalIndex - 1] : undefined;
|
evalIndex > 0
|
||||||
|
? {
|
||||||
|
...gameEval.positions[evalIndex - 1],
|
||||||
|
lines: gameEval.positions[evalIndex - 1].lines.slice(
|
||||||
|
0,
|
||||||
|
multiPv
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,11 +81,12 @@ export const useCurrentPosition = (engineName?: EngineName) => {
|
|||||||
(savedEval.lines?.length ?? 0) >= multiPv &&
|
(savedEval.lines?.length ?? 0) >= multiPv &&
|
||||||
(savedEval.lines[0].depth ?? 0) >= depth
|
(savedEval.lines[0].depth ?? 0) >= depth
|
||||||
) {
|
) {
|
||||||
setPartialEval?.({
|
const positionEval: PositionEval = {
|
||||||
...savedEval,
|
...savedEval,
|
||||||
lines: savedEval.lines.slice(0, multiPv),
|
lines: savedEval.lines.slice(0, multiPv),
|
||||||
});
|
};
|
||||||
return savedEval;
|
setPartialEval?.(positionEval);
|
||||||
|
return positionEval;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawPositionEval = await engine.evaluatePositionWithUpdate({
|
const rawPositionEval = await engine.evaluatePositionWithUpdate({
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ export default function Opening() {
|
|||||||
}
|
}
|
||||||
if (!lastMove) return null;
|
if (!lastMove) return null;
|
||||||
|
|
||||||
const opening = position?.eval?.opening || lastOpening;
|
const opening =
|
||||||
|
position?.eval?.opening && !position?.eval?.opening.includes("Unknown")
|
||||||
|
? position.eval.opening
|
||||||
|
: lastOpening;
|
||||||
if (opening && opening !== lastOpening) {
|
if (opening && opening !== lastOpening) {
|
||||||
setLastOpening(opening);
|
setLastOpening(opening);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,12 @@ import { useGameDatabase } from "@/hooks/useGameDatabase";
|
|||||||
import { useAtomValue, useSetAtom } from "jotai";
|
import { useAtomValue, useSetAtom } from "jotai";
|
||||||
import { Chess } from "chess.js";
|
import { Chess } from "chess.js";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { getStartingFen } from "@/lib/chess";
|
|
||||||
|
|
||||||
export default function LoadGame() {
|
export default function LoadGame() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const game = useAtomValue(gameAtom);
|
const game = useAtomValue(gameAtom);
|
||||||
const { setPgn: setGamePgn } = useChessActions(gameAtom);
|
const { setPgn: setGamePgn } = useChessActions(gameAtom);
|
||||||
const { reset: resetBoard } = useChessActions(boardAtom);
|
const { resetToStartingPosition: resetBoard } = useChessActions(boardAtom);
|
||||||
const { gameFromUrl } = useGameDatabase();
|
const { gameFromUrl } = useGameDatabase();
|
||||||
const setEval = useSetAtom(gameEvalAtom);
|
const setEval = useSetAtom(gameEvalAtom);
|
||||||
const setBoardOrientation = useSetAtom(boardOrientationAtom);
|
const setBoardOrientation = useSetAtom(boardOrientationAtom);
|
||||||
@@ -26,7 +25,7 @@ export default function LoadGame() {
|
|||||||
|
|
||||||
const resetAndSetGamePgn = useCallback(
|
const resetAndSetGamePgn = useCallback(
|
||||||
(pgn: string) => {
|
(pgn: string) => {
|
||||||
resetBoard({ fen: getStartingFen({ pgn }) });
|
resetBoard(pgn);
|
||||||
setEval(undefined);
|
setEval(undefined);
|
||||||
setGamePgn(pgn);
|
setGamePgn(pgn);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import NextMoveButton from "./nextMoveButton";
|
|||||||
import GoToLastPositionButton from "./goToLastPositionButton";
|
import GoToLastPositionButton from "./goToLastPositionButton";
|
||||||
import SaveButton from "./saveButton";
|
import SaveButton from "./saveButton";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { getStartingFen } from "@/lib/chess";
|
|
||||||
|
|
||||||
export default function PanelToolBar() {
|
export default function PanelToolBar() {
|
||||||
const board = useAtomValue(boardAtom);
|
const board = useAtomValue(boardAtom);
|
||||||
const { reset: resetBoard, undoMove: undoBoardMove } =
|
const { resetToStartingPosition: resetBoard, undoMove: undoBoardMove } =
|
||||||
useChessActions(boardAtom);
|
useChessActions(boardAtom);
|
||||||
|
|
||||||
const boardHistory = board.history();
|
const boardHistory = board.history();
|
||||||
@@ -24,7 +23,7 @@ export default function PanelToolBar() {
|
|||||||
if (e.key === "ArrowLeft") {
|
if (e.key === "ArrowLeft") {
|
||||||
undoBoardMove();
|
undoBoardMove();
|
||||||
} else if (e.key === "ArrowDown") {
|
} else if (e.key === "ArrowDown") {
|
||||||
resetBoard({ fen: getStartingFen({ game: board }) });
|
resetBoard();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ export default function PanelToolBar() {
|
|||||||
<Tooltip title="Reset board">
|
<Tooltip title="Reset board">
|
||||||
<Grid>
|
<Grid>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => resetBoard({ fen: getStartingFen({ game: board }) })}
|
onClick={() => resetBoard()}
|
||||||
disabled={boardHistory.length === 0}
|
disabled={boardHistory.length === 0}
|
||||||
sx={{ paddingX: 1.2, paddingY: 0.5 }}
|
sx={{ paddingX: 1.2, paddingY: 0.5 }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -22,12 +22,16 @@ export default function NextMoveButton() {
|
|||||||
|
|
||||||
const nextMoveIndex = boardHistory.length;
|
const nextMoveIndex = boardHistory.length;
|
||||||
const nextMove = game.history({ verbose: true })[nextMoveIndex];
|
const nextMove = game.history({ verbose: true })[nextMoveIndex];
|
||||||
|
const comment = game
|
||||||
|
.getComments()
|
||||||
|
.find((c) => c.fen === nextMove.after)?.comment;
|
||||||
|
|
||||||
if (nextMove) {
|
if (nextMove) {
|
||||||
makeBoardMove({
|
makeBoardMove({
|
||||||
from: nextMove.from,
|
from: nextMove.from,
|
||||||
to: nextMove.to,
|
to: nextMove.to,
|
||||||
promotion: nextMove.promotion,
|
promotion: nextMove.promotion,
|
||||||
|
comment,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [isButtonEnabled, boardHistory, game, makeBoardMove]);
|
}, [isButtonEnabled, boardHistory, game, makeBoardMove]);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default function Layout({ children }: PropsWithChildren) {
|
|||||||
darkMode={useDarkMode}
|
darkMode={useDarkMode}
|
||||||
switchDarkMode={() => setDarkMode((val) => !val)}
|
switchDarkMode={() => setDarkMode((val) => !val)}
|
||||||
/>
|
/>
|
||||||
<main style={{ margin: "2em 2vw" }}>{children}</main>
|
<main style={{ margin: "3vh 2vw" }}>{children}</main>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export default function BoardContainer() {
|
|||||||
return Math.min(width, height - 150);
|
return Math.min(width, height - 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(width - 300, height * 0.85);
|
return Math.min(width - 300, height * 0.83);
|
||||||
}, [screenSize]);
|
}, [screenSize]);
|
||||||
|
|
||||||
useGameData(gameAtom, gameDataAtom);
|
useGameData(gameAtom, gameDataAtom);
|
||||||
|
|||||||
Reference in New Issue
Block a user