This commit is contained in:
Maciej Caderek
2022-04-11 22:46:30 +02:00
parent 9fa3285297
commit 7beecd3c72
17 changed files with 870 additions and 127 deletions

View File

@@ -226,12 +226,16 @@ const main = async () => {
download(data, name, state.gameConfig.format.toLowerCase());
},
toggleSound() {
setState("boardConfig", "sounds", !state.boardConfig.sounds);
saveConfig("board");
setState("siteConfig", "sounds", !state.siteConfig.sounds);
saveConfig("site");
},
toggleSpeech() {
setState("boardConfig", "speech", !state.boardConfig.speech);
saveConfig("board");
setState("siteConfig", "speech", !state.siteConfig.speech);
saveConfig("site");
},
toggleDarkMode() {
setState("siteConfig", "darkMode", !state.siteConfig.darkMode);
saveConfig("site");
},
async openOnLichess() {
if (state.pgn === "") {

View File

@@ -1,10 +1,12 @@
const loadConfig = () => {
const boardConfig = localStorage.getItem("boardConfig");
const gameConfig = localStorage.getItem("gameConfig");
const siteConfig = localStorage.getItem("siteConfig");
return {
boardConfig: boardConfig === null ? {} : JSON.parse(boardConfig),
gameConfig: gameConfig === null ? {} : JSON.parse(gameConfig),
siteConfig: siteConfig === null ? {} : JSON.parse(siteConfig),
};
};

View File

@@ -1,8 +1,17 @@
import { state } from "../state";
const saveConfig = (type: "board" | "game") =>
type === "board"
? localStorage.setItem("boardConfig", JSON.stringify(state.boardConfig))
: localStorage.setItem("gameConfig", JSON.stringify(state.gameConfig));
const saveConfig = (type: "board" | "game" | "site") => {
switch (type) {
case "board":
localStorage.setItem("boardConfig", JSON.stringify(state.boardConfig));
break;
case "game":
localStorage.setItem("gameConfig", JSON.stringify(state.gameConfig));
break;
case "site":
localStorage.setItem("siteConfig", JSON.stringify(state.siteConfig));
break;
}
};
export default saveConfig;

View File

@@ -15,14 +15,8 @@ class Player {
private speech: Speech;
public playing: boolean = false;
// private firstRender: Promise<void>;
constructor(private board: Board, private config: GameConfig) {
this.speech = new Speech();
// this.firstRender = this.board
// .frame(this.game.getPosition(0), this.game.header)
// .then((_) => this.board.render());
}
async init() {
@@ -49,7 +43,6 @@ class Player {
async load(game: Game) {
this.pause();
// await this.firstRender;
this.game = game;
this.ply = 0;
@@ -99,7 +92,7 @@ class Player {
await this.board.frame(this.getPosition(), this.game.header);
this.board.render();
if (state.boardConfig.sounds) {
if (state.siteConfig.sounds) {
sfx.rewind.play();
}
}
@@ -119,11 +112,11 @@ class Player {
await this.board.frame(position, this.game.header);
this.board.render();
if (this.ply > 0 && state.boardConfig.speech) {
if (this.ply > 0 && state.siteConfig.speech) {
this.speech.say(sanToText(position.move?.san as string));
}
if (this.ply > 0 && state.boardConfig.sounds) {
if (this.ply > 0 && state.siteConfig.sounds) {
if (position.mate) {
sfx.snap.play();
} else if (/[ce]/.test(position.move?.flags as string)) {
@@ -135,7 +128,7 @@ class Player {
}
}
if (position.end === 0 && state.boardConfig.speech) {
if (position.end === 0 && state.siteConfig.speech) {
const result = this.game.header.Result;
if (result) {
this.speech.say(

View File

@@ -2,7 +2,7 @@ import isMobile from "is-mobile";
import { createStore } from "solid-js/store";
import Game from "./game/Game";
import loadConfig from "./persistance/loadConfig";
import { BoardConfig, GameConfig } from "./types";
import { BoardConfig, GameConfig, SiteConfig } from "./types";
const mobile = isMobile();
@@ -20,8 +20,6 @@ const initialBoardConfig: BoardConfig = {
showChecks: true,
showCoords: true,
showShadows: false,
sounds: true,
speech: false,
flipped: false,
};
@@ -32,11 +30,18 @@ const initialGameConfig: GameConfig = {
animationSize: "M",
};
const initialSiteConfig: SiteConfig = {
darkMode: true,
sounds: true,
speech: false,
};
export type TabName = "game" | "load" | "share" | "boards" | "pieces";
export type State = {
boardConfig: BoardConfig;
gameConfig: GameConfig;
siteConfig: SiteConfig;
game: Game;
pgn: string;
fen: string;
@@ -56,6 +61,7 @@ const initialState: State = {
...saved.boardConfig,
},
gameConfig: { ...initialGameConfig, ...saved.gameConfig },
siteConfig: { ...initialSiteConfig, ...saved.siteConfig },
game: new Game(),
pgn: "",
fen: "",

View File

@@ -89,8 +89,6 @@ export type BoardConfig = {
showChecks: boolean;
showCoords: boolean;
showShadows: boolean;
sounds?: boolean;
speech?: boolean;
flipped: boolean;
};
@@ -103,6 +101,12 @@ export type GameConfig = {
animationSize: Size;
};
export type SiteConfig = {
darkMode: boolean;
sounds: boolean;
speech: boolean;
};
export type MaterialCount = {
w: {
p: number;
@@ -175,6 +179,7 @@ export type Handlers = {
downloadAnimation: () => Promise<void>;
toggleSound(): void;
toggleSpeech(): void;
toggleDarkMode(): void;
openOnLichess: () => Promise<boolean>;
};

View File

@@ -15,7 +15,7 @@ const App: Component<{ handlers: Handlers; state: DeepReadonly<State> }> = (
props
) => {
return (
<>
<div classList={{ light: !state.siteConfig.darkMode }}>
<Header handlers={props.handlers} />
<div class="layout">
<Show when={state.layout === "triple"}>
@@ -42,7 +42,7 @@ const App: Component<{ handlers: Handlers; state: DeepReadonly<State> }> = (
></GameTabs>
</div>
</div>
</>
</div>
);
};

View File

@@ -20,47 +20,44 @@ const Header: Component<{ handlers: Handlers }> = (props) => {
<div
class="header__options-ico"
onClick={() => {
props.handlers.toggleSound();
}}
title={state.boardConfig.sounds ? "MUTE" : "SOUND ON"}
onClick={props.handlers.toggleSound}
title={state.siteConfig.sounds ? "MUTE" : "SOUND ON"}
>
<i
classList={{
las: true,
"la-volume-mute": !state.boardConfig.sounds,
"la-volume-up": state.boardConfig.sounds,
"la-volume-mute": !state.siteConfig.sounds,
"la-volume-up": state.siteConfig.sounds,
}}
></i>
</div>
<div
class="header__options-ico"
onClick={() => {
props.handlers.toggleSpeech();
}}
title={state.boardConfig.speech ? "SPEECH OFF" : "SPEECH ON"}
onClick={props.handlers.toggleSpeech}
title={state.siteConfig.speech ? "SPEECH OFF" : "SPEECH ON"}
>
<i
classList={{
las: true,
"la-deaf": !state.boardConfig.speech,
"la-assistive-listening-systems": state.boardConfig.speech,
"la-deaf": !state.siteConfig.speech,
"la-assistive-listening-systems": state.siteConfig.speech,
}}
></i>
</div>
<div
class="header__options-ico"
onClick={() => {
setDarkMode(!darkMode());
document.body.classList.toggle("light");
}}
title={darkMode() ? "LIGHT MODE" : "DARK MODE"}
onClick={props.handlers.toggleDarkMode}
title={
state.siteConfig.darkMode
? "SWITCH TO LIGHT MODE"
: "SWITCH TO DARK MODE"
}
>
<i
classList={{
las: true,
"la-sun": darkMode(),
"la-moon": !darkMode(),
"la-sun": state.siteConfig.darkMode,
"la-moon": !state.siteConfig.darkMode,
}}
></i>
</div>

View File

@@ -67,9 +67,16 @@
padding: 0 1rem;
}
.info__analyze {
position: absolute;
bottom: 2rem;
width: 100%;
padding-right: 4rem;
.info__header {
height: 13.1rem;
}
.info__analyze {
margin-top: 2rem;
}
@media (orientation: portrait) {
.info__header {
height: auto;
}
}

View File

@@ -10,84 +10,86 @@ const Info: Component<{ handlers: Handlers }> = (props) => {
return (
<div class="info">
<div className="info__players">
<div class="info__player">
<div className="info__left">
<button className="info__color info__color--white"></button>
<Show when={!state.anonymous} fallback="Anonymous">
{state.game.header.WhitePretty}{" "}
</Show>
<Show when={state.game.header.WhiteElo}>
<span className="info__rating">
{" "}
({state.game.header.WhiteElo})
</span>
</Show>
</div>
<div className="info__right">
<span className="info__score">
{state.game.header.Result === "1-0"
? "1"
: state.game.header.Result === "0-1"
? "0"
: state.game.header.Result === "1/2-1/2"
? "1/2"
: ""}
</span>
</div>
</div>
<div class="info__player">
<div className="info__left">
<button className="info__color info__color--black"></button>
<Show when={!state.anonymous} fallback="Anonymous">
{state.game.header.BlackPretty}{" "}
</Show>
<Show when={state.game.header.BlackElo}>
<span className="info__rating">
{" "}
({state.game.header.BlackElo})
</span>
</Show>
</div>
<div className="info__right">
<span className="info__score">
{state.game.header.Result === "1-0"
? "0"
: state.game.header.Result === "0-1"
? "1"
: state.game.header.Result === "1/2-1/2"
? "1/2"
: ""}
</span>
</div>
</div>
</div>
<div className="info__event">
<Show when={state.game.header.Event}>
<p>{state.game.header.Event}</p>
</Show>
<Show when={state.game.header.Round}>
<p>Round {state.game.header.Round}</p>
</Show>
</div>
<div className="info__site">
<Show when={state.game.header.Site}>
<p>
<Show when={!state.anonymous || !isLink(state.game.header.Site)}>
<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>
<div className="info__header">
<div className="info__players">
<div class="info__player">
<div className="info__left">
<button className="info__color info__color--white"></button>
<Show when={!state.anonymous} fallback="Anonymous">
{state.game.header.WhitePretty}{" "}
</Show>
</Show>
</p>
</Show>
<Show when={state.game.header.DatePretty}>
<p>{state.game.header.DatePretty}</p>
</Show>
<Show when={state.game.header.WhiteElo}>
<span className="info__rating">
{" "}
({state.game.header.WhiteElo})
</span>
</Show>
</div>
<div className="info__right">
<span className="info__score">
{state.game.header.Result === "1-0"
? "1"
: state.game.header.Result === "0-1"
? "0"
: state.game.header.Result === "1/2-1/2"
? "1/2"
: ""}
</span>
</div>
</div>
<div class="info__player">
<div className="info__left">
<button className="info__color info__color--black"></button>
<Show when={!state.anonymous} fallback="Anonymous">
{state.game.header.BlackPretty}{" "}
</Show>
<Show when={state.game.header.BlackElo}>
<span className="info__rating">
{" "}
({state.game.header.BlackElo})
</span>
</Show>
</div>
<div className="info__right">
<span className="info__score">
{state.game.header.Result === "1-0"
? "0"
: state.game.header.Result === "0-1"
? "1"
: state.game.header.Result === "1/2-1/2"
? "1/2"
: ""}
</span>
</div>
</div>
</div>
<div className="info__event">
<Show when={state.game.header.Event}>
<p>{state.game.header.Event}</p>
</Show>
<Show when={state.game.header.Round}>
<p>Round {state.game.header.Round}</p>
</Show>
</div>
<div className="info__site">
<Show when={state.game.header.Site}>
<p>
<Show when={!state.anonymous || !isLink(state.game.header.Site)}>
<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>
<Show when={state.game.header.DatePretty}>
<p>{state.game.header.DatePretty}</p>
</Show>
</div>
</div>
<div className="info__analyze">
<button