61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import './TVMode.css';
|
||
import { WGPPState } from './types';
|
||
|
||
const TVMode = () => {
|
||
|
||
const [state, setState] = useState<Partial<WGPPState>>({});
|
||
const [socket, setSocket] = useState<WebSocket>();
|
||
const [endTime, setEndTime] = useState(0);
|
||
const [secondsRemaining, setSecondsRemaining] =useState(0);
|
||
|
||
useEffect(() => {
|
||
setEndTime(Date.now() + (state?.timeUntilNextMode??15) * 1000);
|
||
const interval = setInterval(() => {
|
||
const remaining = Math.round((endTime - Date.now())/1000);
|
||
setSecondsRemaining(remaining < 0 ? 0 : remaining);
|
||
}, 500);
|
||
return () => clearInterval(interval);
|
||
}, [endTime, state?.timeUntilNextMode]);
|
||
|
||
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);
|
||
};
|
||
}, [])
|
||
|
||
return <div className="stream">
|
||
{state === undefined ?
|
||
<span>Loading...</span> :
|
||
<div>
|
||
<div className="heading">
|
||
<span className={`mode mode-${state.mode}`}>Mode: {state.mode}</span>
|
||
<div>
|
||
<span className="timer">{Math.round(state.timeUntilNextMode ?? 0)}s ⏱️</span>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
Current state: <pre>
|
||
{JSON.stringify(state, null, 4)}
|
||
</pre>
|
||
</div>
|
||
|
||
</div>
|
||
}
|
||
</div>;
|
||
}
|
||
|
||
export default TVMode;
|