- Banner for the user's game in progress with a Continue button - Live games as cards with the real board, updated over WebSocket; the most watched finished games when nothing is live - The user's last 3 games, from their side of the board, with the result as they would say it - The lobby offers to continue the game in progress when a new one is refused - Spectators register once connected and identified, and again after a reconnect, so they are counted - The backend includes games that ended but are not saved yet in /game/:id and the lists
109 lines
4.4 KiB
TypeScript
109 lines
4.4 KiB
TypeScript
import { CommonMancalaGame, MancalaGame } from 'mancala.js';
|
|
import * as React from 'react';
|
|
import { FunctionComponent, useEffect, useState } from 'react';
|
|
import { Link, useNavigate } from 'react-router-dom';
|
|
import Center from '../components/Center';
|
|
import CircularPanel from '../components/CircularPanel';
|
|
import HeaderBar from '../components/headerbar/HeaderBar';
|
|
import HeaderbarIcon from '../components/headerbar/HeaderbarIcon';
|
|
import HeaderbarTitle from '../components/headerbar/HeaderbarTitle';
|
|
import ThemeSwitchMenu from '../components/headerbar/ThemeSwitchMenu';
|
|
import PageContainer from '../components/PageContainer';
|
|
import Row from '../components/Row';
|
|
import { channel_cancel_new_game, channel_on_game_start, channel_on_new_game_rejected } from '@mancala/core';
|
|
import { Context } from '../context/context';
|
|
import { Theme } from '@mancala/core';
|
|
import { getColorByBrightness } from "@mancala/core";
|
|
import Button from "../components/Button";
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
const LobyPage: FunctionComponent<{
|
|
context: Context,
|
|
userKey?: string,
|
|
theme: Theme
|
|
}> = ({ context, userKey, theme }) => {
|
|
|
|
let navigate = useNavigate();
|
|
|
|
const { t } = useTranslation();
|
|
|
|
// Set when the server refuses a new game because the user has one in progress.
|
|
const [activeGameId, setActiveGameId] = useState<string | undefined>(undefined);
|
|
|
|
const onNewGameRejected = (message: { gameId: string }) => setActiveGameId(message.gameId);
|
|
|
|
const onGameStart = (message: Object) => {
|
|
const newGame: CommonMancalaGame = message as CommonMancalaGame;
|
|
navigate(`/game/${newGame.id}`)
|
|
}
|
|
|
|
const onCancelNewGameClick = () => {
|
|
if (context.rtmt.connectionState === "connected") {
|
|
context.rtmt.sendMessage(channel_cancel_new_game, "");
|
|
}
|
|
navigate("/")
|
|
}
|
|
useEffect(() => {
|
|
context.rtmt.addMessageListener(channel_on_game_start, onGameStart);
|
|
context.rtmt.addMessageListener(channel_on_new_game_rejected, onNewGameRejected);
|
|
context.rtmt.sendMessage("new_game", {});
|
|
return () => {
|
|
context.rtmt.removeMessageListener(channel_on_game_start, onGameStart);
|
|
context.rtmt.removeMessageListener(channel_on_new_game_rejected, onNewGameRejected);
|
|
}
|
|
}, []);
|
|
|
|
const textColorOnAppBar = getColorByBrightness(
|
|
context.themeManager.theme.appBarBgColor,
|
|
context.themeManager.theme.textColor,
|
|
context.themeManager.theme.textLightColor
|
|
);
|
|
const textColorOnBoard = getColorByBrightness(
|
|
context.themeManager.theme.boardColor,
|
|
context.themeManager.theme.textColor,
|
|
context.themeManager.theme.textLightColor
|
|
);
|
|
return (
|
|
<PageContainer theme={theme!}>
|
|
<HeaderBar color={theme?.appBarBgColor}>
|
|
<Row>
|
|
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
|
<HeaderbarIcon />
|
|
</Link>
|
|
<Link style={{ textDecoration: 'none' }} to={"/"}>
|
|
<HeaderbarTitle title={t("Mancala")} color={textColorOnAppBar} />
|
|
</Link>
|
|
</Row>
|
|
<Row>
|
|
<ThemeSwitchMenu context={context} textColor={textColorOnAppBar} />
|
|
</Row>
|
|
</HeaderBar>
|
|
<Center>
|
|
<div style={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignContent: "center"
|
|
}}>
|
|
<CircularPanel color={context.themeManager.theme.boardColor}>
|
|
<h4 style={{ margin: "0", color: textColorOnBoard }}>
|
|
{activeGameId ? t("GameInProgress") : `${t("SearchingOpponent")} ${t("PleaseWait")}...`}
|
|
</h4>
|
|
</CircularPanel>
|
|
{activeGameId && <Button
|
|
context={context}
|
|
color={context.themeManager.theme.pitColor}
|
|
text={t("Continue")}
|
|
onClick={() => navigate(`/game/${activeGameId}`)} />}
|
|
<Button
|
|
context={context}
|
|
color={context.themeManager.theme.boardColor}
|
|
text={t("Cancel")}
|
|
onClick={onCancelNewGameClick} />
|
|
</div>
|
|
|
|
</Center>
|
|
</PageContainer>
|
|
);
|
|
}
|
|
|
|
export default LobyPage; |