Follow unread messages
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
Reference in New Issue
Block a user