Basic WS sync
This commit is contained in:
64
matrixgw_frontend/src/widgets/messages/MatrixWS.tsx
Normal file
64
matrixgw_frontend/src/widgets/messages/MatrixWS.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
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";
|
||||
|
||||
const State = {
|
||||
Closed: "Closed",
|
||||
Connected: "Connected",
|
||||
Error: "Error",
|
||||
} as const;
|
||||
|
||||
export function MatrixWS(p: {
|
||||
onMessage: (msg: WsMessage) => void;
|
||||
}): React.ReactElement {
|
||||
const snackbar = useSnackbar();
|
||||
|
||||
const [state, setState] = React.useState<string>(State.Closed);
|
||||
const wsRef = React.useRef<WebSocket | undefined>(undefined);
|
||||
const [connCount, setConnCount] = React.useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
const count = connCount;
|
||||
const ws = new WebSocket(WsApi.WsURL);
|
||||
wsRef.current = ws;
|
||||
|
||||
ws.onopen = () => setState(State.Connected);
|
||||
ws.onerror = (e) => {
|
||||
if (count != connCount) return;
|
||||
|
||||
console.error(`WS Debug error!`, e);
|
||||
snackbar(`WebSocket error!`);
|
||||
setState(State.Error);
|
||||
|
||||
setTimeout(() => setConnCount(connCount + 1), 500);
|
||||
};
|
||||
ws.onclose = () => {
|
||||
setState(State.Closed);
|
||||
wsRef.current = undefined;
|
||||
};
|
||||
|
||||
ws.onmessage = (msg) => {
|
||||
const dec = JSON.parse(msg.data);
|
||||
console.info("WS message", dec);
|
||||
p.onMessage(dec);
|
||||
};
|
||||
|
||||
return () => ws.close();
|
||||
}, [connCount]);
|
||||
|
||||
return (
|
||||
<Tooltip title={state}>
|
||||
<CircleIcon
|
||||
color={
|
||||
state === State.Connected
|
||||
? "success"
|
||||
: state === State.Error
|
||||
? "error"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -2,8 +2,10 @@ import React from "react";
|
||||
import { MatrixApiEvent } from "../../api/matrix/MatrixApiEvent";
|
||||
import type { UsersMap } from "../../api/matrix/MatrixApiProfile";
|
||||
import type { Room } from "../../api/matrix/MatrixApiRoom";
|
||||
import type { WsMessage } from "../../api/WsApi";
|
||||
import { RoomEventsManager } from "../../utils/RoomEventsManager";
|
||||
import { AsyncWidget } from "../AsyncWidget";
|
||||
import { MatrixWS } from "./MatrixWS";
|
||||
import { RoomMessagesList } from "./RoomMessagesList";
|
||||
import { SendMessageForm } from "./SendMessageForm";
|
||||
|
||||
@@ -11,6 +13,7 @@ export function RoomWidget(p: {
|
||||
room: Room;
|
||||
users: UsersMap;
|
||||
}): React.ReactElement {
|
||||
const [_count, setCount] = React.useState(0);
|
||||
const [roomMgr, setRoomMgr] = React.useState<undefined | RoomEventsManager>();
|
||||
|
||||
const load = async () => {
|
||||
@@ -20,6 +23,10 @@ export function RoomWidget(p: {
|
||||
setRoomMgr(mgr);
|
||||
};
|
||||
|
||||
const handleNewMessage = (m: WsMessage) => {
|
||||
if (roomMgr?.processWsMessage(m)) setCount((c) => c + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<AsyncWidget
|
||||
loadKey={p.room.id}
|
||||
@@ -28,6 +35,9 @@ export function RoomWidget(p: {
|
||||
errMsg="Failed to load room!"
|
||||
build={() => (
|
||||
<div style={{ display: "flex", flexDirection: "column", flex: 1 }}>
|
||||
<div style={{ position: "absolute", right: "0px", padding: "10px" }}>
|
||||
<MatrixWS onMessage={handleNewMessage} />
|
||||
</div>
|
||||
<RoomMessagesList mgr={roomMgr!} {...p} />
|
||||
<SendMessageForm {...p} />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user