Merge pull request #9 from jhalitaksoy/feature/theme-chooser

Feature/theme chooser
This commit is contained in:
Halit Aksoy 2022-06-04 20:57:47 +03:00 committed by GitHub
commit 06428ee7d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 135 additions and 10 deletions

View File

@ -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",

View File

@ -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 &&

View File

@ -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);
}

View File

@ -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,

View File

@ -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{

View File

@ -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,

View File

@ -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",

View File

@ -1,4 +1,6 @@
export type Theme = {
id: string;
name: string;
primary: string;
primaryLight: string;
background: string;

View File

@ -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;
}
}

View File

@ -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"