ソースを参照

Fixes issues with invalid avatars and problems with switching between videos.

master
paweldomas 10年前
コミット
c3548eb866

+ 1
- 1
index.html ファイルの表示

22
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
22
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
23
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
23
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
24
     <script src="interface_config.js?v=5"></script>
24
     <script src="interface_config.js?v=5"></script>
25
-    <script src="libs/app.bundle.js?v=106"></script>
25
+    <script src="libs/app.bundle.js?v=107"></script>
26
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
26
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
27
     <link rel="stylesheet" href="css/font.css?v=7"/>
27
     <link rel="stylesheet" href="css/font.css?v=7"/>
28
     <link rel="stylesheet" href="css/toastr.css?v=1">
28
     <link rel="stylesheet" href="css/toastr.css?v=1">

+ 22534
- 22502
libs/app.bundle.js
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 10
- 2
modules/UI/UI.js ファイルの表示

449
     $("#localNick").html(Strophe.getResourceFromJid(jid) + " (" + meHTML + ")");
449
     $("#localNick").html(Strophe.getResourceFromJid(jid) + " (" + meHTML + ")");
450
 
450
 
451
     var settings = Settings.getSettings();
451
     var settings = Settings.getSettings();
452
+
453
+    // Make sure we configure our avatar id, before creating avatar for us
454
+    Avatar.setUserAvatar(jid, settings.email || settings.uid);
455
+
452
     // Add myself to the contact list.
456
     // Add myself to the contact list.
453
-    ContactList.addContact(jid, settings.email || settings.uid);
457
+    ContactList.addContact(jid);
454
 
458
 
455
     // Once we've joined the muc show the toolbar
459
     // Once we've joined the muc show the toolbar
456
     ToolbarToggler.showToolbar();
460
     ToolbarToggler.showToolbar();
572
     if(!config.startAudioMuted ||
576
     if(!config.startAudioMuted ||
573
         config.startAudioMuted > APP.members.size())
577
         config.startAudioMuted > APP.members.size())
574
         UIUtil.playSoundNotification('userJoined');
578
         UIUtil.playSoundNotification('userJoined');
579
+
580
+    // Configure avatar
581
+    Avatar.setUserAvatar(jid, id);
582
+
575
     // Add Peer's container
583
     // Add Peer's container
576
-    VideoLayout.ensurePeerContainerExists(jid,id);
584
+    VideoLayout.ensurePeerContainerExists(jid);
577
 }
585
 }
578
 
586
 
579
 function onMucPresenceStatus(jid, info) {
587
 function onMucPresenceStatus(jid, info) {

+ 33
- 5
modules/UI/avatar/Avatar.js ファイルの表示

17
             }
17
             }
18
             users[jid] = id;
18
             users[jid] = id;
19
         }
19
         }
20
-        var thumbUrl = this.getGravatarUrl(users[jid] || jid, 100);
21
-        var contactListUrl = this.getGravatarUrl(users[jid] || jid);
20
+        var thumbUrl = this.getThumbUrl(jid);
21
+        var contactListUrl = this.getContactListUrl(jid);
22
         var resourceJid = Strophe.getResourceFromJid(jid);
22
         var resourceJid = Strophe.getResourceFromJid(jid);
23
 
23
 
24
         APP.UI.userAvatarChanged(resourceJid, thumbUrl, contactListUrl);
24
         APP.UI.userAvatarChanged(resourceJid, thumbUrl, contactListUrl);
25
     },
25
     },
26
-    getGravatarUrl: function (id, size) {
27
-        if(id === APP.xmpp.myJid() || !id) {
28
-            id = Settings.getSettings().uid;
26
+    /**
27
+     * Returns image URL for the avatar to be displayed on large video area
28
+     * where current active speaker is presented.
29
+     * @param jid full MUC jid of the user for whom we want to obtain avatar URL
30
+     */
31
+    getActiveSpeakerUrl: function (jid) {
32
+        return this.getGravatarUrl(jid, 100);
33
+    },
34
+    /**
35
+     * Returns image URL for the avatar to be displayed on small video thumbnail
36
+     * @param jid full MUC jid of the user for whom we want to obtain avatar URL
37
+     */
38
+    getThumbUrl: function (jid) {
39
+        return this.getGravatarUrl(jid, 100);
40
+    },
41
+    /**
42
+     * Returns the URL for the avatar to be displayed as contactlist item
43
+     * @param jid full MUC jid of the user for whom we want to obtain avatar URL
44
+     */
45
+    getContactListUrl: function (jid) {
46
+        return this.getGravatarUrl(jid, 30);
47
+    },
48
+    getGravatarUrl: function (jid, size) {
49
+        if (!jid) {
50
+            console.error("Get gravatar - jid is undefined");
51
+            return null;
52
+        }
53
+        var id = users[jid];
54
+        if (!id) {
55
+            console.warn("No avatar stored yet for " + jid);
56
+            return null;
29
         }
57
         }
30
         return 'https://www.gravatar.com/avatar/' +
58
         return 'https://www.gravatar.com/avatar/' +
31
             MD5.hexdigest(id.trim().toLowerCase()) +
59
             MD5.hexdigest(id.trim().toLowerCase()) +

+ 8
- 8
modules/UI/side_pannels/contactlist/ContactList.js ファイルの表示

1
 
1
 
2
+var Avatar = require('../../avatar/Avatar');
3
+
2
 var numberOfContacts = 0;
4
 var numberOfContacts = 0;
3
 var notificationInterval;
5
 var notificationInterval;
4
 
6
 
27
  *
29
  *
28
  * @return the newly created avatar element
30
  * @return the newly created avatar element
29
  */
31
  */
30
-function createAvatar(id) {
32
+function createAvatar(jid) {
31
     var avatar = document.createElement('img');
33
     var avatar = document.createElement('img');
32
     avatar.className = "icon-avatar avatar";
34
     avatar.className = "icon-avatar avatar";
33
-    avatar.src = "https://www.gravatar.com/avatar/" + id + "?d=wavatar&size=30";
35
+    avatar.src = Avatar.getContactListUrl(jid);
34
 
36
 
35
     return avatar;
37
     return avatar;
36
 }
38
 }
82
      * Adds a contact for the given peerJid if such doesn't yet exist.
84
      * Adds a contact for the given peerJid if such doesn't yet exist.
83
      *
85
      *
84
      * @param peerJid the peerJid corresponding to the contact
86
      * @param peerJid the peerJid corresponding to the contact
85
-     * @param id the user's email or userId used to get the user's avatar
86
      */
87
      */
87
-    ensureAddContact: function (peerJid, id) {
88
+    ensureAddContact: function (peerJid) {
88
         var resourceJid = Strophe.getResourceFromJid(peerJid);
89
         var resourceJid = Strophe.getResourceFromJid(peerJid);
89
 
90
 
90
         var contact = $('#contacts>li[id="' + resourceJid + '"]');
91
         var contact = $('#contacts>li[id="' + resourceJid + '"]');
91
 
92
 
92
         if (!contact || contact.length <= 0)
93
         if (!contact || contact.length <= 0)
93
-            ContactList.addContact(peerJid, id);
94
+            ContactList.addContact(peerJid);
94
     },
95
     },
95
 
96
 
96
     /**
97
     /**
97
      * Adds a contact for the given peer jid.
98
      * Adds a contact for the given peer jid.
98
      *
99
      *
99
      * @param peerJid the jid of the contact to add
100
      * @param peerJid the jid of the contact to add
100
-     * @param id the email or userId of the user
101
      */
101
      */
102
-    addContact: function (peerJid, id) {
102
+    addContact: function (peerJid) {
103
         var resourceJid = Strophe.getResourceFromJid(peerJid);
103
         var resourceJid = Strophe.getResourceFromJid(peerJid);
104
 
104
 
105
         var contactlist = $('#contacts');
105
         var contactlist = $('#contacts');
113
             }
113
             }
114
         };
114
         };
115
 
115
 
116
-        newContact.appendChild(createAvatar(id));
116
+        newContact.appendChild(createAvatar(peerJid));
117
         newContact.appendChild(createDisplayNameParagraph("participant"));
117
         newContact.appendChild(createDisplayNameParagraph("participant"));
118
 
118
 
119
         if (resourceJid === APP.xmpp.myResource()) {
119
         if (resourceJid === APP.xmpp.myResource()) {

+ 3
- 1
modules/UI/videolayout/ConnectionIndicator.js ファイルの表示

155
     if(this.videoContainer.videoSpanId == "localVideoContainer") {
155
     if(this.videoContainer.videoSpanId == "localVideoContainer") {
156
         result += "<div class=\"jitsipopover_showmore\" " +
156
         result += "<div class=\"jitsipopover_showmore\" " +
157
             "onclick = \"APP.UI.connectionIndicatorShowMore('" +
157
             "onclick = \"APP.UI.connectionIndicatorShowMore('" +
158
-            this.jid + "')\"  data-i18n='connectionindicator." +
158
+            // FIXME: we do not know local jid when this text is generated
159
+            //this.jid + "')\"  data-i18n='connectionindicator." +
160
+            "local')\"  data-i18n='connectionindicator." +
159
                 (this.showMoreValue ? "less" : "more") + "'>" +
161
                 (this.showMoreValue ? "less" : "more") + "'>" +
160
             translate("connectionindicator." + (this.showMoreValue ? "less" : "more")) +
162
             translate("connectionindicator." + (this.showMoreValue ? "less" : "more")) +
161
             "</div><br />";
163
             "</div><br />";

+ 13
- 8
modules/UI/videolayout/LargeVideo.js ファイルの表示

185
 function updateActiveSpeakerAvatarSrc() {
185
 function updateActiveSpeakerAvatarSrc() {
186
     var avatar = $("#activeSpeakerAvatar")[0];
186
     var avatar = $("#activeSpeakerAvatar")[0];
187
     var jid = currentSmallVideo.peerJid;
187
     var jid = currentSmallVideo.peerJid;
188
-    var url = Avatar.getGravatarUrl(jid);
188
+    var url = Avatar.getActiveSpeakerUrl(jid);
189
     if (avatar.src === url)
189
     if (avatar.src === url)
190
         return;
190
         return;
191
     var isMuted = null;
191
     var isMuted = null;
192
     if (!currentSmallVideo.isLocal &&
192
     if (!currentSmallVideo.isLocal &&
193
-       !LargeVideo.VideoLayout.isInLastN(currentSmallVideo.resourceJid)) {
193
+       !LargeVideo.VideoLayout.isInLastN(currentSmallVideo.getResourceJid())) {
194
         isMuted = true;
194
         isMuted = true;
195
     }
195
     }
196
     else
196
     else
280
     isLargeVideoVisible: function() {
280
     isLargeVideoVisible: function() {
281
         return $('#largeVideo').is(':visible');
281
         return $('#largeVideo').is(':visible');
282
     },
282
     },
283
+    /**
284
+     * Returns <tt>true</tt> if the user is currently displayed on large video.
285
+     */
286
+    isCurrentlyOnLarge: function (resourceJid) {
287
+        return currentSmallVideo && resourceJid &&
288
+            currentSmallVideo.getResourceJid() === resourceJid;
289
+    },
283
     /**
290
     /**
284
      * Updates the large video with the given new video source.
291
      * Updates the large video with the given new video source.
285
      */
292
      */
287
         var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid);
294
         var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid);
288
         console.log('hover in ' + resourceJid + ', video: ', newSmallVideo);
295
         console.log('hover in ' + resourceJid + ', video: ', newSmallVideo);
289
 
296
 
290
-        if ((currentSmallVideo && currentSmallVideo.resourceJid !== resourceJid)
291
-            || forceUpdate) {
297
+        if (!LargeVideo.isCurrentlyOnLarge(resourceJid) || forceUpdate) {
292
             $('#activeSpeaker').css('visibility', 'hidden');
298
             $('#activeSpeaker').css('visibility', 'hidden');
293
 
299
 
294
             if(currentSmallVideo) {
300
             if(currentSmallVideo) {
337
         }
343
         }
338
     },
344
     },
339
     onVideoTypeChanged: function (jid) {
345
     onVideoTypeChanged: function (jid) {
340
-        if(jid && currentSmallVideo && jid === currentSmallVideo.peerJid)
346
+        var resourceJid = Strophe.getResourceFromJid(jid);
347
+        if (LargeVideo.isCurrentlyOnLarge(resourceJid))
341
         {
348
         {
342
             var isDesktop = APP.RTC.isVideoSrcDesktop(jid);
349
             var isDesktop = APP.RTC.isVideoSrcDesktop(jid);
343
             getVideoSize = isDesktop
350
             getVideoSize = isDesktop
438
         this.position(null, null, size[0], size[1], true);
445
         this.position(null, null, size[0], size[1], true);
439
     },
446
     },
440
     getResourceJid: function () {
447
     getResourceJid: function () {
441
-        if(!currentSmallVideo)
442
-            return null;
443
-        return currentSmallVideo.resourceJid;
448
+        return currentSmallVideo ? currentSmallVideo.getResourceJid() : null;
444
     },
449
     },
445
     updateAvatar: function (resourceJid) {
450
     updateAvatar: function (resourceJid) {
446
         if (resourceJid === this.getResourceJid()) {
451
         if (resourceJid === this.getResourceJid()) {

+ 12
- 6
modules/UI/videolayout/LocalVideo.js ファイルの表示

13
     this.flipX = true;
13
     this.flipX = true;
14
     this.isLocal = true;
14
     this.isLocal = true;
15
     this.peerJid = null;
15
     this.peerJid = null;
16
-    this.resourceJid = null;
17
 }
16
 }
18
 
17
 
19
 LocalVideo.prototype = Object.create(SmallVideo.prototype);
18
 LocalVideo.prototype = Object.create(SmallVideo.prototype);
184
             self.showDisplayName(true);
183
             self.showDisplayName(true);
185
         },
184
         },
186
         function() {
185
         function() {
187
-            if (!LargeVideo.isLargeVideoVisible()
188
-                || APP.xmpp.myResource() !== LargeVideo.getResourceJid())
186
+            if (!LargeVideo.isLargeVideoVisible() ||
187
+                !LargeVideo.isCurrentlyOnLarge(self.getResourceJid()))
189
                 self.showDisplayName(false);
188
                 self.showDisplayName(false);
190
         }
189
         }
191
     );
190
     );
231
         localVideoContainer.removeChild(localVideo);
230
         localVideoContainer.removeChild(localVideo);
232
         self.VideoLayout.updateRemovedVideo(APP.xmpp.myResource());
231
         self.VideoLayout.updateRemovedVideo(APP.xmpp.myResource());
233
     };
232
     };
234
-}
233
+};
235
 
234
 
236
 LocalVideo.prototype.joined = function (jid) {
235
 LocalVideo.prototype.joined = function (jid) {
237
     this.peerJid = jid;
236
     this.peerJid = jid;
238
-    this.resourceJid = Strophe.getResourceFromJid(jid);
239
-}
237
+};
238
+
239
+LocalVideo.prototype.getResourceJid = function () {
240
+    var myResource = APP.xmpp.myResource();
241
+    if (!myResource) {
242
+        console.error("Requested local resource before we're in the MUC");
243
+    }
244
+    return myResource;
245
+};
240
 
246
 
241
 module.exports = LocalVideo;
247
 module.exports = LocalVideo;

+ 21
- 28
modules/UI/videolayout/RemoteVideo.js ファイルの表示

57
     var popupmenuElement = document.createElement('ul');
57
     var popupmenuElement = document.createElement('ul');
58
     popupmenuElement.className = 'popupmenu';
58
     popupmenuElement.className = 'popupmenu';
59
     popupmenuElement.id
59
     popupmenuElement.id
60
-        = 'remote_popupmenu_' + this.resourceJid;
60
+        = 'remote_popupmenu_' + this.getResourceJid();
61
     spanElement.appendChild(popupmenuElement);
61
     spanElement.appendChild(popupmenuElement);
62
 
62
 
63
     var muteMenuItem = document.createElement('li');
63
     var muteMenuItem = document.createElement('li');
162
     }
162
     }
163
 
163
 
164
     if (isVideo)
164
     if (isVideo)
165
-        this.VideoLayout.updateRemovedVideo(this.resourceJid);
165
+        this.VideoLayout.updateRemovedVideo(this.getResourceJid());
166
 };
166
 };
167
 
167
 
168
 RemoteVideo.prototype.waitForPlayback = function (stream) {
168
 RemoteVideo.prototype.waitForPlayback = function (stream) {
173
     }
173
     }
174
 
174
 
175
     var self = this;
175
     var self = this;
176
-    var sel = this.VideoLayout.getPeerVideoSel(this.resourceJid);
176
+    var resourceJid = this.getResourceJid();
177
+    var sel = this.VideoLayout.getPeerVideoSel(resourceJid);
177
 
178
 
178
     // Register 'onplaying' listener to trigger 'videoactive' on VideoLayout
179
     // Register 'onplaying' listener to trigger 'videoactive' on VideoLayout
179
     // when video playback starts
180
     // when video playback starts
183
             APP.RTC.attachMediaStream(sel, stream);
184
             APP.RTC.attachMediaStream(sel, stream);
184
         }
185
         }
185
         if (RTCBrowserType.isTemasysPluginUsed()) {
186
         if (RTCBrowserType.isTemasysPluginUsed()) {
186
-            sel = $('#' + newElementId);
187
+            sel = self.VideoLayout.getPeerVideoSel(resourceJid);
187
         }
188
         }
188
-        self.VideoLayout.videoactive(sel, self.resourceJid);
189
+        self.VideoLayout.videoactive(sel, resourceJid);
189
         sel[0].onplaying = null;
190
         sel[0].onplaying = null;
190
         if (RTCBrowserType.isTemasysPluginUsed()) {
191
         if (RTCBrowserType.isTemasysPluginUsed()) {
191
             // 'currentTime' is used to check if the video has started
192
             // 'currentTime' is used to check if the video has started
229
 
230
 
230
     // Add click handler.
231
     // Add click handler.
231
     var onClickHandler = function (event) {
232
     var onClickHandler = function (event) {
232
-        /*
233
-         * FIXME It turns out that videoThumb may not exist (if there is
234
-         * no actual video).
235
-         */
236
-        var videoThumb = $('#' + self.videoSpanId + '>' + videoElem).get(0);
237
-        if (videoThumb) {
238
-            self.VideoLayout.handleVideoThumbClicked(
239
-                false,
240
-                self.resourceJid);
241
-        }
233
+
234
+        self.VideoLayout.handleVideoThumbClicked(false, self.getResourceJid());
235
+
242
         // On IE we need to populate this handler on video <object>
236
         // On IE we need to populate this handler on video <object>
243
         // and it does not give event instance as an argument,
237
         // and it does not give event instance as an argument,
244
         // so we check here for methods.
238
         // so we check here for methods.
261
             self.showDisplayName(true);
255
             self.showDisplayName(true);
262
         },
256
         },
263
         function() {
257
         function() {
264
-            var videoSrc = null;
265
-            var videoSelector = $('#' + self.videoSpanId + '>' + videoElem);
266
-            if (videoSelector && videoSelector.length > 0) {
267
-                videoSrc = APP.RTC.getVideoSrc(videoSelector.get(0));
268
-            }
269
-
270
             // If the video has been "pinned" by the user we want to
258
             // If the video has been "pinned" by the user we want to
271
             // keep the display name on place.
259
             // keep the display name on place.
272
-            if (!LargeVideo.isLargeVideoVisible()
273
-                || videoSrc !== APP.RTC.getVideoSrc($('#largeVideo')[0]))
260
+            if (!LargeVideo.isLargeVideoVisible() ||
261
+                !LargeVideo.isCurrentlyOnLarge(self.getResourceJid()))
274
                 self.showDisplayName(false);
262
                 self.showDisplayName(false);
275
         }
263
         }
276
     );
264
     );
330
  */
318
  */
331
 RemoteVideo.prototype.updateRemoteVideoMenu = function (isMuted) {
319
 RemoteVideo.prototype.updateRemoteVideoMenu = function (isMuted) {
332
     var muteMenuItem
320
     var muteMenuItem
333
-        = $('#remote_popupmenu_'
334
-        + this.resourceJid
335
-        + '>li>a.mutelink');
321
+        = $('#remote_popupmenu_' + this.getResourceJid() + '>li>a.mutelink');
336
 
322
 
337
     var mutedIndicator = "<i class='icon-mic-disabled'></i>";
323
     var mutedIndicator = "<i class='icon-mic-disabled'></i>";
338
 
324
 
348
             muteLink.className = 'mutelink';
334
             muteLink.className = 'mutelink';
349
         }
335
         }
350
     }
336
     }
351
-}
337
+};
352
 
338
 
353
 /**
339
 /**
354
  * Sets the display name for the given video span id.
340
  * Sets the display name for the given video span id.
407
     if (menuSpan.length) {
393
     if (menuSpan.length) {
408
         menuSpan.remove();
394
         menuSpan.remove();
409
     }
395
     }
410
-}
396
+};
397
+
398
+RemoteVideo.prototype.getResourceJid = function () {
399
+    if (!this.resourceJid) {
400
+        console.error("Undefined resource jid");
401
+    }
402
+    return this.resourceJid;
403
+};
411
 
404
 
412
 RemoteVideo.createContainer = function (spanId) {
405
 RemoteVideo.createContainer = function (spanId) {
413
     var container = document.createElement('span');
406
     var container = document.createElement('span');

+ 29
- 22
modules/UI/videolayout/SmallVideo.js ファイルの表示

1
+var Avatar = require("../avatar/Avatar");
1
 var UIUtil = require("../util/UIUtil");
2
 var UIUtil = require("../util/UIUtil");
2
 var LargeVideo = require("./LargeVideo");
3
 var LargeVideo = require("./LargeVideo");
3
 var RTCBrowserType = require("../../RTC/RTCBrowserType");
4
 var RTCBrowserType = require("../../RTC/RTCBrowserType");
192
 
193
 
193
 SmallVideo.prototype.enableDominantSpeaker = function (isEnable)
194
 SmallVideo.prototype.enableDominantSpeaker = function (isEnable)
194
 {
195
 {
195
-    var displayName = this.resourceJid;
196
+    var resourceJid = this.getResourceJid();
197
+    var displayName = resourceJid;
196
     var nameSpan = $('#' + this.videoSpanId + '>span.displayname');
198
     var nameSpan = $('#' + this.videoSpanId + '>span.displayname');
197
     if (nameSpan.length > 0)
199
     if (nameSpan.length > 0)
198
         displayName = nameSpan.html();
200
         displayName = nameSpan.html();
199
 
201
 
200
     console.log("UI enable dominant speaker",
202
     console.log("UI enable dominant speaker",
201
         displayName,
203
         displayName,
202
-        this.resourceJid,
204
+        resourceJid,
203
         isEnable);
205
         isEnable);
204
 
206
 
205
 
207
 
207
         return;
209
         return;
208
     }
210
     }
209
 
211
 
210
-    var video = $('#' + this.videoSpanId + '>' + APP.RTC.getVideoElementName());
212
+    if (isEnable) {
213
+        this.showDisplayName(LargeVideo.isLargeVideoOnTop());
211
 
214
 
212
-    if (video && video.length > 0) {
213
-        if (isEnable) {
214
-            this.showDisplayName(LargeVideo.isLargeVideoOnTop());
215
-
216
-            if (!this.container.classList.contains("dominantspeaker"))
217
-                this.container.classList.add("dominantspeaker");
218
-        }
219
-        else {
220
-            this.showDisplayName(false);
215
+        if (!this.container.classList.contains("dominantspeaker"))
216
+            this.container.classList.add("dominantspeaker");
217
+    }
218
+    else {
219
+        this.showDisplayName(false);
221
 
220
 
222
-            if (this.container.classList.contains("dominantspeaker"))
223
-                this.container.classList.remove("dominantspeaker");
224
-        }
221
+        if (this.container.classList.contains("dominantspeaker"))
222
+            this.container.classList.remove("dominantspeaker");
225
     }
223
     }
226
 
224
 
227
     this.showAvatar();
225
     this.showAvatar();
305
  * video because there is no dominant speaker and no focused speaker
303
  * video because there is no dominant speaker and no focused speaker
306
  */
304
  */
307
 SmallVideo.prototype.showAvatar = function (show) {
305
 SmallVideo.prototype.showAvatar = function (show) {
308
-    if (!this.hasAvatar)
309
-        return;
306
+    if (!this.hasAvatar) {
307
+        if (this.peerJid) {
308
+            // Init avatar
309
+            this.avatarChanged(Avatar.getThumbUrl(this.peerJid));
310
+        } else {
311
+            console.error("Unable to init avatar - no peerjid", this);
312
+            return;
313
+        }
314
+    }
310
 
315
 
316
+    var resourceJid = this.getResourceJid();
311
     var videoElem = APP.RTC.getVideoElementName();
317
     var videoElem = APP.RTC.getVideoElementName();
312
     var video = $('#' + this.videoSpanId).find(videoElem);
318
     var video = $('#' + this.videoSpanId).find(videoElem);
313
-    var avatar = $('#avatar_' + this.resourceJid);
319
+    var avatar = $('#avatar_' + resourceJid);
314
 
320
 
315
     if (show === undefined || show === null) {
321
     if (show === undefined || show === null) {
316
         if (!this.isLocal &&
322
         if (!this.isLocal &&
317
-            !this.VideoLayout.isInLastN(this.resourceJid)) {
323
+            !this.VideoLayout.isInLastN(resourceJid)) {
318
             show = true;
324
             show = true;
319
         }
325
         }
320
         else
326
         else
324
 
330
 
325
     }
331
     }
326
 
332
 
327
-    if (LargeVideo.showAvatar(this.resourceJid, show))
333
+    if (LargeVideo.showAvatar(resourceJid, show))
328
     {
334
     {
329
         setVisibility(avatar, false);
335
         setVisibility(avatar, false);
330
         setVisibility(video, false);
336
         setVisibility(video, false);
339
 
345
 
340
 SmallVideo.prototype.avatarChanged = function (thumbUrl) {
346
 SmallVideo.prototype.avatarChanged = function (thumbUrl) {
341
     var thumbnail = $('#' + this.videoSpanId);
347
     var thumbnail = $('#' + this.videoSpanId);
342
-    var avatar = $('#avatar_' + this.resourceJid);
348
+    var resourceJid = this.getResourceJid();
349
+    var avatar = $('#avatar_' + resourceJid);
343
     this.hasAvatar = true;
350
     this.hasAvatar = true;
344
 
351
 
345
     // set the avatar in the thumbnail
352
     // set the avatar in the thumbnail
348
     } else {
355
     } else {
349
         if (thumbnail && thumbnail.length > 0) {
356
         if (thumbnail && thumbnail.length > 0) {
350
             avatar = document.createElement('img');
357
             avatar = document.createElement('img');
351
-            avatar.id = 'avatar_' + this.resourceJid;
358
+            avatar.id = 'avatar_' + resourceJid;
352
             avatar.className = 'userAvatar';
359
             avatar.className = 'userAvatar';
353
             avatar.src = thumbUrl;
360
             avatar.src = thumbUrl;
354
             thumbnail.append(avatar);
361
             thumbnail.append(avatar);

+ 49
- 59
modules/UI/videolayout/VideoLayout.js ファイルの表示

72
 
72
 
73
         localVideoThumbnail.changeVideo(stream, isMuted);
73
         localVideoThumbnail.changeVideo(stream, isMuted);
74
 
74
 
75
-        LargeVideo.updateLargeVideo(
76
-            APP.xmpp.myResource(),
77
-            /* force update only before conference starts */
78
-            !APP.xmpp.isConferenceInProgress());
79
-
75
+        /* force update if we're currently being displayed */
76
+        if (LargeVideo.isCurrentlyOnLarge(APP.xmpp.myResource())) {
77
+            LargeVideo.updateLargeVideo(APP.xmpp.myResource(), true);
78
+        }
80
     };
79
     };
81
 
80
 
82
     my.mucJoined = function () {
81
     my.mucJoined = function () {
116
      */
115
      */
117
     my.updateRemovedVideo = function(resourceJid) {
116
     my.updateRemovedVideo = function(resourceJid) {
118
 
117
 
119
-        var videoElem = RTC.getVideoElementName();
120
-
121
         if (resourceJid === LargeVideo.getResourceJid()) {
118
         if (resourceJid === LargeVideo.getResourceJid()) {
122
-            // this is currently displayed as large
123
-            // pick the last visible video in the row
124
-            // if nobody else is left, this picks the local video
125
-            var pick
126
-                = $('#remoteVideos>' +
127
-                    'span[id!="mixedstream"]:visible:last>' + videoElem).get(0);
128
-
129
-            if (!pick) {
130
-                console.info("Last visible video no longer exists");
131
-                pick = $('#remoteVideos>' +
132
-                    'span[id!="mixedstream"]>' + videoElem).get(0);
133
-
134
-                if (!pick || !APP.RTC.getVideoSrc(pick)) {
135
-                    // Try local video
136
-                    console.info("Fallback to local video...");
137
-                    pick = $('#remoteVideos>span>span>' + videoElem).get(0);
138
-                }
139
-            }
140
-
141
-            // mute if localvideo
142
-            if (pick) {
143
-                var container = pick.parentNode;
119
+            var newResourceJid;
120
+            // We'll show user's avatar if he is the dominant speaker or if
121
+            // his video thumbnail is pinned
122
+            if (resourceJid === focusedVideoResourceJid ||
123
+                resourceJid === currentDominantSpeaker) {
124
+                newResourceJid = resourceJid;
144
             } else {
125
             } else {
145
-                console.warn("Failed to elect large video");
146
-                container = $('#remoteVideos>span[id!="mixedstream"]:visible:last').get(0);
147
-
126
+                // Otherwise select last visible video
127
+                newResourceJid = this.electLastVisibleVideo();
148
             }
128
             }
129
+            LargeVideo.updateLargeVideo(newResourceJid);
130
+        }
131
+    };
149
 
132
 
150
-            var jid = null;
151
-            if(container)
152
-            {
153
-                if(container.id == "localVideoWrapper")
154
-                {
155
-                    jid = APP.xmpp.myResource();
156
-                }
157
-                else
158
-                {
159
-                    jid = VideoLayout.getPeerContainerResourceJid(container);
160
-                }
133
+    my.electLastVisibleVideo = function() {
134
+        // pick the last visible video in the row
135
+        // if nobody else is left, this picks the local video
136
+        var jid;
137
+        var videoElem = RTC.getVideoElementName();
138
+        var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>' + videoElem);
139
+        if (pick.length && APP.RTC.getVideoSrc(pick[0])) {
140
+            return VideoLayout.getPeerContainerResourceJid(pick[0].parentNode);
141
+        } else {
142
+            console.info("Last visible video no longer exists");
143
+            pick = $('#remoteVideos>span[id!="mixedstream"]>' + videoElem);
144
+            if (pick.length && APP.RTC.getVideoSrc(pick[0])) {
145
+                return VideoLayout.getPeerContainerResourceJid(pick[0].parentNode);
146
+            } else {
147
+                // Try local video
148
+                console.info("Fallback to local video...");
149
+                return APP.xmpp.myResource();
161
             }
150
             }
162
-            else
163
-                return;
164
-
165
-            LargeVideo.updateLargeVideo(jid);
166
         }
151
         }
167
     };
152
     };
168
     
153
     
224
             }
209
             }
225
         }
210
         }
226
 
211
 
227
-        if (LargeVideo.getResourceJid() === resourceJid &&
228
-            LargeVideo.isLargeVideoOnTop()) {
229
-            return;
230
-        }
231
-
232
         // Triggers a "video.selected" event. The "false" parameter indicates
212
         // Triggers a "video.selected" event. The "false" parameter indicates
233
         // this isn't a prezi.
213
         // this isn't a prezi.
234
         $(document).trigger("video.selected", [false]);
214
         $(document).trigger("video.selected", [false]);
250
      * in the document and creates it eventually.
230
      * in the document and creates it eventually.
251
      * 
231
      * 
252
      * @param peerJid peer Jid to check.
232
      * @param peerJid peer Jid to check.
253
-     * @param userId user email or id for setting the avatar
254
      * 
233
      * 
255
      * @return Returns <tt>true</tt> if the peer container exists,
234
      * @return Returns <tt>true</tt> if the peer container exists,
256
      * <tt>false</tt> - otherwise
235
      * <tt>false</tt> - otherwise
257
      */
236
      */
258
-    my.ensurePeerContainerExists = function(peerJid, userId) {
259
-        ContactList.ensureAddContact(peerJid, userId);
237
+    my.ensurePeerContainerExists = function(peerJid) {
238
+        ContactList.ensureAddContact(peerJid);
260
 
239
 
261
         var resourceJid = Strophe.getResourceFromJid(peerJid);
240
         var resourceJid = Strophe.getResourceFromJid(peerJid);
262
 
241
 
263
         if(!remoteVideos[resourceJid])
242
         if(!remoteVideos[resourceJid])
264
         {
243
         {
265
             remoteVideos[resourceJid] = new RemoteVideo(peerJid, VideoLayout);
244
             remoteVideos[resourceJid] = new RemoteVideo(peerJid, VideoLayout);
266
-            Avatar.setUserAvatar(peerJid, userId);
267
 
245
 
268
             // In case this is not currently in the last n we don't show it.
246
             // In case this is not currently in the last n we don't show it.
269
             if (localLastNCount
247
             if (localLastNCount
282
     };
260
     };
283
 
261
 
284
     my.videoactive = function (videoelem, resourceJid) {
262
     my.videoactive = function (videoelem, resourceJid) {
263
+
264
+        console.info(resourceJid + " video is now active");
265
+
285
         videoelem.show();
266
         videoelem.show();
286
         VideoLayout.resizeThumbnails();
267
         VideoLayout.resizeThumbnails();
287
 
268
 
291
         if ((!focusedVideoResourceJid &&
272
         if ((!focusedVideoResourceJid &&
292
             !currentDominantSpeaker &&
273
             !currentDominantSpeaker &&
293
             !require("../prezi/Prezi").isPresentationVisible()) ||
274
             !require("../prezi/Prezi").isPresentationVisible()) ||
275
+            focusedVideoResourceJid === resourceJid ||
294
             (resourceJid &&
276
             (resourceJid &&
295
                 currentDominantSpeaker === resourceJid)) {
277
                 currentDominantSpeaker === resourceJid)) {
296
             LargeVideo.updateLargeVideo(resourceJid, true);
278
             LargeVideo.updateLargeVideo(resourceJid, true);
469
             return;
451
             return;
470
         }
452
         }
471
 
453
 
472
-        if (jid == APP.xmpp.myJid()) {
454
+        if (jid === APP.xmpp.myJid()) {
473
             $("#localVideoContainer").click();
455
             $("#localVideoContainer").click();
474
             return;
456
             return;
475
         }
457
         }
824
     };
806
     };
825
 
807
 
826
     my.showMore = function (jid) {
808
     my.showMore = function (jid) {
827
-        if(APP.xmpp.myJid = jid)
809
+        if (jid === 'local')
828
         {
810
         {
829
             localVideoThumbnail.connectionIndicator.showMore();
811
             localVideoThumbnail.connectionIndicator.showMore();
830
         }
812
         }
831
         else
813
         else
832
         {
814
         {
833
-            remoteVideos[Strophe.getResourceFromJid(jid)].connectionIndicator.showMore();
815
+            var remoteVideo = remoteVideos[Strophe.getResourceFromJid(jid)];
816
+            if (remoteVideo) {
817
+                remoteVideo.connectionIndicator.showMore();
818
+            } else {
819
+                console.info("Error - no remote video for jid: " + jid);
820
+            }
834
         }
821
         }
835
 
822
 
836
     };
823
     };
880
         var smallVideo = VideoLayout.getSmallVideo(resourceJid);
867
         var smallVideo = VideoLayout.getSmallVideo(resourceJid);
881
         if(smallVideo)
868
         if(smallVideo)
882
             smallVideo.avatarChanged(thumbUrl);
869
             smallVideo.avatarChanged(thumbUrl);
870
+        else
871
+            console.warn(
872
+                "Missed avatar update - no small video yet for " + resourceJid);
883
         LargeVideo.updateAvatar(resourceJid, thumbUrl);
873
         LargeVideo.updateAvatar(resourceJid, thumbUrl);
884
     };
874
     };
885
 
875
 

読み込み中…
キャンセル
保存