import WebFont from "webfontloader"; import * as Hammer from "hammerjs"; import { render } from "solid-js/web"; import { BoardStyle, PiecesStyle } 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 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"; const main = async () => { const board = new Board(state.boardConfig); const player = new Player(board, state.gameConfig); /* Register handlers */ const handlers = { prev() { player.pause(); player.prev(); }, next() { player.pause(); player.next(); }, first() { player.pause(); player.first(); }, last() { player.pause(); player.last(); }, toggleBorder() { board.toggleBorder(); setState("boardConfig", "showBorder", !state.boardConfig.showBorder); }, showBorder() { board.showBorder(); setState("boardConfig", "showBorder", true); }, hideBorder() { board.hideBorder(); setState("boardConfig", "showBorder", false); }, toggleExtraInfo() { board.toggleExtraInfo(); setState( "boardConfig", "showExtraInfo", !state.boardConfig.showExtraInfo ); }, toggleAnonymous() { setState("boardConfig", "anonymous", !state.boardConfig.anonymous); board.updateConfig({ anonymous: state.boardConfig.anonymous }); }, toggleTitleScreen() { setState("gameConfig", "titleScreen", !state.gameConfig.titleScreen); }, flip() { console.log("FLIP"); board.flip(); setState("boardConfig", "flipped", !state.boardConfig.flipped); }, togglePlay() { player.playing ? player.pause() : player.play(); }, goto(ply: number) { player.pause(); player.goto(ply); }, changeBoardStyle(style: BoardStyle) { board.setStyle(style); setState("boardConfig", "boardStyle", style); }, changePiecesStyle(style: PiecesStyle) { board.setPiecesStyle(style); setState("boardConfig", "piecesStyle", style); }, async loadPGN(pgn: string) { const game = new Game().loadPGN(pgn); setState({ pgn: game.pgn, fen: "", moves: game.getMoves(), ply: 0, game, }); window.location.hash = `v1/pgn/${compressPGN(game.pgn)}`; await player.load(game); setState("activeTab", "game"); }, async loadFEN(fen: string) { const game = new Game().loadFEN(fen); setState({ pgn: "", fen, moves: game.getMoves(), ply: 0, game }); await player.load(game); }, async importPGN(link: string) { const result = await importFromLink(link); if (result.error) { return; } await this.loadPGN(result.pgn); }, async downloadImage() { const data = await createImage( state.fen, state.pgn, state.ply, state.boardConfig, state.gameConfig.picSize ); download(data, "fen", "png"); }, async downloadAnimation() { const data = await createAnimation( state.pgn, state.boardConfig, state.gameConfig.format, state.gameConfig.animationSize ); download(data, "game", state.gameConfig.format.toLowerCase()); }, }; /* Render the page */ render( () => , document.getElementById("root") as HTMLElement ); const $board = document.querySelector("#board"); $board?.appendChild(board.canvas); /* Restore game from the url */ 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" )); /* Register events */ 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" ) { 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]); handlers.loadPGN(content); } }); 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"], }, custom: { families: ["Chess"], urls: ["/fonts.css"], }, active: main, });