import WebFont from "webfontloader"; // import * as Hammer from "hammerjs"; import { render } from "solid-js/web"; import { BoardStyle } from "./types"; import Board from "./board/Board"; import Game from "./game/Game"; import Player from "./player/Player"; import App from "./ui/App"; import { state, setState } from "./state"; import saveConfig from "./persistance/saveConfig"; import createImage from "./encoders/createImage"; import createAnimation from "./encoders/createAnimation"; import readFile from "./utils/readFile"; import download from "./utils/download"; import { compressPGN } from "./game/PGNHelpers"; import extractUrlData from "./persistance/extractUrlData"; import importFromLink from "./imports/importFromLink"; import isFEN from "./utils/isFEN"; import isPGN from "./utils/isPGN"; import isSafeLink from "./utils/isSafeLink"; import { PiecesStyle } from "./board/styles-pieces/piecesStyles"; const main = async () => { const board = new Board(state.boardConfig); const player = new Player(board, state.gameConfig); player.watch((playing) => setState("playing", playing)); /* Register handlers */ const handlers = { prev() { player.pause(); player.prev(); }, next() { player.pause(); player.next(); }, first() { player.pause(); player.first(); }, last() { player.pause(); player.last(); }, togglePlay() { player.playing ? player.pause() : player.play(); }, goto(ply: number) { player.pause(); player.goto(ply); }, toggleBorder() { board.toggleBorder(); setState("boardConfig", "showBorder", !state.boardConfig.showBorder); saveConfig("board"); }, showBorder() { board.showBorder(); setState("boardConfig", "showBorder", true); saveConfig("board"); }, hideBorder() { board.hideBorder(); setState("boardConfig", "showBorder", false); saveConfig("board"); }, toggleExtraInfo() { board.toggleExtraInfo(); setState( "boardConfig", "showExtraInfo", !state.boardConfig.showExtraInfo ); saveConfig("board"); }, toggleAnonymous() { setState("anonymous", !state.anonymous); board.anonymous = state.anonymous; if (state.pgn !== "") { const pgn = state.anonymous ? state.game.anonymousPGN : state.game.pgn; window.location.hash = `pgn/${compressPGN(pgn)}`; setState("refreshHash", false); } }, toggleTitleScreen() { setState("gameConfig", "titleScreen", !state.gameConfig.titleScreen); saveConfig("game"); }, toggleShadows() { board.toggleShadows(); setState("boardConfig", "showShadows", !state.boardConfig.showShadows); saveConfig("board"); }, flip() { console.log("FLIP"); board.flip(); setState("boardConfig", "flipped", !state.boardConfig.flipped); }, changeBoardStyle(style: BoardStyle) { board.setStyle(style); setState("boardConfig", "boardStyle", style); saveConfig("board"); }, changePiecesStyle(style: PiecesStyle) { board.setPiecesStyle(style); setState("boardConfig", "piecesStyle", style); saveConfig("board"); }, async loadPGN(pgn: string, side: "w" | "b" = "w") { const game = new Game().loadPGN(pgn); setState({ pgn: game.pgn, fen: "", moves: game.getMoves(), ply: 0, game, }); window.location.hash = `pgn/${compressPGN(game.pgn)}`; await player.load(game); setState("activeTab", "game"); if (side === "w") { board.flipWhite(); } else { board.flipBlack(); } setState("boardConfig", "flipped", side === "b"); document.title = `SHARECHESS - ${game.getTitle({ anonymous: false })}`; }, async loadFEN(fen: string, hash = true) { const game = new Game().loadFEN(fen); setState({ pgn: "", fen, moves: game.getMoves(), ply: 0, game, }); await player.load(game); if (hash) { window.location.hash = `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 = `SHARECHESS - FEN ${fen}`; }, async load(data: string) { setState("refreshHash", false); if (isFEN(data)) { await this.loadFEN(data); return true; } if (isPGN(data)) { await this.loadPGN(data); return true; } if (isSafeLink(data)) { await this.importPGN(data); return true; } return false; }, async importPGN(link: string) { const result = await importFromLink(link); if (result.error) { return; } await this.loadPGN(result.pgn, result.side); }, async downloadImage() { await new Promise((resolve) => setTimeout(resolve, 0)); const data = await createImage( state.fen, state.pgn, state.ply, state.boardConfig, state.gameConfig.picSize ); download(data, `fen_${Date.now()}`, "png"); }, async downloadAnimation() { await new Promise((resolve) => setTimeout(resolve, 0)); const data = await createAnimation( state.pgn, state.boardConfig, state.gameConfig.format, state.gameConfig.animationSize, state.gameConfig.titleScreen ); const name = state.game.getFileName(state.anonymous); download(data, name, state.gameConfig.format.toLowerCase()); }, toggleSound() { setState("boardConfig", "sounds", !state.boardConfig.sounds); saveConfig("board"); }, }; /* Render the page */ render( () => , document.getElementById("root") as HTMLElement ); const $board = document.querySelector("#board"); $board?.prepend(board.canvas); /* Load game from the url */ const loadFromUrl = async (refreshHash: boolean = true) => { setState("refreshHash", refreshHash); const { pgn, fen } = extractUrlData(); await (pgn ? handlers.loadPGN(pgn) : fen ? handlers.loadFEN(fen) : handlers.loadFEN( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", false )); setState("refreshHash", true); }; await loadFromUrl(false); /* Register events */ document.addEventListener("dblclick", function (el) { el.preventDefault(); }); window.addEventListener("resize", () => { setState( "layout", window.innerWidth < window.innerHeight ? "single" : window.innerWidth < 1366 ? "double" : "triple" ); }); window.addEventListener("hashchange", () => { if (!state.refreshHash) { setState("refreshHash", true); return; } loadFromUrl(); }); if (!state.mobile) { const keyMapping: { [key: string]: () => void } = { ArrowLeft: handlers.prev, ArrowRight: handlers.next, ArrowUp: handlers.first, ArrowDown: handlers.last, " ": handlers.togglePlay, b: handlers.toggleBorder, f: handlers.flip, e: handlers.toggleExtraInfo, }; document.addEventListener("keydown", (e) => { const target = e.target as HTMLElement | null; if ( keyMapping[e.key] && target?.nodeName !== "INPUT" && target?.nodeName !== "TEXTAREA" ) { e.preventDefault(); keyMapping[e.key](); } }); const preventDefaults = (e: Event) => { e.preventDefault(); e.stopPropagation(); }; ["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => { document.addEventListener(eventName, preventDefaults, false); }); document.addEventListener("drop", async (e) => { if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) { const content = await readFile(e.dataTransfer.files[0]); setState("refreshHash", false); handlers.loadPGN(content); } }); } else { // const hammer = new Hammer.Manager(board.canvas); // hammer.add(new Hammer.Swipe()); // hammer.add(new Hammer.Pinch()); // hammer.add(new Hammer.Press({ time: 500 })); // hammer.add(new Hammer.Tap({ taps: 1 })); // hammer.on("swiperight", handlers.next); // hammer.on("swipeleft", handlers.prev); // hammer.on("swipeup", handlers.first); // hammer.on("swipedown", handlers.last); // hammer.on("pinchin", handlers.showBorder); // hammer.on("pinchout", handlers.hideBorder); // hammer.on("tap", handlers.next); // hammer.on("press", handlers.flip); } }; /* Boot */ WebFont.load({ google: { families: ["Ubuntu:500,700", "Fira Mono:500"], }, custom: { families: ["Chess"], urls: ["/fonts.css"], }, active: main, });