Skip to content

Commit

Permalink
Rotate button
Browse files Browse the repository at this point in the history
Allow spectators to rotate the board.
Will orient the board to the closer side.
  • Loading branch information
ymmot239 committed Oct 31, 2024
1 parent 61644c0 commit 51ce908
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/client/chessboard/board-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Side } from "../../common/game-types";
interface BoardContainerProps extends PropsWithChildren {
side: Side;
onWidthChange: (width: number) => void;
rotation: number;
}

export function BoardContainer(props: BoardContainerProps) {
Expand All @@ -27,7 +28,7 @@ export function BoardContainer(props: BoardContainerProps) {
...transform,
transform:
props.side === Side.SPECTATOR ?
"rotate(" + Math.random() * 360 + "deg)"
"rotate(" + (props.rotation%180) + "deg)"
: "",
}}
>
Expand Down
38 changes: 36 additions & 2 deletions src/client/chessboard/chessboard-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Move } from "../../common/game-types";
import { Side, PieceType } from "../../common/game-types";
import { customSquareRenderer } from "./custom-square-renderer";
import { CustomSquareContext } from "./custom-square-context";
import { BoardOrientation } from "react-chessboard/dist/chessboard/types";

interface ChessboardWrapperProps {
/**
Expand All @@ -17,6 +18,10 @@ interface ChessboardWrapperProps {
* The side of the current player.
*/
side: Side;
/**
* The rotation of the current player.
*/
rotation: number;
/**
* A callback function this component invokes whenever a move is made.
*/
Expand All @@ -41,6 +46,8 @@ export function ChessboardWrapper(props: ChessboardWrapperProps): JSX.Element {
Square | undefined
>();

const [orientation, setOrientation] = useState<BoardOrientation>("white");

// Maps squares to style objects
let legalSquares: string[] = [];
if (lastClickedSquare !== undefined) {
Expand All @@ -62,12 +69,35 @@ export function ChessboardWrapper(props: ChessboardWrapperProps): JSX.Element {
setLastClickedSquare(undefined);
};


switch (props.side) {
case Side.WHITE:
if(orientation !== "white")
setOrientation("white");
break;
case Side.BLACK:
if(orientation !== "black")
setOrientation("black");
break;
default:
if ((props.rotation%360) < 180) {
if(orientation !== "black"){
setOrientation("black");
}
} else {
if(orientation !== "white"){
setOrientation("white");
}
}
}


// Don't render while width isn't set
let chessboard: JSX.Element | null = null;
if (width !== undefined) {
chessboard = (
<Chessboard
boardOrientation={side === Side.WHITE ? "white" : "black"}
boardOrientation={orientation}
boardWidth={width}
position={chess.fen}
onPromotionCheck={(from: Square, to: Square) => {
Expand Down Expand Up @@ -151,7 +181,11 @@ export function ChessboardWrapper(props: ChessboardWrapperProps): JSX.Element {
}

return (
<BoardContainer side={side} onWidthChange={setWidth}>
<BoardContainer
side={side}
onWidthChange={setWidth}
rotation={props.rotation}
>
<CustomSquareContext.Provider
value={{ legalSquares, chess, lastClickedSquare, side }}
>
Expand Down
4 changes: 3 additions & 1 deletion src/client/game/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function Game(): JSX.Element {
const [gameInterruptedReason, setGameInterruptedReason] =
useState<GameInterruptedReason>();
const [gameHoldReason, setGameHoldReason] = useState<GameHoldReason>();
const [rotation, setRotation] = useState<number>(0);

const sendMessage = useSocket(
getMessageHandler(
Expand Down Expand Up @@ -121,12 +122,13 @@ export function Game(): JSX.Element {

return (
<>
<NavbarMenu sendMessage={sendMessage} side={side} />
<NavbarMenu sendMessage={sendMessage} side={side} setRotation={setRotation} />
<div id="body-container">
<ChessboardWrapper
side={side}
chess={chess}
onMove={handleMove}
rotation={rotation?rotation:0}
/>
{gameEndDialog}
{gameOfferDialog}
Expand Down
22 changes: 20 additions & 2 deletions src/client/game/navbar-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,32 @@ import {
} from "../../common/game-end-reasons";
import { SendMessage } from "../../common/message/message";
import { Side } from "../../common/game-types";
import { Dispatch } from "react";

interface NavbarMenuProps {
sendMessage: SendMessage;
side: Side;
setRotation: Dispatch<React.SetStateAction<number>> //set state type
}

export function NavbarMenu(props: NavbarMenuProps): JSX.Element {
// Store react router state for game
const navigate = useNavigate();

const rotateButton = props.side===Side.SPECTATOR?
<Button
minimal
text="Rotate"
intent="primary"
onClick={()=>{
props.setRotation(
oldRotation=>{
return((oldRotation+90));
}
)
}}
/>:"";

return (
<Navbar>
<NavbarGroup>
Expand Down Expand Up @@ -53,7 +70,7 @@ export function NavbarMenu(props: NavbarMenuProps): JSX.Element {
new GameInterruptedMessage(
props.side === Side.WHITE ?
GameInterruptedReason.WHITE_RESIGNED
: GameInterruptedReason.BLACK_RESIGNED, // TODO change to either WHITE_RESIGNED or BLACK_RESIGNED
: GameInterruptedReason.BLACK_RESIGNED,
),
);
}}
Expand All @@ -66,13 +83,14 @@ export function NavbarMenu(props: NavbarMenuProps): JSX.Element {
onClick={async () => {
props.sendMessage(
new GameHoldMessage(
GameHoldReason.DRAW_CONFIRMATION, // TODO change to either WHITE_RESIGNED or BLACK_RESIGNED
GameHoldReason.DRAW_CONFIRMATION,
),
);
}}
/>
</NavbarGroup>
<NavbarGroup align="right">
{rotateButton}
<h3>{props.side}</h3>
<Button icon="cog" minimal onClick={() => navigate("/debug")} />
</NavbarGroup>
Expand Down

0 comments on commit 51ce908

Please sign in to comment.