Reduce the number of unnecessary Redux state changes
This commit is contained in:
parent
3fa62c3757
commit
4d335e086b
|
@ -46,7 +46,7 @@ ReducerRegistry.register('features/base/connection',
|
|||
return {
|
||||
...state,
|
||||
connectionOptions: {
|
||||
...(state.connectionOptions || {}),
|
||||
...state.connectionOptions,
|
||||
...buildConnectionOptions(action.domain)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -25,8 +25,9 @@ import {
|
|||
* @property {boolean} local - If true, participant is local.
|
||||
* @property {boolean} pinned - If true, participant is currently a
|
||||
* "PINNED_ENDPOINT".
|
||||
* @property {boolean} speaking - If true, participant is currently a dominant
|
||||
* speaker.
|
||||
* @property {boolean} dominantSpeaker - If this participant is the dominant
|
||||
* speaker in the (associated) conference, <tt>true</tt>; otherwise,
|
||||
* <tt>false</tt>.
|
||||
* @property {string} email - Participant email.
|
||||
*/
|
||||
|
||||
|
@ -36,7 +37,7 @@ import {
|
|||
* @type {string[]}
|
||||
*/
|
||||
const PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE
|
||||
= [ 'id', 'local', 'pinned', 'speaking' ];
|
||||
= [ 'dominantSpeaker', 'id', 'local', 'pinned' ];
|
||||
|
||||
/**
|
||||
* Reducer function for a single participant.
|
||||
|
@ -53,10 +54,11 @@ function participant(state, action) {
|
|||
switch (action.type) {
|
||||
case DOMINANT_SPEAKER_CHANGED:
|
||||
// Only one dominant speaker is allowed.
|
||||
return {
|
||||
...state,
|
||||
speaking: state.id === action.participant.id
|
||||
};
|
||||
return (
|
||||
_setStateProperty(
|
||||
state,
|
||||
'dominantSpeaker',
|
||||
state.id === action.participant.id));
|
||||
|
||||
case PARTICIPANT_ID_CHANGED:
|
||||
if (state.id === action.oldValue) {
|
||||
|
@ -68,8 +70,7 @@ function participant(state, action) {
|
|||
avatar: state.avatar || _getAvatarURL(id, state.email)
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
break;
|
||||
|
||||
case PARTICIPANT_JOINED: {
|
||||
const participant = action.participant; // eslint-disable-line no-shadow
|
||||
|
@ -94,7 +95,7 @@ function participant(state, action) {
|
|||
name,
|
||||
pinned: participant.pinned || false,
|
||||
role: participant.role || PARTICIPANT_ROLE.NONE,
|
||||
speaking: participant.speaking || false
|
||||
dominantSpeaker: participant.dominantSpeaker || false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -117,19 +118,18 @@ function participant(state, action) {
|
|||
|
||||
return newState;
|
||||
}
|
||||
|
||||
return state;
|
||||
break;
|
||||
|
||||
case PIN_PARTICIPANT:
|
||||
// Currently, only one pinned participant is allowed.
|
||||
return {
|
||||
...state,
|
||||
pinned: state.id === action.participant.id
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
return (
|
||||
_setStateProperty(
|
||||
state,
|
||||
'pinned',
|
||||
state.id === action.participant.id));
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,3 +201,30 @@ function _getAvatarURL(participantId, email) {
|
|||
|
||||
return urlPref + avatarId + urlSuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific property of a specific state to a specific value. Prevents
|
||||
* unnecessary state changes (when the specified <tt>value</tt> is equal to the
|
||||
* value of the specified <tt>property</tt> of the specified <tt>state</tt>).
|
||||
*
|
||||
* @param {Object} state - The (Redux) state from which a new state is to be
|
||||
* constructed by setting the specified <tt>property</tt> to the specified
|
||||
* <tt>value</tt>.
|
||||
* @param {string} property - The property of <tt>state</tt> which is to be
|
||||
* assigned the specified <tt>value</tt> (in the new state).
|
||||
* @param {*} value - The value to assign to the specified <tt>property</tt>.
|
||||
* @returns {Object} The specified <tt>state</tt> if the value of the specified
|
||||
* <tt>property</tt> equals the specified <tt>value/tt>; otherwise, a new state
|
||||
* constructed from the specified <tt>state</tt> by setting the specified
|
||||
* <tt>property</tt> to the specified <tt>value</tt>.
|
||||
*/
|
||||
function _setStateProperty(state, property, value) {
|
||||
if (state[property] !== value) {
|
||||
return {
|
||||
...state,
|
||||
[property]: value
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -81,8 +81,9 @@ class Thumbnail extends Component {
|
|||
// participants would be hearing themselves.
|
||||
const audioMuted = !audioTrack || audioTrack.muted;
|
||||
const renderAudio = !audioMuted && !audioTrack.local;
|
||||
const participantId = participant.id;
|
||||
const participantNotInLargeVideo
|
||||
= participant.id !== largeVideo.participantId;
|
||||
= participantId !== largeVideo.participantId;
|
||||
const videoMuted = !videoTrack || videoTrack.muted;
|
||||
|
||||
return (
|
||||
|
@ -96,7 +97,7 @@ class Thumbnail extends Component {
|
|||
= { audioTrack.jitsiTrack.getOriginalStream() } /> }
|
||||
|
||||
<ParticipantView
|
||||
participantId = { participant.id }
|
||||
participantId = { participantId }
|
||||
showAvatar = { participantNotInLargeVideo }
|
||||
showVideo = { participantNotInLargeVideo }
|
||||
zOrder = { 1 } />
|
||||
|
@ -104,7 +105,7 @@ class Thumbnail extends Component {
|
|||
{ participant.role === PARTICIPANT_ROLE.MODERATOR
|
||||
&& <ModeratorIndicator /> }
|
||||
|
||||
{ participant.speaking
|
||||
{ participant.dominantSpeaker
|
||||
&& <DominantSpeakerIndicator /> }
|
||||
|
||||
{ audioMuted
|
||||
|
|
|
@ -26,13 +26,17 @@ export function selectParticipant() {
|
|||
const largeVideo = state['features/largeVideo'];
|
||||
const tracks = state['features/base/tracks'];
|
||||
|
||||
const videoTrack = getTrackByMediaTypeAndParticipant(
|
||||
tracks, MEDIA_TYPE.VIDEO, largeVideo.participantId);
|
||||
const id = largeVideo.participantId;
|
||||
const videoTrack
|
||||
= getTrackByMediaTypeAndParticipant(
|
||||
tracks,
|
||||
MEDIA_TYPE.VIDEO,
|
||||
id);
|
||||
|
||||
try {
|
||||
conference.selectParticipant(
|
||||
videoTrack && videoTrack.videoType === VIDEO_TYPE.CAMERA
|
||||
? largeVideo.participantId
|
||||
? id
|
||||
: null);
|
||||
} catch (err) {
|
||||
_handleParticipantError(err);
|
||||
|
@ -51,11 +55,8 @@ export function selectParticipant() {
|
|||
export function selectParticipantInLargeVideo() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const participants = state['features/base/participants'];
|
||||
const tracks = state['features/base/tracks'];
|
||||
const participantId = _electParticipantInLargeVideo(state);
|
||||
const largeVideo = state['features/largeVideo'];
|
||||
const participantId
|
||||
= _electParticipantInLargeVideo(participants, tracks);
|
||||
|
||||
if (participantId !== largeVideo.participantId) {
|
||||
dispatch({
|
||||
|
@ -77,57 +78,54 @@ export function selectParticipantInLargeVideo() {
|
|||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
function _electLastVisibleVideo(tracks) {
|
||||
let videoTrack;
|
||||
|
||||
// First we try to get most recent remote video track.
|
||||
for (let i = tracks.length - 1; i >= 0; i--) {
|
||||
if (tracks[i].mediaType === MEDIA_TYPE.VIDEO && !tracks[i].local) {
|
||||
videoTrack = tracks[i];
|
||||
break;
|
||||
for (let i = tracks.length - 1; i >= 0; --i) {
|
||||
const track = tracks[i];
|
||||
|
||||
if (!track.local && track.mediaType === MEDIA_TYPE.VIDEO) {
|
||||
return track;
|
||||
}
|
||||
}
|
||||
|
||||
// And if no remote video tracks are available, we select the local one.
|
||||
if (!videoTrack) {
|
||||
videoTrack = getLocalVideoTrack(tracks);
|
||||
}
|
||||
|
||||
return videoTrack;
|
||||
return getLocalVideoTrack(tracks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the participant ID who is to be on the stage i.e. should be displayed
|
||||
* in LargeVideo.
|
||||
* Returns the identifier of the participant who is to be on the stage i.e.
|
||||
* should be displayed in <tt>LargeVideo</tt>.
|
||||
*
|
||||
* @param {Participant[]} participants - All participants.
|
||||
* @param {Track[]} tracks - All tracks.
|
||||
* @param {Object} state - The Redux state from which the participant to be
|
||||
* displayed in <tt>LargeVideo</tt> is to be elected.
|
||||
* @private
|
||||
* @returns {(string|undefined)}
|
||||
*/
|
||||
function _electParticipantInLargeVideo(participants, tracks) {
|
||||
// First get the pinned participant. If local participant is pinned, he will
|
||||
// be shown in LargeVideo.
|
||||
function _electParticipantInLargeVideo(state) {
|
||||
// First get the pinned participant. If the local participant is pinned,
|
||||
// he/she will be shown in LargeVideo.
|
||||
const participants = state['features/base/participants'];
|
||||
let participant = participants.find(p => p.pinned);
|
||||
let id = participant ? participant.id : undefined;
|
||||
|
||||
// If no participant is pinned, get the dominant speaker. But local
|
||||
// participant won't be displayed in LargeVideo even if he is the dominant
|
||||
// speaker.
|
||||
if (!id) {
|
||||
participant = participants.find(p => p.speaking && !p.local);
|
||||
// No participant is pinned so get the dominant speaker. But the local
|
||||
// participant won't be displayed in LargeVideo even if he/she is the
|
||||
// dominant speaker.
|
||||
participant = participants.find(p => p.dominantSpeaker && !p.local);
|
||||
if (participant) {
|
||||
id = participant.id;
|
||||
}
|
||||
}
|
||||
|
||||
// If no participant is pinned and no dominant speaker, just get the
|
||||
// participant with last visible video track. This may turn out to be local
|
||||
// participant.
|
||||
if (!id) {
|
||||
// There is no dominant speaker so get the participant with the last
|
||||
// visible video track. This may turn out to be the local
|
||||
// participant.
|
||||
const tracks = state['features/base/tracks'];
|
||||
const videoTrack = _electLastVisibleVideo(tracks);
|
||||
|
||||
id = videoTrack && videoTrack.participantId;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
|
|
@ -24,16 +24,14 @@ ReducerRegistry.register(
|
|||
participantId: action.newValue
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
break;
|
||||
|
||||
case LARGE_VIDEO_PARTICIPANT_CHANGED:
|
||||
return {
|
||||
...state,
|
||||
participantId: action.participantId
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
return state;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue