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:
parent
f77e1dc591
commit
b7133f5717
|
@ -1237,6 +1237,7 @@ export default {
|
||||||
= connection.initJitsiConference(
|
= connection.initJitsiConference(
|
||||||
APP.conference.roomName,
|
APP.conference.roomName,
|
||||||
this._getConferenceOptions());
|
this._getConferenceOptions());
|
||||||
|
|
||||||
APP.store.dispatch(conferenceWillJoin(room));
|
APP.store.dispatch(conferenceWillJoin(room));
|
||||||
this._setLocalAudioVideoStreams(localTracks);
|
this._setLocalAudioVideoStreams(localTracks);
|
||||||
this._room = room; // FIXME do not use this
|
this._room = room; // FIXME do not use this
|
||||||
|
|
|
@ -496,18 +496,22 @@
|
||||||
display:none !important;
|
display:none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dominantSpeakerAvatarContainer,
|
||||||
#dominantSpeakerAvatar,
|
#dominantSpeakerAvatar,
|
||||||
.dynamic-shadow {
|
.dynamic-shadow {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dominantSpeakerAvatar {
|
#dominantSpeakerAvatarContainer {
|
||||||
top: 50px;
|
top: 50px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
|
overflow: hidden;
|
||||||
visibility: inherit;
|
visibility: inherit;
|
||||||
|
}
|
||||||
|
#dominantSpeakerAvatar {
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ import { I18nextProvider } from 'react-i18next';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import { i18next } from '../../../react/features/base/i18n';
|
import { i18next } from '../../../react/features/base/i18n';
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
getAvatarURLByParticipantId
|
||||||
|
} from '../../../react/features/base/participants';
|
||||||
import { PresenceLabel } from '../../../react/features/presence-status';
|
import { PresenceLabel } from '../../../react/features/presence-status';
|
||||||
/* eslint-enable no-unused-vars */
|
/* eslint-enable no-unused-vars */
|
||||||
|
|
||||||
|
@ -14,9 +18,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
import {
|
import {
|
||||||
JitsiParticipantConnectionStatus
|
JitsiParticipantConnectionStatus
|
||||||
} from '../../../react/features/base/lib-jitsi-meet';
|
} from '../../../react/features/base/lib-jitsi-meet';
|
||||||
import {
|
|
||||||
getAvatarURLByParticipantId
|
|
||||||
} from '../../../react/features/base/participants';
|
|
||||||
import {
|
import {
|
||||||
updateKnownLargeVideoResolution
|
updateKnownLargeVideoResolution
|
||||||
} from '../../../react/features/large-video';
|
} from '../../../react/features/large-video';
|
||||||
|
@ -95,6 +96,9 @@ export default class LargeVideoManager {
|
||||||
= this._onVideoResolutionUpdate.bind(this);
|
= this._onVideoResolutionUpdate.bind(this);
|
||||||
|
|
||||||
this.videoContainer.addResizeListener(this._onVideoResolutionUpdate);
|
this.videoContainer.addResizeListener(this._onVideoResolutionUpdate);
|
||||||
|
|
||||||
|
this._dominantSpeakerAvatarContainer
|
||||||
|
= document.getElementById('dominantSpeakerAvatarContainer');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +113,8 @@ export default class LargeVideoManager {
|
||||||
|
|
||||||
this.removePresenceLabel();
|
this.removePresenceLabel();
|
||||||
|
|
||||||
|
ReactDOM.unmountComponentAtNode(this._dominantSpeakerAvatarContainer);
|
||||||
|
|
||||||
this.$container.css({ display: 'none' });
|
this.$container.css({ display: 'none' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +400,17 @@ export default class LargeVideoManager {
|
||||||
* Updates the src of the dominant speaker avatar
|
* Updates the src of the dominant speaker avatar
|
||||||
*/
|
*/
|
||||||
updateAvatar(avatarUrl) {
|
updateAvatar(avatarUrl) {
|
||||||
$('#dominantSpeakerAvatar').attr('src', avatarUrl);
|
if (avatarUrl) {
|
||||||
|
ReactDOM.render(
|
||||||
|
<Avatar
|
||||||
|
id = "dominantSpeakerAvatar"
|
||||||
|
uri = { avatarUrl } />,
|
||||||
|
this._dominantSpeakerAvatarContainer
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ReactDOM.unmountComponentAtNode(
|
||||||
|
this._dominantSpeakerAvatarContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -265,7 +265,7 @@ export class VideoContainer extends LargeContainer {
|
||||||
*/
|
*/
|
||||||
this.$wrapperParent = this.$wrapper.parent();
|
this.$wrapperParent = this.$wrapper.parent();
|
||||||
|
|
||||||
this.avatarHeight = $('#dominantSpeakerAvatar').height();
|
this.avatarHeight = $('#dominantSpeakerAvatarContainer').height();
|
||||||
|
|
||||||
const onPlayingCallback = function(event) {
|
const onPlayingCallback = function(event) {
|
||||||
if (typeof resizeContainer === 'function') {
|
if (typeof resizeContainer === 'function') {
|
||||||
|
@ -408,7 +408,7 @@ export class VideoContainer extends LargeContainer {
|
||||||
*/
|
*/
|
||||||
_positionParticipantStatus($element) {
|
_positionParticipantStatus($element) {
|
||||||
if (this.avatarDisplayed) {
|
if (this.avatarDisplayed) {
|
||||||
const $avatarImage = $('#dominantSpeakerAvatar');
|
const $avatarImage = $('#dominantSpeakerAvatarContainer');
|
||||||
|
|
||||||
$element.css(
|
$element.css(
|
||||||
'top',
|
'top',
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
} from '../../../react/features/base/lib-jitsi-meet';
|
} from '../../../react/features/base/lib-jitsi-meet';
|
||||||
import { VIDEO_TYPE } from '../../../react/features/base/media';
|
import { VIDEO_TYPE } from '../../../react/features/base/media';
|
||||||
import {
|
import {
|
||||||
|
getLocalParticipant as getLocalParticipantFromStore,
|
||||||
getPinnedParticipant,
|
getPinnedParticipant,
|
||||||
pinParticipant
|
pinParticipant
|
||||||
} from '../../../react/features/base/participants';
|
} 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
|
* Returns the user ID of the remote participant that is current the dominant
|
||||||
* speaker.
|
* speaker.
|
||||||
|
@ -181,7 +192,7 @@ const VideoLayout = {
|
||||||
},
|
},
|
||||||
|
|
||||||
changeLocalVideo(stream) {
|
changeLocalVideo(stream) {
|
||||||
const localId = APP.conference.getMyUserId();
|
const localId = getLocalParticipant().id;
|
||||||
|
|
||||||
this.onVideoTypeChanged(localId, stream.videoType);
|
this.onVideoTypeChanged(localId, stream.videoType);
|
||||||
|
|
||||||
|
@ -198,7 +209,7 @@ const VideoLayout = {
|
||||||
*/
|
*/
|
||||||
mucJoined() {
|
mucJoined() {
|
||||||
if (largeVideo && !largeVideo.id) {
|
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
|
// FIXME: replace this call with a generic update call once SmallVideo
|
||||||
|
@ -302,7 +313,7 @@ const VideoLayout = {
|
||||||
// Go with local video
|
// Go with local video
|
||||||
logger.info('Fallback to local video...');
|
logger.info('Fallback to local video...');
|
||||||
|
|
||||||
const id = APP.conference.getMyUserId();
|
const { id } = getLocalParticipant();
|
||||||
|
|
||||||
logger.info(`electLastVisibleVideo: ${id}`);
|
logger.info(`electLastVisibleVideo: ${id}`);
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,7 @@ export default class LargeVideo extends Component<{}> {
|
||||||
|
|
||||||
<div id = 'dominantSpeaker'>
|
<div id = 'dominantSpeaker'>
|
||||||
<div className = 'dynamic-shadow' />
|
<div className = 'dynamic-shadow' />
|
||||||
<img
|
<div id = 'dominantSpeakerAvatarContainer' />
|
||||||
id = 'dominantSpeakerAvatar'
|
|
||||||
src = '' />
|
|
||||||
</div>
|
</div>
|
||||||
<div id = 'remotePresenceMessage' />
|
<div id = 'remotePresenceMessage' />
|
||||||
<span id = 'remoteConnectionMessage' />
|
<span id = 'remoteConnectionMessage' />
|
||||||
|
|
Loading…
Reference in New Issue