mirror of
https://github.com/vector-im/element-call.git
synced 2026-07-30 19:39:22 +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 { useReactions } from "../useReactions";
|
||||||
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";
|
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";
|
||||||
|
|
||||||
interface InnerButtonButtonProps extends ComponentPropsWithoutRef<"button"> {
|
interface InnerButtonProps extends ComponentPropsWithoutRef<"button"> {
|
||||||
raised: boolean;
|
raised: boolean;
|
||||||
}
|
}
|
||||||
const InnerButton: FC<InnerButtonButtonProps> = ({ raised, ...props }) => {
|
|
||||||
|
const InnerButton: FC<InnerButtonProps> = ({ raised, ...props }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -37,7 +38,7 @@ const InnerButton: FC<InnerButtonButtonProps> = ({ raised, ...props }) => {
|
|||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
role="img"
|
role="img"
|
||||||
aria-label="raised hand"
|
aria-hidden
|
||||||
style={{
|
style={{
|
||||||
width: "30px",
|
width: "30px",
|
||||||
height: "0px",
|
height: "0px",
|
||||||
@@ -52,7 +53,7 @@ const InnerButton: FC<InnerButtonButtonProps> = ({ raised, ...props }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface RaisedHandToggleButton {
|
interface RaisedHandToggleButtonProps {
|
||||||
rtcSession: MatrixRTCSession;
|
rtcSession: MatrixRTCSession;
|
||||||
client: MatrixClient;
|
client: MatrixClient;
|
||||||
}
|
}
|
||||||
@@ -60,30 +61,27 @@ interface RaisedHandToggleButton {
|
|||||||
export function RaiseHandToggleButton({
|
export function RaiseHandToggleButton({
|
||||||
client,
|
client,
|
||||||
rtcSession,
|
rtcSession,
|
||||||
}: RaisedHandToggleButton): ReactNode {
|
}: RaisedHandToggleButtonProps): ReactNode {
|
||||||
const { raisedHands, removeRaisedHand, addRaisedHand, myReactionId } =
|
const { raisedHands, myReactionId } = useReactions();
|
||||||
useReactions();
|
|
||||||
const [busy, setBusy] = useState(false);
|
const [busy, setBusy] = useState(false);
|
||||||
const userId = client.getUserId()!;
|
const userId = client.getUserId()!;
|
||||||
const isHandRaised = !!raisedHands[userId];
|
const isHandRaised = !!raisedHands[userId];
|
||||||
const memberships = useMatrixRTCSessionMemberships(rtcSession);
|
const memberships = useMatrixRTCSessionMemberships(rtcSession);
|
||||||
|
|
||||||
const toggleRaisedHand = useCallback(() => {
|
const toggleRaisedHand = useCallback(async () => {
|
||||||
if (isHandRaised) {
|
if (isHandRaised) {
|
||||||
if (myReactionId) {
|
if (!myReactionId) {
|
||||||
|
logger.warn(`Hand raised but no reaction event to redact!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
client
|
await client.redactEvent(rtcSession.room.roomId, myReactionId);
|
||||||
.redactEvent(rtcSession.room.roomId, myReactionId)
|
logger.debug("Redacted raise hand event");
|
||||||
.then(() => {
|
} catch (ex) {
|
||||||
logger.debug("Redacted raise hand event");
|
logger.error("Failed to redact reaction event", myReactionId, ex);
|
||||||
removeRaisedHand(userId);
|
} finally {
|
||||||
})
|
setBusy(false);
|
||||||
.catch((e) => {
|
|
||||||
logger.error("Failed to redact reaction event", e);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setBusy(false);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const myMembership = memberships.find((m) => m.sender === userId);
|
const myMembership = memberships.find((m) => m.sender === userId);
|
||||||
@@ -92,29 +90,25 @@ export function RaiseHandToggleButton({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const parentEventId = myMembership.eventId;
|
const parentEventId = myMembership.eventId;
|
||||||
setBusy(true);
|
try {
|
||||||
client
|
setBusy(true);
|
||||||
.sendEvent(rtcSession.room.roomId, EventType.Reaction, {
|
const reaction = await client.sendEvent(
|
||||||
"m.relates_to": {
|
rtcSession.room.roomId,
|
||||||
rel_type: RelationType.Annotation,
|
EventType.Reaction,
|
||||||
event_id: parentEventId,
|
{
|
||||||
key: "🖐️",
|
"m.relates_to": {
|
||||||
|
rel_type: RelationType.Annotation,
|
||||||
|
event_id: parentEventId,
|
||||||
|
key: "🖐️",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
);
|
||||||
.then((reaction) => {
|
logger.debug("Sent raise hand event", reaction.event_id);
|
||||||
logger.debug("Sent raise hand event", reaction.event_id);
|
} catch (ex) {
|
||||||
addRaisedHand(userId, {
|
logger.error("Failed to send reaction event", ex);
|
||||||
membershipEventId: parentEventId,
|
} finally {
|
||||||
reactionEventId: reaction.event_id,
|
setBusy(false);
|
||||||
time: new Date(),
|
}
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
logger.error("Failed to send reaction event", e);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setBusy(false);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
client,
|
client,
|
||||||
@@ -122,8 +116,6 @@ export function RaiseHandToggleButton({
|
|||||||
memberships,
|
memberships,
|
||||||
myReactionId,
|
myReactionId,
|
||||||
rtcSession.room.roomId,
|
rtcSession.room.roomId,
|
||||||
addRaisedHand,
|
|
||||||
removeRaisedHand,
|
|
||||||
userId,
|
userId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import { useClientState } from "./ClientContext";
|
|||||||
|
|
||||||
interface ReactionsContextType {
|
interface ReactionsContextType {
|
||||||
raisedHands: Record<string, Date>;
|
raisedHands: Record<string, Date>;
|
||||||
addRaisedHand: (userId: string, info: RaisedHandInfo) => void;
|
|
||||||
removeRaisedHand: (userId: string) => void;
|
|
||||||
supportsReactions: boolean;
|
supportsReactions: boolean;
|
||||||
myReactionId: string | null;
|
myReactionId: string | null;
|
||||||
}
|
}
|
||||||
@@ -99,23 +97,20 @@ export const ReactionsProvider = ({
|
|||||||
[raisedHands],
|
[raisedHands],
|
||||||
);
|
);
|
||||||
|
|
||||||
const addRaisedHand = useCallback(
|
const addRaisedHand = useCallback((userId: string, info: RaisedHandInfo) => {
|
||||||
(userId: string, info: RaisedHandInfo) => {
|
setRaisedHands((prevRaisedHands) => ({
|
||||||
setRaisedHands({
|
...prevRaisedHands,
|
||||||
...raisedHands,
|
[userId]: info,
|
||||||
[userId]: info,
|
}));
|
||||||
});
|
}, []);
|
||||||
},
|
|
||||||
[raisedHands],
|
|
||||||
);
|
|
||||||
|
|
||||||
const removeRaisedHand = useCallback(
|
const removeRaisedHand = useCallback((userId: string) => {
|
||||||
(userId: string) => {
|
delete raisedHands[userId];
|
||||||
delete raisedHands[userId];
|
setRaisedHands((prevRaisedHands) => {
|
||||||
setRaisedHands({ ...raisedHands });
|
delete prevRaisedHands[userId];
|
||||||
},
|
return { ...prevRaisedHands };
|
||||||
[raisedHands],
|
});
|
||||||
);
|
}, []);
|
||||||
|
|
||||||
// This effect will check the state whenever the membership of the session changes.
|
// This effect will check the state whenever the membership of the session changes.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -168,13 +163,16 @@ export const ReactionsProvider = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Deliberately ignoring addRaisedHand, raisedHands which was causing looping.
|
}, [room, memberships, addRaisedHand, removeRaisedHand]);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [room, memberships]);
|
|
||||||
|
|
||||||
// This effect handles any *live* reaction/redactions in the room.
|
// This effect handles any *live* reaction/redactions in the room.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleReactionEvent = (event: MatrixEvent): void => {
|
const handleReactionEvent = (event: MatrixEvent): void => {
|
||||||
|
if (event.isSending()) {
|
||||||
|
// Skip any events that are still sending.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const sender = event.getSender();
|
const sender = event.getSender();
|
||||||
const reactionEventId = event.getId();
|
const reactionEventId = event.getId();
|
||||||
if (!sender || !reactionEventId) {
|
if (!sender || !reactionEventId) {
|
||||||
@@ -222,9 +220,14 @@ export const ReactionsProvider = ({
|
|||||||
room.on(MatrixRoomEvent.Timeline, handleReactionEvent);
|
room.on(MatrixRoomEvent.Timeline, handleReactionEvent);
|
||||||
room.on(MatrixRoomEvent.Redaction, 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 => {
|
return (): void => {
|
||||||
room.off(MatrixRoomEvent.Timeline, handleReactionEvent);
|
room.off(MatrixRoomEvent.Timeline, handleReactionEvent);
|
||||||
room.off(MatrixRoomEvent.Redaction, handleReactionEvent);
|
room.off(MatrixRoomEvent.Redaction, handleReactionEvent);
|
||||||
|
room.off(MatrixRoomEvent.LocalEchoUpdated, handleReactionEvent);
|
||||||
};
|
};
|
||||||
}, [room, addRaisedHand, removeRaisedHand, memberships, raisedHands]);
|
}, [room, addRaisedHand, removeRaisedHand, memberships, raisedHands]);
|
||||||
|
|
||||||
@@ -232,8 +235,6 @@ export const ReactionsProvider = ({
|
|||||||
<ReactionsContext.Provider
|
<ReactionsContext.Provider
|
||||||
value={{
|
value={{
|
||||||
raisedHands: resultRaisedHands,
|
raisedHands: resultRaisedHands,
|
||||||
addRaisedHand,
|
|
||||||
removeRaisedHand,
|
|
||||||
supportsReactions,
|
supportsReactions,
|
||||||
myReactionId,
|
myReactionId,
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user