Sfoglia il codice sorgente

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
j8
virtuacoplenny 6 anni fa
parent
commit
b7133f5717
Nessun account collegato all'indirizzo email del committer

+ 1
- 0
conference.js Vedi File

@@ -1237,6 +1237,7 @@ export default {
1237 1237
             = connection.initJitsiConference(
1238 1238
                 APP.conference.roomName,
1239 1239
                 this._getConferenceOptions());
1240
+
1240 1241
         APP.store.dispatch(conferenceWillJoin(room));
1241 1242
         this._setLocalAudioVideoStreams(localTracks);
1242 1243
         this._room = room; // FIXME do not use this

+ 5
- 1
css/_videolayout_default.scss Vedi File

@@ -496,18 +496,22 @@
496 496
     display:none !important;
497 497
 }
498 498
 
499
+#dominantSpeakerAvatarContainer,
499 500
 #dominantSpeakerAvatar,
500 501
 .dynamic-shadow {
501 502
     width: 200px;
502 503
     height: 200px;
503 504
 }
504 505
 
505
-#dominantSpeakerAvatar {
506
+#dominantSpeakerAvatarContainer {
506 507
     top: 50px;
507 508
     margin: auto;
508 509
     position: relative;
509 510
     border-radius: 100px;
511
+    overflow: hidden;
510 512
     visibility: inherit;
513
+}
514
+#dominantSpeakerAvatar {
511 515
     background-color: #000000;
512 516
 }
513 517
 

+ 20
- 4
modules/UI/videolayout/LargeVideoManager.js Vedi File

@@ -6,6 +6,10 @@ import { I18nextProvider } from 'react-i18next';
6 6
 import { Provider } from 'react-redux';
7 7
 
8 8
 import { i18next } from '../../../react/features/base/i18n';
9
+import {
10
+    Avatar,
11
+    getAvatarURLByParticipantId
12
+} from '../../../react/features/base/participants';
9 13
 import { PresenceLabel } from '../../../react/features/presence-status';
10 14
 /* eslint-enable no-unused-vars */
11 15
 
@@ -14,9 +18,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
14 18
 import {
15 19
     JitsiParticipantConnectionStatus
16 20
 } from '../../../react/features/base/lib-jitsi-meet';
17
-import {
18
-    getAvatarURLByParticipantId
19
-} from '../../../react/features/base/participants';
20 21
 import {
21 22
     updateKnownLargeVideoResolution
22 23
 } from '../../../react/features/large-video';
@@ -95,6 +96,9 @@ export default class LargeVideoManager {
95 96
             = this._onVideoResolutionUpdate.bind(this);
96 97
 
97 98
         this.videoContainer.addResizeListener(this._onVideoResolutionUpdate);
99
+
100
+        this._dominantSpeakerAvatarContainer
101
+            = document.getElementById('dominantSpeakerAvatarContainer');
98 102
     }
99 103
 
100 104
     /**
@@ -109,6 +113,8 @@ export default class LargeVideoManager {
109 113
 
110 114
         this.removePresenceLabel();
111 115
 
116
+        ReactDOM.unmountComponentAtNode(this._dominantSpeakerAvatarContainer);
117
+
112 118
         this.$container.css({ display: 'none' });
113 119
     }
114 120
 
@@ -394,7 +400,17 @@ export default class LargeVideoManager {
394 400
      * Updates the src of the dominant speaker avatar
395 401
      */
396 402
     updateAvatar(avatarUrl) {
397
-        $('#dominantSpeakerAvatar').attr('src', avatarUrl);
403
+        if (avatarUrl) {
404
+            ReactDOM.render(
405
+                <Avatar
406
+                    id = "dominantSpeakerAvatar"
407
+                    uri = { avatarUrl } />,
408
+                this._dominantSpeakerAvatarContainer
409
+            );
410
+        } else {
411
+            ReactDOM.unmountComponentAtNode(
412
+                this._dominantSpeakerAvatarContainer);
413
+        }
398 414
     }
399 415
 
400 416
     /**

+ 2
- 2
modules/UI/videolayout/VideoContainer.js Vedi File

@@ -265,7 +265,7 @@ export class VideoContainer extends LargeContainer {
265 265
          */
266 266
         this.$wrapperParent = this.$wrapper.parent();
267 267
 
268
-        this.avatarHeight = $('#dominantSpeakerAvatar').height();
268
+        this.avatarHeight = $('#dominantSpeakerAvatarContainer').height();
269 269
 
270 270
         const onPlayingCallback = function(event) {
271 271
             if (typeof resizeContainer === 'function') {
@@ -408,7 +408,7 @@ export class VideoContainer extends LargeContainer {
408 408
      */
409 409
     _positionParticipantStatus($element) {
410 410
         if (this.avatarDisplayed) {
411
-            const $avatarImage = $('#dominantSpeakerAvatar');
411
+            const $avatarImage = $('#dominantSpeakerAvatarContainer');
412 412
 
413 413
             $element.css(
414 414
                 'top',

+ 14
- 3
modules/UI/videolayout/VideoLayout.js Vedi File

@@ -10,6 +10,7 @@ import {
10 10
 } from '../../../react/features/base/lib-jitsi-meet';
11 11
 import { VIDEO_TYPE } from '../../../react/features/base/media';
12 12
 import {
13
+    getLocalParticipant as getLocalParticipantFromStore,
13 14
     getPinnedParticipant,
14 15
     pinParticipant
15 16
 } from '../../../react/features/base/participants';
@@ -75,6 +76,16 @@ function getAllThumbnails() {
75 76
     ];
76 77
 }
77 78
 
79
+/**
80
+ * Private helper to get the redux representation of the local participant.
81
+ *
82
+ * @private
83
+ * @returns {Object}
84
+ */
85
+function getLocalParticipant() {
86
+    return getLocalParticipantFromStore(APP.store.getState());
87
+}
88
+
78 89
 /**
79 90
  * Returns the user ID of the remote participant that is current the dominant
80 91
  * speaker.
@@ -181,7 +192,7 @@ const VideoLayout = {
181 192
     },
182 193
 
183 194
     changeLocalVideo(stream) {
184
-        const localId = APP.conference.getMyUserId();
195
+        const localId = getLocalParticipant().id;
185 196
 
186 197
         this.onVideoTypeChanged(localId, stream.videoType);
187 198
 
@@ -198,7 +209,7 @@ const VideoLayout = {
198 209
      */
199 210
     mucJoined() {
200 211
         if (largeVideo && !largeVideo.id) {
201
-            this.updateLargeVideo(APP.conference.getMyUserId(), true);
212
+            this.updateLargeVideo(getLocalParticipant().id, true);
202 213
         }
203 214
 
204 215
         // FIXME: replace this call with a generic update call once SmallVideo
@@ -302,7 +313,7 @@ const VideoLayout = {
302 313
         // Go with local video
303 314
         logger.info('Fallback to local video...');
304 315
 
305
-        const id = APP.conference.getMyUserId();
316
+        const { id } = getLocalParticipant();
306 317
 
307 318
         logger.info(`electLastVisibleVideo: ${id}`);
308 319
 

+ 1
- 3
react/features/large-video/components/LargeVideo.web.js Vedi File

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

Loading…
Annulla
Salva