-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: reimplement pgn & fen copy fields -> move to sidebar -> fix pgn…
… copy when starting fen is provided
- Loading branch information
1 parent
9d388c6
commit 7c5302b
Showing
3 changed files
with
103 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,117 @@ | ||
/* eslint-disable jsx-a11y/click-events-have-key-events */ | ||
import { Chess } from 'chess.ts' | ||
import { useEffect, useState } from 'react' | ||
import { useContext, useEffect, useState } from 'react' | ||
|
||
import { Move } from 'src/types' | ||
import { Move, PlayedGame } from 'src/types' | ||
import { GameControllerContext } from 'src/contexts' | ||
|
||
interface Props { | ||
moves: Move[] | ||
game: PlayedGame | ||
whitePlayer: string | ||
blackPlayer: string | ||
maiaVersion: string | ||
} | ||
|
||
export const ExportGame: React.FC<Props> = ({ moves }) => { | ||
export const ExportGame: React.FC<Props> = ({ | ||
game, | ||
whitePlayer, | ||
blackPlayer, | ||
maiaVersion, | ||
}) => { | ||
const [fen, setFen] = useState('') | ||
const [pgn, setPgn] = useState('') | ||
const { currentIndex } = useContext(GameControllerContext) | ||
|
||
useEffect(() => { | ||
const chess = new Chess() | ||
moves.forEach((move) => { | ||
game.moves.forEach((move) => { | ||
if (move.san) { | ||
chess.move(move.san) | ||
} | ||
}) | ||
setPgn(chess.pgn()) | ||
}, [moves]) | ||
}, [game.moves]) | ||
|
||
useEffect(() => { | ||
const initial = new Chess(game.moves[0].board) | ||
initial.addHeader('ID', game.id) | ||
initial.addHeader('Event', `Play v. ${maiaVersion}`) | ||
initial.addHeader('Site', `https://maiachess.com/`) | ||
initial.addHeader('White', whitePlayer) | ||
initial.addHeader('Black', blackPlayer) | ||
if (game.termination) { | ||
initial.addHeader('Result', game.termination.result) | ||
if (game.termination.condition) { | ||
initial.addHeader('Termination', game.termination.condition) | ||
} | ||
} | ||
game.moves.forEach((move, index) => { | ||
if (!move.san || index > currentIndex) { | ||
return | ||
} | ||
|
||
initial.move(move.san) | ||
}) | ||
setFen(game.moves[currentIndex].board) | ||
setPgn(initial.pgn()) | ||
}, [currentIndex, game.moves]) | ||
|
||
const copy = (content: string) => { | ||
navigator.clipboard.writeText(content) | ||
} | ||
|
||
return ( | ||
<div className="flex flex-row items-center justify-center gap-2"> | ||
<div className="flex h-10 items-center overflow-hidden rounded border border-primary/10 bg-background-1"> | ||
<div className="flex w-[500px] items-center justify-start bg-background-1 px-4"> | ||
<p className="whitespace-nowrap text-sm text-secondary"> | ||
{moves[moves.length - 1].board} | ||
<div className="flex flex-col gap-1"> | ||
<div className="flex flex-col gap-0.5"> | ||
<div className="flex items-center justify-between"> | ||
<p className="select-none text-sm font-semibold tracking-wider text-secondary"> | ||
FEN | ||
</p> | ||
<i | ||
tabIndex={0} | ||
role="button" | ||
onClick={() => copy(fen)} | ||
className="material-symbols-outlined select-none text-base text-secondary hover:text-primary" | ||
> | ||
content_copy | ||
</i> | ||
</div> | ||
<button | ||
onClick={() => copy(moves[moves.length - 1].board)} | ||
className="flex h-10 w-10 min-w-10 items-center justify-center border-l border-primary/10 bg-background-2 transition duration-200 hover:bg-background-3" | ||
<div | ||
role="button" | ||
tabIndex={0} | ||
onClick={() => copy(fen)} | ||
className="border-1 group flex cursor-pointer overflow-x-hidden rounded border border-white/5 bg-background-1/50 px-4 py-2" | ||
> | ||
<span className="material-symbols-outlined text-xl"> | ||
<p className="whitespace-nowrap text-xs text-secondary group-hover:text-secondary/80"> | ||
{fen} | ||
</p> | ||
</div> | ||
</div> | ||
<div className="flex flex-col gap-0.5"> | ||
<div className="flex items-center justify-between"> | ||
<p className="select-none text-sm font-semibold tracking-wider text-secondary"> | ||
PGN | ||
</p> | ||
<i | ||
tabIndex={0} | ||
role="button" | ||
onClick={() => copy(pgn)} | ||
className="material-symbols-outlined select-none text-base text-secondary hover:text-primary" | ||
> | ||
content_copy | ||
</span> | ||
</button> | ||
</i> | ||
</div> | ||
<div | ||
role="button" | ||
tabIndex={0} | ||
onClick={() => copy(pgn)} | ||
className="border-1 group flex cursor-pointer overflow-x-hidden rounded border border-white/5 bg-background-1/50 px-4 py-2" | ||
> | ||
<p className="whitespace-pre-wrap text-xs text-secondary group-hover:text-secondary/80"> | ||
{pgn} | ||
</p> | ||
</div> | ||
</div> | ||
<button | ||
onClick={() => copy(pgn)} | ||
className="flex h-10 items-center justify-center rounded border border-primary/10 bg-background-2 px-4 py-1 transition duration-300 hover:bg-background-3" | ||
> | ||
Copy PGN | ||
</button> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters