Files
MatrixGW/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx
Pierre HUBERT bbf558bbf9
Some checks failed
continuous-integration/drone/pr Build is failing
continuous-integration/drone/push Build is failing
WIP ESLint fixes
2025-12-03 11:16:14 +01:00

94 lines
2.3 KiB
TypeScript

import React from "react";
import { WsApi, type WsMessage } from "../../api/WsApi";
import { useSnackbar } from "../../hooks/contexts_provider/SnackbarProvider";
import CircleIcon from "@mui/icons-material/Circle";
import { Tooltip } from "@mui/material";
export const WSState = {
Closed: "Closed",
Connected: "Connected",
Error: "Error",
} as const;
export function MatrixWS(p: {
onMessage: (msg: WsMessage) => void;
onStateChange?: (state: string) => void;
}): React.ReactElement {
const snackbar = useSnackbar();
// Keep only the latest version of onMessage
const cbRef = React.useRef(p.onMessage);
React.useEffect(() => {
cbRef.current = p.onMessage;
}, [p.onMessage]);
// Keep only the latest version of onStateChange
const stateCbRef = React.useRef(p.onStateChange);
React.useEffect(() => {
stateCbRef.current = p.onStateChange;
}, [p.onStateChange]);
const [state, setState] = React.useState<string>(WSState.Closed);
const wsId = React.useRef<number | undefined>(undefined);
const [connCount, setConnCount] = React.useState(0);
React.useEffect(() => {
const id = Math.random();
const ws = new WebSocket(WsApi.WsURL);
wsId.current = id;
// Open
ws.onopen = () => {
if (wsId.current != id) return;
setState(WSState.Connected);
stateCbRef.current?.(WSState.Connected);
};
// Error
ws.onerror = (e) => {
if (wsId.current != id) return;
console.error(`WS Debug error!`, e);
snackbar(`WebSocket error!`);
setState(WSState.Error);
stateCbRef.current?.(WSState.Error);
setTimeout(() => setConnCount(connCount + 1), 500);
};
// Close
ws.onclose = () => {
if (wsId.current !== id) return;
setState(WSState.Closed);
stateCbRef.current?.(WSState.Closed);
wsId.current = undefined;
};
// Message
ws.onmessage = (msg) => {
if (wsId.current !== id) return;
const dec = JSON.parse(msg.data);
console.info("WS message", dec);
cbRef.current(dec);
};
return () => ws.close();
}, [connCount, snackbar]);
return (
<Tooltip title={state}>
<CircleIcon
color={
state === WSState.Connected
? "success"
: state === WSState.Error
? "error"
: undefined
}
/>
</Tooltip>
);
}