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
This commit is contained in:
virtuacoplenny 2019-02-06 19:19:02 -08:00 committed by GitHub
parent f77e1dc591
commit b7133f5717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 13 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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(
<Avatar
id = "dominantSpeakerAvatar"
uri = { avatarUrl } />,
this._dominantSpeakerAvatarContainer
);
} else {
ReactDOM.unmountComponentAtNode(
this._dominantSpeakerAvatarContainer);
}
}
/**

View File

@ -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',

View File

@ -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}`);

View File

@ -34,9 +34,7 @@ export default class LargeVideo extends Component<{}> {
<div id = 'dominantSpeaker'>
<div className = 'dynamic-shadow' />
<img
id = 'dominantSpeakerAvatar'
src = '' />
<div id = 'dominantSpeakerAvatarContainer' />
</div>
<div id = 'remotePresenceMessage' />
<span id = 'remoteConnectionMessage' />