WIP
This commit is contained in:
12
src/main.tsx
12
src/main.tsx
@@ -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 === "") {
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
12
src/state.ts
12
src/state.ts
@@ -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: "",
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user