lanpartyplayspokemon/frontend/src/TVMode.tsx
2022-10-29 15:19:16 +02:00

72 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { CSSProperties, useEffect, useMemo, useState } from 'react';
import './TVMode.css';
import { ButtonType, buttonTypeList, WGPPState } from './types';
const TVMode = () => {
const [state, setState] = useState<Partial<WGPPState>>({});
const [socket, setSocket] = useState<WebSocket>();
useEffect(() => {
const url = new URL(`api/client`, window.location.href);
url.protocol = url.protocol.replace("http", "ws");
const sock = new WebSocket(url.href);
sock.onmessage = (e) => {
const newState = JSON.parse(e.data) as Partial<WGPPState>;
// Merge old and new state
setState(oldState => ({ ...oldState , ...newState }));
}
setSocket(sock);
return () => {
sock.close();
setSocket(undefined);
};
}, [])
const totalCount = useMemo(() => buttonTypeList.reduce((acc, v) => (state?.votes?.[v] ?? 0) + acc, 0), [state]);
const voteList = useMemo(() =>
buttonTypeList
.map(b => [b, state?.votes?.[b] ?? 0] as [ButtonType, number])
//.sort((a, b) => b[1] - a[1])
, [state]);
return <div className="stream">
{state === undefined ?
<span>Loading...</span> :
<div>
<span className={`mode mode-${state.mode}`}>{state.mode}</span>
<div className="row">
<div>
<span>
next:&nbsp;
</span>
<span className={`subtitle mode-${state.nextMode}`}>{state.nextMode}</span>
</div>
<span className="timer">{Math.round(state.timeUntilNextMode ?? 0)}s </span>
</div>
<div className="voting">
{voteList.flatMap(([b, numVotes], index) => {
const percentage = numVotes === 0 ? 0 : Math.round(numVotes / totalCount * 100);
return <div className="vote" style={{ "--vote-percentage": percentage + "%" } as CSSProperties} key={index}>
<div className="bar-wrap">
<div className="bar" style={{ "--vote-percentage": percentage + "%" } as CSSProperties} >{b}</div>
</div>
<span className="percentage">{percentage === 0 ? "" : `${percentage}%`}</span>
</div>;
})}
</div>
<div>
Current state: <pre>
{JSON.stringify(state, null, 4)}
</pre>
</div>
</div>
}
</div>;
}
export default TVMode;