From b7133f5717b4ed95e04b4a3434530632e1fd0920 Mon Sep 17 00:00:00 2001 From: virtuacoplenny Date: Wed, 6 Feb 2019 19:19:02 -0800 Subject: [PATCH] fix(large-video): do not show avatar if no url (#3871) * fix(large-video): do not show avatar if no url By default the large video dominant speaker avatar has an empty src, which will result in a broken image displaying. There is also disconnect with non-react code trying to set an undefined src. To prevent such until local avatar generation work is done in the future, just don't show the avatar. * fix(conference): set the room instance earlier Set the room instance on APP.conference before triggering a redux update of the conference being set,, because middleware can then fire and call methods on APP.conference that depend on the room being set. * get local participant directly from store instead of from global --- conference.js | 1 + css/_videolayout_default.scss | 6 ++++- modules/UI/videolayout/LargeVideoManager.js | 24 +++++++++++++++---- modules/UI/videolayout/VideoContainer.js | 4 ++-- modules/UI/videolayout/VideoLayout.js | 17 ++++++++++--- .../large-video/components/LargeVideo.web.js | 4 +--- 6 files changed, 43 insertions(+), 13 deletions(-) diff --git a/conference.js b/conference.js index 91460f30f..e14cb6e23 100644 --- a/conference.js +++ b/conference.js @@ -1237,6 +1237,7 @@ export default { = connection.initJitsiConference( APP.conference.roomName, this._getConferenceOptions()); + APP.store.dispatch(conferenceWillJoin(room)); this._setLocalAudioVideoStreams(localTracks); this._room = room; // FIXME do not use this diff --git a/css/_videolayout_default.scss b/css/_videolayout_default.scss index 3864ebba4..0f6b163ec 100644 --- a/css/_videolayout_default.scss +++ b/css/_videolayout_default.scss @@ -496,18 +496,22 @@ display:none !important; } +#dominantSpeakerAvatarContainer, #dominantSpeakerAvatar, .dynamic-shadow { width: 200px; height: 200px; } -#dominantSpeakerAvatar { +#dominantSpeakerAvatarContainer { top: 50px; margin: auto; position: relative; border-radius: 100px; + overflow: hidden; visibility: inherit; +} +#dominantSpeakerAvatar { background-color: #000000; } diff --git a/modules/UI/videolayout/LargeVideoManager.js b/modules/UI/videolayout/LargeVideoManager.js index 8fa3e8383..769d0fa93 100644 --- a/modules/UI/videolayout/LargeVideoManager.js +++ b/modules/UI/videolayout/LargeVideoManager.js @@ -6,6 +6,10 @@ import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { i18next } from '../../../react/features/base/i18n'; +import { + Avatar, + getAvatarURLByParticipantId +} from '../../../react/features/base/participants'; import { PresenceLabel } from '../../../react/features/presence-status'; /* eslint-enable no-unused-vars */ @@ -14,9 +18,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename); import { JitsiParticipantConnectionStatus } from '../../../react/features/base/lib-jitsi-meet'; -import { - getAvatarURLByParticipantId -} from '../../../react/features/base/participants'; import { updateKnownLargeVideoResolution } from '../../../react/features/large-video'; @@ -95,6 +96,9 @@ export default class LargeVideoManager { = this._onVideoResolutionUpdate.bind(this); this.videoContainer.addResizeListener(this._onVideoResolutionUpdate); + + this._dominantSpeakerAvatarContainer + = document.getElementById('dominantSpeakerAvatarContainer'); } /** @@ -109,6 +113,8 @@ export default class LargeVideoManager { this.removePresenceLabel(); + ReactDOM.unmountComponentAtNode(this._dominantSpeakerAvatarContainer); + this.$container.css({ display: 'none' }); } @@ -394,7 +400,17 @@ export default class LargeVideoManager { * Updates the src of the dominant speaker avatar */ updateAvatar(avatarUrl) { - $('#dominantSpeakerAvatar').attr('src', avatarUrl); + if (avatarUrl) { + ReactDOM.render( + , + this._dominantSpeakerAvatarContainer + ); + } else { + ReactDOM.unmountComponentAtNode( + this._dominantSpeakerAvatarContainer); + } } /** diff --git a/modules/UI/videolayout/VideoContainer.js b/modules/UI/videolayout/VideoContainer.js index b5e3b189b..69dc65b5d 100644 --- a/modules/UI/videolayout/VideoContainer.js +++ b/modules/UI/videolayout/VideoContainer.js @@ -265,7 +265,7 @@ export class VideoContainer extends LargeContainer { */ this.$wrapperParent = this.$wrapper.parent(); - this.avatarHeight = $('#dominantSpeakerAvatar').height(); + this.avatarHeight = $('#dominantSpeakerAvatarContainer').height(); const onPlayingCallback = function(event) { if (typeof resizeContainer === 'function') { @@ -408,7 +408,7 @@ export class VideoContainer extends LargeContainer { */ _positionParticipantStatus($element) { if (this.avatarDisplayed) { - const $avatarImage = $('#dominantSpeakerAvatar'); + const $avatarImage = $('#dominantSpeakerAvatarContainer'); $element.css( 'top', diff --git a/modules/UI/videolayout/VideoLayout.js b/modules/UI/videolayout/VideoLayout.js index 9501e20f9..fcbb50217 100644 --- a/modules/UI/videolayout/VideoLayout.js +++ b/modules/UI/videolayout/VideoLayout.js @@ -10,6 +10,7 @@ import { } from '../../../react/features/base/lib-jitsi-meet'; import { VIDEO_TYPE } from '../../../react/features/base/media'; import { + getLocalParticipant as getLocalParticipantFromStore, getPinnedParticipant, pinParticipant } from '../../../react/features/base/participants'; @@ -75,6 +76,16 @@ function getAllThumbnails() { ]; } +/** + * Private helper to get the redux representation of the local participant. + * + * @private + * @returns {Object} + */ +function getLocalParticipant() { + return getLocalParticipantFromStore(APP.store.getState()); +} + /** * Returns the user ID of the remote participant that is current the dominant * speaker. @@ -181,7 +192,7 @@ const VideoLayout = { }, changeLocalVideo(stream) { - const localId = APP.conference.getMyUserId(); + const localId = getLocalParticipant().id; this.onVideoTypeChanged(localId, stream.videoType); @@ -198,7 +209,7 @@ const VideoLayout = { */ mucJoined() { if (largeVideo && !largeVideo.id) { - this.updateLargeVideo(APP.conference.getMyUserId(), true); + this.updateLargeVideo(getLocalParticipant().id, true); } // FIXME: replace this call with a generic update call once SmallVideo @@ -302,7 +313,7 @@ const VideoLayout = { // Go with local video logger.info('Fallback to local video...'); - const id = APP.conference.getMyUserId(); + const { id } = getLocalParticipant(); logger.info(`electLastVisibleVideo: ${id}`); diff --git a/react/features/large-video/components/LargeVideo.web.js b/react/features/large-video/components/LargeVideo.web.js index 04253801a..7e11c6af5 100644 --- a/react/features/large-video/components/LargeVideo.web.js +++ b/react/features/large-video/components/LargeVideo.web.js @@ -34,9 +34,7 @@ export default class LargeVideo extends Component<{}> {
- +