Pārlūkot izejas kodu

Ongoing work on video thumbnail layout

j8
yanas 8 gadus atpakaļ
vecāks
revīzija
a17a98991c

+ 0
- 4
conference.js Parādīt failu

1279
             APP.UI.updateRecordingState(status);
1279
             APP.UI.updateRecordingState(status);
1280
         });
1280
         });
1281
 
1281
 
1282
-        room.on(ConferenceEvents.USER_STATUS_CHANGED, function (id, status) {
1283
-            APP.UI.updateUserStatus(id, status);
1284
-        });
1285
-
1286
         room.on(ConferenceEvents.KICKED, () => {
1282
         room.on(ConferenceEvents.KICKED, () => {
1287
             APP.UI.hideStats();
1283
             APP.UI.hideStats();
1288
             APP.UI.notifyKicked();
1284
             APP.UI.notifyKicked();

+ 3
- 2
css/_variables.scss Parādīt failu

11
 $defaultToolbarSize: 50px;
11
 $defaultToolbarSize: 50px;
12
 
12
 
13
 // Video layout.
13
 // Video layout.
14
-$thumbnailIndicatorSize: 23px;
14
+$thumbnailToolbarHeight: 22px;
15
 $thumbnailIndicatorBorder: 0px;
15
 $thumbnailIndicatorBorder: 0px;
16
+$thumbnailIndicatorSize: $thumbnailToolbarHeight;
16
 $thumbnailVideoMargin: 2px;
17
 $thumbnailVideoMargin: 2px;
17
-$thumbnailToolbarHeight: 25px;
18
 
18
 
19
 /**
19
 /**
20
  * Color variables.
20
  * Color variables.
46
 $dominantSpeakerBg: #165ecc;
46
 $dominantSpeakerBg: #165ecc;
47
 $raiseHandBg: #D6D61E;
47
 $raiseHandBg: #D6D61E;
48
 $audioLevelBg: #44A5FF;
48
 $audioLevelBg: #44A5FF;
49
+$connectionIndicatorBg: #48CC8C;
49
 $audioLevelShadow: rgba(9, 36, 77, 0.9);
50
 $audioLevelShadow: rgba(9, 36, 77, 0.9);
50
 $videoStateIndicatorColor: $defaultColor;
51
 $videoStateIndicatorColor: $defaultColor;
51
 $videoStateIndicatorBackground: $toolbarBackground;
52
 $videoStateIndicatorBackground: $toolbarBackground;

+ 77
- 83
css/_videolayout_default.scss Parādīt failu

58
 /**
58
 /**
59
  * The toolbar of the video thumbnail.
59
  * The toolbar of the video thumbnail.
60
  */
60
  */
61
-.videocontainer__toolbar {
61
+.videocontainer__toolbar,
62
+.videocontainer__toptoolbar {
62
     position: absolute;
63
     position: absolute;
63
-    bottom: 0;
64
     left: 0;
64
     left: 0;
65
     z-index: 1;
65
     z-index: 1;
66
     width: 100%;
66
     width: 100%;
67
     box-sizing: border-box; // Includes the padding in the 100% width.
67
     box-sizing: border-box; // Includes the padding in the 100% width.
68
     height: $thumbnailToolbarHeight;
68
     height: $thumbnailToolbarHeight;
69
-    max-height: 100%;
70
     padding: 0 5px 0 5px;
69
     padding: 0 5px 0 5px;
71
 }
70
 }
72
 
71
 
72
+.videocontainer__toolbar {
73
+    bottom: 0;
74
+}
75
+
76
+.videocontainer__toptoolbar {
77
+    top: 0;
78
+}
79
+
73
 #remoteVideos .videocontainer.videoContainerFocused,
80
 #remoteVideos .videocontainer.videoContainerFocused,
74
 #remoteVideos .videocontainer:hover {
81
 #remoteVideos .videocontainer:hover {
75
     cursor: hand;
82
     cursor: hand;
201
     padding: 0;
208
     padding: 0;
202
 }
209
 }
203
 
210
 
204
-.videocontainer>span.status {
205
-    display: inline-block;
206
-    position: absolute;
207
-    color: #FFFFFF;
208
-    background: rgba(0,0,0,.7);
209
-    text-align: center;
210
-    text-overflow: ellipsis;
211
-    width: 70%;
212
-    height: 15%;
213
-    left: 15%;
214
-    bottom: 2%;
215
-    padding: 5px;
216
-    font-size: 10pt;
217
-    overflow: hidden;
218
-    white-space: nowrap;
219
-    z-index: 2;
220
-    border-radius:3px;
221
-}
222
-
223
-.connectionindicator
224
-{
225
-    display: inline-block;
226
-    position: absolute;
227
-    top: 7px;
228
-    right: 0;
229
-    padding: 0px 5px;
230
-    z-index: 3;
231
-    width: 18px;
232
-    height: 13px;
233
-}
234
-
235
-.connection.connection_empty
236
-{
237
-    color: #8B8B8B;/*#FFFFFF*/
238
-    overflow: hidden;
239
-}
240
-
241
-.connection.connection_lost
242
-{
243
-    color: #8B8B8B;
244
-    overflow: visible;
245
-}
246
-
247
-.connection.connection_full
248
-{
249
-    color: #FFFFFF;/*#15A1ED*/
250
-    overflow: hidden;
251
-}
252
-
253
-.connection
254
-{
255
-    position: absolute;
256
-    left: 0px;
257
-    top: 0px;
258
-    font-size: 8pt;
259
-    border: 0px;
260
-    width: 18px;
261
-    height: 13px;
262
-}
263
-
264
-#localVideoContainer>span.status:hover,
265
 #localVideoContainer .displayname:hover {
211
 #localVideoContainer .displayname:hover {
266
     cursor: text;
212
     cursor: text;
267
 }
213
 }
268
 
214
 
269
-.videocontainer>span.status,
270
 .videocontainer .displayname {
215
 .videocontainer .displayname {
271
     pointer-events: none;
216
     pointer-events: none;
272
 }
217
 }
279
     pointer-events: auto !important;
224
     pointer-events: auto !important;
280
 }
225
 }
281
 
226
 
282
-.videocontainer>a.status,
283
 .videocontainer>a.displayname {
227
 .videocontainer>a.displayname {
284
     display: inline-block;
228
     display: inline-block;
285
     position: absolute;
229
     position: absolute;
324
   margin: 0px 0px 0px 5px;
268
   margin: 0px 0px 0px 5px;
325
 }
269
 }
326
 
270
 
327
-.videocontainer>span.indicator {
328
-    position: absolute;
329
-    top: 0px;
330
-    left: 0px;
271
+#raisehandindicator {
272
+  background: $raiseHandBg;
273
+}
274
+
275
+#connectionindicator {
276
+  background: $connectionIndicatorBg;
277
+}
278
+
279
+.videocontainer__toptoolbar span.indicator {
280
+    font-size: 8pt;
281
+    text-align: center;
282
+    line-height: $thumbnailToolbarHeight;
283
+    padding: 0;
284
+    margin-right: 5px;
285
+    float: left;
331
     @include circle($thumbnailIndicatorSize);
286
     @include circle($thumbnailIndicatorSize);
332
     box-sizing: border-box;
287
     box-sizing: border-box;
333
-    line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
334
     z-index: 3;
288
     z-index: 3;
335
-    text-align: center;
336
     background: $dominantSpeakerBg;
289
     background: $dominantSpeakerBg;
337
-    margin: 7px;
338
-    display: inline-block;
339
     color: $thumbnailPictogramColor;
290
     color: $thumbnailPictogramColor;
340
-    font-size: 8pt;
341
     border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
291
     border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
292
+
293
+    .indicatoricon {
294
+        width: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
295
+        height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
296
+        line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
297
+        margin-left: 5px; // TOP toolbar padding;
298
+    }
299
+
300
+    .connection.connection_empty
301
+    {
302
+        color: #8B8B8B;/*#FFFFFF*/
303
+        overflow: hidden;
304
+    }
305
+
306
+    .connection.connection_lost
307
+    {
308
+        color: #8B8B8B;
309
+        overflow: visible;
310
+    }
311
+
312
+    .connection.connection_full
313
+    {
314
+        color: #FFFFFF;/*#15A1ED*/
315
+        overflow: hidden;
316
+    }
317
+
318
+    .connection,
319
+    .icon-connection,
320
+    .icon-connection-lost {
321
+        font-size: 6pt;
322
+        line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
323
+    }
324
+
325
+    .connection
326
+    {
327
+        position: absolute;
328
+        left: 0px;
329
+        top: 0px;
330
+        border: 0px;
331
+    }
342
 }
332
 }
343
 
333
 
344
-.videocontainer>#raisehandindicator {
345
-    background: $raiseHandBg;
334
+.remotevideomenu
335
+{
336
+    display: inline-block;
337
+    position: absolute;
338
+    top: 0px;
339
+    right: 0;
340
+    margin: 7px;
341
+    z-index: 3;
342
+    width: 18px;
343
+    height: 13px;
344
+    color: #FFF;
345
+    font-size: 8pt;
346
 }
346
 }
347
 
347
 
348
 /**
348
 /**
385
     }
385
     }
386
 }
386
 }
387
 
387
 
388
-#indicatoricon {
389
-    width: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
390
-    height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
391
-    line-height: $thumbnailIndicatorSize - 2*$thumbnailIndicatorBorder;
392
-}
393
-
394
 #reloadPresentation {
388
 #reloadPresentation {
395
     display: none;
389
     display: none;
396
     position: absolute;
390
     position: absolute;

+ 1
- 0
index.html Parādīt failu

254
                     </span>
254
                     </span>
255
                     <audio id="localAudio" autoplay muted></audio>
255
                     <audio id="localAudio" autoplay muted></audio>
256
                     <div class="videocontainer__toolbar"></div>
256
                     <div class="videocontainer__toolbar"></div>
257
+                    <div class="videocontainer__toptoolbar"></div>
257
                 </span>
258
                 </span>
258
                 <audio id="userJoined" src="sounds/joined.wav" preload="auto"></audio>
259
                 <audio id="userJoined" src="sounds/joined.wav" preload="auto"></audio>
259
                 <audio id="userLeft" src="sounds/left.wav" preload="auto"></audio>
260
                 <audio id="userLeft" src="sounds/left.wav" preload="auto"></audio>

+ 0
- 4
modules/UI/UI.js Parādīt failu

609
     VideoLayout.removeParticipantContainer(id);
609
     VideoLayout.removeParticipantContainer(id);
610
 };
610
 };
611
 
611
 
612
-UI.updateUserStatus = function (id, status) {
613
-    VideoLayout.setPresenceStatus(id, status);
614
-};
615
-
616
 /**
612
 /**
617
  * Update videotype for specified user.
613
  * Update videotype for specified user.
618
  * @param {string} id user id
614
  * @param {string} id user id

+ 40
- 1
modules/UI/util/UIUtil.js Parādīt failu

136
             element.setAttribute('data-i18n', '[content]' + key);
136
             element.setAttribute('data-i18n', '[content]' + key);
137
 
137
 
138
             APP.translation.translateElement($(element));
138
             APP.translation.translateElement($(element));
139
-        }      
139
+        }
140
     },
140
     },
141
 
141
 
142
     /**
142
     /**
388
                 "cursor": "default"
388
                 "cursor": "default"
389
             });
389
             });
390
         }
390
         }
391
+    },
392
+
393
+    /**
394
+     * Gets an "indicator" span for a video thumbnail.
395
+     * If element doesn't exist then creates it and appends
396
+     * video span container.
397
+     *
398
+     * @param {object} opts
399
+     * @param opts.indicatorId {String} - identificator of indicator
400
+     * @param opts.videoSpanId {String} - identificator of video span
401
+     * @param opts.content {String} HTML content of indicator
402
+     * @param opts.tooltip {String} - tooltip key for translation
403
+     *
404
+     * @returns {HTMLSpanElement} indicatorSpan
405
+     */
406
+    getVideoThumbnailIndicatorSpan(opts = {}) {
407
+        let indicatorId = opts.indicatorId;
408
+        let videoSpanId = opts.videoSpanId;
409
+        let indicators = $(`#${videoSpanId} #${indicatorId}]`);
410
+        let indicatorSpan;
411
+
412
+        if (indicators.length <= 0) {
413
+            indicatorSpan = document.createElement('span');
414
+            indicatorSpan.className = 'indicator';
415
+            indicatorSpan.id = indicatorId;
416
+
417
+            indicatorSpan.innerHTML = opts.content;
418
+
419
+            this.setTooltip(indicatorSpan, opts.tooltip, "top");
420
+            APP.translation.translateElement($(indicatorSpan));
421
+
422
+            document.getElementById(videoSpanId)
423
+                .querySelector('.videocontainer__toptoolbar')
424
+                .appendChild(indicatorSpan);
425
+        } else {
426
+            indicatorSpan = indicators[0];
427
+        }
428
+
429
+        return indicatorSpan;
391
     }
430
     }
392
 };
431
 };
393
 
432
 

+ 21
- 14
modules/UI/videolayout/ConnectionIndicator.js Parādīt failu

2
 /* jshint -W101 */
2
 /* jshint -W101 */
3
 import JitsiPopover from "../util/JitsiPopover";
3
 import JitsiPopover from "../util/JitsiPopover";
4
 import VideoLayout from "./VideoLayout";
4
 import VideoLayout from "./VideoLayout";
5
+import UIUtil from "../util/UIUtil";
5
 
6
 
6
 /**
7
 /**
7
  * Constructs new connection indicator.
8
  * Constructs new connection indicator.
8
  * @param videoContainer the video container associated with the indicator.
9
  * @param videoContainer the video container associated with the indicator.
10
+ * @param videoId the identifier of the video
9
  * @constructor
11
  * @constructor
10
  */
12
  */
11
-function ConnectionIndicator(videoContainer, id) {
13
+function ConnectionIndicator(videoContainer, videoId) {
12
     this.videoContainer = videoContainer;
14
     this.videoContainer = videoContainer;
13
     this.bandwidth = null;
15
     this.bandwidth = null;
14
     this.packetLoss = null;
16
     this.packetLoss = null;
18
     this.isResolutionHD = null;
20
     this.isResolutionHD = null;
19
     this.transport = [];
21
     this.transport = [];
20
     this.popover = null;
22
     this.popover = null;
21
-    this.id = id;
23
+    this.id = videoId;
22
     this.create();
24
     this.create();
23
 }
25
 }
24
 
26
 
247
 
249
 
248
 function createIcon(classes, iconClass) {
250
 function createIcon(classes, iconClass) {
249
     var icon = document.createElement("span");
251
     var icon = document.createElement("span");
252
+    icon.classList.add("indicatoricon");
250
     for(var i in classes) {
253
     for(var i in classes) {
251
         icon.classList.add(classes[i]);
254
         icon.classList.add(classes[i]);
252
     }
255
     }
259
  * Creates the indicator
262
  * Creates the indicator
260
  */
263
  */
261
 ConnectionIndicator.prototype.create = function () {
264
 ConnectionIndicator.prototype.create = function () {
262
-    this.connectionIndicatorContainer = document.createElement("div");
263
-    this.connectionIndicatorContainer.className = "connectionindicator";
264
-    this.connectionIndicatorContainer.style.display = "none";
265
-    this.videoContainer.container.appendChild(
266
-        this.connectionIndicatorContainer);
267
-    this.popover = new JitsiPopover(
268
-        $("#" + this.videoContainer.videoSpanId + " > .connectionindicator"), {
269
-            content: "<div class=\"connection-info\" " +
270
-                        "data-i18n='connectionindicator.na'></div>",
271
-            skin: "black",
272
-            onBeforePosition: el => APP.translation.translateElement(el)
273
-        });
265
+    let indicatorId = 'connectionindicator';
266
+    let element = UIUtil.getVideoThumbnailIndicatorSpan({
267
+        videoSpanId: this.videoContainer.videoSpanId,
268
+        indicatorId
269
+    });
270
+    element.classList.add('hide');
271
+    this.connectionIndicatorContainer = element;
272
+
273
+    let popoverContent = (
274
+        `<div class="connection-info" data-i18n="${indicatorId}.na"></div>`
275
+    );
276
+    this.popover = new JitsiPopover(element, {
277
+        content: popoverContent,
278
+        skin: "black",
279
+        onBeforePosition: el => APP.translation.translateElement(el)
280
+    });
274
 
281
 
275
     // override popover show method to make sure we will update the content
282
     // override popover show method to make sure we will update the content
276
     // before showing the popover
283
     // before showing the popover

+ 6
- 4
modules/UI/videolayout/RemoteVideo.js Parādīt failu

233
     RemoteVideo.prototype.addRemoteVideoMenu = function () {
233
     RemoteVideo.prototype.addRemoteVideoMenu = function () {
234
 
234
 
235
         var spanElement = document.createElement('span');
235
         var spanElement = document.createElement('span');
236
-        spanElement.className = 'remotevideomenu toolbar-icon right';
236
+        spanElement.className = 'remotevideomenu';
237
 
237
 
238
-        this.container
239
-            .querySelector('.videocontainer__toolbar')
240
-            .appendChild(spanElement);
238
+        this.container.appendChild(spanElement);
241
 
239
 
242
         var menuElement = document.createElement('i');
240
         var menuElement = document.createElement('i');
243
         menuElement.className = 'icon-menu-up';
241
         menuElement.className = 'icon-menu-up';
569
     container.id = spanId;
567
     container.id = spanId;
570
     container.className = 'videocontainer';
568
     container.className = 'videocontainer';
571
 
569
 
570
+    let indicatorBar = document.createElement('div');
571
+    indicatorBar.className = "videocontainer__toptoolbar";
572
+    container.appendChild(indicatorBar);
573
+
572
     let toolbar = document.createElement('div');
574
     let toolbar = document.createElement('div');
573
     toolbar.className = "videocontainer__toolbar";
575
     toolbar.className = "videocontainer__toolbar";
574
     container.appendChild(toolbar);
576
     container.appendChild(toolbar);

+ 17
- 66
modules/UI/videolayout/SmallVideo.js Parādīt failu

126
     return this.videoType;
126
     return this.videoType;
127
 };
127
 };
128
 
128
 
129
-/**
130
- * Shows the presence status message for the given video.
131
- */
132
-SmallVideo.prototype.setPresenceStatus = function (statusMsg) {
133
-    if (!this.container) {
134
-        // No container
135
-        return;
136
-    }
137
-
138
-    var statusSpan = $('#' + this.videoSpanId + '>span.status');
139
-    if (!statusSpan.length) {
140
-        //Add status span
141
-        statusSpan = document.createElement('span');
142
-        statusSpan.className = 'status';
143
-        statusSpan.id = this.videoSpanId + '_status';
144
-        $('#' + this.videoSpanId)[0].appendChild(statusSpan);
145
-
146
-        statusSpan = $('#' + this.videoSpanId + '>span.status');
147
-    }
148
-
149
-    // Display status
150
-    if (statusMsg && statusMsg.length) {
151
-        $('#' + this.videoSpanId + '_status').text(statusMsg);
152
-        statusSpan.get(0).setAttribute("style", "display:inline-block;");
153
-    }
154
-    else {
155
-        // Hide
156
-        statusSpan.get(0).setAttribute("style", "display:none;");
157
-    }
158
-};
159
-
160
 /**
129
 /**
161
  * Creates an audio or video element for a particular MediaStream.
130
  * Creates an audio or video element for a particular MediaStream.
162
  */
131
  */
528
         return;
497
         return;
529
     }
498
     }
530
 
499
 
531
-    var indicatorSpan = this.getIndicatorSpan({
532
-        id: 'dominantspeakerindicator',
500
+    let indicatorSpanId = "dominantspeakerindicator";
501
+    let indicatorSpan = UIUtil.getVideoThumbnailIndicatorSpan({
502
+        videoSpanId: this.videoSpanId,
503
+        indicatorId: indicatorSpanId,
533
         content: '<i id="indicatoricon" class="fa fa-bullhorn"></i>',
504
         content: '<i id="indicatoricon" class="fa fa-bullhorn"></i>',
534
         tooltip: 'speaker'
505
         tooltip: 'speaker'
535
     });
506
     });
536
 
507
 
537
-    indicatorSpan.style.display = show ? "" : "none";
508
+    if (show) {
509
+        indicatorSpan.classList.add('hide');
510
+    } else {
511
+        indicatorSpan.classList.remove('hide')
512
+    }
538
 };
513
 };
539
 
514
 
540
 /**
515
 /**
548
         return;
523
         return;
549
     }
524
     }
550
 
525
 
551
-    var indicatorSpan = this.getIndicatorSpan({
552
-        id: 'raisehandindicator',
526
+    let indicatorSpanId = "raisehandindicator";
527
+    let indicatorSpan = UIUtil.getVideoThumbnailIndicatorSpan({
528
+        indicatorId: indicatorSpanId,
529
+        videoSpanId: this.videoSpanId,
553
         content: '<i id="indicatoricon" class="icon-raised-hand"></i>',
530
         content: '<i id="indicatoricon" class="icon-raised-hand"></i>',
554
         tooltip: 'raisedHand'
531
         tooltip: 'raisedHand'
555
     });
532
     });
556
 
533
 
557
-    indicatorSpan.style.display = show ? "" : "none";
558
-};
559
-
560
-/**
561
- * Gets (creating if necessary) the "indicator" span for this SmallVideo.
562
- *
563
- * @param options.id {String} element ID
564
- * @param options.content {String} HTML content of the indicator
565
- * @param options.tooltip {String} The key that should be passed to tooltip
566
- *
567
- * @returns {HTMLElement} DOM represention of the indicator
568
- */
569
-SmallVideo.prototype.getIndicatorSpan = function(options) {
570
-    var indicator = this.container.querySelector('#' + options.id);
571
-
572
-    if (indicator) {
573
-        return indicator;
534
+    if (show) {
535
+        indicatorSpan.classList.add('hide');
536
+    } else {
537
+        indicatorSpan.classList.remove('hide')
574
     }
538
     }
575
-
576
-    indicator = document.createElement('span');
577
-    indicator.className = 'indicator';
578
-    indicator.id = options.id;
579
-
580
-    indicator.innerHTML = options.content;
581
-
582
-    UIUtil.setTooltip(indicator, options.tooltip, "top");
583
-    APP.translation.translateElement($(indicator));
584
-
585
-    this.container.appendChild(indicator);
586
-
587
-    return indicator;
588
 };
539
 };
589
 
540
 
590
 /**
541
 /**

+ 0
- 9
modules/UI/videolayout/VideoLayout.js Parādīt failu

449
         }
449
         }
450
     },
450
     },
451
 
451
 
452
-    /**
453
-     * Shows the presence status message for the given video.
454
-     */
455
-    setPresenceStatus (id, statusMsg) {
456
-        let remoteVideo = remoteVideos[id];
457
-        if (remoteVideo)
458
-            remoteVideo.setPresenceStatus(statusMsg);
459
-    },
460
-
461
     /**
452
     /**
462
      * Shows a visual indicator for the moderator of the conference.
453
      * Shows a visual indicator for the moderator of the conference.
463
      * On local or remote participants.
454
      * On local or remote participants.

Notiek ielāde…
Atcelt
Saglabāt