Refactored to use reaction and redaction events

Signed-off-by: Milton Moura <miltonmoura@gmail.com>
This commit is contained in:
Milton Moura
2024-09-08 00:57:45 +00:00
parent 48cf487e0a
commit 2d1917c22a

View File

@@ -10,14 +10,11 @@ import {
RoomContext, RoomContext,
useLocalParticipant, useLocalParticipant,
} from "@livekit/components-react"; } from "@livekit/components-react";
import { ConnectionState, Room } from "livekit-client";
import { import {
ConnectionState, MatrixEvent,
// eslint-disable-next-line camelcase RoomEvent as MatrixRoomEvent,
DataPacket_Kind, } from "matrix-js-sdk/src/matrix";
Participant,
Room,
RoomEvent,
} from "livekit-client";
import { MatrixClient } from "matrix-js-sdk/src/client"; import { MatrixClient } from "matrix-js-sdk/src/client";
import { import {
FC, FC,
@@ -37,6 +34,8 @@ import classNames from "classnames";
import { BehaviorSubject, of } from "rxjs"; import { BehaviorSubject, of } from "rxjs";
import { useObservableEagerState } from "observable-hooks"; import { useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { EventType, RelationType } from "matrix-js-sdk/src/matrix";
import { ReactionEventContent } from "matrix-js-sdk/src/types";
import LogoMark from "../icons/LogoMark.svg?react"; import LogoMark from "../icons/LogoMark.svg?react";
import LogoType from "../icons/LogoType.svg?react"; import LogoType from "../icons/LogoType.svg?react";
@@ -87,6 +86,7 @@ import { makeSpotlightExpandedLayout } from "../grid/SpotlightExpandedLayout";
import { makeSpotlightLandscapeLayout } from "../grid/SpotlightLandscapeLayout"; import { makeSpotlightLandscapeLayout } from "../grid/SpotlightLandscapeLayout";
import { makeSpotlightPortraitLayout } from "../grid/SpotlightPortraitLayout"; import { makeSpotlightPortraitLayout } from "../grid/SpotlightPortraitLayout";
import { RaisedHandsProvider, useRaisedHands } from "./useRaisedHands"; import { RaisedHandsProvider, useRaisedHands } from "./useRaisedHands";
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
@@ -309,33 +309,36 @@ export const InCallView: FC<InCallViewProps> = ({
[vm], [vm],
); );
const memberships = useMatrixRTCSessionMemberships(rtcSession);
const { raisedHands, setRaisedHands } = useRaisedHands(); const { raisedHands, setRaisedHands } = useRaisedHands();
const isHandRaised = raisedHands.includes( const [reactionId, setReactionId] = useState<string | null>(null);
localParticipant.identity.split(":")[0] + const [username, localpart] = localParticipant.identity.split(":");
":" + const userId = `${username}:${localpart}`;
localParticipant.identity.split(":")[1], const isHandRaised = raisedHands.includes(userId);
);
useEffect(() => { useEffect(() => {
const handleDataReceived = ( const handleReactionEvent = (event: MatrixEvent): void => {
payload: Uint8Array, if (event.getType() === EventType.Reaction) {
participant?: Participant, // TODO: check if target of reaction is a call membership event
// eslint-disable-next-line camelcase const content = event.getContent() as ReactionEventContent;
kind?: DataPacket_Kind, if (content?.["m.relates_to"].key === "🖐️") {
): void => { setRaisedHands([...raisedHands, event.getSender()!]);
const decoder = new TextDecoder(); }
const strData = decoder.decode(payload); }
// get json object from strData if (event.getType() === EventType.RoomRedaction) {
const data = JSON.parse(strData); // TODO: check target of redaction event
setRaisedHands(data.raisedHands); setRaisedHands(raisedHands.filter((id) => id !== event.getSender()));
}
}; };
livekitRoom.on(RoomEvent.DataReceived, handleDataReceived); client.on(MatrixRoomEvent.Timeline, handleReactionEvent);
client.on(MatrixRoomEvent.Redaction, handleReactionEvent);
return (): void => { return (): void => {
livekitRoom.off(RoomEvent.DataReceived, handleDataReceived); client.on(MatrixRoomEvent.Timeline, handleReactionEvent);
client.off(MatrixRoomEvent.Redaction, handleReactionEvent);
}; };
}, [livekitRoom, setRaisedHands]); }, [client, raisedHands, setRaisedHands]);
useEffect(() => { useEffect(() => {
widget?.api.transport widget?.api.transport
@@ -518,35 +521,54 @@ export const InCallView: FC<InCallViewProps> = ({
.catch(logger.error); .catch(logger.error);
}, [localParticipant, isScreenShareEnabled]); }, [localParticipant, isScreenShareEnabled]);
const toggleRaisedHand = useCallback(() => { const toggleRaisedHand = useCallback(async () => {
// TODO: wtf
const userId =
localParticipant.identity.split(":")[0] +
":" +
localParticipant.identity.split(":")[1];
const raisedHand = raisedHands.includes(userId);
let result = raisedHands;
if (raisedHand) {
result = raisedHands.filter((id) => id !== userId);
} else {
result = [...raisedHands, userId];
}
try { try {
const strData = JSON.stringify({ if (isHandRaised) {
raisedHands: result, try {
}); if (reactionId) {
const encoder = new TextEncoder(); await client.redactEvent(rtcSession.room.roomId, reactionId);
const data = encoder.encode(strData); setReactionId(null);
livekitRoom.localParticipant.publishData(data, { reliable: true }); setRaisedHands(raisedHands.filter((id) => id !== userId));
setRaisedHands(result); logger.debug("Redacted reaction event");
}
} catch (e) {
logger.error("Failed to redact reaction event", e);
}
} else {
const m = memberships.filter((m) => m.sender === userId);
const eventId = m[0].eventId!;
try {
const reaction = await client.sendEvent(
rtcSession.room.roomId,
EventType.Reaction,
{
"m.relates_to": {
rel_type: RelationType.Annotation,
event_id: eventId,
key: "🖐️",
},
},
);
setReactionId(reaction.event_id);
setRaisedHands([...raisedHands, userId]);
logger.debug("Sent reaction event", reaction.event_id);
} catch (e) {
logger.error("Failed to send reaction event", e);
}
}
} catch (e) { } catch (e) {
logger.error(e); logger.error(e);
} }
}, [ }, [
livekitRoom.localParticipant, client,
localParticipant.identity, isHandRaised,
memberships,
raisedHands, raisedHands,
reactionId,
rtcSession.room.roomId,
setRaisedHands, setRaisedHands,
setReactionId,
userId,
]); ]);
let footer: JSX.Element | null; let footer: JSX.Element | null;