Merge pull request #9 from jhalitaksoy/feature/theme-chooser
Feature/theme chooser
This commit is contained in:
commit
06428ee7d4
@ -14,6 +14,8 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@szhsin/react-menu": "^3.0.2",
|
||||
"@types/": "szhsin/react-menu",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"mancala.js": "^0.0.2-beta.2",
|
||||
"react": "^17.0.2",
|
||||
|
||||
65
src/Home.tsx
65
src/Home.tsx
@ -18,6 +18,10 @@ import { GameMove } from "./models/GameMove";
|
||||
import PitAnimator from "./animation/PitAnimator";
|
||||
import BoardViewModel from "./viewmodel/BoardViewModel";
|
||||
import { v4 } from "uuid";
|
||||
import { Menu, MenuButton, MenuItem } from "@szhsin/react-menu";
|
||||
import "@szhsin/react-menu/dist/index.css";
|
||||
import "@szhsin/react-menu/dist/transitions/slide.css";
|
||||
import { getColorByLuminance } from "./util/ColorUtil";
|
||||
|
||||
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting";
|
||||
|
||||
@ -116,6 +120,12 @@ const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
context.themeManager.onThemeChange = () => {
|
||||
updateBoardViewModel(pitAnimator.getBoardViewModelFromGame(game));
|
||||
};
|
||||
}, [boardViewModel]);
|
||||
|
||||
const resetGameState = () => {
|
||||
setGame(undefined);
|
||||
setCrashMessage(undefined);
|
||||
@ -185,7 +195,11 @@ const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
||||
}
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const menuTextColor = getColorByLuminance(
|
||||
context.themeManager.theme.appBarBgColor,
|
||||
context.themeManager.theme.primary,
|
||||
context.themeManager.theme.primaryLight
|
||||
);
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@ -225,7 +239,54 @@ const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
|
||||
}}
|
||||
>
|
||||
<h1 style={{ margin: "10px 0px" }}>{context.texts.Mancala}</h1>
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
marginRight: "1vw",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
menuStyle={{
|
||||
background: context.themeManager.theme.appBarBgColor,
|
||||
}}
|
||||
menuButton={
|
||||
<span class="material-symbols-outlined">light_mode</span>
|
||||
}
|
||||
transition
|
||||
align="end"
|
||||
>
|
||||
{context.themeManager.themes.map((theme) => {
|
||||
return (
|
||||
<MenuItem
|
||||
style={{
|
||||
color: menuTextColor,
|
||||
}}
|
||||
onClick={() => (context.themeManager.theme = theme)}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
borderRadius: "5vw",
|
||||
background: theme.boardColor,
|
||||
width: "1vw",
|
||||
height: "1vw",
|
||||
marginRight: "1vw",
|
||||
}}
|
||||
></div>
|
||||
{theme.name}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</div>
|
||||
{renderNewGameButton()}
|
||||
{game &&
|
||||
!userKeyWhoLeave &&
|
||||
|
||||
@ -162,7 +162,7 @@ export default class PitAnimator {
|
||||
}
|
||||
}
|
||||
|
||||
private getBoardViewModelFromGame(game: MancalaGame): BoardViewModel {
|
||||
public getBoardViewModelFromGame(game: MancalaGame): BoardViewModel {
|
||||
const pitViewModels = this.createPitViewModelsFromGame(game);
|
||||
return BoardViewModelFactory.create(v4(), pitViewModels);
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import { Texts, TrTr } from "./const/texts";
|
||||
import { RTMT } from "./rtmt/rtmt";
|
||||
import { RTMTWS } from "./rtmt/rtmt_websocket";
|
||||
import { UserKeyStore, UserKeyStoreImpl } from "./store/key_store";
|
||||
import defaultTheme from "./theme/DefaultTheme";
|
||||
import ThemeManager from "./theme/ThemeManager";
|
||||
|
||||
export type Context = {
|
||||
@ -16,7 +15,7 @@ export const initContext = () => {
|
||||
const rtmt = new RTMTWS();
|
||||
const userKeyStore = new UserKeyStoreImpl();
|
||||
const texts = TrTr;
|
||||
const themeManager = new ThemeManager(defaultTheme);
|
||||
const themeManager = new ThemeManager();
|
||||
return {
|
||||
rtmt: rtmt,
|
||||
userKeyStore: userKeyStore,
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
<script src="./App.tsx"></script>
|
||||
</body>
|
||||
|
||||
<link rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />
|
||||
|
||||
<style>
|
||||
html{
|
||||
|
||||
@ -11,6 +11,8 @@ const colors = {
|
||||
const colorSpecial = "#F6A9A9";
|
||||
|
||||
const defaultTheme: Theme = {
|
||||
id: "1",
|
||||
name: "Default Light Theme",
|
||||
background: "#EEEEEE",
|
||||
appBarBgColor: colors.quaternary,
|
||||
primary: colors.primary,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { Theme } from "./Theme";
|
||||
|
||||
const oldTheme: Theme = {
|
||||
id: "0",
|
||||
name: "Old Theme",
|
||||
background: "#EEEEEE",
|
||||
appBarBgColor: "rgb(228, 228, 228)",
|
||||
appBarBgColor: "#e4e4e4",
|
||||
primary: "#4D606E",
|
||||
primaryLight: "#EEEEEE",
|
||||
playerTurnColor: "#84b8a6",
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export type Theme = {
|
||||
id: string;
|
||||
name: string;
|
||||
primary: string;
|
||||
primaryLight: string;
|
||||
background: string;
|
||||
|
||||
@ -1,18 +1,39 @@
|
||||
import defaultTheme from "./DefaultTheme";
|
||||
import oldTheme from "./OldTheme";
|
||||
import { Theme } from "./Theme";
|
||||
|
||||
export const themes = [defaultTheme, oldTheme];
|
||||
|
||||
const THEME_ID = "theme_id";
|
||||
|
||||
export default class ThemeManager {
|
||||
_theme: Theme;
|
||||
onThemeChange: (theme: Theme) => void;
|
||||
constructor(theme: Theme) {
|
||||
this._theme = theme;
|
||||
constructor() {
|
||||
this._theme = this.readFromLocalStorage() || defaultTheme;
|
||||
}
|
||||
|
||||
public get theme() {
|
||||
return this._theme;
|
||||
}
|
||||
|
||||
public set theme(value) {
|
||||
public set theme(value: Theme) {
|
||||
this._theme = value;
|
||||
this.onThemeChange?.(value);
|
||||
this.writetToLocalStorage(value);
|
||||
}
|
||||
|
||||
private writetToLocalStorage(value: Theme) {
|
||||
localStorage.setItem(THEME_ID, value.id);
|
||||
}
|
||||
|
||||
private readFromLocalStorage(): Theme {
|
||||
const themeID = localStorage.getItem(THEME_ID);
|
||||
const theme = themes.find((eachTheme: Theme) => themeID === eachTheme.id);
|
||||
return theme;
|
||||
}
|
||||
|
||||
public get themes(): Theme[] {
|
||||
return themes;
|
||||
}
|
||||
}
|
||||
|
||||
36
yarn.lock
36
yarn.lock
@ -1011,6 +1011,21 @@
|
||||
"@parcel/utils" "^1.11.0"
|
||||
physical-cpu-count "^2.0.0"
|
||||
|
||||
"@szhsin/react-menu@^3.0.2":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@szhsin/react-menu/-/react-menu-3.0.2.tgz#d22971c53d56e6d404c9d3c98f533907cd8f03dc"
|
||||
integrity sha512-m9Ly+cT+CxQx3xhq90CVaOLQWU7f7UKeMxfDt1gPYV23tDwEe8Zo6PO547qPlAEGEwwb9MdA38U8OyueXKJc2g==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
react-transition-state "^1.1.4"
|
||||
|
||||
"@types/@szhsin/react-menu":
|
||||
version "3.0.2"
|
||||
resolved "https://codeload.github.com/szhsin/react-menu/tar.gz/28284b2183801fb4f6a95e9270ce580441c5da70"
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
react-transition-state "^1.1.4"
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.5"
|
||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz"
|
||||
@ -3364,7 +3379,7 @@ log-symbols@^2.2.0:
|
||||
dependencies:
|
||||
chalk "^2.0.1"
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
@ -4333,6 +4348,15 @@ process@^0.11.10:
|
||||
resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
prop-types@^15.7.2:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz"
|
||||
@ -4433,6 +4457,16 @@ react-dom@^17.0.2:
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react-is@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-transition-state@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-state/-/react-transition-state-1.1.4.tgz#113224eaa27e0ff81661305e44d5e0348cdf61ac"
|
||||
integrity sha512-6nQLWWx95gYazCm6OdtD1zGbRiirvVXPrDtHAGsYb4xs9spMM7bA8Vx77KCpjL8PJ8qz1lXFGz2PTboCSvt7iw==
|
||||
|
||||
react@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user