Kaynağa Gözat

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

master
Leonard Kim 7 yıl önce
ebeveyn
işleme
05801711a7

+ 15
- 5
modules/FollowMe.js Dosyayı Görüntüle

1
+/* global APP */
2
+
1
 /*
3
 /*
2
  * Copyright @ 2015 Atlassian Pty Ltd
4
  * Copyright @ 2015 Atlassian Pty Ltd
3
  *
5
  *
15
  */
17
  */
16
 const logger = require('jitsi-meet-logger').getLogger(__filename);
18
 const logger = require('jitsi-meet-logger').getLogger(__filename);
17
 
19
 
20
+import {
21
+    getPinnedParticipant,
22
+    pinParticipant
23
+} from '../react/features/base/participants';
18
 import UIEvents from '../service/UI/UIEvents';
24
 import UIEvents from '../service/UI/UIEvents';
19
 import VideoLayout from './UI/videolayout/VideoLayout';
25
 import VideoLayout from './UI/videolayout/VideoLayout';
20
 
26
 
444
         if (smallVideo) {
450
         if (smallVideo) {
445
             this.nextOnStageTimer = 0;
451
             this.nextOnStageTimer = 0;
446
             clearTimeout(this.nextOnStageTimout);
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
         } else {
463
         } else {
454
             // If there's no SmallVideo object for the given id, lets wait and
464
             // If there's no SmallVideo object for the given id, lets wait and

+ 0
- 9
modules/UI/UI.js Dosyayı Görüntüle

959
     return VideoLayout.getLargeVideo();
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
  * Shows "Please go to chrome webstore to install the desktop sharing extension"
963
  * Shows "Please go to chrome webstore to install the desktop sharing extension"
973
  * 2 button dialog with buttons - cancel and go to web store.
964
  * 2 button dialog with buttons - cancel and go to web store.

+ 1
- 1
modules/UI/shared_video/SharedVideo.js Dosyayı Görüntüle

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

+ 1
- 1
modules/UI/shared_video/SharedVideoThumb.js Dosyayı Görüntüle

59
  * The thumb click handler.
59
  * The thumb click handler.
60
  */
60
  */
61
 SharedVideoThumb.prototype.videoClick = function() {
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 Dosyayı Görüntüle

260
     }
260
     }
261
 
261
 
262
     if (!ignoreClick) {
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 Dosyayı Görüntüle

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

+ 19
- 1
modules/UI/videolayout/SmallVideo.js Dosyayı Görüntüle

12
     from '../../../react/features/audio-level-indicator';
12
     from '../../../react/features/audio-level-indicator';
13
 import {
13
 import {
14
     Avatar as AvatarDisplay,
14
     Avatar as AvatarDisplay,
15
-    getAvatarURLByParticipantId
15
+    getAvatarURLByParticipantId,
16
+    getPinnedParticipant,
17
+    pinParticipant
16
 } from '../../../react/features/base/participants';
18
 } from '../../../react/features/base/participants';
17
 import {
19
 import {
18
     ConnectionIndicator
20
     ConnectionIndicator
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
  * Removes the React element responsible for showing connection status, dominant
841
  * Removes the React element responsible for showing connection status, dominant
824
  * speaker, and raised hand icons.
842
  * speaker, and raised hand icons.

+ 44
- 52
modules/UI/videolayout/VideoLayout.js Dosyayı Görüntüle

5
     JitsiParticipantConnectionStatus
5
     JitsiParticipantConnectionStatus
6
 } from '../../../react/features/base/lib-jitsi-meet';
6
 } from '../../../react/features/base/lib-jitsi-meet';
7
 import {
7
 import {
8
-    getParticipants,
9
     getPinnedParticipant,
8
     getPinnedParticipant,
10
     pinParticipant
9
     pinParticipant
11
 } from '../../../react/features/base/participants';
10
 } from '../../../react/features/base/participants';
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
  * Returns the user ID of the remote participant that is current the dominant
68
  * Returns the user ID of the remote participant that is current the dominant
47
  * speaker.
69
  * speaker.
50
  * @returns {string|null}
72
  * @returns {string|null}
51
  */
73
  */
52
 function getCurrentRemoteDominantSpeakerID() {
74
 function getCurrentRemoteDominantSpeakerID() {
53
-    const dominantSpeaker = getParticipants(APP.store.getState)
75
+    const dominantSpeaker = getAllParticipants()
54
         .find(participant => participant.dominantSpeaker);
76
         .find(participant => participant.dominantSpeaker);
55
 
77
 
56
     if (dominantSpeaker) {
78
     if (dominantSpeaker) {
93
         // the local video thumb maybe one pixel
115
         // the local video thumb maybe one pixel
94
         this.resizeThumbnails(true);
116
         this.resizeThumbnails(true);
95
 
117
 
96
-        this.handleVideoThumbClicked = this.handleVideoThumbClicked.bind(this);
97
-
98
         this.registerListeners();
118
         this.registerListeners();
99
     },
119
     },
100
 
120
 
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
      * @returns {void}
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
             } else {
421
             } else {
415
-                // if there is no currentDominantSpeaker, it can also be
422
+                // if there is no currentDominantSpeakerID, it can also be
416
                 // that local participant is the dominant speaker
423
                 // that local participant is the dominant speaker
417
                 // we should act as a participant has left and was on large
424
                 // we should act as a participant has left and was on large
418
                 // and we should choose somebody (electLastVisibleVideo)
425
                 // and we should choose somebody (electLastVisibleVideo)
419
                 this.updateLargeVideo(this.electLastVisibleVideo());
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
      * @returns {void}
679
      * @returns {void}
685
      */
680
      */
686
     onDominantSpeakerChanged(id) {
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
         if (!remoteVideos[id]) {
686
         if (!remoteVideos[id]) {
695
             return;
687
             return;
797
         // Unlock large video
789
         // Unlock large video
798
         if (this.getPinnedId() === id) {
790
         if (this.getPinnedId() === id) {
799
             logger.info('Focused video owner has left the conference');
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
         const remoteVideo = remoteVideos[id];
795
         const remoteVideo = remoteVideos[id];

+ 19
- 1
react/features/video-layout/middleware.web.js Dosyayı Görüntüle

1
+// @flow
2
+
1
 import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js';
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
 import { MiddlewareRegistry } from '../base/redux';
10
 import { MiddlewareRegistry } from '../base/redux';
5
 
11
 
12
+declare var APP: Object;
13
+
6
 /**
14
 /**
7
  * Middleware which intercepts actions and updates the legacy component
15
  * Middleware which intercepts actions and updates the legacy component
8
  * {@code VideoLayout} as needed. The purpose of this middleware is to redux-ify
16
  * {@code VideoLayout} as needed. The purpose of this middleware is to redux-ify
13
  */
21
  */
14
 // eslint-disable-next-line no-unused-vars
22
 // eslint-disable-next-line no-unused-vars
15
 MiddlewareRegistry.register(store => next => action => {
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
     const result = next(action);
26
     const result = next(action);
17
 
27
 
18
     switch (action.type) {
28
     switch (action.type) {
19
     case DOMINANT_SPEAKER_CHANGED:
29
     case DOMINANT_SPEAKER_CHANGED:
20
         VideoLayout.onDominantSpeakerChanged(action.participant.id);
30
         VideoLayout.onDominantSpeakerChanged(action.participant.id);
21
         break;
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
     return result;
42
     return result;

Loading…
İptal
Kaydet