This commit is contained in:
Maciej Caderek
2022-04-13 02:31:58 +02:00
parent e4bad17c0a
commit 5d59275f48
24 changed files with 747 additions and 409 deletions

View File

@@ -2,16 +2,18 @@ import { Component, Show } from "solid-js";
import type { DeepReadonly } from "solid-js/store";
import { Handlers } from "../types";
import { setState, State, state } from "../state";
import { State, state } from "../state";
import Header from "./components/Header";
import GameTabs from "./components/GameTabs";
import SetupTabs from "./components/SetupTabs";
import Controls from "./components/Controls";
import Popup from "./components/Popup";
import "./App.css";
import saveConfig from "../persistance/saveConfig";
import WrongBrowserPopup from "./components/popups/WrongBrowserPopup";
import AndroidAppPopup from "./components/popups/AndroidAppPopup";
import IOSAppPopup from "./components/popups/IOSAppPopup";
import About from "./components/About";
const App: Component<{ handlers: Handlers; state: DeepReadonly<State> }> = (
props
@@ -44,17 +46,10 @@ const App: Component<{ handlers: Handlers; state: DeepReadonly<State> }> = (
></GameTabs>
</div>
</div>
<Show when={state.siteConfig.wrongBrowserPopup}>
<Popup
handlers={props.handlers}
onClose={() => {
setState("siteConfig", "wrongBrowserPopup", false);
saveConfig("site");
}}
>
{state.browser} | {state.os}
</Popup>
</Show>
<About />
<WrongBrowserPopup />
<AndroidAppPopup />
<IOSAppPopup />
</div>
);
};

View File

@@ -0,0 +1,77 @@
.about {
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
display: grid;
vertical-align: middle;
padding-top: var(--header-height);
pointer-events: none;
}
.about__box {
background-color: var(--color-bg-input);
min-height: 100%;
width: 100%;
margin: auto;
padding: 2rem;
padding-top: 6rem;
border-radius: 0.5rem;
position: relative;
pointer-events: all;
}
.about__close {
width: 3.2rem;
position: absolute;
top: 1rem;
right: 1rem;
}
.about__title {
text-align: left;
margin: 0 4.2rem 3rem 0;
}
.about__content {
text-align: left;
font-size: 1.2rem;
max-width: 800px;
margin: auto;
}
.about__content p {
margin-top: 2rem;
font-size: 1.4rem;
line-height: 2rem;
}
.about__content ul {
margin-top: 2rem;
list-style: none;
font-size: 1.4rem;
line-height: 3rem;
}
.about__content li {
margin-top: 0.5rem;
margin-left: 2rem;
}
.about__content kbd {
margin-top: 0.5rem;
margin-left: 2rem;
background-color: var(--color-tab);
color: var(--color-text-contrast);
padding: 0.5rem 1rem;
margin-right: 1rem;
border-radius: 0.5rem;
box-shadow: 0.5rem 0.5rem 1rem #00000033;
font-family: "Fira Mono", monospace;
font-weight: 500;
}
.about__shortcuts {
display: grid;
grid-template-columns: 1fr 1fr;
}

View File

@@ -0,0 +1,90 @@
import { Component, Show } from "solid-js";
import { setState, state } from "../../state";
import "./About.css";
const About: Component = () => {
return (
<Show when={state.about}>
<div className="about">
<div className="about__box">
<button
className="about__close"
onClick={() => setState("about", !state.about)}
>
<i class="las la-times"></i>
</button>
<div className="about__content">
<h2>About</h2>
<p>
<b>ShareChess</b> is a free, open source website that allows you
to share chess games as self-contained replay links (the whole
game is stored in the url without the need for a database), PNG
images, or GIF / MP4 / WebM animations.
</p>
<p>
The website provides a high variety of chessboard and piece
designs to serve as an open alternative for commercial chess GIF
makers.
</p>
<p>
You can find the complete source code on our{" "}
<a href="https://github.com/sharechess/sharechess">GitHub page</a>
.
</p>
<hr />
<h2>Keyboard Shortcuts</h2>
<div className="about__shortcuts">
<ul>
<li>
<kbd></kbd> Next move
</li>
<li>
<kbd></kbd> Previous move
</li>
<li>
<kbd></kbd> Start position
</li>
<li>
<kbd></kbd> Final position
</li>
<li>
<kbd>f</kbd> Flip the board
</li>
<li>
<kbd>Space</kbd> Play / Pause
</li>
<li>
<kbd>Enter</kbd> Analyze on Lichess
</li>
</ul>
<ul>
<li>
<kbd>l</kbd> Load from clipboard
</li>
<li>
<kbd>a</kbd> Toggle anonymous
</li>
<li>
<kbd>b</kbd> Toggle border
</li>
<li>
<kbd>i</kbd> Toggle extra info
</li>
<li>
<kbd>h</kbd> Toggle header (title screen)
</li>
<li>
<kbd>s</kbd> Toggle shadows
</li>
</ul>
</div>
</div>
</div>
</div>
</Show>
);
};
export default About;

View File

@@ -1,11 +1,9 @@
import { Component, createSignal } from "solid-js";
import { Component } from "solid-js";
import { Handlers } from "../../types";
import { state } from "../../state";
import { setState, state } from "../../state";
import "./Header.css";
const Header: Component<{ handlers: Handlers }> = (props) => {
const [darkMode, setDarkMode] = createSignal(true);
return (
<header class="header-box">
<div class="header__logo">
@@ -14,9 +12,13 @@ const Header: Component<{ handlers: Handlers }> = (props) => {
</a>
</div>
<div class="header__options">
{/* <div class="header__options-ico" onClick={() => {}}>
<div
class="header__options-ico"
onClick={() => setState("about", !state.about)}
title="ABOUT"
>
<i class="las la-question-circle"></i>
</div> */}
</div>
<div
class="header__options-ico"

View File

@@ -17,8 +17,7 @@ const Load: Component<{ handlers: Handlers; class?: string }> = (props) => {
<button
classList={{ "load__game-btn": true, "btn--error": clipError() }}
onClick={async () => {
const clip = await navigator.clipboard.readText();
const success = await props.handlers.load(clip);
const success = await props.handlers.loadFromClipboard();
if (!success) {
setClipError(true);

View File

@@ -4,6 +4,7 @@ import Scrollable from "./reusable/Scrollable";
import { state, setState } from "../../state";
import "./Share.css";
import download from "../../utils/download";
import link from "../../persistance/link";
const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
const [copyId, setCopyId] = createSignal("");
@@ -19,6 +20,17 @@ const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
<Scrollable class={"share" + (props.class ? ` ${props.class}` : "")}>
<div className="share__view">
<h2 class="header--first">Board options</h2>
<button
classList={{
options__button: true,
"options__button--last": false,
"options__button--active": state.anonymous,
}}
onClick={props.handlers.toggleAnonymous}
title="TOGGLE ANONYMOUS"
>
<i class="las la-user-secret"></i>
</button>
<button
classList={{
options__button: true,
@@ -57,17 +69,6 @@ const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
>
<i class="las la-heading"></i>
</button>
<button
classList={{
options__button: true,
"options__button--last": false,
"options__button--active": state.anonymous,
}}
onClick={props.handlers.toggleAnonymous}
title="TOGGLE ANONYMOUS"
>
<i class="las la-user-secret"></i>
</button>
<button
classList={{
options__button: true,
@@ -110,8 +111,7 @@ const Share: Component<{ handlers: Handlers; class?: string }> = (props) => {
<button
class="share__btn share__btn--right"
onClick={() => {
const link = `${location.origin}/#fen/${encodeURI(state.fen)}`;
navigator.clipboard.writeText(link);
navigator.clipboard.writeText(link.getFENLink(state.fen));
blinkCopy("fen-link");
}}
>

View File

@@ -0,0 +1,38 @@
import { Component, Show } from "solid-js";
import { setState, state } from "../../../state";
import Popup from "../reusable/Popup";
import saveConfig from "../../../persistance/saveConfig";
const AndroidAppPopup: Component = () => {
return (
<Show
when={state.siteConfig.androidAppPopup && state.os?.includes("Android")}
>
<Popup
onClose={() => {
setState("siteConfig", "androidAppPopup", false);
saveConfig("site");
}}
title="Tip"
>
<p>
For easy access, you can install this website as a standalone app.
</p>
<ul>
To do that:
<li>open the website in Chrome,</li>
<li>tap the menu icon (3 dots in the corner),</li>
<li>
tap{" "}
<u>
<b>Add to Home screen</b>
</u>
.
</li>
</ul>
</Popup>
</Show>
);
};
export default AndroidAppPopup;

View File

@@ -0,0 +1,36 @@
import { Component, Show } from "solid-js";
import { setState, state } from "../../../state";
import Popup from "../reusable/Popup";
import saveConfig from "../../../persistance/saveConfig";
const IOSAppPopup: Component = () => {
return (
<Show when={state.siteConfig.iOSAppPopup && state.os?.includes("iOS")}>
<Popup
onClose={() => {
setState("siteConfig", "iOSAppPopup", false);
saveConfig("site");
}}
title="Tip"
>
<p>
For easy access, you can install this website as a standalone app.
</p>
<ul>
To do that:
<li>open the website in Safari,</li>
<li>tap the Share icon,</li>
<li>
tap{" "}
<u>
<b>Add to Home Screen</b>
</u>
.
</li>
</ul>
</Popup>
</Show>
);
};
export default IOSAppPopup;

View File

@@ -0,0 +1,36 @@
import { Component, Show } from "solid-js";
import { setState, state } from "../../../state";
import Popup from "../reusable/Popup";
import saveConfig from "../../../persistance/saveConfig";
const WrongBrowserPopup: Component = () => {
return (
<Show
when={
!state.siteConfig.iOSAppPopup &&
state.siteConfig.wrongBrowserPopup &&
state.os === "iOS" &&
!state.browser?.includes("Safari")
}
>
<Popup
onClose={() => {
setState("siteConfig", "wrongBrowserPopup", false);
saveConfig("site");
}}
title="Note"
>
<p>Saving files may not work correctly in this browser.</p>
<p>
To enjoy the full functionality of the website, please open it in{" "}
<u>
<b>Safari</b>
</u>
.
</p>
</Popup>
</Show>
);
};
export default WrongBrowserPopup;

View File

@@ -3,7 +3,7 @@
height: 100vh;
position: absolute;
top: 0;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.7);
padding: 2rem;
display: grid;
vertical-align: middle;
@@ -18,6 +18,7 @@
border-radius: 0.5rem;
box-shadow: 0 0 2rem #00000099;
position: relative;
border: solid 1px var(--color-highlight);
}
.popup__close {
@@ -29,6 +30,23 @@
.popup__title {
text-align: left;
margin: 0 4.2rem 2rem 0;
/* background-color: aqua; */
margin: 0 4.2rem 3rem 0;
}
.popup__content {
text-align: left;
font-size: 1.2rem;
}
.popup__content p {
margin-top: 2rem;
}
.popup__content ul {
margin-top: 2rem;
}
.popup__content li {
margin-top: 0.5rem;
margin-left: 2rem;
}

View File

@@ -1,19 +1,18 @@
import { Component } from "solid-js";
import { Handlers } from "../../types";
import { state, setState } from "../../state";
import "./Popup.css";
const Popup: Component<{ handlers: Handlers; onClose: () => void }> = (
props
) => {
const Popup: Component<{
onClose: () => void;
title: string;
}> = (props) => {
return (
<div className="popup">
<div className="popup__box">
<button className="popup__close" onClick={props.onClose}>
<i class="las la-times"></i>
</button>
<h2 className="popup__title">Popup title</h2>
<h2 className="popup__title">{props.title}</h2>
<div className="popup__content">{props.children}</div>
</div>
</div>