mirror of
https://github.com/vector-im/element-call.git
synced 2026-03-31 07:00:26 +00:00
Fix redactions not working because they pick up events in transit.
This commit is contained in:
@@ -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,
|
||||
]);
|
||||
|
||||
|
||||
@@ -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,
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user