Follow unread messages

This commit is contained in:
2025-11-28 18:06:40 +01:00
parent d10c4d1a1c
commit a656c077bc
3 changed files with 56 additions and 16 deletions

View File

@@ -6,7 +6,10 @@ import {
} from "../../api/matrix/MatrixApiProfile"; } from "../../api/matrix/MatrixApiProfile";
import { MatrixApiRoom, type Room } from "../../api/matrix/MatrixApiRoom"; import { MatrixApiRoom, type Room } from "../../api/matrix/MatrixApiRoom";
import { MatrixSyncApi } from "../../api/MatrixSyncApi"; import { MatrixSyncApi } from "../../api/MatrixSyncApi";
import type { WsMessage } from "../../api/WsApi";
import { AsyncWidget } from "../AsyncWidget"; import { AsyncWidget } from "../AsyncWidget";
import { useUserInfo } from "../dashboard/BaseAuthenticatedPage";
import { MatrixWS } from "./MatrixWS";
import { RoomSelector } from "./RoomSelector"; import { RoomSelector } from "./RoomSelector";
import { RoomWidget } from "./RoomWidget"; import { RoomWidget } from "./RoomWidget";
import { SpaceSelector } from "./SpaceSelector"; import { SpaceSelector } from "./SpaceSelector";
@@ -14,6 +17,7 @@ import { SpaceSelector } from "./SpaceSelector";
export function MainMessageWidget(): React.ReactElement { export function MainMessageWidget(): React.ReactElement {
const [rooms, setRooms] = React.useState<Room[] | undefined>(); const [rooms, setRooms] = React.useState<Room[] | undefined>();
const [users, setUsers] = React.useState<UsersMap | undefined>(); const [users, setUsers] = React.useState<UsersMap | undefined>();
const user = useUserInfo();
const load = async () => { const load = async () => {
await MatrixSyncApi.Start(); await MatrixSyncApi.Start();
@@ -30,13 +34,39 @@ export function MainMessageWidget(): React.ReactElement {
setUsers(await MatrixApiProfile.GetMultiple([...users])); 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 ( return (
<AsyncWidget <AsyncWidget
loadKey={1} loadKey={1}
load={load} load={load}
ready={!!rooms && !!users} ready={!!rooms && !!users}
errMsg="Failed to initialize messaging component!" errMsg="Failed to initialize messaging component!"
build={() => <_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: { function _MainMessageWidget(p: {
rooms: Room[]; rooms: Room[];
users: UsersMap; users: UsersMap;
onEvent: (m: WsMessage) => void;
}): React.ReactElement { }): React.ReactElement {
const [space, setSpace] = React.useState<string | undefined>(); const [space, setSpace] = React.useState<string | undefined>();
const [room, setRoom] = React.useState<Room | undefined>(); const [room, setRoom] = React.useState<Room | undefined>();
@@ -68,16 +99,19 @@ function _MainMessageWidget(p: {
/> />
<Divider orientation="vertical" /> <Divider orientation="vertical" />
{room === undefined && ( {room === undefined && (
<div <>
style={{ <MatrixWS onMessage={p.onEvent} />
display: "flex", <div
justifyContent: "center", style={{
alignItems: "center", display: "flex",
flex: 1, justifyContent: "center",
}} alignItems: "center",
> flex: 1,
No room selected. }}
</div> >
No room selected.
</div>
</>
)} )}
{room && <RoomWidget {...p} room={room} />} {room && <RoomWidget {...p} room={room} />}
</div> </div>

View File

@@ -16,17 +16,17 @@ export function MatrixWS(p: {
const snackbar = useSnackbar(); const snackbar = useSnackbar();
const [state, setState] = React.useState<string>(State.Closed); const [state, setState] = React.useState<string>(State.Closed);
const wsRef = React.useRef<WebSocket | undefined>(undefined); const wsId = React.useRef<number | undefined>(undefined);
const [connCount, setConnCount] = React.useState(0); const [connCount, setConnCount] = React.useState(0);
React.useEffect(() => { React.useEffect(() => {
const count = connCount; const id = Math.random();
const ws = new WebSocket(WsApi.WsURL); const ws = new WebSocket(WsApi.WsURL);
wsRef.current = ws; wsId.current = id;
ws.onopen = () => setState(State.Connected); ws.onopen = () => setState(State.Connected);
ws.onerror = (e) => { ws.onerror = (e) => {
if (count != connCount) return; if (wsId.current != id) return;
console.error(`WS Debug error!`, e); console.error(`WS Debug error!`, e);
snackbar(`WebSocket error!`); snackbar(`WebSocket error!`);
@@ -34,12 +34,16 @@ export function MatrixWS(p: {
setTimeout(() => setConnCount(connCount + 1), 500); setTimeout(() => setConnCount(connCount + 1), 500);
}; };
ws.onclose = () => { ws.onclose = () => {
if (wsId.current !== id) return;
setState(State.Closed); setState(State.Closed);
wsRef.current = undefined; wsId.current = undefined;
}; };
ws.onmessage = (msg) => { ws.onmessage = (msg) => {
if (wsId.current !== id) return;
const dec = JSON.parse(msg.data); const dec = JSON.parse(msg.data);
console.info("WS message", dec); console.info("WS message", dec);
p.onMessage(dec); p.onMessage(dec);

View File

@@ -12,6 +12,7 @@ import { SendMessageForm } from "./SendMessageForm";
export function RoomWidget(p: { export function RoomWidget(p: {
room: Room; room: Room;
users: UsersMap; users: UsersMap;
onEvent: (m: WsMessage) => void;
}): React.ReactElement { }): React.ReactElement {
const [_count, setCount] = React.useState(0); const [_count, setCount] = React.useState(0);
const [roomMgr, setRoomMgr] = React.useState<undefined | RoomEventsManager>(); const [roomMgr, setRoomMgr] = React.useState<undefined | RoomEventsManager>();
@@ -25,6 +26,7 @@ export function RoomWidget(p: {
const handleNewMessage = (m: WsMessage) => { const handleNewMessage = (m: WsMessage) => {
if (roomMgr?.processWsMessage(m)) setCount((c) => c + 1); if (roomMgr?.processWsMessage(m)) setCount((c) => c + 1);
p.onEvent(m);
}; };
return ( return (