From a354a4013de6a2917ed021fa54adcf3b44283f04 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 31 Oct 2024 16:04:37 +0000 Subject: [PATCH] Fix redactions not working because they pick up events in transit. --- src/button/RaisedHandToggleButton.tsx | 82 ++++++++++++--------------- src/useReactions.tsx | 47 +++++++-------- 2 files changed, 61 insertions(+), 68 deletions(-) diff --git a/src/button/RaisedHandToggleButton.tsx b/src/button/RaisedHandToggleButton.tsx index 25bb3e70..01955651 100644 --- a/src/button/RaisedHandToggleButton.tsx +++ b/src/button/RaisedHandToggleButton.tsx @@ -22,10 +22,11 @@ import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; import { useReactions } from "../useReactions"; import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships"; -interface InnerButtonButtonProps extends ComponentPropsWithoutRef<"button"> { +interface InnerButtonProps extends ComponentPropsWithoutRef<"button"> { raised: boolean; } -const InnerButton: FC = ({ raised, ...props }) => { + +const InnerButton: FC = ({ raised, ...props }) => { const { t } = useTranslation(); return ( @@ -37,7 +38,7 @@ const InnerButton: FC = ({ raised, ...props }) => { >

= ({ raised, ...props }) => { ); }; -interface RaisedHandToggleButton { +interface RaisedHandToggleButtonProps { rtcSession: MatrixRTCSession; client: MatrixClient; } @@ -60,30 +61,27 @@ interface RaisedHandToggleButton { export function RaiseHandToggleButton({ client, rtcSession, -}: RaisedHandToggleButton): ReactNode { - const { raisedHands, removeRaisedHand, addRaisedHand, myReactionId } = - useReactions(); +}: RaisedHandToggleButtonProps): ReactNode { + const { raisedHands, myReactionId } = useReactions(); const [busy, setBusy] = useState(false); const userId = client.getUserId()!; const isHandRaised = !!raisedHands[userId]; const memberships = useMatrixRTCSessionMemberships(rtcSession); - const toggleRaisedHand = useCallback(() => { + const toggleRaisedHand = useCallback(async () => { if (isHandRaised) { - if (myReactionId) { + if (!myReactionId) { + logger.warn(`Hand raised but no reaction event to redact!`); + return; + } + try { setBusy(true); - client - .redactEvent(rtcSession.room.roomId, myReactionId) - .then(() => { - logger.debug("Redacted raise hand event"); - removeRaisedHand(userId); - }) - .catch((e) => { - logger.error("Failed to redact reaction event", e); - }) - .finally(() => { - setBusy(false); - }); + await client.redactEvent(rtcSession.room.roomId, myReactionId); + logger.debug("Redacted raise hand event"); + } catch (ex) { + logger.error("Failed to redact reaction event", myReactionId, ex); + } finally { + setBusy(false); } } else { const myMembership = memberships.find((m) => m.sender === userId); @@ -92,29 +90,25 @@ export function RaiseHandToggleButton({ return; } const parentEventId = myMembership.eventId; - setBusy(true); - client - .sendEvent(rtcSession.room.roomId, EventType.Reaction, { - "m.relates_to": { - rel_type: RelationType.Annotation, - event_id: parentEventId, - key: "🖐️", + try { + setBusy(true); + const reaction = await client.sendEvent( + rtcSession.room.roomId, + EventType.Reaction, + { + "m.relates_to": { + rel_type: RelationType.Annotation, + event_id: parentEventId, + key: "🖐️", + }, }, - }) - .then((reaction) => { - logger.debug("Sent raise hand event", reaction.event_id); - addRaisedHand(userId, { - membershipEventId: parentEventId, - reactionEventId: reaction.event_id, - time: new Date(), - }); - }) - .catch((e) => { - logger.error("Failed to send reaction event", e); - }) - .finally(() => { - setBusy(false); - }); + ); + logger.debug("Sent raise hand event", reaction.event_id); + } catch (ex) { + logger.error("Failed to send reaction event", ex); + } finally { + setBusy(false); + } } }, [ client, @@ -122,8 +116,6 @@ export function RaiseHandToggleButton({ memberships, myReactionId, rtcSession.room.roomId, - addRaisedHand, - removeRaisedHand, userId, ]); diff --git a/src/useReactions.tsx b/src/useReactions.tsx index 692d8ced..42827b56 100644 --- a/src/useReactions.tsx +++ b/src/useReactions.tsx @@ -29,8 +29,6 @@ import { useClientState } from "./ClientContext"; interface ReactionsContextType { raisedHands: Record; - addRaisedHand: (userId: string, info: RaisedHandInfo) => void; - removeRaisedHand: (userId: string) => void; supportsReactions: boolean; myReactionId: string | null; } @@ -99,23 +97,20 @@ export const ReactionsProvider = ({ [raisedHands], ); - const addRaisedHand = useCallback( - (userId: string, info: RaisedHandInfo) => { - setRaisedHands({ - ...raisedHands, - [userId]: info, - }); - }, - [raisedHands], - ); + const addRaisedHand = useCallback((userId: string, info: RaisedHandInfo) => { + setRaisedHands((prevRaisedHands) => ({ + ...prevRaisedHands, + [userId]: info, + })); + }, []); - const removeRaisedHand = useCallback( - (userId: string) => { - delete raisedHands[userId]; - setRaisedHands({ ...raisedHands }); - }, - [raisedHands], - ); + const removeRaisedHand = useCallback((userId: string) => { + delete raisedHands[userId]; + setRaisedHands((prevRaisedHands) => { + delete prevRaisedHands[userId]; + return { ...prevRaisedHands }; + }); + }, []); // This effect will check the state whenever the membership of the session changes. useEffect(() => { @@ -168,13 +163,16 @@ export const ReactionsProvider = ({ } } } - // Deliberately ignoring addRaisedHand, raisedHands which was causing looping. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [room, memberships]); + }, [room, memberships, addRaisedHand, removeRaisedHand]); // This effect handles any *live* reaction/redactions in the room. useEffect(() => { const handleReactionEvent = (event: MatrixEvent): void => { + if (event.isSending()) { + // Skip any events that are still sending. + return; + } + const sender = event.getSender(); const reactionEventId = event.getId(); if (!sender || !reactionEventId) { @@ -222,9 +220,14 @@ export const ReactionsProvider = ({ room.on(MatrixRoomEvent.Timeline, handleReactionEvent); room.on(MatrixRoomEvent.Redaction, handleReactionEvent); + // We listen for a local echo to get the real event ID, as timeline events + // may still be sending. + room.on(MatrixRoomEvent.LocalEchoUpdated, handleReactionEvent); + return (): void => { room.off(MatrixRoomEvent.Timeline, handleReactionEvent); room.off(MatrixRoomEvent.Redaction, handleReactionEvent); + room.off(MatrixRoomEvent.LocalEchoUpdated, handleReactionEvent); }; }, [room, addRaisedHand, removeRaisedHand, memberships, raisedHands]); @@ -232,8 +235,6 @@ export const ReactionsProvider = ({