93 lines
2.6 KiB
JavaScript
93 lines
2.6 KiB
JavaScript
import equal from 'fast-deep-equal';
|
|
|
|
/**
|
|
* Call State
|
|
* ---
|
|
* Duck file that keeps state of call participants
|
|
*/
|
|
|
|
export const ACTION_PARTICIPANT_JOINED = 'ACTION_PARTICIPANT_JOINED';
|
|
export const ACTION_PARTICIPANT_UPDATED = 'ACTION_PARTICIPANT_UPDATED';
|
|
export const ACTION_PARTICIPANTED_LEFT = 'ACTION_PARTICIPANT_LEFT';
|
|
|
|
export const initialCallState = {
|
|
audioTracks: {},
|
|
videoTracks: {},
|
|
callItems: {},
|
|
fatalError: false,
|
|
};
|
|
|
|
function getId(participant) {
|
|
return participant.local ? 'local' : participant.user_id;
|
|
}
|
|
|
|
export function isLocal(id) {
|
|
return id === 'local';
|
|
}
|
|
|
|
function getCallItems(newParticipants, prevCallItems) {
|
|
const callItems = {};
|
|
const entries = Object.entries(newParticipants);
|
|
entries.forEach(([id, participant]) => {
|
|
const prevState = prevCallItems[id];
|
|
const hasLoaded = !prevState?.isLoading;
|
|
const missingTracks = !(participant.audioTrack || participant.videoTrack);
|
|
const joined = prevState?.joined || new Date().getTime() / 1000;
|
|
const local = isLocal(id);
|
|
|
|
callItems[id] = {
|
|
id,
|
|
name: participant.user_name || 'Guest',
|
|
audioTrack: participant.audioTrack,
|
|
videoTrack: participant.videoTrack,
|
|
hasNameSet: !!participant.user_name,
|
|
isActiveSpeaker: !!prevState?.isActiveSpeaker,
|
|
isCamMuted: !participant.video,
|
|
isLoading: !hasLoaded && missingTracks,
|
|
isLocal: local,
|
|
isMicMuted: !participant.audio,
|
|
isOwner: !!participant.owner,
|
|
isRecording: !!participant.record,
|
|
lastActiveDate: prevState?.lastActiveDate ?? null,
|
|
mutedByHost: participant?.tracks?.audio?.off?.byRemoteRequest,
|
|
isScreenshare: false,
|
|
joined,
|
|
};
|
|
|
|
if (participant.screenVideoTrack || participant.screenAudioTrack) {
|
|
callItems[`${id}-screen`] = {
|
|
audioTrack: participant.tracks.screenAudio.persistentTrack,
|
|
hasNameSet: null,
|
|
id: `${id}-screen`,
|
|
isLoading: false,
|
|
isLocal: local,
|
|
isScreenshare: true,
|
|
lastActiveDate: prevState?.lastActiveDate ?? null,
|
|
name: participant.user_name,
|
|
videoTrack: participant.screenVideoTrack,
|
|
};
|
|
}
|
|
});
|
|
return callItems;
|
|
}
|
|
|
|
export function isScreenShare(id) {
|
|
return id.endsWith('-screen');
|
|
}
|
|
|
|
export function containsScreenShare(participants) {
|
|
return Object.keys(participants).some((id) => isScreenShare(id));
|
|
}
|
|
|
|
export function callReducer(state, action) {
|
|
switch (action.type) {
|
|
case ACTION_PARTICIPANT_UPDATED:
|
|
return {
|
|
...state,
|
|
callItems: getCallItems(action.participants, state.callItems),
|
|
};
|
|
default:
|
|
throw new Error();
|
|
}
|
|
}
|