mancala/src/Home.tsx

179 lines
5.3 KiB
TypeScript

import * as React from 'react';
import { FunctionComponent, useState } from 'react';
import BoardView from './components/BoardView';
import { context } from './context'
import { RTMTWS } from './rtmt/rtmt_websocket';
import { channel_game_move, channel_leave_game, channel_on_game_update, channel_on_game_user_leave } from './channel_names';
import Button from './components/Button';
import InfoPanel from './components/InfoPanel';
import { CommonMancalaGame, MancalaGame, Pit } from 'mancala.js'
import { GameMove } from './models/GameMove';
type ConnectionState = "connecting" | "error" | "connected" | "reconnecting"
const Home: FunctionComponent<{ initial?: number }> = ({ initial = 0 }) => {
const [userKey, setUserKey] = useState(undefined);
const [connectionState, setConnetionState] = useState<ConnectionState>("connecting")
const [searchingOpponent, setSearchingOpponent] = useState<boolean>(false)
const [game, setGame] = useState<CommonMancalaGame>(undefined)
const [crashMessage, setCrashMessage] = useState<string>(undefined)
const [userKeyWhoLeave, setUserKeyWhoLeave] = useState<string>(undefined)
const onConnectionDone = () => {
setConnetionState("connected")
}
const onConnectionLost = () => {
connectToServer("reconnecting")
}
const onConnectionError = (event: Event) => {
setConnetionState("error")
}
const connectToServer = (connectionState: ConnectionState) => {
setConnetionState(connectionState)
context.userKeyStore.getUserKey((userKey: string) => {
setUserKey(userKey)
const rtmtws = context.rtmt as RTMTWS
if (rtmtws) {
rtmtws.initWebSocket(userKey, onConnectionDone, onConnectionLost, onConnectionError)
} else {
console.error("context.rtmt is not RTMTWS");
}
})
}
const listenMessages = () => {
context.rtmt.listenMessage(channel_on_game_update, (message: Object) => {
const newGame: CommonMancalaGame = message as CommonMancalaGame;
setGame(MancalaGame.createFromMancalaGame(newGame))
})
context.rtmt.listenMessage("on_game_start", (message: Object) => {
const newGame: CommonMancalaGame = message as CommonMancalaGame;
setSearchingOpponent(false)
setGame(MancalaGame.createFromMancalaGame(newGame))
})
context.rtmt.listenMessage("on_game_crashed", (message : any) => {
const newCrashMessage = message as string
console.error("on_game_crash");
console.error(newCrashMessage);
setCrashMessage(newCrashMessage)
})
context.rtmt.listenMessage(channel_on_game_user_leave, (message : any) => {
const userKeyWhoLeave = message;
setUserKeyWhoLeave(userKeyWhoLeave)
})
}
React.useEffect(() => {
listenMessages()
connectToServer("connecting")
}, [])
const resetGameState = () => {
setGame(undefined)
setCrashMessage(undefined)
setUserKeyWhoLeave(undefined)
}
const newGameClick = () => {
resetGameState()
setSearchingOpponent(true)
context.rtmt.sendMessage("new_game", {})
}
const leaveGame = () => {
context.rtmt.sendMessage(channel_leave_game, {})
}
const onHoleSelect = (index: number, hole: Pit) => {
const gameMove: GameMove = { index: index }
context.rtmt.sendMessage(channel_game_move, gameMove)
}
const showConnectionState = connectionState != "connected"
const connectionStateText = () => {
let map: { [key: string]: string } = {
"connecting": context.texts.Connecting,
"connected": context.texts.Connected,
"error": context.texts.CannotConnect,
"reconnecting": context.texts.ConnectingAgain
};
return map[connectionState]
}
const renderNewGameButton = () => {
const newGame = <Button text={context.texts.NewGame} color="#005f73" onClick={newGameClick} />
if (userKeyWhoLeave) {
return newGame
}
if (crashMessage) {
return newGame
}
if (!game) {
return newGame
} else if (game.state == "ended") {
return newGame
}
return <></>
}
return <div style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
background: "#EEEEEE",
flex: "1",
}}>
{showConnectionState &&
<div style={{
position: "absolute",
bottom: "0px",
left: "0px",
padding: "15px ",
borderTopRightRadius: "1vw",
minWidth: "10vw",
minHeight: "1vw",
background: "#2F2504",
color: "white",
}}>
{connectionStateText()}
</div>}
<div style={{
padding: "0px 50px",
background: "rgb(228, 228, 228)",
display: 'flex',
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
alignSelf: "stretch"
}}>
<h1 style={{ margin: "10px 0px" }}>{context.texts.Mancala}</h1>
<div>
{renderNewGameButton()}
{game && !userKeyWhoLeave && !crashMessage && (game?.state === "playing" || game?.state === "initial") && < Button color="#005f73" text={context.texts.Leave} onClick={leaveGame} />}
</div>
</div>
<InfoPanel
game={game}
crashMessage={crashMessage}
userKey={userKey}
userKeyWhoLeave={userKeyWhoLeave}
searchingOpponent={searchingOpponent} />
{game && <BoardView userKey={userKey} game={game} onHoleSelect={onHoleSelect} />}
</div >
}
export default Home