From a656c077bcd768920bb3102dbb44ce8c810469f4 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Fri, 28 Nov 2025 18:06:40 +0100 Subject: [PATCH] Follow unread messages --- .../widgets/messages/MainMessagesWidget.tsx | 56 +++++++++++++++---- .../src/widgets/messages/MatrixWS.tsx | 14 +++-- .../src/widgets/messages/RoomWidget.tsx | 2 + 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx index d8ec52a..c268ff2 100644 --- a/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx +++ b/matrixgw_frontend/src/widgets/messages/MainMessagesWidget.tsx @@ -6,7 +6,10 @@ import { } from "../../api/matrix/MatrixApiProfile"; import { MatrixApiRoom, type Room } from "../../api/matrix/MatrixApiRoom"; import { MatrixSyncApi } from "../../api/MatrixSyncApi"; +import type { WsMessage } from "../../api/WsApi"; import { AsyncWidget } from "../AsyncWidget"; +import { useUserInfo } from "../dashboard/BaseAuthenticatedPage"; +import { MatrixWS } from "./MatrixWS"; import { RoomSelector } from "./RoomSelector"; import { RoomWidget } from "./RoomWidget"; import { SpaceSelector } from "./SpaceSelector"; @@ -14,6 +17,7 @@ import { SpaceSelector } from "./SpaceSelector"; export function MainMessageWidget(): React.ReactElement { const [rooms, setRooms] = React.useState(); const [users, setUsers] = React.useState(); + const user = useUserInfo(); const load = async () => { await MatrixSyncApi.Start(); @@ -30,13 +34,39 @@ export function MainMessageWidget(): React.ReactElement { setUsers(await MatrixApiProfile.GetMultiple([...users])); }; + const handleEvent = (m: WsMessage) => { + // Add a new unread message + if ( + m.type === "RoomMessageEvent" && + !m.data["m.new_content"] && + m.sender !== user.info.matrix_user_id + ) { + setRooms((r) => { + const n = r ? [...r] : undefined; + const idx = n?.findIndex((el) => el.id === m.room_id); + if (idx) + n![idx] = { + ...n![idx], + number_unread_messages: n![idx].number_unread_messages + 1, + }; + return n; + }); + } + }; + return ( <_MainMessageWidget rooms={rooms!} users={users!} />} + build={() => ( + <_MainMessageWidget + rooms={rooms!} + users={users!} + onEvent={handleEvent} + /> + )} /> ); } @@ -44,6 +74,7 @@ export function MainMessageWidget(): React.ReactElement { function _MainMessageWidget(p: { rooms: Room[]; users: UsersMap; + onEvent: (m: WsMessage) => void; }): React.ReactElement { const [space, setSpace] = React.useState(); const [room, setRoom] = React.useState(); @@ -68,16 +99,19 @@ function _MainMessageWidget(p: { /> {room === undefined && ( -
- No room selected. -
+ <> + +
+ No room selected. +
+ )} {room && } diff --git a/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx b/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx index 8d826de..169c354 100644 --- a/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx +++ b/matrixgw_frontend/src/widgets/messages/MatrixWS.tsx @@ -16,17 +16,17 @@ export function MatrixWS(p: { const snackbar = useSnackbar(); const [state, setState] = React.useState(State.Closed); - const wsRef = React.useRef(undefined); + const wsId = React.useRef(undefined); const [connCount, setConnCount] = React.useState(0); React.useEffect(() => { - const count = connCount; + const id = Math.random(); const ws = new WebSocket(WsApi.WsURL); - wsRef.current = ws; + wsId.current = id; ws.onopen = () => setState(State.Connected); ws.onerror = (e) => { - if (count != connCount) return; + if (wsId.current != id) return; console.error(`WS Debug error!`, e); snackbar(`WebSocket error!`); @@ -34,12 +34,16 @@ export function MatrixWS(p: { setTimeout(() => setConnCount(connCount + 1), 500); }; + ws.onclose = () => { + if (wsId.current !== id) return; setState(State.Closed); - wsRef.current = undefined; + wsId.current = undefined; }; ws.onmessage = (msg) => { + if (wsId.current !== id) return; + const dec = JSON.parse(msg.data); console.info("WS message", dec); p.onMessage(dec); diff --git a/matrixgw_frontend/src/widgets/messages/RoomWidget.tsx b/matrixgw_frontend/src/widgets/messages/RoomWidget.tsx index 4888f63..c231cce 100644 --- a/matrixgw_frontend/src/widgets/messages/RoomWidget.tsx +++ b/matrixgw_frontend/src/widgets/messages/RoomWidget.tsx @@ -12,6 +12,7 @@ import { SendMessageForm } from "./SendMessageForm"; export function RoomWidget(p: { room: Room; users: UsersMap; + onEvent: (m: WsMessage) => void; }): React.ReactElement { const [_count, setCount] = React.useState(0); const [roomMgr, setRoomMgr] = React.useState(); @@ -25,6 +26,7 @@ export function RoomWidget(p: { const handleNewMessage = (m: WsMessage) => { if (roomMgr?.processWsMessage(m)) setCount((c) => c + 1); + p.onEvent(m); }; return (