feat(pinning): move web pinning logic into redux
- Re-use the native redux pinning implementation for web - Remove pinning logic from conference.js - To the native pinning add a check for sharedVideo so youtube videos do not send a pin event - Add shared videos as a participant to enable pinning and so they can eventually get added to the filmstrip - Emit UIEvents.PINNED_ENDPOINT from middleware
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
import UIEvents from '../../../../service/UI/UIEvents';
|
||||
|
||||
import { CONNECTION_ESTABLISHED } from '../connection';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import { setVideoMuted, VIDEO_MUTISM_AUTHORITY } from '../media';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getParticipantById,
|
||||
getPinnedParticipant,
|
||||
PIN_PARTICIPANT
|
||||
} from '../participants';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
@@ -168,27 +170,46 @@ function _conferenceJoined(store, next, action) {
|
||||
*/
|
||||
function _pinParticipant(store, next, action) {
|
||||
const state = store.getState();
|
||||
const { conference } = state['features/base/conference'];
|
||||
const participants = state['features/base/participants'];
|
||||
const id = action.participant.id;
|
||||
const participantById = getParticipantById(participants, id);
|
||||
let pin;
|
||||
|
||||
// The following condition prevents signaling to pin local participant. The
|
||||
// logic is:
|
||||
const shouldEmitToLegacyApp = typeof APP !== 'undefined';
|
||||
|
||||
if (shouldEmitToLegacyApp) {
|
||||
const pinnedParticipant = getPinnedParticipant(participants);
|
||||
const actionName = action.participant.id ? 'pinned' : 'unpinned';
|
||||
let videoType;
|
||||
|
||||
if ((participantById && participantById.local)
|
||||
|| (!id && pinnedParticipant && pinnedParticipant.local)) {
|
||||
videoType = 'local';
|
||||
} else {
|
||||
videoType = 'remote';
|
||||
}
|
||||
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
`${actionName}.${videoType}`,
|
||||
{ value: conference.getParticipantCount() });
|
||||
}
|
||||
|
||||
// The following condition prevents signaling to pin local participant and
|
||||
// shared videos. The logic is:
|
||||
// - If we have an ID, we check if the participant identified by that ID is
|
||||
// local.
|
||||
// local or a bot/fake participant (such as with shared video).
|
||||
// - If we don't have an ID (i.e. no participant identified by an ID), we
|
||||
// check for local participant. If she's currently pinned, then this
|
||||
// action will unpin her and that's why we won't signal here too.
|
||||
if (participantById) {
|
||||
pin = !participantById.local;
|
||||
pin = !participantById.local && !participantById.isBot;
|
||||
} else {
|
||||
const localParticipant = getLocalParticipant(participants);
|
||||
|
||||
pin = !localParticipant || !localParticipant.pinned;
|
||||
}
|
||||
if (pin) {
|
||||
const { conference } = state['features/base/conference'];
|
||||
|
||||
try {
|
||||
conference.pinParticipant(id);
|
||||
@@ -197,6 +218,10 @@ function _pinParticipant(store, next, action) {
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldEmitToLegacyApp) {
|
||||
APP.UI.emitEvent(UIEvents.PINNED_ENDPOINT, id, Boolean(id));
|
||||
}
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,38 @@ export function getParticipantById(stateOrGetState, id) {
|
||||
return participants.find(p => p.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a count of the known participants in the passed in redux state,
|
||||
* excluding any fake participants.
|
||||
*
|
||||
* @param {(Function|Object|Participant[])} stateOrGetState - The redux state
|
||||
* features/base/participants, the (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the
|
||||
* features/base/participants state.
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getParticipantCount(stateOrGetState) {
|
||||
const participants = _getParticipants(stateOrGetState);
|
||||
const realParticipants = participants.filter(p => !p.isBot);
|
||||
|
||||
return realParticipants.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the participant which has its pinned state set to truthy.
|
||||
*
|
||||
* @param {(Function|Object|Participant[])} stateOrGetState - The redux state
|
||||
* features/base/participants, the (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the
|
||||
* features/base/participants state.
|
||||
* @returns {(Participant|undefined)}
|
||||
*/
|
||||
export function getPinnedParticipant(stateOrGetState) {
|
||||
const participants = _getParticipants(stateOrGetState);
|
||||
|
||||
return participants.find(p => p.pinned);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of participants from Redux state.
|
||||
*
|
||||
|
||||
@@ -73,6 +73,7 @@ function _participant(state, action) {
|
||||
connectionStatus,
|
||||
dominantSpeaker,
|
||||
email,
|
||||
isBot,
|
||||
local,
|
||||
pinned,
|
||||
role
|
||||
@@ -108,6 +109,7 @@ function _participant(state, action) {
|
||||
dominantSpeaker: dominantSpeaker || false,
|
||||
email,
|
||||
id,
|
||||
isBot,
|
||||
local: local || false,
|
||||
name,
|
||||
pinned: pinned || false,
|
||||
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
import { SET_CONFIG } from '../base/config';
|
||||
import { SET_LOCATION_URL } from '../base/connection';
|
||||
import { LIB_INIT_ERROR } from '../base/lib-jitsi-meet';
|
||||
import { PARTICIPANT_JOINED } from '../base/participants';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getParticipantCount,
|
||||
PARTICIPANT_JOINED
|
||||
} from '../base/participants';
|
||||
import { MiddlewareRegistry } from '../base/redux';
|
||||
|
||||
import { setCallOverlayVisible, setJWT } from './actions';
|
||||
@@ -96,13 +100,8 @@ function _maybeSetCallOverlayVisible({ dispatch, getState }, next, action) {
|
||||
default: {
|
||||
// The CallOverlay it to no longer be displayed/visible as soon
|
||||
// as another participant joins.
|
||||
const participants = state['features/base/participants'];
|
||||
|
||||
callOverlayVisible
|
||||
= Boolean(
|
||||
participants
|
||||
&& participants.length === 1
|
||||
&& participants[0].local);
|
||||
callOverlayVisible = getParticipantCount(state) === 1
|
||||
&& Boolean(getLocalParticipant(state));
|
||||
|
||||
// However, the CallDialog is not to be displayed/visible again
|
||||
// after all remote participants leave.
|
||||
|
||||
Reference in New Issue
Block a user