Fix redactions not working because they pick up events in transit.

This commit is contained in:
Half-Shot
2024-10-31 16:04:37 +00:00
parent 7229f4bf1b
commit a354a4013d
2 changed files with 61 additions and 68 deletions

View File

@@ -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<InnerButtonButtonProps> = ({ raised, ...props }) => {
const InnerButton: FC<InnerButtonProps> = ({ raised, ...props }) => {
const { t } = useTranslation();
return (
@@ -37,7 +38,7 @@ const InnerButton: FC<InnerButtonButtonProps> = ({ raised, ...props }) => {
>
<p
role="img"
aria-label="raised hand"
aria-hidden
style={{
width: "30px",
height: "0px",
@@ -52,7 +53,7 @@ const InnerButton: FC<InnerButtonButtonProps> = ({ 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,
]);

View File

@@ -29,8 +29,6 @@ import { useClientState } from "./ClientContext";
interface ReactionsContextType {
raisedHands: Record<string, Date>;
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 = ({
<ReactionsContext.Provider
value={{
raisedHands: resultRaisedHands,
addRaisedHand,
removeRaisedHand,
supportsReactions,
myReactionId,
}}