This commit is contained in:
Maciej Caderek
2022-02-18 04:21:35 +01:00
parent 70b2245570
commit ec4a63b59b
8 changed files with 123 additions and 31 deletions

View File

@@ -7,6 +7,7 @@ import drawPieces from "./layers/drawPieces";
import drawHeader from "./layers/drawHeader";
import drawExtraInfo from "./layers/drawExtraInfo";
import boards from "./styles-board";
import isLink from "../utils/isLink";
const defaultConfig: BoardConfig = {
size: 720,
@@ -130,6 +131,7 @@ class Board {
setStyle(style: BoardStyle) {
this.style = boards[style];
this.cfg.boardStyle = style;
this.refresh();
return this;
}
@@ -146,6 +148,26 @@ class Board {
return this;
}
flipWhite() {
if (!this.cfg.flipped) {
return;
}
this.cfg.flipped = false;
this.refresh();
return this;
}
flipBlack() {
if (this.cfg.flipped) {
return;
}
this.cfg.flipped = true;
this.refresh();
return this;
}
hideBorder() {
this.cfg.showBorder = false;
this.setSize(this.size);
@@ -182,8 +204,14 @@ class Board {
Black: "Anonymous",
WhitePretty: "Anonymous",
BlackPretty: "Anonymous",
Site: isLink(this.header.Site) ? null : this.header.Site,
}
: this.header;
: {
...this.header,
Site: isLink(this.header.Site)
? (this.header.Site as string).replace(/^http[s]*:\/\//, "")
: this.header.Site,
};
}
async titleFrame(header: Header) {

View File

@@ -1,7 +1,8 @@
import { PieceType, PieceColor, BoardData, Position } from "../types";
import { PieceType, PieceColor, BoardData, Position, Header } from "../types";
import { Chess, ChessInstance } from "chess.js";
import { cleanPGN } from "./PGNHelpers";
import { formatDate, formatName } from "../utils/formatters";
import isLink from "../utils/isLink";
const MATERIAL_VALUE: Map<PieceType, number> = new Map([
["q", 9],
@@ -196,6 +197,17 @@ class Game {
return this.game.pgn();
}
get anonymousPGN() {
const pgn = this.game
.pgn()
.replace(/\[White .+\]/, '[White "Anonymous"]')
.replace(/\[Black .+\]/, '[Black "Anonymous"]');
return isLink(this.header.Site)
? pgn.replace(/\[Site .+\]/, '[Site "?"]')
: pgn;
}
getPosition(ply: number) {
const position = this.positions[ply];

View File

@@ -71,6 +71,13 @@ const main = async () => {
toggleAnonymous() {
setState("boardConfig", "anonymous", !state.boardConfig.anonymous);
board.updateConfig({ anonymous: state.boardConfig.anonymous });
if (state.pgn !== "") {
const pgn = state.boardConfig.anonymous
? state.game.anonymousPGN
: state.game.pgn;
window.location.hash = `v1/pgn/${compressPGN(pgn)}`;
}
},
toggleTitleScreen() {
setState("gameConfig", "titleScreen", !state.gameConfig.titleScreen);
@@ -98,7 +105,7 @@ const main = async () => {
setState("boardConfig", "piecesStyle", style);
saveConfig("board");
},
async loadPGN(pgn: string) {
async loadPGN(pgn: string, side: "w" | "b" = "w") {
const game = new Game().loadPGN(pgn);
setState({
pgn: game.pgn,
@@ -111,23 +118,38 @@ const main = async () => {
await player.load(game);
setState("activeTab", "game");
if (side === "w") {
board.flipWhite();
} else {
board.flipBlack();
}
setState("boardConfig", "flipped", side === "b");
document.title = `SHORTCASTLE - ${game.getTitle({ anonymous: false })}`;
},
async loadFEN(fen: string) {
async loadFEN(fen: string, hash = true) {
const game = new Game().loadFEN(fen);
setState({ pgn: "", fen, moves: game.getMoves(), ply: 0, game });
window.location.hash = `v1/fen/${state.fen}`;
await player.load(game);
setState("activeTab", "game");
if (
game.getPosition(0).turn === "b" &&
state.boardConfig.flipped === false
) {
setState("boardConfig", "flipped", true);
board.flip();
await player.load(game);
if (hash) {
window.location.hash = `v1/fen/${state.fen}`;
setState("activeTab", "game");
}
const side = game.getPosition(0).turn;
if (side === "w") {
board.flipWhite();
} else {
board.flipBlack();
}
setState("boardConfig", "flipped", side === "b");
document.title = `SHORTCASTLE - FEN ${fen}`;
},
async importPGN(link: string) {
@@ -137,7 +159,7 @@ const main = async () => {
return;
}
await this.loadPGN(result.pgn);
await this.loadPGN(result.pgn, result.side);
},
async downloadImage() {
await new Promise((resolve) => setTimeout(resolve, 0));
@@ -182,7 +204,8 @@ const main = async () => {
: fen
? handlers.loadFEN(fen)
: handlers.loadFEN(
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
false
));
/* Register events */

View File

@@ -43,7 +43,11 @@ export type State = {
};
const initialState: State = {
boardConfig: { ...initialBoardConfig, ...saved.boardConfig },
boardConfig: {
...initialBoardConfig,
...saved.boardConfig,
anonymous: false,
},
gameConfig: { ...initialGameConfig, ...saved.gameConfig },
game: new Game(),
pgn: "",

View File

@@ -162,7 +162,7 @@ a:hover {
}
.board {
border: solid 1rem var(--color-bg-block);
box-shadow: 0 0 2rem #00000099;
border-radius: 5px;
max-width: 100%;
max-height: 100%;

View File

@@ -3,6 +3,7 @@ import { Handlers } from "../../types";
import { state } from "../../state";
import "./Info.css";
import isSafeLink from "../../utils/isSafeLink";
import isLink from "../../utils/isLink";
const Info: Component<{ handlers: Handlers }> = () => {
return (
@@ -10,17 +11,17 @@ const Info: Component<{ handlers: Handlers }> = () => {
<div className="info__players">
<p>
<button className="info__color info__color--white"></button>
{state.game.header.WhitePretty}{" "}
<span className="info__rating">
{state.game.header.WhiteElo ?? "????"}
</span>
<Show when={!state.boardConfig.anonymous} fallback="Anonymous">
{state.game.header.WhitePretty}{" "}
</Show>
<span className="info__rating">{state.game.header.WhiteElo}</span>
</p>
<p>
<button className="info__color info__color--black"></button>
{state.game.header.BlackPretty}{" "}
<span className="info__rating">
{state.game.header.BlackElo ?? "????"}
</span>
<Show when={!state.boardConfig.anonymous} fallback="Anonymous">
{state.game.header.BlackPretty}{" "}
</Show>
<span className="info__rating">{state.game.header.BlackElo}</span>
</p>
</div>
<div className="info__event">
@@ -35,12 +36,18 @@ const Info: Component<{ handlers: Handlers }> = () => {
<Show when={state.game.header.Site}>
<p>
<Show
when={isSafeLink(state.game.header.Site)}
fallback={state.game.header.Site}
when={
!state.boardConfig.anonymous || !isLink(state.game.header.Site)
}
>
<a href={state.game.header.Site ?? ""}>
{state.game.header.Site?.replace(/^https:\/\//, "")}
</a>
<Show
when={isSafeLink(state.game.header.Site)}
fallback={state.game.header.Site}
>
<a href={state.game.header.Site ?? ""}>
{state.game.header.Site?.replace(/^https:\/\//, "")}
</a>
</Show>
</Show>
</p>
</Show>

View File

@@ -192,7 +192,11 @@ const Share: Component<{ handlers: Handlers }> = (props) => {
<button
class="share__btn"
onClick={() => {
navigator.clipboard.writeText(state.pgn);
navigator.clipboard.writeText(
state.boardConfig.anonymous
? state.game.anonymousPGN
: state.pgn
);
blinkCopy("pgn");
}}
>

14
src/utils/isLink.ts Normal file
View File

@@ -0,0 +1,14 @@
const isLink = (text: string | null) => {
if (text === null) {
return false;
}
try {
new URL(text);
return true;
} catch {
return false;
}
};
export default isLink;