Browse Source

ref(video-layout): get pinned ID directly from redux

master
Leonard Kim 7 years ago
parent
commit
05801711a7

+ 15
- 5
modules/FollowMe.js View File

@@ -1,3 +1,5 @@
1
+/* global APP */
2
+
1 3
 /*
2 4
  * Copyright @ 2015 Atlassian Pty Ltd
3 5
  *
@@ -15,6 +17,10 @@
15 17
  */
16 18
 const logger = require('jitsi-meet-logger').getLogger(__filename);
17 19
 
20
+import {
21
+    getPinnedParticipant,
22
+    pinParticipant
23
+} from '../react/features/base/participants';
18 24
 import UIEvents from '../service/UI/UIEvents';
19 25
 import VideoLayout from './UI/videolayout/VideoLayout';
20 26
 
@@ -444,11 +450,15 @@ class FollowMe {
444 450
         if (smallVideo) {
445 451
             this.nextOnStageTimer = 0;
446 452
             clearTimeout(this.nextOnStageTimout);
447
-            /* eslint-disable no-mixed-operators */
448
-            if (pin && !VideoLayout.isPinned(clickId)
449
-                || !pin && VideoLayout.isPinned(clickId)) {
450
-                /* eslint-disable no-mixed-operators */
451
-                VideoLayout.handleVideoThumbClicked(clickId);
453
+
454
+            if (pin) {
455
+                APP.store.dispatch(pinParticipant(clickId));
456
+            } else {
457
+                const { id } = getPinnedParticipant(APP.store.getState()) || {};
458
+
459
+                if (id === clickId) {
460
+                    APP.store.dispatch(pinParticipant(null));
461
+                }
452 462
             }
453 463
         } else {
454 464
             // If there's no SmallVideo object for the given id, lets wait and

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

@@ -959,15 +959,6 @@ UI.getLargeVideo = function() {
959 959
     return VideoLayout.getLargeVideo();
960 960
 };
961 961
 
962
-/**
963
- * Returns whether or not the passed in user id is currently pinned to the large
964
- * video.
965
- *
966
- * @param {string} userId - The id of the user to check is pinned or not.
967
- * @returns {boolean} True if the user is currently pinned to the large video.
968
- */
969
-UI.isPinned = userId => VideoLayout.getPinnedId() === userId;
970
-
971 962
 /**
972 963
  * Shows "Please go to chrome webstore to install the desktop sharing extension"
973 964
  * 2 button dialog with buttons - cancel and go to web store.

+ 1
- 1
modules/UI/shared_video/SharedVideo.js View File

@@ -317,7 +317,7 @@ export default class SharedVideoManager {
317 317
                 name: 'YouTube'
318 318
             }));
319 319
 
320
-            VideoLayout.handleVideoThumbClicked(self.url);
320
+            thumb.videoClick();
321 321
 
322 322
             // If we are sending the command and we are starting the player
323 323
             // we need to continuously send the player current time position

+ 1
- 1
modules/UI/shared_video/SharedVideoThumb.js View File

@@ -59,7 +59,7 @@ SharedVideoThumb.prototype.createContainer = function(spanId) {
59 59
  * The thumb click handler.
60 60
  */
61 61
 SharedVideoThumb.prototype.videoClick = function() {
62
-    this.VideoLayout.handleVideoThumbClicked(this.url);
62
+    this._togglePin();
63 63
 };
64 64
 
65 65
 /**

+ 1
- 1
modules/UI/videolayout/LocalVideo.js View File

@@ -260,7 +260,7 @@ LocalVideo.prototype._onContainerClick = function(event) {
260 260
     }
261 261
 
262 262
     if (!ignoreClick) {
263
-        this.VideoLayout.handleVideoThumbClicked(this.id);
263
+        this._togglePin();
264 264
     }
265 265
 };
266 266
 

+ 9
- 4
modules/UI/videolayout/RemoteVideo.js View File

@@ -11,7 +11,10 @@ import { i18next } from '../../../react/features/base/i18n';
11 11
 import {
12 12
     JitsiParticipantConnectionStatus
13 13
 } from '../../../react/features/base/lib-jitsi-meet';
14
-
14
+import {
15
+    getPinnedParticipant,
16
+    pinParticipant
17
+} from '../../../react/features/base/participants';
15 18
 import { PresenceLabel } from '../../../react/features/presence-status';
16 19
 import {
17 20
     REMOTE_CONTROL_MENU_STATES,
@@ -234,10 +237,12 @@ RemoteVideo.prototype._requestRemoteControlPermissions = function() {
234 237
         if (result === true) {
235 238
             // the remote control permissions has been granted
236 239
             // pin the controlled participant
237
-            const pinnedId = this.VideoLayout.getPinnedId();
240
+            const pinnedParticipant
241
+                = getPinnedParticipant(APP.store.getState()) || {};
242
+            const pinnedId = pinnedParticipant.id;
238 243
 
239 244
             if (pinnedId !== this.id) {
240
-                this.VideoLayout.handleVideoThumbClicked(this.id);
245
+                APP.store.dispatch(pinParticipant(this.id));
241 246
             }
242 247
         }
243 248
     }, error => {
@@ -648,7 +653,7 @@ RemoteVideo.prototype._onContainerClick = function(event) {
648 653
             || classList.contains('popover');
649 654
 
650 655
     if (!ignoreClick) {
651
-        this.VideoLayout.handleVideoThumbClicked(this.id);
656
+        this._togglePin();
652 657
     }
653 658
 
654 659
     // On IE we need to populate this handler on video <object> and it does not

+ 19
- 1
modules/UI/videolayout/SmallVideo.js View File

@@ -12,7 +12,9 @@ import { AudioLevelIndicator }
12 12
     from '../../../react/features/audio-level-indicator';
13 13
 import {
14 14
     Avatar as AvatarDisplay,
15
-    getAvatarURLByParticipantId
15
+    getAvatarURLByParticipantId,
16
+    getPinnedParticipant,
17
+    pinParticipant
16 18
 } from '../../../react/features/base/participants';
17 19
 import {
18 20
     ConnectionIndicator
@@ -819,6 +821,22 @@ SmallVideo.prototype.updateIndicators = function() {
819 821
     );
820 822
 };
821 823
 
824
+/**
825
+ * Pins the participant displayed by this thumbnail or unpins if already pinned.
826
+ *
827
+ * @private
828
+ * @returns {void}
829
+ */
830
+SmallVideo.prototype._togglePin = function() {
831
+    const pinnedParticipant
832
+        = getPinnedParticipant(APP.store.getState()) || {};
833
+    const participantIdToPin
834
+        = pinnedParticipant && pinnedParticipant.id === this.id
835
+            ? null : this.id;
836
+
837
+    APP.store.dispatch(pinParticipant(participantIdToPin));
838
+};
839
+
822 840
 /**
823 841
  * Removes the React element responsible for showing connection status, dominant
824 842
  * speaker, and raised hand icons.

+ 44
- 52
modules/UI/videolayout/VideoLayout.js View File

@@ -5,7 +5,6 @@ import {
5 5
     JitsiParticipantConnectionStatus
6 6
 } from '../../../react/features/base/lib-jitsi-meet';
7 7
 import {
8
-    getParticipants,
9 8
     getPinnedParticipant,
10 9
     pinParticipant
11 10
 } from '../../../react/features/base/participants';
@@ -42,6 +41,29 @@ function onLocalFlipXChanged(val) {
42 41
     }
43 42
 }
44 43
 
44
+/**
45
+ * Returns the redux representation of all known users.
46
+ *
47
+ * @private
48
+ * @returns {Array}
49
+ */
50
+function getAllParticipants() {
51
+    return APP.store.getState()['features/base/participants'];
52
+}
53
+
54
+/**
55
+ * Returns an array of all thumbnails in the filmstrip.
56
+ *
57
+ * @private
58
+ * @returns {Array}
59
+ */
60
+function getAllThumbnails() {
61
+    return [
62
+        localVideoThumbnail,
63
+        ...Object.values(remoteVideos)
64
+    ];
65
+}
66
+
45 67
 /**
46 68
  * Returns the user ID of the remote participant that is current the dominant
47 69
  * speaker.
@@ -50,7 +72,7 @@ function onLocalFlipXChanged(val) {
50 72
  * @returns {string|null}
51 73
  */
52 74
 function getCurrentRemoteDominantSpeakerID() {
53
-    const dominantSpeaker = getParticipants(APP.store.getState)
75
+    const dominantSpeaker = getAllParticipants()
54 76
         .find(participant => participant.dominantSpeaker);
55 77
 
56 78
     if (dominantSpeaker) {
@@ -93,8 +115,6 @@ const VideoLayout = {
93 115
         // the local video thumb maybe one pixel
94 116
         this.resizeThumbnails(true);
95 117
 
96
-        this.handleVideoThumbClicked = this.handleVideoThumbClicked.bind(this);
97
-
98 118
         this.registerListeners();
99 119
     },
100 120
 
@@ -376,61 +396,36 @@ const VideoLayout = {
376 396
     },
377 397
 
378 398
     /**
379
-     * Updates the desired pinned participant and notifies web UI of the change.
399
+     * Callback invoked to update display when the pin participant has changed.
380 400
      *
381
-     * @param {string|null} id - The participant id of the participant to be
382
-     * pinned. Pass in null to unpin without pinning another participant.
401
+     * @paramn {string|null} pinnedParticipantID - The participant ID of the
402
+     * participant that is pinned or null if no one is pinned.
383 403
      * @returns {void}
384 404
      */
385
-    pinParticipant(id) {
386
-        APP.store.dispatch(pinParticipant(id));
387
-        APP.UI.emitEvent(UIEvents.PINNED_ENDPOINT, id, Boolean(id));
388
-    },
389
-
390
-    /**
391
-     * Handles the click on a video thumbnail.
392
-     *
393
-     * @param id the identifier of the video thumbnail
394
-     */
395
-    handleVideoThumbClicked(id) {
396
-        const smallVideo = VideoLayout.getSmallVideo(id);
397
-        const pinnedId = this.getPinnedId();
398
-
399
-        if (pinnedId) {
400
-            const oldSmallVideo = VideoLayout.getSmallVideo(pinnedId);
401
-
402
-            if (oldSmallVideo && !interfaceConfig.filmStripOnly) {
403
-                oldSmallVideo.focus(false);
404
-            }
405
+    onPinChange(pinnedParticipantID) {
406
+        if (interfaceConfig.filmStripOnly) {
407
+            return;
405 408
         }
406 409
 
407
-        // Unpin if currently pinned.
408
-        if (pinnedId === id) {
409
-            this.pinParticipant(null);
410
+        getAllThumbnails().forEach(thumbnail =>
411
+            thumbnail.focus(pinnedParticipantID === thumbnail.getId()));
410 412
 
411
-            // Enable the currently set dominant speaker.
412
-            if (getCurrentRemoteDominantSpeakerID()) {
413
-                this.updateLargeVideo(getCurrentRemoteDominantSpeakerID());
413
+        if (pinnedParticipantID) {
414
+            this.updateLargeVideo(pinnedParticipantID);
415
+        } else {
416
+            const currentDominantSpeakerID
417
+                = getCurrentRemoteDominantSpeakerID();
418
+
419
+            if (currentDominantSpeakerID) {
420
+                this.updateLargeVideo(currentDominantSpeakerID);
414 421
             } else {
415
-                // if there is no currentDominantSpeaker, it can also be
422
+                // if there is no currentDominantSpeakerID, it can also be
416 423
                 // that local participant is the dominant speaker
417 424
                 // we should act as a participant has left and was on large
418 425
                 // and we should choose somebody (electLastVisibleVideo)
419 426
                 this.updateLargeVideo(this.electLastVisibleVideo());
420 427
             }
421
-
422
-            return;
423
-        }
424
-
425
-        // Update focused/pinned interface.
426
-        if (id) {
427
-            if (smallVideo && !interfaceConfig.filmStripOnly) {
428
-                smallVideo.focus(true);
429
-                this.pinParticipant(id);
430
-            }
431 428
         }
432
-
433
-        this.updateLargeVideo(id);
434 429
     },
435 430
 
436 431
     /**
@@ -684,12 +679,9 @@ const VideoLayout = {
684 679
      * @returns {void}
685 680
      */
686 681
     onDominantSpeakerChanged(id) {
687
-        Object.values(remoteVideos).forEach(remoteVideo =>
688
-            remoteVideo.showDominantSpeakerIndicator(
689
-                id === remoteVideo.getId()));
682
+        getAllThumbnails().forEach(thumbnail =>
683
+            thumbnail.showDominantSpeakerIndicator(id === thumbnail.getId()));
690 684
 
691
-        localVideoThumbnail.showDominantSpeakerIndicator(
692
-            APP.conference.isLocalId(id));
693 685
 
694 686
         if (!remoteVideos[id]) {
695 687
             return;
@@ -797,7 +789,7 @@ const VideoLayout = {
797 789
         // Unlock large video
798 790
         if (this.getPinnedId() === id) {
799 791
             logger.info('Focused video owner has left the conference');
800
-            this.pinParticipant(null);
792
+            APP.store.dispatch(pinParticipant(null));
801 793
         }
802 794
 
803 795
         const remoteVideo = remoteVideos[id];

+ 19
- 1
react/features/video-layout/middleware.web.js View File

@@ -1,8 +1,16 @@
1
+// @flow
2
+
1 3
 import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
4
+import UIEvents from '../../../service/UI/UIEvents';
2 5
 
3
-import { DOMINANT_SPEAKER_CHANGED } from '../base/participants';
6
+import {
7
+    DOMINANT_SPEAKER_CHANGED,
8
+    PIN_PARTICIPANT
9
+} from '../base/participants';
4 10
 import { MiddlewareRegistry } from '../base/redux';
5 11
 
12
+declare var APP: Object;
13
+
6 14
 /**
7 15
  * Middleware which intercepts actions and updates the legacy component
8 16
  * {@code VideoLayout} as needed. The purpose of this middleware is to redux-ify
@@ -13,12 +21,22 @@ import { MiddlewareRegistry } from '../base/redux';
13 21
  */
14 22
 // eslint-disable-next-line no-unused-vars
15 23
 MiddlewareRegistry.register(store => next => action => {
24
+    // Purposefully perform additional actions after state update to mimic
25
+    // being connected to the store for updates.
16 26
     const result = next(action);
17 27
 
18 28
     switch (action.type) {
19 29
     case DOMINANT_SPEAKER_CHANGED:
20 30
         VideoLayout.onDominantSpeakerChanged(action.participant.id);
21 31
         break;
32
+
33
+    case PIN_PARTICIPANT:
34
+        VideoLayout.onPinChange(action.participant.id);
35
+        APP.UI.emitEvent(
36
+            UIEvents.PINNED_ENDPOINT,
37
+            action.participant.id,
38
+            Boolean(action.participant.id));
39
+        break;
22 40
     }
23 41
 
24 42
     return result;

Loading…
Cancel
Save