ref(video-layout): get pinned ID directly from redux
This commit is contained in:
parent
57f7abc6dd
commit
05801711a7
|
@ -1,3 +1,5 @@
|
|||
/* global APP */
|
||||
|
||||
/*
|
||||
* Copyright @ 2015 Atlassian Pty Ltd
|
||||
*
|
||||
|
@ -15,6 +17,10 @@
|
|||
*/
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
import {
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../react/features/base/participants';
|
||||
import UIEvents from '../service/UI/UIEvents';
|
||||
import VideoLayout from './UI/videolayout/VideoLayout';
|
||||
|
||||
|
@ -444,11 +450,15 @@ class FollowMe {
|
|||
if (smallVideo) {
|
||||
this.nextOnStageTimer = 0;
|
||||
clearTimeout(this.nextOnStageTimout);
|
||||
/* eslint-disable no-mixed-operators */
|
||||
if (pin && !VideoLayout.isPinned(clickId)
|
||||
|| !pin && VideoLayout.isPinned(clickId)) {
|
||||
/* eslint-disable no-mixed-operators */
|
||||
VideoLayout.handleVideoThumbClicked(clickId);
|
||||
|
||||
if (pin) {
|
||||
APP.store.dispatch(pinParticipant(clickId));
|
||||
} else {
|
||||
const { id } = getPinnedParticipant(APP.store.getState()) || {};
|
||||
|
||||
if (id === clickId) {
|
||||
APP.store.dispatch(pinParticipant(null));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If there's no SmallVideo object for the given id, lets wait and
|
||||
|
|
|
@ -959,15 +959,6 @@ UI.getLargeVideo = function() {
|
|||
return VideoLayout.getLargeVideo();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether or not the passed in user id is currently pinned to the large
|
||||
* video.
|
||||
*
|
||||
* @param {string} userId - The id of the user to check is pinned or not.
|
||||
* @returns {boolean} True if the user is currently pinned to the large video.
|
||||
*/
|
||||
UI.isPinned = userId => VideoLayout.getPinnedId() === userId;
|
||||
|
||||
/**
|
||||
* Shows "Please go to chrome webstore to install the desktop sharing extension"
|
||||
* 2 button dialog with buttons - cancel and go to web store.
|
||||
|
|
|
@ -317,7 +317,7 @@ export default class SharedVideoManager {
|
|||
name: 'YouTube'
|
||||
}));
|
||||
|
||||
VideoLayout.handleVideoThumbClicked(self.url);
|
||||
thumb.videoClick();
|
||||
|
||||
// If we are sending the command and we are starting the player
|
||||
// we need to continuously send the player current time position
|
||||
|
|
|
@ -59,7 +59,7 @@ SharedVideoThumb.prototype.createContainer = function(spanId) {
|
|||
* The thumb click handler.
|
||||
*/
|
||||
SharedVideoThumb.prototype.videoClick = function() {
|
||||
this.VideoLayout.handleVideoThumbClicked(this.url);
|
||||
this._togglePin();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -260,7 +260,7 @@ LocalVideo.prototype._onContainerClick = function(event) {
|
|||
}
|
||||
|
||||
if (!ignoreClick) {
|
||||
this.VideoLayout.handleVideoThumbClicked(this.id);
|
||||
this._togglePin();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ import { i18next } from '../../../react/features/base/i18n';
|
|||
import {
|
||||
JitsiParticipantConnectionStatus
|
||||
} from '../../../react/features/base/lib-jitsi-meet';
|
||||
|
||||
import {
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
import { PresenceLabel } from '../../../react/features/presence-status';
|
||||
import {
|
||||
REMOTE_CONTROL_MENU_STATES,
|
||||
|
@ -234,10 +237,12 @@ RemoteVideo.prototype._requestRemoteControlPermissions = function() {
|
|||
if (result === true) {
|
||||
// the remote control permissions has been granted
|
||||
// pin the controlled participant
|
||||
const pinnedId = this.VideoLayout.getPinnedId();
|
||||
const pinnedParticipant
|
||||
= getPinnedParticipant(APP.store.getState()) || {};
|
||||
const pinnedId = pinnedParticipant.id;
|
||||
|
||||
if (pinnedId !== this.id) {
|
||||
this.VideoLayout.handleVideoThumbClicked(this.id);
|
||||
APP.store.dispatch(pinParticipant(this.id));
|
||||
}
|
||||
}
|
||||
}, error => {
|
||||
|
@ -648,7 +653,7 @@ RemoteVideo.prototype._onContainerClick = function(event) {
|
|||
|| classList.contains('popover');
|
||||
|
||||
if (!ignoreClick) {
|
||||
this.VideoLayout.handleVideoThumbClicked(this.id);
|
||||
this._togglePin();
|
||||
}
|
||||
|
||||
// On IE we need to populate this handler on video <object> and it does not
|
||||
|
|
|
@ -12,7 +12,9 @@ import { AudioLevelIndicator }
|
|||
from '../../../react/features/audio-level-indicator';
|
||||
import {
|
||||
Avatar as AvatarDisplay,
|
||||
getAvatarURLByParticipantId
|
||||
getAvatarURLByParticipantId,
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
import {
|
||||
ConnectionIndicator
|
||||
|
@ -819,6 +821,22 @@ SmallVideo.prototype.updateIndicators = function() {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Pins the participant displayed by this thumbnail or unpins if already pinned.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
SmallVideo.prototype._togglePin = function() {
|
||||
const pinnedParticipant
|
||||
= getPinnedParticipant(APP.store.getState()) || {};
|
||||
const participantIdToPin
|
||||
= pinnedParticipant && pinnedParticipant.id === this.id
|
||||
? null : this.id;
|
||||
|
||||
APP.store.dispatch(pinParticipant(participantIdToPin));
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the React element responsible for showing connection status, dominant
|
||||
* speaker, and raised hand icons.
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
JitsiParticipantConnectionStatus
|
||||
} from '../../../react/features/base/lib-jitsi-meet';
|
||||
import {
|
||||
getParticipants,
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../../../react/features/base/participants';
|
||||
|
@ -42,6 +41,29 @@ function onLocalFlipXChanged(val) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the redux representation of all known users.
|
||||
*
|
||||
* @private
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getAllParticipants() {
|
||||
return APP.store.getState()['features/base/participants'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all thumbnails in the filmstrip.
|
||||
*
|
||||
* @private
|
||||
* @returns {Array}
|
||||
*/
|
||||
function getAllThumbnails() {
|
||||
return [
|
||||
localVideoThumbnail,
|
||||
...Object.values(remoteVideos)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user ID of the remote participant that is current the dominant
|
||||
* speaker.
|
||||
|
@ -50,7 +72,7 @@ function onLocalFlipXChanged(val) {
|
|||
* @returns {string|null}
|
||||
*/
|
||||
function getCurrentRemoteDominantSpeakerID() {
|
||||
const dominantSpeaker = getParticipants(APP.store.getState)
|
||||
const dominantSpeaker = getAllParticipants()
|
||||
.find(participant => participant.dominantSpeaker);
|
||||
|
||||
if (dominantSpeaker) {
|
||||
|
@ -93,8 +115,6 @@ const VideoLayout = {
|
|||
// the local video thumb maybe one pixel
|
||||
this.resizeThumbnails(true);
|
||||
|
||||
this.handleVideoThumbClicked = this.handleVideoThumbClicked.bind(this);
|
||||
|
||||
this.registerListeners();
|
||||
},
|
||||
|
||||
|
@ -376,61 +396,36 @@ const VideoLayout = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Updates the desired pinned participant and notifies web UI of the change.
|
||||
* Callback invoked to update display when the pin participant has changed.
|
||||
*
|
||||
* @param {string|null} id - The participant id of the participant to be
|
||||
* pinned. Pass in null to unpin without pinning another participant.
|
||||
* @paramn {string|null} pinnedParticipantID - The participant ID of the
|
||||
* participant that is pinned or null if no one is pinned.
|
||||
* @returns {void}
|
||||
*/
|
||||
pinParticipant(id) {
|
||||
APP.store.dispatch(pinParticipant(id));
|
||||
APP.UI.emitEvent(UIEvents.PINNED_ENDPOINT, id, Boolean(id));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the click on a video thumbnail.
|
||||
*
|
||||
* @param id the identifier of the video thumbnail
|
||||
*/
|
||||
handleVideoThumbClicked(id) {
|
||||
const smallVideo = VideoLayout.getSmallVideo(id);
|
||||
const pinnedId = this.getPinnedId();
|
||||
|
||||
if (pinnedId) {
|
||||
const oldSmallVideo = VideoLayout.getSmallVideo(pinnedId);
|
||||
|
||||
if (oldSmallVideo && !interfaceConfig.filmStripOnly) {
|
||||
oldSmallVideo.focus(false);
|
||||
}
|
||||
onPinChange(pinnedParticipantID) {
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unpin if currently pinned.
|
||||
if (pinnedId === id) {
|
||||
this.pinParticipant(null);
|
||||
getAllThumbnails().forEach(thumbnail =>
|
||||
thumbnail.focus(pinnedParticipantID === thumbnail.getId()));
|
||||
|
||||
// Enable the currently set dominant speaker.
|
||||
if (getCurrentRemoteDominantSpeakerID()) {
|
||||
this.updateLargeVideo(getCurrentRemoteDominantSpeakerID());
|
||||
if (pinnedParticipantID) {
|
||||
this.updateLargeVideo(pinnedParticipantID);
|
||||
} else {
|
||||
const currentDominantSpeakerID
|
||||
= getCurrentRemoteDominantSpeakerID();
|
||||
|
||||
if (currentDominantSpeakerID) {
|
||||
this.updateLargeVideo(currentDominantSpeakerID);
|
||||
} else {
|
||||
// if there is no currentDominantSpeaker, it can also be
|
||||
// if there is no currentDominantSpeakerID, it can also be
|
||||
// that local participant is the dominant speaker
|
||||
// we should act as a participant has left and was on large
|
||||
// and we should choose somebody (electLastVisibleVideo)
|
||||
this.updateLargeVideo(this.electLastVisibleVideo());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Update focused/pinned interface.
|
||||
if (id) {
|
||||
if (smallVideo && !interfaceConfig.filmStripOnly) {
|
||||
smallVideo.focus(true);
|
||||
this.pinParticipant(id);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateLargeVideo(id);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -684,12 +679,9 @@ const VideoLayout = {
|
|||
* @returns {void}
|
||||
*/
|
||||
onDominantSpeakerChanged(id) {
|
||||
Object.values(remoteVideos).forEach(remoteVideo =>
|
||||
remoteVideo.showDominantSpeakerIndicator(
|
||||
id === remoteVideo.getId()));
|
||||
getAllThumbnails().forEach(thumbnail =>
|
||||
thumbnail.showDominantSpeakerIndicator(id === thumbnail.getId()));
|
||||
|
||||
localVideoThumbnail.showDominantSpeakerIndicator(
|
||||
APP.conference.isLocalId(id));
|
||||
|
||||
if (!remoteVideos[id]) {
|
||||
return;
|
||||
|
@ -797,7 +789,7 @@ const VideoLayout = {
|
|||
// Unlock large video
|
||||
if (this.getPinnedId() === id) {
|
||||
logger.info('Focused video owner has left the conference');
|
||||
this.pinParticipant(null);
|
||||
APP.store.dispatch(pinParticipant(null));
|
||||
}
|
||||
|
||||
const remoteVideo = remoteVideos[id];
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
|
||||
// @flow
|
||||
|
||||
import { DOMINANT_SPEAKER_CHANGED } from '../base/participants';
|
||||
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
|
||||
import {
|
||||
DOMINANT_SPEAKER_CHANGED,
|
||||
PIN_PARTICIPANT
|
||||
} from '../base/participants';
|
||||
import { MiddlewareRegistry } from '../base/redux';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
/**
|
||||
* Middleware which intercepts actions and updates the legacy component
|
||||
* {@code VideoLayout} as needed. The purpose of this middleware is to redux-ify
|
||||
|
@ -13,12 +21,22 @@ import { MiddlewareRegistry } from '../base/redux';
|
|||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
// Purposefully perform additional actions after state update to mimic
|
||||
// being connected to the store for updates.
|
||||
const result = next(action);
|
||||
|
||||
switch (action.type) {
|
||||
case DOMINANT_SPEAKER_CHANGED:
|
||||
VideoLayout.onDominantSpeakerChanged(action.participant.id);
|
||||
break;
|
||||
|
||||
case PIN_PARTICIPANT:
|
||||
VideoLayout.onPinChange(action.participant.id);
|
||||
APP.UI.emitEvent(
|
||||
UIEvents.PINNED_ENDPOINT,
|
||||
action.participant.id,
|
||||
Boolean(action.participant.id));
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue