fixed participantState
This commit is contained in:
parent
e8fd32ad56
commit
aa53966923
|
|
@ -8,6 +8,7 @@
|
|||
* - A session id for each remote participant
|
||||
* - "<id>-screen" for each shared screen
|
||||
*/
|
||||
import fasteq from 'fast-deep-equal';
|
||||
import {
|
||||
DEVICE_STATE_OFF,
|
||||
DEVICE_STATE_BLOCKED,
|
||||
|
|
@ -15,8 +16,9 @@ import {
|
|||
} from './useDevices';
|
||||
|
||||
const initialParticipantsState = {
|
||||
participants: {
|
||||
local: {
|
||||
lastPendingUnknownActiveSpeaker: null,
|
||||
participants: [
|
||||
{
|
||||
camMutedByHost: false,
|
||||
hasNameSet: false,
|
||||
id: 'local',
|
||||
|
|
@ -31,9 +33,9 @@ const initialParticipantsState = {
|
|||
lastActiveDate: null,
|
||||
micMutedByHost: false,
|
||||
name: '',
|
||||
position: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
screens: [],
|
||||
};
|
||||
|
||||
// --- Derived data ---
|
||||
|
|
@ -63,36 +65,7 @@ function getMaxPosition(participants) {
|
|||
);
|
||||
}
|
||||
|
||||
function getUpdatedParticipant(participant, participants) {
|
||||
const id = getId(participant);
|
||||
const prevItem = participants[id];
|
||||
|
||||
const { local } = participant;
|
||||
const { audio, video } = participant.tracks;
|
||||
|
||||
return {
|
||||
...prevItem,
|
||||
camMutedByHost: video?.off?.byRemoteRequest,
|
||||
hasNameSet: !!participant.user_name,
|
||||
id,
|
||||
isCamMuted:
|
||||
video?.state === DEVICE_STATE_OFF ||
|
||||
video?.state === DEVICE_STATE_BLOCKED,
|
||||
isLoading:
|
||||
audio?.state === DEVICE_STATE_LOADING ||
|
||||
video?.state === DEVICE_STATE_LOADING,
|
||||
isLocal: local,
|
||||
isMicMuted:
|
||||
audio?.state === DEVICE_STATE_OFF ||
|
||||
audio?.state === DEVICE_STATE_BLOCKED,
|
||||
isOwner: !!participant.owner,
|
||||
isRecording: !!participant.record,
|
||||
micMutedByHost: audio?.off?.byRemoteRequest,
|
||||
name: participant.user_name,
|
||||
};
|
||||
}
|
||||
|
||||
function getNewParticipant(participant, participants) {
|
||||
function getNewParticipant(participant) {
|
||||
const id = getId(participant);
|
||||
|
||||
const { local } = participant;
|
||||
|
|
@ -119,11 +92,41 @@ function getNewParticipant(participant, participants) {
|
|||
lastActiveDate: null,
|
||||
micMutedByHost: audio?.off?.byRemoteRequest,
|
||||
name: participant.user_name,
|
||||
position: local ? 0 : getMaxPosition(participants) + 1,
|
||||
};
|
||||
}
|
||||
|
||||
function getScreenItem(participant, participants) {
|
||||
function getUpdatedParticipant(participant, participants) {
|
||||
const id = getId(participant);
|
||||
const prevItem = participants.find((p) => p.id === id);
|
||||
|
||||
// In case we haven't set up this participant, yet.
|
||||
if (!prevItem) return getNewParticipant(participant);
|
||||
|
||||
const { local } = participant;
|
||||
const { audio, video } = participant.tracks;
|
||||
return {
|
||||
...prevItem,
|
||||
camMutedByHost: video?.off?.byRemoteRequest,
|
||||
hasNameSet: !!participant.user_name,
|
||||
id,
|
||||
isCamMuted:
|
||||
video?.state === DEVICE_STATE_OFF ||
|
||||
video?.state === DEVICE_STATE_BLOCKED,
|
||||
isLoading:
|
||||
audio?.state === DEVICE_STATE_LOADING ||
|
||||
video?.state === DEVICE_STATE_LOADING,
|
||||
isLocal: local,
|
||||
isMicMuted:
|
||||
audio?.state === DEVICE_STATE_OFF ||
|
||||
audio?.state === DEVICE_STATE_BLOCKED,
|
||||
isOwner: !!participant.owner,
|
||||
isRecording: !!participant.record,
|
||||
micMutedByHost: audio?.off?.byRemoteRequest,
|
||||
name: participant.user_name,
|
||||
};
|
||||
}
|
||||
|
||||
function getScreenItem(participant) {
|
||||
const id = getId(participant);
|
||||
return {
|
||||
hasNameSet: null,
|
||||
|
|
@ -133,7 +136,6 @@ function getScreenItem(participant, participants) {
|
|||
isScreenshare: true,
|
||||
lastActiveDate: null,
|
||||
name: participant.user_name,
|
||||
position: getMaxPosition(participants) + 1,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -151,49 +153,66 @@ function participantsReducer(prevState, action) {
|
|||
switch (action.type) {
|
||||
case ACTIVE_SPEAKER: {
|
||||
const { participants, ...state } = prevState;
|
||||
if (!action.id) return prevState;
|
||||
if (!action.id)
|
||||
return {
|
||||
...prevState,
|
||||
lastPendingUnknownActiveSpeaker: null,
|
||||
};
|
||||
const date = new Date();
|
||||
const isParticipantKnown = participants.some((p) => p.id === action.id);
|
||||
return {
|
||||
...state,
|
||||
participants: Object.keys(participants).reduce(
|
||||
(items, id) => ({
|
||||
...items,
|
||||
[id]: {
|
||||
...participants[id],
|
||||
isActiveSpeaker: id === action.id,
|
||||
lastActiveDate:
|
||||
id === action.id
|
||||
? new Date()
|
||||
: participants[id]?.lastActiveDate,
|
||||
lastPendingUnknownActiveSpeaker: isParticipantKnown
|
||||
? null
|
||||
: {
|
||||
date,
|
||||
id: action.id,
|
||||
},
|
||||
}),
|
||||
{}
|
||||
),
|
||||
participants: participants.map((p) => ({
|
||||
...p,
|
||||
isActiveSpeaker: p.id === action.id,
|
||||
lastActiveDate: p.id === action.id ? date : p?.lastActiveDate,
|
||||
})),
|
||||
};
|
||||
}
|
||||
case PARTICIPANT_JOINED: {
|
||||
const item = getNewParticipant(
|
||||
action.participant,
|
||||
prevState.participants
|
||||
);
|
||||
const { id } = item;
|
||||
const screenId = getScreenId(id);
|
||||
const item = getNewParticipant(action.participant);
|
||||
|
||||
const newParticipants = {
|
||||
...prevState.participants,
|
||||
[id]: item,
|
||||
};
|
||||
const participants = [...prevState.participants];
|
||||
const screens = [...prevState.screens];
|
||||
|
||||
const isPendingActiveSpeaker =
|
||||
item.id === prevState.lastPendingUnknownActiveSpeaker?.id;
|
||||
if (isPendingActiveSpeaker) {
|
||||
item.isActiveSpeaker = true;
|
||||
item.lastActiveDate = prevState.lastPendingUnknownActiveSpeaker?.date;
|
||||
}
|
||||
|
||||
if (item.isCamMuted) {
|
||||
participants.push(item);
|
||||
} else {
|
||||
const firstInactiveCamOffIndex = prevState.participants.findIndex(
|
||||
(p) => p.isCamMuted && !p.isLocal && !p.isActiveSpeaker
|
||||
);
|
||||
if (firstInactiveCamOffIndex >= 0) {
|
||||
participants.splice(firstInactiveCamOffIndex, 0, item);
|
||||
} else {
|
||||
participants.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Participant is sharing screen
|
||||
if (action.participant.screen) {
|
||||
newParticipants[screenId] = getScreenItem(
|
||||
action.participant,
|
||||
newParticipants
|
||||
);
|
||||
screens.push(getScreenItem(action.participant));
|
||||
}
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
participants: newParticipants,
|
||||
lastPendingUnknownActiveSpeaker: isPendingActiveSpeaker
|
||||
? null
|
||||
: prevState.lastPendingUnknownActiveSpeaker,
|
||||
participants,
|
||||
screens,
|
||||
};
|
||||
}
|
||||
case PARTICIPANT_UPDATED: {
|
||||
|
|
@ -204,60 +223,58 @@ function participantsReducer(prevState, action) {
|
|||
const { id } = item;
|
||||
const screenId = getScreenId(id);
|
||||
|
||||
const newParticipants = {
|
||||
...prevState.participants,
|
||||
};
|
||||
newParticipants[id] = item;
|
||||
const participants = [...prevState.participants];
|
||||
const idx = participants.findIndex((p) => p.id === id);
|
||||
participants[idx] = item;
|
||||
|
||||
const screens = [...prevState.screens];
|
||||
const screenIdx = screens.findIndex((s) => s.id === screenId);
|
||||
|
||||
if (action.participant.screen) {
|
||||
newParticipants[screenId] = getScreenItem(
|
||||
action.participant,
|
||||
newParticipants
|
||||
);
|
||||
} else {
|
||||
delete newParticipants[screenId];
|
||||
const screenItem = getScreenItem(action.participant);
|
||||
if (screenIdx >= 0) {
|
||||
screens[screenIdx] = screenItem;
|
||||
} else {
|
||||
screens.push(screenItem);
|
||||
}
|
||||
} else if (screenIdx >= 0) {
|
||||
screens.splice(screenIdx, 1);
|
||||
}
|
||||
|
||||
return {
|
||||
const newState = {
|
||||
...prevState,
|
||||
participants: newParticipants,
|
||||
participants,
|
||||
screens,
|
||||
};
|
||||
|
||||
if (fasteq(newState, prevState)) {
|
||||
return prevState;
|
||||
}
|
||||
|
||||
return newState;
|
||||
}
|
||||
case PARTICIPANT_LEFT: {
|
||||
const id = getId(action.participant);
|
||||
const screenId = getScreenId(id);
|
||||
const { ...participants } = prevState.participants;
|
||||
delete participants[id];
|
||||
delete participants[screenId];
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
participants,
|
||||
participants: [...prevState.participants].filter((p) => p.id !== id),
|
||||
screens: [...prevState.screens].filter((s) => s.id !== screenId),
|
||||
};
|
||||
}
|
||||
case SWAP_POSITION: {
|
||||
const { participants, ...state } = prevState;
|
||||
const participants = [...prevState.participants];
|
||||
if (!action.id1 || !action.id2) return prevState;
|
||||
const pos1 = participants[action.id1]?.position;
|
||||
const pos2 = participants[action.id2]?.position;
|
||||
if (!pos1 || !pos2) return prevState;
|
||||
const idx1 = participants.findIndex((p) => p.id === action.id1);
|
||||
const idx2 = participants.findIndex((p) => p.id === action.id2);
|
||||
if (idx1 === -1 || idx2 === -1) return prevState;
|
||||
const tmp = participants[idx1];
|
||||
participants[idx1] = participants[idx2];
|
||||
participants[idx2] = tmp;
|
||||
return {
|
||||
...state,
|
||||
participants: Object.keys(participants).reduce((items, id) => {
|
||||
let { position } = participants[id];
|
||||
if (action.id1 === id) {
|
||||
position = pos2;
|
||||
}
|
||||
if (action.id2 === id) {
|
||||
position = pos1;
|
||||
}
|
||||
return {
|
||||
...items,
|
||||
[id]: {
|
||||
...participants[id],
|
||||
position,
|
||||
},
|
||||
};
|
||||
}, {}),
|
||||
...prevState,
|
||||
participants,
|
||||
};
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
"@daily-co/daily-js": "^0.12.0",
|
||||
"classnames": "^2.3.1",
|
||||
"debounce": "^1.2.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"nanoid": "^3.1.23",
|
||||
"no-scroll": "^2.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
|
|
|
|||
|
|
@ -1532,7 +1532,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
|||
md5.js "^1.3.4"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
fast-deep-equal@^3.1.1:
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
|
|
|||
Loading…
Reference in New Issue