|
|
@ -1,7 +1,10 @@ |
|
|
|
/* global APP, $, interfaceConfig, JitsiMeetJS */ |
|
|
|
/* global APP, $, interfaceConfig, JitsiMeetJS */ |
|
|
|
const logger = require("jitsi-meet-logger").getLogger(__filename); |
|
|
|
const logger = require("jitsi-meet-logger").getLogger(__filename); |
|
|
|
|
|
|
|
|
|
|
|
import { pinParticipant } from '../../../react/features/base/participants'; |
|
|
|
import { |
|
|
|
|
|
|
|
getPinnedParticipant, |
|
|
|
|
|
|
|
pinParticipant |
|
|
|
|
|
|
|
} from '../../../react/features/base/participants'; |
|
|
|
|
|
|
|
|
|
|
|
import Filmstrip from "./Filmstrip"; |
|
|
|
import Filmstrip from "./Filmstrip"; |
|
|
|
import UIEvents from "../../../service/UI/UIEvents"; |
|
|
|
import UIEvents from "../../../service/UI/UIEvents"; |
|
|
@ -22,14 +25,6 @@ var currentDominantSpeaker = null; |
|
|
|
|
|
|
|
|
|
|
|
var eventEmitter = null; |
|
|
|
var eventEmitter = null; |
|
|
|
|
|
|
|
|
|
|
|
// TODO Remove this private reference to pinnedId once other components
|
|
|
|
|
|
|
|
// interested in its updates are moved to react/redux.
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Currently focused video jid |
|
|
|
|
|
|
|
* @type {String} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
var pinnedId = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* flipX state of the localVideo |
|
|
|
* flipX state of the localVideo |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -63,7 +58,7 @@ function onContactClicked (id) { |
|
|
|
// let the bridge adjust its lastN set for myjid and store
|
|
|
|
// let the bridge adjust its lastN set for myjid and store
|
|
|
|
// the pinned user in the lastNPickupId variable to be
|
|
|
|
// the pinned user in the lastNPickupId variable to be
|
|
|
|
// picked up later by the lastN changed event handler.
|
|
|
|
// picked up later by the lastN changed event handler.
|
|
|
|
APP.store.dispatch(pinParticipant(remoteVideo.id)); |
|
|
|
this.pinParticipant(remoteVideo.id); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -281,6 +276,7 @@ var VideoLayout = { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const pinnedId = this.getPinnedId(); |
|
|
|
let newId; |
|
|
|
let newId; |
|
|
|
|
|
|
|
|
|
|
|
if (pinnedId) |
|
|
|
if (pinnedId) |
|
|
@ -392,11 +388,25 @@ var VideoLayout = { |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
isPinned (id) { |
|
|
|
isPinned (id) { |
|
|
|
return (pinnedId) ? (id === pinnedId) : false; |
|
|
|
return id === this.getPinnedId(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
getPinnedId () { |
|
|
|
getPinnedId () { |
|
|
|
return pinnedId; |
|
|
|
const { id } = getPinnedParticipant(APP.store.getState()) || {}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return id || null; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Updates the desired pinned participant and notifies web UI of the change. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param {string|null} id - The participant id of the participant to be |
|
|
|
|
|
|
|
* pinned. Pass in null to unpin without pinning another participant. |
|
|
|
|
|
|
|
* @returns {void} |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
pinParticipant(id) { |
|
|
|
|
|
|
|
APP.store.dispatch(pinParticipant(id)); |
|
|
|
|
|
|
|
APP.UI.emitEvent(UIEvents.PINNED_ENDPOINT, id, Boolean(id)); |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -406,6 +416,8 @@ var VideoLayout = { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
handleVideoThumbClicked (id) { |
|
|
|
handleVideoThumbClicked (id) { |
|
|
|
var smallVideo = VideoLayout.getSmallVideo(id); |
|
|
|
var smallVideo = VideoLayout.getSmallVideo(id); |
|
|
|
|
|
|
|
const pinnedId = this.getPinnedId(); |
|
|
|
|
|
|
|
|
|
|
|
if(pinnedId) { |
|
|
|
if(pinnedId) { |
|
|
|
var oldSmallVideo = VideoLayout.getSmallVideo(pinnedId); |
|
|
|
var oldSmallVideo = VideoLayout.getSmallVideo(pinnedId); |
|
|
|
if (oldSmallVideo && !interfaceConfig.filmStripOnly) { |
|
|
|
if (oldSmallVideo && !interfaceConfig.filmStripOnly) { |
|
|
@ -416,9 +428,7 @@ var VideoLayout = { |
|
|
|
// Unpin if currently pinned.
|
|
|
|
// Unpin if currently pinned.
|
|
|
|
if (pinnedId === id) |
|
|
|
if (pinnedId === id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pinnedId = null; |
|
|
|
this.pinParticipant(null); |
|
|
|
|
|
|
|
|
|
|
|
APP.store.dispatch(pinParticipant(null)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enable the currently set dominant speaker.
|
|
|
|
// Enable the currently set dominant speaker.
|
|
|
|
if (currentDominantSpeaker) { |
|
|
|
if (currentDominantSpeaker) { |
|
|
@ -436,14 +446,11 @@ var VideoLayout = { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Lock new video
|
|
|
|
|
|
|
|
pinnedId = id; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update focused/pinned interface.
|
|
|
|
// Update focused/pinned interface.
|
|
|
|
if (id) { |
|
|
|
if (id) { |
|
|
|
if (smallVideo && !interfaceConfig.filmStripOnly) { |
|
|
|
if (smallVideo && !interfaceConfig.filmStripOnly) { |
|
|
|
smallVideo.focus(true); |
|
|
|
smallVideo.focus(true); |
|
|
|
APP.store.dispatch(pinParticipant(id)); |
|
|
|
this.pinParticipant(id); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -530,6 +537,8 @@ var VideoLayout = { |
|
|
|
* @returns {void} |
|
|
|
* @returns {void} |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
_maybePlaceParticipantOnLargeVideo(resourceJid) { |
|
|
|
_maybePlaceParticipantOnLargeVideo(resourceJid) { |
|
|
|
|
|
|
|
const pinnedId = this.getPinnedId(); |
|
|
|
|
|
|
|
|
|
|
|
if ((!pinnedId && |
|
|
|
if ((!pinnedId && |
|
|
|
!currentDominantSpeaker && |
|
|
|
!currentDominantSpeaker && |
|
|
|
this.isLargeContainerTypeVisible(VIDEO_CONTAINER_TYPE)) || |
|
|
|
this.isLargeContainerTypeVisible(VIDEO_CONTAINER_TYPE)) || |
|
|
@ -727,7 +736,7 @@ var VideoLayout = { |
|
|
|
// Update the large video if the video source is already available,
|
|
|
|
// Update the large video if the video source is already available,
|
|
|
|
// otherwise wait for the "videoactive.jingle" event.
|
|
|
|
// otherwise wait for the "videoactive.jingle" event.
|
|
|
|
// FIXME: there is no "videoactive.jingle" event.
|
|
|
|
// FIXME: there is no "videoactive.jingle" event.
|
|
|
|
if (!interfaceConfig.filmStripOnly && !pinnedId |
|
|
|
if (!interfaceConfig.filmStripOnly && !this.getPinnedId() |
|
|
|
&& remoteVideo.hasVideoStarted() |
|
|
|
&& remoteVideo.hasVideoStarted() |
|
|
|
&& !this.getCurrentlyOnLargeContainer().stayOnStage()) { |
|
|
|
&& !this.getCurrentlyOnLargeContainer().stayOnStage()) { |
|
|
|
this.updateLargeVideo(id); |
|
|
|
this.updateLargeVideo(id); |
|
|
@ -819,10 +828,9 @@ var VideoLayout = { |
|
|
|
|
|
|
|
|
|
|
|
removeParticipantContainer (id) { |
|
|
|
removeParticipantContainer (id) { |
|
|
|
// Unlock large video
|
|
|
|
// Unlock large video
|
|
|
|
if (pinnedId === id) { |
|
|
|
if (this.getPinnedId() === id) { |
|
|
|
logger.info("Focused video owner has left the conference"); |
|
|
|
logger.info("Focused video owner has left the conference"); |
|
|
|
pinnedId = null; |
|
|
|
this.pinParticipant(null); |
|
|
|
APP.store.dispatch(pinParticipant(null)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (currentDominantSpeaker === id) { |
|
|
|
if (currentDominantSpeaker === id) { |
|
|
@ -1072,6 +1080,8 @@ var VideoLayout = { |
|
|
|
// (pinned remote video) use its video type,
|
|
|
|
// (pinned remote video) use its video type,
|
|
|
|
// if not then use default type - large video
|
|
|
|
// if not then use default type - large video
|
|
|
|
if (!show) { |
|
|
|
if (!show) { |
|
|
|
|
|
|
|
const pinnedId = this.getPinnedId(); |
|
|
|
|
|
|
|
|
|
|
|
if(pinnedId) |
|
|
|
if(pinnedId) |
|
|
|
containerTypeToShow = this.getRemoteVideoType(pinnedId); |
|
|
|
containerTypeToShow = this.getRemoteVideoType(pinnedId); |
|
|
|
else |
|
|
|
else |
|
|
|