Browse Source

feat(1-on-1): Initial implementation

- Expose an api on Filmstrip to hide the remote videos container, which does so
  by adding a class
- Modify listeners for user join, leave, share video to call the api
- Hide the container when there is 1 or fewer remote participants
- Always show the container if self view is in focus
- Show the container if the number of remote thumbnails does not match the count
  of remote participants, such as the case of sharing a video
master
Leonard Kim 8 years ago
parent
commit
2333249b05

+ 23
- 0
conference.js View File

@@ -1286,6 +1286,8 @@ export default {
1286 1286
 
1287 1287
             // check the roles for the new user and reflect them
1288 1288
             APP.UI.updateUserRole(user);
1289
+
1290
+            updateRemoteThumbnailsVisibility();
1289 1291
         });
1290 1292
         room.on(ConferenceEvents.USER_LEFT, (id, user) => {
1291 1293
             APP.store.dispatch(participantLeft(id, user));
@@ -1293,6 +1295,8 @@ export default {
1293 1295
             APP.API.notifyUserLeft(id);
1294 1296
             APP.UI.removeUser(id, user.getDisplayName());
1295 1297
             APP.UI.onSharedVideoStop(id);
1298
+
1299
+            updateRemoteThumbnailsVisibility();
1296 1300
         });
1297 1301
 
1298 1302
         room.on(ConferenceEvents.USER_STATUS_CHANGED, (id, status) => {
@@ -1475,6 +1479,8 @@ export default {
1475 1479
                         reportError(e);
1476 1480
                     }
1477 1481
                 }
1482
+
1483
+                updateRemoteThumbnailsVisibility();
1478 1484
             });
1479 1485
         }
1480 1486
 
@@ -1811,6 +1817,8 @@ export default {
1811 1817
                     }
1812 1818
                 });
1813 1819
             }
1820
+
1821
+            updateRemoteThumbnailsVisibility();
1814 1822
         });
1815 1823
         room.addCommandListener(
1816 1824
             this.commands.defaults.SHARED_VIDEO, ({value, attributes}, id) => {
@@ -1826,6 +1834,21 @@ export default {
1826 1834
                     APP.UI.onSharedVideoUpdate(id, value, attributes);
1827 1835
                 }
1828 1836
             });
1837
+
1838
+        function updateRemoteThumbnailsVisibility() {
1839
+            const localUserId = APP.conference.getMyUserId();
1840
+            const remoteParticipantsCount = room.getParticipantCount() - 1;
1841
+
1842
+            // Get the remote thumbnail count for cases where there are
1843
+            // non-participants displaying video, such as with video sharing.
1844
+            const remoteVideosCount = APP.UI.getRemoteVideosCount();
1845
+
1846
+            const shouldShowRemoteThumbnails = APP.UI.isPinned(localUserId)
1847
+                || remoteVideosCount > 1
1848
+                || remoteParticipantsCount !== remoteVideosCount;
1849
+
1850
+            APP.UI.setRemoteThumbnailsVisibility(shouldShowRemoteThumbnails);
1851
+        }
1829 1852
     },
1830 1853
     /**
1831 1854
     * Adds any room listener.

+ 3
- 0
config.js View File

@@ -57,6 +57,9 @@ var config = { // eslint-disable-line no-unused-vars
57 57
     webrtcIceTcpDisable: false,
58 58
 
59 59
     openSctp: true, // Toggle to enable/disable SCTP channels
60
+
61
+    // Disable hiding of remote thumbnails when in a 1-on-1 conference call.
62
+    disable1On1Mode: false,
60 63
     disableStats: false,
61 64
     disableAudioLevels: false,
62 65
     channelLastN: -1, // The default value of the channel attribute last-n.

+ 9
- 0
css/_filmstrip.scss View File

@@ -138,4 +138,13 @@
138 138
         margin-bottom: auto;
139 139
         padding-right: $defaultToolbarSize;
140 140
     }
141
+
142
+    .remote-videos-container {
143
+        transition: opacity 1s;
144
+
145
+        &.hide-videos {
146
+            opacity: 0;
147
+            pointer-events: none;
148
+        }
149
+    }
141 150
 }

+ 30
- 0
modules/UI/UI.js View File

@@ -309,6 +309,10 @@ UI.start = function () {
309 309
     SideContainerToggler.init(eventEmitter);
310 310
     Filmstrip.init(eventEmitter);
311 311
 
312
+    // By default start with remote videos hidden and rely on other logic to
313
+    // make them visible.
314
+    UI.setRemoteThumbnailsVisibility(false);
315
+
312 316
     VideoLayout.init(eventEmitter);
313 317
     if (!interfaceConfig.filmStripOnly) {
314 318
         VideoLayout.initLargeVideo();
@@ -1146,6 +1150,15 @@ UI.getLargeVideo = function () {
1146 1150
     return VideoLayout.getLargeVideo();
1147 1151
 };
1148 1152
 
1153
+/**
1154
+ * Returns whether or not the passed in user id is currently pinned to the large
1155
+ * video.
1156
+ *
1157
+ * @param {string} userId - The id of the user to check is pinned or not.
1158
+ * @returns {boolean} True if the user is currently pinned to the large video.
1159
+ */
1160
+UI.isPinned = userId => VideoLayout.getPinnedId() === userId;
1161
+
1149 1162
 /**
1150 1163
  * Shows dialog with a link to FF extension.
1151 1164
  */
@@ -1396,6 +1409,23 @@ UI.isRingOverlayVisible = () => RingOverlay.isVisible();
1396 1409
  */
1397 1410
 UI.onUserFeaturesChanged = user => VideoLayout.onUserFeaturesChanged(user);
1398 1411
 
1412
+/**
1413
+ * Returns the number of known remote videos.
1414
+ *
1415
+ * @returns {number} The number of remote videos.
1416
+ */
1417
+UI.getRemoteVideosCount = () => VideoLayout.getRemoteVideosCount();
1418
+
1419
+/**
1420
+ * Makes remote thumbnail videos visible or not visible.
1421
+ *
1422
+ * @param {boolean} shouldHide - True if remote thumbnails should be hidden,
1423
+ * false f they should be visible.
1424
+ * @returns {void}
1425
+ */
1426
+UI.setRemoteThumbnailsVisibility
1427
+    = shouldHide => Filmstrip.setRemoteVideoVisibility(shouldHide);
1428
+
1399 1429
 const UIListeners = new Map([
1400 1430
     [
1401 1431
         UIEvents.ETHERPAD_CLICKED,

+ 3
- 0
modules/UI/shared_video/SharedVideo.js View File

@@ -456,6 +456,9 @@ export default class SharedVideoManager {
456 456
                 // revert to original behavior (prevents pausing
457 457
                 // for participants not sharing the video to pause it)
458 458
                 $("#sharedVideo").css("pointer-events","auto");
459
+
460
+                this.emitter.emit(
461
+                    UIEvents.UPDATE_SHARED_VIDEO, null, 'removed');
459 462
         });
460 463
 
461 464
         this.url = null;

+ 22
- 1
modules/UI/videolayout/Filmstrip.js View File

@@ -1,4 +1,4 @@
1
-/* global $, APP, JitsiMeetJS, interfaceConfig */
1
+/* global $, APP, config, JitsiMeetJS, interfaceConfig */
2 2
 
3 3
 import UIEvents from "../../../service/UI/UIEvents";
4 4
 import UIUtil from "../util/UIUtil";
@@ -25,6 +25,27 @@ const Filmstrip = {
25 25
         }
26 26
     },
27 27
 
28
+    /**
29
+     * Sets a class on the remote videos container for CSS to adjust visibility
30
+     * of the remote videos. Will no-op if config.debug is truthy, as should be
31
+     * the case with torture tests.
32
+     *
33
+     * @param {boolean} shouldHide - True if remote videos should be hidden,
34
+     * false if they should be visible.
35
+     * @returns {void}
36
+     */
37
+    setRemoteVideoVisibility(shouldShow) {
38
+        // FIXME Checking config.debug is a grand hack to avoid fixing the
39
+        // torture tests after the 1-on-1 UI was implemented, which hides remote
40
+        // videos on 1-on-1 calls. If this check is to be kept, at least create
41
+        // new torture tests to verify 1-on-1 mode.
42
+        if (config.debug || config.disable1On1Mode) {
43
+            return;
44
+        }
45
+
46
+        this.filmstripRemoteVideos.toggleClass('hide-videos', !shouldShow);
47
+    },
48
+
28 49
     /**
29 50
      * Initializes the filmstrip toolbar.
30 51
      */

+ 9
- 0
modules/UI/videolayout/VideoLayout.js View File

@@ -1133,6 +1133,15 @@ var VideoLayout = {
1133 1133
      */
1134 1134
     getLargeVideoWrapper() {
1135 1135
         return this.getCurrentlyOnLargeContainer().$wrapper;
1136
+    },
1137
+
1138
+    /**
1139
+     * Returns the number of remove video ids.
1140
+     *
1141
+     * @returns {number} The number of remote videos.
1142
+     */
1143
+    getRemoteVideosCount() {
1144
+        return Object.keys(remoteVideos).length;
1136 1145
     }
1137 1146
 };
1138 1147
 

Loading…
Cancel
Save