From 3e20babe240dd40b2164fc9a6300ff031d54f421 Mon Sep 17 00:00:00 2001 From: Maciej Caderek Date: Mon, 14 Feb 2022 17:46:14 +0100 Subject: [PATCH] WIP --- gif.worker.js => public/gif.worker.js | 0 src/imports/importFromLink.ts | 38 +++++++++++++++++++++++++++ src/main.tsx | 11 ++++++++ src/state.ts | 2 ++ src/types.ts | 1 + src/ui/components/GameTabs.tsx | 19 +++++++------- src/ui/components/Load.css | 4 +++ src/ui/components/Load.tsx | 32 +++++++++++++++++----- 8 files changed, 90 insertions(+), 17 deletions(-) rename gif.worker.js => public/gif.worker.js (100%) create mode 100644 src/imports/importFromLink.ts diff --git a/gif.worker.js b/public/gif.worker.js similarity index 100% rename from gif.worker.js rename to public/gif.worker.js diff --git a/src/imports/importFromLink.ts b/src/imports/importFromLink.ts new file mode 100644 index 0000000..61a25c1 --- /dev/null +++ b/src/imports/importFromLink.ts @@ -0,0 +1,38 @@ +type Result = + | { error: false; pgn: string; side: "w" | "b" } + | { error: true; errorType: "INCORRECT_LINK" | "SERVER_ERROR" }; + +const importFromLichess = async (link: string): Promise => { + const [first, second] = link + .replace(/^https:\/\/(www\.)*lichess\.org\/*/, "") + .split("/") + .map((x) => x.trim()); + + if (/^(([a-z0-9]{8})|([a-z0-9]{12}))$/i.test(first)) { + const id = first.slice(0, 8); + + const res = await fetch( + `https://lichess.org/game/export/${id}?evals=0&clocks=0` + ); + + if (!String(res.status).startsWith("2")) { + return { error: true, errorType: "SERVER_ERROR" }; + } + + const pgn = await res.text(); + + return { error: false, pgn, side: second === "black" ? "b" : "w" }; + } + + return { error: true, errorType: "INCORRECT_LINK" }; +}; + +const importFromLink = async (link: string): Promise => { + if (/^https:\/\/(www\.)*lichess\.org/.test(link)) { + return importFromLichess(link); + } + + return { error: true, errorType: "INCORRECT_LINK" }; +}; + +export default importFromLink; diff --git a/src/main.tsx b/src/main.tsx index 7732157..f71295f 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -17,6 +17,7 @@ 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); @@ -101,12 +102,22 @@ const main = async () => { 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, diff --git a/src/state.ts b/src/state.ts index 7a2a37f..19e69d3 100644 --- a/src/state.ts +++ b/src/state.ts @@ -37,6 +37,7 @@ export type State = { moves: string[]; ply: number; mobile: boolean; + activeTab: "game" | "load"; }; const initialState: State = { @@ -48,6 +49,7 @@ const initialState: State = { moves: [], ply: 0, mobile: isMobile(), + activeTab: "load", }; const [state, setState] = createStore(initialState); diff --git a/src/types.ts b/src/types.ts index 95790f9..4a54ff4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -209,6 +209,7 @@ export type Handlers = { changePiecesStyle: (style: PiecesStyle) => void; loadPGN: (pgn: string) => Promise; loadFEN: (fen: string) => Promise; + importPGN: (link: string) => Promise; downloadImage: () => Promise; downloadAnimation: () => Promise; }; diff --git a/src/ui/components/GameTabs.tsx b/src/ui/components/GameTabs.tsx index 0b5ad70..1865d22 100644 --- a/src/ui/components/GameTabs.tsx +++ b/src/ui/components/GameTabs.tsx @@ -1,44 +1,43 @@ -import { Component, createSignal, Switch, Match } from "solid-js"; +import { Component, Switch, Match } from "solid-js"; import Moves from "./Moves"; import Controls from "./Controls"; import Load from "./Load"; import { Handlers } from "../../types"; import "./GameTabs.css"; +import { setState, state } from "../../state"; const GameTabs: Component<{ moves: readonly string[]; handlers: Handlers }> = ( props ) => { - const [tab, setTab] = createSignal("load"); - return (
- + - - setTab("moves")} /> + +
diff --git a/src/ui/components/Load.css b/src/ui/components/Load.css index cb050c6..a2e8c48 100644 --- a/src/ui/components/Load.css +++ b/src/ui/components/Load.css @@ -41,3 +41,7 @@ margin-top: 10px; color: #677794; } + +.load__link-input { + margin-top: 20px; +} diff --git a/src/ui/components/Load.tsx b/src/ui/components/Load.tsx index 7af0b8e..548f79f 100644 --- a/src/ui/components/Load.tsx +++ b/src/ui/components/Load.tsx @@ -3,11 +3,10 @@ import { Handlers } from "../../types"; import readFile from "../../utils/readFile"; import "./Load.css"; -const Load: Component<{ handlers: Handlers; showMoves: () => void }> = ( - props -) => { +const Load: Component<{ handlers: Handlers }> = (props) => { const [fen, setFEN] = createSignal(""); const [pgn, setPGN] = createSignal(""); + const [link, setLink] = createSignal(""); return (
@@ -15,7 +14,7 @@ const Load: Component<{ handlers: Handlers; showMoves: () => void }> = ( class="load__fen-input" type="text" name="load-fen" - placeholder="PASTE FEN..." + placeholder="Paste FEN..." spellcheck={false} value={fen()} onInput={(e) => setFEN(e.currentTarget.value)} @@ -32,10 +31,31 @@ const Load: Component<{ handlers: Handlers; showMoves: () => void }> = ( LOAD FEN
+ setLink(e.currentTarget.value)} + /> + +