import MuiSlider from "@mui/material/Slider"; import React from "react"; import { useState, useEffect, useRef } from "react"; type StateItem = { value: number, status: "open" | "owned" | "locked", }; type State = Array; type ClientAction = { action_type: "grab" | "release", slider: number, } | { action_type: "move", slider: number, new_value: number, } const Sliders: React.FC = () => { const ws = useRef(); const reconnectInterval = useRef(); const [state, setState] = useState(); const connect = () => { // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState if (ws.current !== undefined && ws.current.readyState !== 3) return; const wsURL = new URL("ws", window.location.href); wsURL.protocol = wsURL.protocol.replace("http", "ws"); ws.current = new WebSocket(wsURL.href); ws.current.onmessage = (ev) => { setState(JSON.parse(ev.data)); } } useEffect(() => { connect(); reconnectInterval.current = window.setInterval(connect, 1000); return () => { if (reconnectInterval.current !== undefined) window.clearInterval(reconnectInterval.current); if (ws.current !== undefined) ws.current.close(); }; }, []); const cb = (action: ClientAction) => { if (ws.current !== undefined && ws.current.readyState !== 3) { ws.current.send(JSON.stringify({ action: action, })); } } return <> {state?.map((item, index) => )} } const styleOverride = { "& .MuiSlider-track": { transition: "none" }, "& .MuiSlider-thumb": { transition: "none" }, }; const Slider: React.FC<{ item: StateItem, index: number, cb: (action: ClientAction) => void, }> = ({ item, index, cb }) => { const disabled = item.status === "locked"; const [value, setValue] = useState(item.value); useEffect(() => { if (item.status !== "owned") setValue(item.value); }, [item]); const onChange = (n: number) => { setValue(n); cb({ action_type: "move", slider: index, new_value: n, }); }; const onGrab = () => { cb({ action_type: "grab", slider: index, }); }; const onRelease = () => { cb({ action_type: "release", slider: index, }); }; return { onChange(n as number) }} onMouseDown={onGrab} onTouchStart={onGrab} onMouseUp={onRelease} onTouchEnd={onRelease} /> }; export default Sliders;