-
Notifications
You must be signed in to change notification settings - Fork 0
/
useParticipantPositions.tsx
60 lines (55 loc) · 2.18 KB
/
useParticipantPositions.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { useEffect, useState } from 'react';
import { Participant, Track, LocalDataTrack } from 'twilio-video';
import useParticipants from '../useParticipants/useParticipants';
import useVideoContext from '../useVideoContext/useVideoContext';
export interface Position {
x: number;
y: number;
}
export type ParticipantPositions = Record<Participant.SID, Position>;
// TODO: Remove existing pattern of abusing useState hook to "select" data from larger room context.
// Effects for subcsribing to events should all be centralized into a single hook.
// Mutable twilio room state should be recreated as an immutable version in the top-level component's state.
export default function useParticipantPositions() {
const {
room: { localParticipant },
localTracks,
} = useVideoContext();
const participants = useParticipants();
const [participantPositions, setParticipantPositions] = useState<ParticipantPositions>({});
useEffect(() => {
// Send current position if a new participant is added (although this sends it whenever there is any change in list of participants)
if (localParticipant && participantPositions[localParticipant.sid]) {
const dataTrack = localTracks.find(track => track.kind === 'data') as LocalDataTrack | null;
const localPosition = participantPositions[localParticipant.sid];
dataTrack?.send(`${localPosition.x},${localPosition.y}`);
}
participants.forEach(participant => {
participant.on('trackSubscribed', (track: Track) => {
if (track.kind === 'data') {
track.on('message', data => {
const [x, y] = data.split(',');
setParticipantPositions(prevParticipantPositions => {
return {
...prevParticipantPositions,
[participant.sid]: {
x,
y,
},
};
});
});
}
});
});
return () => {
participants.forEach(participant => {
participant.removeAllListeners('trackSubscribed');
});
};
}, [localParticipant, localTracks, participantPositions, participants]);
return {
participantPositions,
setParticipantPositions,
};
}