Handle cases when a new member event happens.

This commit is contained in:
Half-Shot
2024-10-29 15:08:59 +00:00
parent 0b6cf18d22
commit 528e692d6b
2 changed files with 42 additions and 10 deletions

View File

@@ -99,19 +99,20 @@ export function RaiseHandToggleButton({
logger.error("Cannot find own membership event"); logger.error("Cannot find own membership event");
return; return;
} }
const parentEventId = myMembership.eventId;
setBusy(true); setBusy(true);
client client
.sendEvent(rtcSession.room.roomId, EventType.Reaction, { .sendEvent(rtcSession.room.roomId, EventType.Reaction, {
"m.relates_to": { "m.relates_to": {
rel_type: RelationType.Annotation, rel_type: RelationType.Annotation,
event_id: myMembership.eventId, event_id: parentEventId,
key: "🖐️", key: "🖐️",
}, },
}) })
.then((reaction) => { .then((reaction) => {
logger.debug("Sent raise hand event", reaction.event_id); logger.debug("Sent raise hand event", reaction.event_id);
setMyReactionId(reaction.event_id); setMyReactionId(reaction.event_id);
addRaisedHand(userId, new Date()); addRaisedHand(userId, parentEventId, new Date());
}) })
.catch((e) => { .catch((e) => {
logger.error("Failed to send reaction event", e); logger.error("Failed to send reaction event", e);

View File

@@ -19,6 +19,7 @@ import {
ReactNode, ReactNode,
useCallback, useCallback,
useEffect, useEffect,
useMemo,
} from "react"; } from "react";
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
@@ -28,7 +29,7 @@ import { useClientState } from "./ClientContext";
interface ReactionsContextType { interface ReactionsContextType {
raisedHands: Record<string, Date>; raisedHands: Record<string, Date>;
raisedHandCount: number; raisedHandCount: number;
addRaisedHand: (userId: string, date: Date) => void; addRaisedHand: (userId: string, parentEventId: string, date: Date) => void;
removeRaisedHand: (userId: string) => void; removeRaisedHand: (userId: string) => void;
supportsReactions: boolean; supportsReactions: boolean;
myReactionId: string | null; myReactionId: string | null;
@@ -54,7 +55,15 @@ export const ReactionsProvider = ({
children: ReactNode; children: ReactNode;
rtcSession: MatrixRTCSession; rtcSession: MatrixRTCSession;
}): JSX.Element => { }): JSX.Element => {
const [raisedHands, setRaisedHands] = useState<Record<string, Date>>({}); const [raisedHands, setRaisedHands] = useState<
Record<
string,
{
time: Date;
parentEventId: string;
}
>
>({});
const [myReactionId, setMyReactionId] = useState<string | null>(null); const [myReactionId, setMyReactionId] = useState<string | null>(null);
const [raisedHandCount, setRaisedHandCount] = useState(0); const [raisedHandCount, setRaisedHandCount] = useState(0);
const memberships = useMatrixRTCSessionMemberships(rtcSession); const memberships = useMatrixRTCSessionMemberships(rtcSession);
@@ -64,10 +73,13 @@ export const ReactionsProvider = ({
const room = rtcSession.room; const room = rtcSession.room;
const addRaisedHand = useCallback( const addRaisedHand = useCallback(
(userId: string, time: Date) => { (userId: string, parentEventId: string, time: Date) => {
setRaisedHands({ setRaisedHands({
...raisedHands, ...raisedHands,
[userId]: time, [userId]: {
time,
parentEventId,
},
}); });
setRaisedHandCount(Object.keys(raisedHands).length + 1); setRaisedHandCount(Object.keys(raisedHands).length + 1);
}, },
@@ -77,6 +89,9 @@ export const ReactionsProvider = ({
const removeRaisedHand = useCallback( const removeRaisedHand = useCallback(
(userId: string) => { (userId: string) => {
delete raisedHands[userId]; delete raisedHands[userId];
if (userId) {
setMyReactionId(null);
}
setRaisedHands(raisedHands); setRaisedHands(raisedHands);
setRaisedHandCount(Object.keys(raisedHands).length); setRaisedHandCount(Object.keys(raisedHands).length);
}, },
@@ -99,6 +114,10 @@ export const ReactionsProvider = ({
if (!m.sender || !m.eventId) { if (!m.sender || !m.eventId) {
continue; continue;
} }
if (raisedHands[m.sender].parentEventId !== m.eventId) {
// Membership event for sender has changed.
removeRaisedHand(m.sender);
}
const reaction = getLastReactionEvent(m.eventId); const reaction = getLastReactionEvent(m.eventId);
const eventId = reaction?.getId(); const eventId = reaction?.getId();
if (!eventId) { if (!eventId) {
@@ -107,7 +126,7 @@ export const ReactionsProvider = ({
if (reaction && reaction.getType() === EventType.Reaction) { if (reaction && reaction.getType() === EventType.Reaction) {
const content = reaction.getContent() as ReactionEventContent; const content = reaction.getContent() as ReactionEventContent;
if (content?.["m.relates_to"]?.key === "🖐️") { if (content?.["m.relates_to"]?.key === "🖐️") {
addRaisedHand(m.sender, new Date(reaction.localTimestamp)); addRaisedHand(m.sender, m.eventId, new Date(reaction.localTimestamp));
if (m.sender === room.client.getUserId()) { if (m.sender === room.client.getUserId()) {
setMyReactionId(eventId); setMyReactionId(eventId);
} }
@@ -116,7 +135,7 @@ export const ReactionsProvider = ({
} }
// Deliberately ignoring addRaisedHand which was causing looping. // Deliberately ignoring addRaisedHand which was causing looping.
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [room, memberships]); }, [raisedHands, room, memberships]);
useEffect(() => { useEffect(() => {
const handleReactionEvent = (event: MatrixEvent): void => { const handleReactionEvent = (event: MatrixEvent): void => {
@@ -129,7 +148,11 @@ export const ReactionsProvider = ({
// TODO: check if target of reaction is a call membership event // TODO: check if target of reaction is a call membership event
const content = event.getContent() as ReactionEventContent; const content = event.getContent() as ReactionEventContent;
if (content?.["m.relates_to"].key === "🖐️") { if (content?.["m.relates_to"].key === "🖐️") {
addRaisedHand(sender, new Date(event.localTimestamp)); addRaisedHand(
sender,
content["m.relates_to"].event_id,
new Date(event.localTimestamp),
);
} }
} else if (event.getType() === EventType.RoomRedaction) { } else if (event.getType() === EventType.RoomRedaction) {
// TODO: check target of redaction event // TODO: check target of redaction event
@@ -146,10 +169,18 @@ export const ReactionsProvider = ({
}; };
}, [room, addRaisedHand, removeRaisedHand]); }, [room, addRaisedHand, removeRaisedHand]);
const resultRaisedHands = useMemo(
() =>
Object.fromEntries(
Object.entries(raisedHands).map(([uid, data]) => [uid, data.time]),
),
[raisedHands],
);
return ( return (
<ReactionsContext.Provider <ReactionsContext.Provider
value={{ value={{
raisedHands, raisedHands: resultRaisedHands,
raisedHandCount, raisedHandCount,
addRaisedHand, addRaisedHand,
removeRaisedHand, removeRaisedHand,