Sfoglia il codice sorgente

ref(stage-filmstrip) Refactor as new layout

Fixes screensharing selection issues. Now when there’s a screen share we just use the old VERTICAL_FILMSTRIP_VIEW layout
Add THUMBAIL_TYPE to determine how to display thumbnails
master
robertpin 3 anni fa
parent
commit
0abefa87aa
27 ha cambiato i file con 448 aggiunte e 351 eliminazioni
  1. 138
    136
      css/filmstrip/_vertical_filmstrip.scss
  2. 9
    4
      css/filmstrip/_vertical_filmstrip_overrides.scss
  3. 2
    2
      modules/UI/videolayout/VideoContainer.js
  4. 2
    2
      react/features/base/participants/functions.js
  5. 7
    14
      react/features/conference/components/web/Conference.js
  6. 9
    9
      react/features/display-name/components/web/DisplayName.js
  7. 8
    1
      react/features/filmstrip/actionTypes.ts
  8. 22
    14
      react/features/filmstrip/actions.web.js
  9. 22
    19
      react/features/filmstrip/components/web/Filmstrip.js
  10. 4
    8
      react/features/filmstrip/components/web/MainFilmstrip.js
  11. 1
    2
      react/features/filmstrip/components/web/StageFilmstrip.js
  12. 9
    11
      react/features/filmstrip/components/web/StatusIndicators.js
  13. 44
    41
      react/features/filmstrip/components/web/Thumbnail.js
  14. 13
    12
      react/features/filmstrip/components/web/ThumbnailBottomIndicators.js
  15. 17
    16
      react/features/filmstrip/components/web/ThumbnailTopIndicators.js
  16. 10
    10
      react/features/filmstrip/components/web/VideoMenuTriggerButton.js
  17. 15
    7
      react/features/filmstrip/constants.js
  18. 2
    2
      react/features/filmstrip/functions.native.js
  19. 52
    16
      react/features/filmstrip/functions.web.js
  20. 19
    6
      react/features/filmstrip/middleware.web.js
  21. 8
    1
      react/features/filmstrip/reducer.js
  22. 9
    3
      react/features/filmstrip/subscriber.web.js
  23. 7
    2
      react/features/large-video/actions.any.js
  24. 2
    1
      react/features/video-layout/constants.js
  25. 5
    0
      react/features/video-layout/functions.any.js
  26. 6
    6
      react/features/video-menu/components/web/LocalVideoMenuTriggerButton.js
  27. 6
    6
      react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.js

+ 138
- 136
css/filmstrip/_vertical_filmstrip.scss Vedi File

1
-.vertical-filmstrip span:not(.tile-view) .filmstrip {
2
-    &.hide-videos {
3
-        .remote-videos {
4
-            & > div {
5
-                opacity: 0;
6
-                pointer-events: none;
1
+.vertical-filmstrip, .stage-filmstrip {
2
+    span:not(.tile-view) .filmstrip {
3
+        &.hide-videos {
4
+            .remote-videos {
5
+                & > div {
6
+                    opacity: 0;
7
+                    pointer-events: none;
8
+                }
7
             }
9
             }
8
         }
10
         }
9
-    }
10
-
11
-    /*
12
-     * Firefox sets flex items to min-height: auto and min-width: auto,
13
-     * preventing flex children from shrinking like they do on other browsers.
14
-     * Setting min-height and min-width 0 is a workaround for the issue so
15
-     * Firefox behaves like other browsers.
16
-     * https://bugzilla.mozilla.org/show_bug.cgi?id=1043520
17
-     */
18
-    @mixin minHWAutoFix() {
19
-        min-height: 0;
20
-        min-width: 0;
21
-    }
22
 
11
 
23
-    @extend %align-right;
24
-    align-items: flex-end;
25
-    bottom: 0;
26
-    box-sizing: border-box;
27
-    display: flex;
28
-    flex-direction: column-reverse;
29
-    height: 100%;
30
-    width: 100%;
31
-    padding: 0;
32
-    /**
33
-     * fixed positioning is necessary for remote menus and tooltips to pop
34
-     * out of the scrolling filmstrip. AtlasKit dialogs and tooltips use
35
-     * a library called popper which will position its elements fixed if
36
-     * any parent is also fixed.
37
-     */
38
-    position: fixed;
39
-    top: 0;
40
-    right: 0;
41
-    z-index: $filmstripVideosZ;
42
-
43
-    &.no-vertical-padding {
44
-        padding: 0;
45
-    }
46
-
47
-    /**
48
-     * Hide videos by making them slight to the right.
49
-     */
50
-    .filmstrip__videos {
51
-        @extend %align-right;
52
-        bottom: 0;
53
-        padding: 0;
54
-        position:relative;
55
-        right: 0;
56
-        width: auto;
57
-
58
-        /**
59
-         * An id selector is used to match id specificity with existing
60
-         * filmstrip styles.
12
+        /*
13
+         * Firefox sets flex items to min-height: auto and min-width: auto,
14
+         * preventing flex children from shrinking like they do on other browsers.
15
+         * Setting min-height and min-width 0 is a workaround for the issue so
16
+         * Firefox behaves like other browsers.
17
+         * https://bugzilla.mozilla.org/show_bug.cgi?id=1043520
61
          */
18
          */
62
-        &#remoteVideos {
63
-            border: $thumbnailsBorder solid transparent;
64
-            padding-left: 0;
65
-            border-left: 0;
66
-            width: 100%;
67
-            height: 100%;
68
-            justify-content: center;
19
+        @mixin minHWAutoFix() {
20
+            min-height: 0;
21
+            min-width: 0;
69
         }
22
         }
70
-    }
71
 
23
 
72
-    /**
73
-     * Re-styles the local Video to better fit vertical filmstrip layout.
74
-     */
75
-    #filmstripLocalVideo {
76
-        align-self: initial;
77
-        margin-bottom: 5px;
24
+        @extend %align-right;
25
+        align-items: flex-end;
26
+        bottom: 0;
27
+        box-sizing: border-box;
78
         display: flex;
28
         display: flex;
79
         flex-direction: column-reverse;
29
         flex-direction: column-reverse;
80
-        height: auto;
81
-        justify-content: flex-start;
30
+        height: 100%;
82
         width: 100%;
31
         width: 100%;
32
+        padding: 0;
33
+        /**
34
+         * fixed positioning is necessary for remote menus and tooltips to pop
35
+         * out of the scrolling filmstrip. AtlasKit dialogs and tooltips use
36
+         * a library called popper which will position its elements fixed if
37
+         * any parent is also fixed.
38
+         */
39
+        position: fixed;
40
+        top: 0;
41
+        right: 0;
42
+        z-index: $filmstripVideosZ;
83
 
43
 
84
-        #filmstripLocalVideoThumbnail {
85
-            width: calc(100% - 15px);
44
+        &.no-vertical-padding {
45
+            padding: 0;
46
+        }
86
 
47
 
87
-            .videocontainer {
88
-                height: 0px;
48
+        /**
49
+         * Hide videos by making them slight to the right.
50
+         */
51
+        .filmstrip__videos {
52
+            @extend %align-right;
53
+            bottom: 0;
54
+            padding: 0;
55
+            position:relative;
56
+            right: 0;
57
+            width: auto;
58
+
59
+            /**
60
+             * An id selector is used to match id specificity with existing
61
+             * filmstrip styles.
62
+             */
63
+            &#remoteVideos {
64
+                border: $thumbnailsBorder solid transparent;
65
+                padding-left: 0;
66
+                border-left: 0;
89
                 width: 100%;
67
                 width: 100%;
68
+                height: 100%;
69
+                justify-content: center;
90
             }
70
             }
91
         }
71
         }
92
-    }
93
 
72
 
94
-    #filmstripLocalScreenShare {
95
-        align-self: initial;
96
-        margin-bottom: 5px;
97
-        display: flex;
98
-        flex-direction: column-reverse;
99
-        height: auto;
100
-        justify-content: flex-start;
101
-        width: 100%;
73
+        /**
74
+         * Re-styles the local Video to better fit vertical filmstrip layout.
75
+         */
76
+        #filmstripLocalVideo {
77
+            align-self: initial;
78
+            margin-bottom: 5px;
79
+            display: flex;
80
+            flex-direction: column-reverse;
81
+            height: auto;
82
+            justify-content: flex-start;
83
+            width: 100%;
102
 
84
 
103
-        #filmstripLocalScreenShareThumbnail {
104
-            width: calc(100% - 15px);
85
+            #filmstripLocalVideoThumbnail {
86
+                width: calc(100% - 15px);
105
 
87
 
106
-            .videocontainer {
107
-                height: 0px;
108
-                width: 100%;
88
+                .videocontainer {
89
+                    height: 0px;
90
+                    width: 100%;
91
+                }
109
             }
92
             }
110
         }
93
         }
111
-    }
112
 
94
 
113
-    /**
114
-     * Remove unnecssary padding that is normally used to prevent horizontal
115
-     * filmstrip from overlapping the left edge of the screen.
116
-     */
117
-    #filmstripLocalVideo,
118
-    #filmstripLocalScreenShare,
119
-    .remote-videos {
120
-        padding: 0;
121
-    }
95
+        #filmstripLocalScreenShare {
96
+            align-self: initial;
97
+            margin-bottom: 5px;
98
+            display: flex;
99
+            flex-direction: column-reverse;
100
+            height: auto;
101
+            justify-content: flex-start;
102
+            width: 100%;
122
 
103
 
123
-    #remoteVideos {
124
-        @include minHWAutoFix();
104
+            #filmstripLocalScreenShareThumbnail {
105
+                width: calc(100% - 15px);
125
 
106
 
126
-        flex-direction: column;
127
-        flex-grow: 1;
128
-    }
107
+                .videocontainer {
108
+                    height: 0px;
109
+                    width: 100%;
110
+                }
111
+            }
112
+        }
129
 
113
 
130
-    .resizable-filmstrip #remoteVideos .videocontainer {
131
-        border-left: 0;
132
-        margin: 0;
133
-    }
114
+        /**
115
+         * Remove unnecssary padding that is normally used to prevent horizontal
116
+         * filmstrip from overlapping the left edge of the screen.
117
+         */
118
+        #filmstripLocalVideo,
119
+        #filmstripLocalScreenShare,
120
+        .remote-videos {
121
+            padding: 0;
122
+        }
134
 
123
 
135
-    &.reduce-height {
136
-        height: calc(100% - calc(#{$newToolbarSizeWithPadding} + #{$scrollHeight}));
137
-    }
124
+        #remoteVideos {
125
+            @include minHWAutoFix();
138
 
126
 
139
-    .filmstrip__videos.vertical-view-grid#remoteVideos {
140
-        align-items: 'center';
141
-        border: 0px;
142
-        padding-right: 7px;
127
+            flex-direction: column;
128
+            flex-grow: 1;
129
+        }
143
 
130
 
144
-        &.has-scroll {
145
-            padding-right: 0px;
131
+        .resizable-filmstrip #remoteVideos .videocontainer {
132
+            border-left: 0;
133
+            margin: 0;
146
         }
134
         }
147
 
135
 
148
-        .remote-videos > div {
149
-            left: 0px; // fixes an issue on FF - the div is aligned to the right by default for some reason
136
+        &.reduce-height {
137
+            height: calc(100% - calc(#{$newToolbarSizeWithPadding} + #{$scrollHeight}));
150
         }
138
         }
151
 
139
 
152
-        .videocontainer {
140
+        .filmstrip__videos.vertical-view-grid#remoteVideos {
141
+            align-items: 'center';
153
             border: 0px;
142
             border: 0px;
154
-            margin: 2px;
155
-        }
156
-    }
143
+            padding-right: 7px;
157
 
144
 
158
-    .remote-videos {
159
-        display: flex;
160
-        overscroll-behavior: contain;
145
+            &.has-scroll {
146
+                padding-right: 0px;
147
+            }
161
 
148
 
162
-        &.height-transition {
163
-            transition: height .3s ease-in;
164
-        }
149
+            .remote-videos > div {
150
+                left: 0px; // fixes an issue on FF - the div is aligned to the right by default for some reason
151
+            }
165
 
152
 
166
-        & > div {
167
-            position: absolute;
168
-            transition: opacity 1s;
153
+            .videocontainer {
154
+                border: 0px;
155
+                margin: 2px;
156
+            }
169
         }
157
         }
170
 
158
 
171
-        &.is-not-overflowing > div {
172
-            bottom: 0px;
159
+        .remote-videos {
160
+            display: flex;
161
+            overscroll-behavior: contain;
162
+
163
+            &.height-transition {
164
+                transition: height .3s ease-in;
165
+            }
166
+
167
+            & > div {
168
+                position: absolute;
169
+                transition: opacity 1s;
170
+            }
171
+
172
+            &.is-not-overflowing > div {
173
+                bottom: 0px;
174
+            }
173
         }
175
         }
174
     }
176
     }
175
 }
177
 }

+ 9
- 4
css/filmstrip/_vertical_filmstrip_overrides.scss Vedi File

3
  * clashing with the filmstrip.
3
  * clashing with the filmstrip.
4
  */
4
  */
5
 .vertical-filmstrip #etherpad,
5
 .vertical-filmstrip #etherpad,
6
-.vertical-filmstrip #sharedvideo {
6
+.stage-filmstrip #etherpad,
7
+.vertical-filmstrip #sharedvideo,
8
+.stage-filmstrip #sharedvideo {
7
     text-align: left;
9
     text-align: left;
8
 }
10
 }
9
 
11
 
10
 /**
12
 /**
11
  * Overrides for small videos in vertical filmstrip mode.
13
  * Overrides for small videos in vertical filmstrip mode.
12
  */
14
  */
13
-.vertical-filmstrip .filmstrip__videos .videocontainer {
15
+.vertical-filmstrip .filmstrip__videos .videocontainer,
16
+.stage-filmstrip .filmstrip__videos .videocontainer {
14
     .self-view-mobile-portrait video {
17
     .self-view-mobile-portrait video {
15
         object-fit: contain;
18
         object-fit: contain;
16
     }
19
     }
27
  * The class opening is for when the filmstrip is transitioning from hidden
30
  * The class opening is for when the filmstrip is transitioning from hidden
28
  * to visible.
31
  * to visible.
29
  */
32
  */
30
-.vertical-filmstrip .large-video-labels {
33
+.vertical-filmstrip .large-video-labels,
34
+.stage-filmstrip .large-video-labels {
31
     &.with-filmstrip {
35
     &.with-filmstrip {
32
         right: 150px;
36
         right: 150px;
33
     }
37
     }
47
  * Overrides for self view when in portrait mode on mobile.
51
  * Overrides for self view when in portrait mode on mobile.
48
  * This is done in order to keep the aspect ratio.
52
  * This is done in order to keep the aspect ratio.
49
  */
53
  */
50
-.vertical-filmstrip .self-view-mobile-portrait #localVideo_container {
54
+.vertical-filmstrip .self-view-mobile-portrait #localVideo_container,
55
+.stage-filmstrip .self-view-mobile-portrait #localVideo_container {
51
     object-fit: contain;
56
     object-fit: contain;
52
 }
57
 }

+ 2
- 2
modules/UI/videolayout/VideoContainer.js Vedi File

6
 
6
 
7
 import { browser } from '../../../react/features/base/lib-jitsi-meet';
7
 import { browser } from '../../../react/features/base/lib-jitsi-meet';
8
 import { isTestModeEnabled } from '../../../react/features/base/testing';
8
 import { isTestModeEnabled } from '../../../react/features/base/testing';
9
-import { FILMSTRIP_BREAKPOINT, shouldDisplayStageFilmstrip } from '../../../react/features/filmstrip';
9
+import { FILMSTRIP_BREAKPOINT } from '../../../react/features/filmstrip';
10
 import { ORIENTATION, LargeVideoBackground, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
10
 import { ORIENTATION, LargeVideoBackground, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
11
 import { LAYOUTS, getCurrentLayout } from '../../../react/features/video-layout';
11
 import { LAYOUTS, getCurrentLayout } from '../../../react/features/video-layout';
12
 /* eslint-enable no-unused-vars */
12
 /* eslint-enable no-unused-vars */
414
 
414
 
415
         const verticalFilmstripWidth = state['features/filmstrip'].width?.current;
415
         const verticalFilmstripWidth = state['features/filmstrip'].width?.current;
416
 
416
 
417
-        if (currentLayout === LAYOUTS.TILE_VIEW || shouldDisplayStageFilmstrip(state)) {
417
+        if (currentLayout === LAYOUTS.TILE_VIEW || currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW) {
418
             // We don't need to resize the large video since it won't be displayed and we'll resize when returning back
418
             // We don't need to resize the large video since it won't be displayed and we'll resize when returning back
419
             // to stage view.
419
             // to stage view.
420
             return;
420
             return;

+ 2
- 2
react/features/base/participants/functions.js Vedi File

4
 import type { Store } from 'redux';
4
 import type { Store } from 'redux';
5
 
5
 
6
 import { i18next } from '../../base/i18n';
6
 import { i18next } from '../../base/i18n';
7
-import { isStageFilmstripEnabled } from '../../filmstrip/functions';
7
+import { isStageFilmstripAvailable } from '../../filmstrip/functions';
8
 import { GRAVATAR_BASE_URL, isCORSAvatarURL } from '../avatar';
8
 import { GRAVATAR_BASE_URL, isCORSAvatarURL } from '../avatar';
9
 import { getSourceNameSignalingFeatureFlag } from '../config';
9
 import { getSourceNameSignalingFeatureFlag } from '../config';
10
 import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet';
10
 import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet';
372
 export function getPinnedParticipant(stateful: Object | Function) {
372
 export function getPinnedParticipant(stateful: Object | Function) {
373
     const state = toState(stateful);
373
     const state = toState(stateful);
374
     const { pinnedParticipant } = state['features/base/participants'];
374
     const { pinnedParticipant } = state['features/base/participants'];
375
-    const stageFilmstrip = isStageFilmstripEnabled(state);
375
+    const stageFilmstrip = isStageFilmstripAvailable(state);
376
 
376
 
377
     if (stageFilmstrip) {
377
     if (stageFilmstrip) {
378
         const { activeParticipants } = state['features/filmstrip'];
378
         const { activeParticipants } = state['features/filmstrip'];

+ 7
- 14
react/features/conference/components/web/Conference.js Vedi File

1
 // @flow
1
 // @flow
2
 
2
 
3
-import clsx from 'clsx';
4
 import _ from 'lodash';
3
 import _ from 'lodash';
5
 import React from 'react';
4
 import React from 'react';
6
 
5
 
12
 import { connect as reactReduxConnect } from '../../../base/redux';
11
 import { connect as reactReduxConnect } from '../../../base/redux';
13
 import { setColorAlpha } from '../../../base/util';
12
 import { setColorAlpha } from '../../../base/util';
14
 import { Chat } from '../../../chat';
13
 import { Chat } from '../../../chat';
15
-import { MainFilmstrip, StageFilmstrip, shouldDisplayStageFilmstrip } from '../../../filmstrip';
14
+import { MainFilmstrip, StageFilmstrip } from '../../../filmstrip';
16
 import { CalleeInfoContainer } from '../../../invite';
15
 import { CalleeInfoContainer } from '../../../invite';
17
 import { LargeVideo } from '../../../large-video';
16
 import { LargeVideo } from '../../../large-video';
18
 import { LobbyScreen } from '../../../lobby';
17
 import { LobbyScreen } from '../../../lobby';
59
 export const LAYOUT_CLASSNAMES = {
58
 export const LAYOUT_CLASSNAMES = {
60
     [LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'horizontal-filmstrip',
59
     [LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'horizontal-filmstrip',
61
     [LAYOUTS.TILE_VIEW]: 'tile-view',
60
     [LAYOUTS.TILE_VIEW]: 'tile-view',
62
-    [LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'vertical-filmstrip'
61
+    [LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'vertical-filmstrip',
62
+    [LAYOUTS.STAGE_FILMSTRIP_VIEW]: 'stage-filmstrip'
63
 };
63
 };
64
 
64
 
65
 /**
65
 /**
103
      */
103
      */
104
     _showPrejoin: boolean,
104
     _showPrejoin: boolean,
105
 
105
 
106
-    /**
107
-     * Whether or not the stage filmstrip should be displayed.
108
-     */
109
-    _showStageFilmstrip: boolean,
110
-
111
     dispatch: Function,
106
     dispatch: Function,
112
     t: Function
107
     t: Function
113
 }
108
 }
220
             _notificationsVisible,
215
             _notificationsVisible,
221
             _overflowDrawer,
216
             _overflowDrawer,
222
             _showLobby,
217
             _showLobby,
223
-            _showPrejoin,
224
-            _showStageFilmstrip
218
+            _showPrejoin
225
         } = this.props;
219
         } = this.props;
226
 
220
 
227
         return (
221
         return (
233
                 ref = { this._setBackground }>
227
                 ref = { this._setBackground }>
234
                 <Chat />
228
                 <Chat />
235
                 <div
229
                 <div
236
-                    className = { clsx(_layoutClassName, _showStageFilmstrip && 'stage-filmstrip') }
230
+                    className = { _layoutClassName }
237
                     id = 'videoconference_page'
231
                     id = 'videoconference_page'
238
                     onMouseMove = { isMobileBrowser() ? undefined : this._onShowToolbar }>
232
                     onMouseMove = { isMobileBrowser() ? undefined : this._onShowToolbar }>
239
                     <ConferenceInfo />
233
                     <ConferenceInfo />
242
                         id = 'videospace'
236
                         id = 'videospace'
243
                         onTouchStart = { this._onVidespaceTouchStart }>
237
                         onTouchStart = { this._onVidespaceTouchStart }>
244
                         <LargeVideo />
238
                         <LargeVideo />
245
-                        {_showStageFilmstrip && <StageFilmstrip />}
239
+                        <StageFilmstrip />
246
                         <MainFilmstrip />
240
                         <MainFilmstrip />
247
                     </div>
241
                     </div>
248
 
242
 
402
         _overflowDrawer: overflowDrawer,
396
         _overflowDrawer: overflowDrawer,
403
         _roomName: getConferenceNameForTitle(state),
397
         _roomName: getConferenceNameForTitle(state),
404
         _showLobby: getIsLobbyVisible(state),
398
         _showLobby: getIsLobbyVisible(state),
405
-        _showPrejoin: isPrejoinPageVisible(state),
406
-        _showStageFilmstrip: shouldDisplayStageFilmstrip(state)
399
+        _showPrejoin: isPrejoinPageVisible(state)
407
     };
400
     };
408
 }
401
 }
409
 
402
 

+ 9
- 9
react/features/display-name/components/web/DisplayName.js Vedi File

36
      */
36
      */
37
     allowEditing: boolean,
37
     allowEditing: boolean,
38
 
38
 
39
-    /**
40
-     * The current layout of the filmstrip.
41
-     */
42
-    currentLayout: string,
43
-
44
     /**
39
     /**
45
      * Invoked to update the participant's display name.
40
      * Invoked to update the participant's display name.
46
      */
41
      */
70
     /**
65
     /**
71
      * Invoked to obtain translated strings.
66
      * Invoked to obtain translated strings.
72
      */
67
      */
73
-    t: Function
68
+    t: Function,
69
+
70
+    /**
71
+     * The type of thumbnail.
72
+     */
73
+    thumbnailType: string
74
 };
74
 };
75
 
75
 
76
 /**
76
 /**
183
         const {
183
         const {
184
             _nameToDisplay,
184
             _nameToDisplay,
185
             allowEditing,
185
             allowEditing,
186
-            currentLayout,
187
             displayNameSuffix,
186
             displayNameSuffix,
188
             classes,
187
             classes,
189
             elementID,
188
             elementID,
190
-            t
189
+            t,
190
+            thumbnailType
191
         } = this.props;
191
         } = this.props;
192
 
192
 
193
         if (allowEditing && this.state.isEditing) {
193
         if (allowEditing && this.state.isEditing) {
211
         return (
211
         return (
212
             <Tooltip
212
             <Tooltip
213
                 content = { appendSuffix(_nameToDisplay, displayNameSuffix) }
213
                 content = { appendSuffix(_nameToDisplay, displayNameSuffix) }
214
-                position = { getIndicatorsTooltipPosition(currentLayout) }>
214
+                position = { getIndicatorsTooltipPosition(thumbnailType) }>
215
                 <span
215
                 <span
216
                     className = { `displayname ${classes.displayName}` }
216
                     className = { `displayname ${classes.displayName}` }
217
                     id = { elementID }
217
                     id = { elementID }

+ 8
- 1
react/features/filmstrip/actionTypes.ts Vedi File

171
  */
171
  */
172
 export const SET_MAX_STAGE_PARTICIPANTS = 'SET_MAX_STAGE_PARTICIPANTS';
172
 export const SET_MAX_STAGE_PARTICIPANTS = 'SET_MAX_STAGE_PARTICIPANTS';
173
 
173
 
174
-
175
 /**
174
 /**
176
  * The type of Redux action which toggles the pin state of stage participants.
175
  * The type of Redux action which toggles the pin state of stage participants.
177
  * {
176
  * {
180
  * }
179
  * }
181
  */
180
  */
182
 export const TOGGLE_PIN_STAGE_PARTICIPANT = 'TOGGLE_PIN_STAGE_PARTICIPANT';
181
 export const TOGGLE_PIN_STAGE_PARTICIPANT = 'TOGGLE_PIN_STAGE_PARTICIPANT';
182
+
183
+/**
184
+ * The type of Redux action which clears the list of stage participants.
185
+ * {
186
+ *     type: CLEAR_STAGE_PARTICIPANTS
187
+ * }
188
+ */
189
+export const CLEAR_STAGE_PARTICIPANTS = 'CLEAR_STAGE_PARTICIPANTS';

+ 22
- 14
react/features/filmstrip/actions.web.js Vedi File

24
     SET_VERTICAL_VIEW_DIMENSIONS,
24
     SET_VERTICAL_VIEW_DIMENSIONS,
25
     SET_VOLUME,
25
     SET_VOLUME,
26
     SET_MAX_STAGE_PARTICIPANTS,
26
     SET_MAX_STAGE_PARTICIPANTS,
27
-    TOGGLE_PIN_STAGE_PARTICIPANT
27
+    TOGGLE_PIN_STAGE_PARTICIPANT,
28
+    CLEAR_STAGE_PARTICIPANTS
28
 } from './actionTypes';
29
 } from './actionTypes';
29
 import {
30
 import {
30
     HORIZONTAL_FILMSTRIP_MARGIN,
31
     HORIZONTAL_FILMSTRIP_MARGIN,
266
         const state = getState();
267
         const state = getState();
267
         const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
268
         const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
268
         const {
269
         const {
269
-            disableResponsiveTiles,
270
-            disableTileEnlargement,
271
             tileView = {}
270
             tileView = {}
272
         } = state['features/base/config'];
271
         } = state['features/base/config'];
273
         const { visible } = state['features/filmstrip'];
272
         const { visible } = state['features/filmstrip'];
282
             width,
281
             width,
283
             columns,
282
             columns,
284
             rows
283
             rows
285
-        } = disableResponsiveTiles
286
-            ? calculateNonResponsiveTileViewDimensions(state, true)
287
-            : calculateResponsiveTileViewDimensions({
288
-                clientWidth: availableWidth,
289
-                clientHeight,
290
-                disableTileEnlargement,
291
-                maxColumns,
292
-                noHorizontalContainerMargin: verticalWidth > 0,
293
-                numberOfParticipants,
294
-                numberOfVisibleTiles
295
-            });
284
+        } = calculateResponsiveTileViewDimensions({
285
+            clientWidth: availableWidth,
286
+            clientHeight,
287
+            disableTileEnlargement: false,
288
+            maxColumns,
289
+            noHorizontalContainerMargin: verticalWidth > 0,
290
+            numberOfParticipants,
291
+            numberOfVisibleTiles
292
+        });
296
         const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
293
         const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
297
         const hasScroll = clientHeight < thumbnailsTotalHeight;
294
         const hasScroll = clientHeight < thumbnailsTotalHeight;
298
         const filmstripWidth
295
         const filmstripWidth
469
         participantId
466
         participantId
470
     };
467
     };
471
 }
468
 }
469
+
470
+/**
471
+ * Clears the stage participants list.
472
+ *
473
+ * @returns {Object}
474
+ */
475
+export function clearStageParticipants() {
476
+    return {
477
+        type: CLEAR_STAGE_PARTICIPANTS
478
+    };
479
+}

+ 22
- 19
react/features/filmstrip/components/web/Filmstrip.js Vedi File

20
 import { shouldHideSelfView } from '../../../base/settings/functions.any';
20
 import { shouldHideSelfView } from '../../../base/settings/functions.any';
21
 import { showToolbox } from '../../../toolbox/actions.web';
21
 import { showToolbox } from '../../../toolbox/actions.web';
22
 import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
22
 import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
23
-import { LAYOUTS } from '../../../video-layout';
23
+import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
24
 import {
24
 import {
25
     setFilmstripVisible,
25
     setFilmstripVisible,
26
     setVisibleRemoteParticipants,
26
     setVisibleRemoteParticipants,
110
     /**
110
     /**
111
      * The local screen share participant. This prop is behind the sourceNameSignaling feature flag.
111
      * The local screen share participant. This prop is behind the sourceNameSignaling feature flag.
112
      */
112
      */
113
-     _localScreenShare: Object,
113
+    _localScreenShare: Object,
114
 
114
 
115
     /**
115
     /**
116
      * The maximum width of the vertical filmstrip.
116
      * The maximum width of the vertical filmstrip.
318
         const { isMouseDown } = this.state;
318
         const { isMouseDown } = this.state;
319
         const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
319
         const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
320
 
320
 
321
-        switch (_currentLayout) {
322
-        case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
321
+        if (_currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && _stageFilmstrip) {
322
+            if (_visible) {
323
+                filmstripStyle.maxWidth = `calc(100% - ${_verticalViewMaxWidth}px)`;
324
+            }
325
+        } else if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
326
+            || (_currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && !_stageFilmstrip)) {
323
             filmstripStyle.maxWidth = _verticalViewMaxWidth;
327
             filmstripStyle.maxWidth = _verticalViewMaxWidth;
324
             if (!_visible) {
328
             if (!_visible) {
325
                 filmstripStyle.right = `-${filmstripStyle.maxWidth}px`;
329
                 filmstripStyle.right = `-${filmstripStyle.maxWidth}px`;
326
             }
330
             }
327
-            break;
328
-        }
329
-        case LAYOUTS.TILE_VIEW: {
330
-            if (_stageFilmstrip && _visible) {
331
-                filmstripStyle.maxWidth = `calc(100% - ${_verticalViewMaxWidth}px)`;
332
-            }
333
-            break;
334
-        }
335
         }
331
         }
336
 
332
 
337
         let toolbar = null;
333
         let toolbar = null;
338
 
334
 
339
-        if (!this.props._iAmRecorder && this.props._isFilmstripButtonEnabled && _currentLayout !== LAYOUTS.TILE_VIEW) {
335
+        if (!this.props._iAmRecorder && this.props._isFilmstripButtonEnabled
336
+            && _currentLayout !== LAYOUTS.TILE_VIEW && !_stageFilmstrip) {
340
             toolbar = this._renderToggleButton();
337
             toolbar = this._renderToggleButton();
341
         }
338
         }
342
 
339
 
343
         const filmstrip = (<>
340
         const filmstrip = (<>
344
             <div
341
             <div
345
                 className = { clsx(this.props._videosClassName,
342
                 className = { clsx(this.props._videosClassName,
346
-                    !tileViewActive && !_resizableFilmstrip && 'filmstrip-hover',
343
+                    !tileViewActive && !_stageFilmstrip && !_resizableFilmstrip && 'filmstrip-hover',
347
                     _verticalViewGrid && 'vertical-view-grid') }
344
                     _verticalViewGrid && 'vertical-view-grid') }
348
                 id = 'remoteVideos'>
345
                 id = 'remoteVideos'>
349
                 {!_disableSelfView && !_verticalViewGrid && (
346
                 {!_disableSelfView && !_verticalViewGrid && (
351
                         className = 'filmstrip__videos'
348
                         className = 'filmstrip__videos'
352
                         id = 'filmstripLocalVideo'>
349
                         id = 'filmstripLocalVideo'>
353
                         {
350
                         {
354
-                            !tileViewActive && <div id = 'filmstripLocalVideoThumbnail'>
351
+                            !tileViewActive && !_stageFilmstrip && <div id = 'filmstripLocalVideoThumbnail'>
355
                                 <Thumbnail
352
                                 <Thumbnail
356
                                     key = 'local' />
353
                                     key = 'local' />
357
                             </div>
354
                             </div>
364
                         id = 'filmstripLocalScreenShare'>
361
                         id = 'filmstripLocalScreenShare'>
365
                         <div id = 'filmstripLocalScreenShareThumbnail'>
362
                         <div id = 'filmstripLocalScreenShareThumbnail'>
366
                             {
363
                             {
367
-                                !tileViewActive && <Thumbnail
364
+                                !tileViewActive && !_stageFilmstrip && <Thumbnail
368
                                     key = 'localScreenShare'
365
                                     key = 'localScreenShare'
369
                                     participantID = { _localScreenShare.id } />
366
                                     participantID = { _localScreenShare.id } />
370
 
367
 
604
             _filmstripHeight,
601
             _filmstripHeight,
605
             _filmstripWidth,
602
             _filmstripWidth,
606
             _hasScroll,
603
             _hasScroll,
604
+            _isVerticalFilmstrip,
607
             _remoteParticipantsLength,
605
             _remoteParticipantsLength,
608
             _resizableFilmstrip,
606
             _resizableFilmstrip,
609
             _rows,
607
             _rows,
619
             return null;
617
             return null;
620
         }
618
         }
621
 
619
 
622
-        if (_currentLayout === LAYOUTS.TILE_VIEW || _verticalViewGrid) {
620
+        if (_currentLayout === LAYOUTS.TILE_VIEW || _verticalViewGrid || _stageFilmstrip) {
623
             return (
621
             return (
624
                 <FixedSizeGrid
622
                 <FixedSizeGrid
625
                     className = 'filmstrip__videos remote-videos'
623
                     className = 'filmstrip__videos remote-videos'
669
                 props.className += ' is-not-overflowing';
667
                 props.className += ' is-not-overflowing';
670
             }
668
             }
671
 
669
 
672
-        } else if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
670
+        } else if (_isVerticalFilmstrip) {
673
             const itemSize = _thumbnailHeight + TILE_VERTICAL_MARGIN;
671
             const itemSize = _thumbnailHeight + TILE_VERTICAL_MARGIN;
674
             const isNotOverflowing = !_hasScroll;
672
             const isNotOverflowing = !_hasScroll;
675
 
673
 
820
         shouldReduceHeight ? 'reduce-height' : ''
818
         shouldReduceHeight ? 'reduce-height' : ''
821
     } ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
819
     } ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
822
 
820
 
821
+    const _currentLayout = getCurrentLayout(state);
822
+    const _isVerticalFilmstrip = _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
823
+        || (!ownProps._stageFilmstrip && _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW);
824
+
823
     return {
825
     return {
824
         _className: className,
826
         _className: className,
825
         _chatOpen: state['features/chat'].isOpen,
827
         _chatOpen: state['features/chat'].isOpen,
828
+        _currentLayout,
826
         _disableSelfView: disableSelfView,
829
         _disableSelfView: disableSelfView,
827
         _hasScroll,
830
         _hasScroll,
828
         _iAmRecorder: Boolean(iAmRecorder),
831
         _iAmRecorder: Boolean(iAmRecorder),
829
         _isFilmstripButtonEnabled: isButtonEnabled('filmstrip', state),
832
         _isFilmstripButtonEnabled: isButtonEnabled('filmstrip', state),
830
         _isToolboxVisible: isToolboxVisible(state),
833
         _isToolboxVisible: isToolboxVisible(state),
831
-        _isVerticalFilmstrip: ownProps._currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW,
834
+        _isVerticalFilmstrip,
832
         _localScreenShare: getSourceNameSignalingFeatureFlag(state) && localScreenShare,
835
         _localScreenShare: getSourceNameSignalingFeatureFlag(state) && localScreenShare,
833
         _maxFilmstripWidth: clientWidth - MIN_STAGE_VIEW_WIDTH,
836
         _maxFilmstripWidth: clientWidth - MIN_STAGE_VIEW_WIDTH,
834
         _thumbnailsReordered: enableThumbnailReordering,
837
         _thumbnailsReordered: enableThumbnailReordering,

+ 4
- 8
react/features/filmstrip/components/web/MainFilmstrip.js Vedi File

17
 
17
 
18
 type Props = {
18
 type Props = {
19
 
19
 
20
-    /**
21
-     * The current layout of the filmstrip.
22
-     */
23
-    _currentLayout: string,
24
-
25
     /**
20
     /**
26
      * The number of columns in tile view.
21
      * The number of columns in tile view.
27
      */
22
      */
143
         && clientWidth <= ASPECT_RATIO_BREAKPOINT;
138
         && clientWidth <= ASPECT_RATIO_BREAKPOINT;
144
 
139
 
145
     const shouldReduceHeight = reduceHeight && (
140
     const shouldReduceHeight = reduceHeight && (
146
-        isMobileBrowser() || _currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW);
141
+        isMobileBrowser() || (_currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW
142
+            && _currentLayout !== LAYOUTS.STAGE_FILMSTRIP_VIEW));
147
 
143
 
148
     let _thumbnailSize, remoteFilmstripHeight, remoteFilmstripWidth;
144
     let _thumbnailSize, remoteFilmstripHeight, remoteFilmstripWidth;
149
 
145
 
154
         remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
150
         remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
155
         remoteFilmstripWidth = filmstripWidth;
151
         remoteFilmstripWidth = filmstripWidth;
156
         break;
152
         break;
157
-    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
153
+    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
154
+    case LAYOUTS.STAGE_FILMSTRIP_VIEW: {
158
         const {
155
         const {
159
             remote,
156
             remote,
160
             remoteVideosContainer,
157
             remoteVideosContainer,
189
 
186
 
190
     return {
187
     return {
191
         _columns: gridDimensions.columns,
188
         _columns: gridDimensions.columns,
192
-        _currentLayout,
193
         _filmstripHeight: remoteFilmstripHeight,
189
         _filmstripHeight: remoteFilmstripHeight,
194
         _filmstripWidth: remoteFilmstripWidth,
190
         _filmstripWidth: remoteFilmstripWidth,
195
         _hasScroll,
191
         _hasScroll,

+ 1
- 2
react/features/filmstrip/components/web/StageFilmstrip.js Vedi File

92
     _visible: boolean
92
     _visible: boolean
93
 };
93
 };
94
 
94
 
95
-const StageFilmstrip = (props: Props) => props._currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW && (
95
+const StageFilmstrip = (props: Props) => props._currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && (
96
     <span className = { LAYOUT_CLASSNAMES[LAYOUTS.TILE_VIEW] }>
96
     <span className = { LAYOUT_CLASSNAMES[LAYOUTS.TILE_VIEW] }>
97
         <Filmstrip
97
         <Filmstrip
98
             { ...props }
98
             { ...props }
99
-            _currentLayout = { LAYOUTS.TILE_VIEW }
100
             _stageFilmstrip = { true } />
99
             _stageFilmstrip = { true } />
101
     </span>
100
     </span>
102
 );
101
 );

+ 9
- 11
react/features/filmstrip/components/web/StatusIndicators.js Vedi File

6
 import { getParticipantByIdOrUndefined, PARTICIPANT_ROLE } from '../../../base/participants';
6
 import { getParticipantByIdOrUndefined, PARTICIPANT_ROLE } from '../../../base/participants';
7
 import { connect } from '../../../base/redux';
7
 import { connect } from '../../../base/redux';
8
 import { getTrackByMediaTypeAndParticipant, isLocalTrackMuted, isRemoteTrackMuted } from '../../../base/tracks';
8
 import { getTrackByMediaTypeAndParticipant, isLocalTrackMuted, isRemoteTrackMuted } from '../../../base/tracks';
9
-import { getCurrentLayout } from '../../../video-layout';
10
 import { getIndicatorsTooltipPosition } from '../../functions.web';
9
 import { getIndicatorsTooltipPosition } from '../../functions.web';
11
 
10
 
12
 import AudioMutedIndicator from './AudioMutedIndicator';
11
 import AudioMutedIndicator from './AudioMutedIndicator';
20
  */
19
  */
21
 type Props = {
20
 type Props = {
22
 
21
 
23
-    /**
24
-     * The current layout of the filmstrip.
25
-     */
26
-    _currentLayout: string,
27
-
28
     /**
22
     /**
29
      * Indicates if the audio muted indicator should be visible or not.
23
      * Indicates if the audio muted indicator should be visible or not.
30
      */
24
      */
43
     /**
37
     /**
44
      * The ID of the participant for which the status bar is rendered.
38
      * The ID of the participant for which the status bar is rendered.
45
      */
39
      */
46
-    participantID: String
40
+    participantID: String,
41
+
42
+    /**
43
+     * The type of thumbnail.
44
+     */
45
+    thumbnailType: string
47
 };
46
 };
48
 
47
 
49
 /**
48
 /**
60
      */
59
      */
61
     render() {
60
     render() {
62
         const {
61
         const {
63
-            _currentLayout,
64
             _showAudioMutedIndicator,
62
             _showAudioMutedIndicator,
65
             _showModeratorIndicator,
63
             _showModeratorIndicator,
66
-            _showScreenShareIndicator
64
+            _showScreenShareIndicator,
65
+            thumbnailType
67
         } = this.props;
66
         } = this.props;
68
-        const tooltipPosition = getIndicatorsTooltipPosition(_currentLayout);
67
+        const tooltipPosition = getIndicatorsTooltipPosition(thumbnailType);
69
 
68
 
70
         return (
69
         return (
71
             <>
70
             <>
111
     const { disableModeratorIndicator } = state['features/base/config'];
110
     const { disableModeratorIndicator } = state['features/base/config'];
112
 
111
 
113
     return {
112
     return {
114
-        _currentLayout: getCurrentLayout(state),
115
         _showAudioMutedIndicator: isAudioMuted && audio,
113
         _showAudioMutedIndicator: isAudioMuted && audio,
116
         _showModeratorIndicator:
114
         _showModeratorIndicator:
117
             !disableModeratorIndicator && participant && participant.role === PARTICIPANT_ROLE.MODERATOR && moderator,
115
             !disableModeratorIndicator && participant && participant.role === PARTICIPANT_ROLE.MODERATOR && moderator,

+ 44
- 41
react/features/filmstrip/components/web/Thumbnail.js Vedi File

36
     DISPLAY_MODE_TO_CLASS_NAME,
36
     DISPLAY_MODE_TO_CLASS_NAME,
37
     DISPLAY_VIDEO,
37
     DISPLAY_VIDEO,
38
     SHOW_TOOLBAR_CONTEXT_MENU_AFTER,
38
     SHOW_TOOLBAR_CONTEXT_MENU_AFTER,
39
+    THUMBNAIL_TYPE,
39
     VIDEO_TEST_EVENTS
40
     VIDEO_TEST_EVENTS
40
 } from '../../constants';
41
 } from '../../constants';
41
 import {
42
 import {
44
     getDisplayModeInput,
45
     getDisplayModeInput,
45
     isVideoPlayable,
46
     isVideoPlayable,
46
     showGridInVerticalView,
47
     showGridInVerticalView,
47
-    isStageFilmstripEnabled,
48
-    shouldDisplayStageFilmstrip
48
+    isStageFilmstripAvailable
49
 } from '../../functions';
49
 } from '../../functions';
50
+import { getThumbnailTypeFromLayout } from '../../functions.web';
50
 
51
 
51
 import FakeScreenShareParticipant from './FakeScreenShareParticipant';
52
 import FakeScreenShareParticipant from './FakeScreenShareParticipant';
52
 import ThumbnailAudioIndicator from './ThumbnailAudioIndicator';
53
 import ThumbnailAudioIndicator from './ThumbnailAudioIndicator';
91
      */
92
      */
92
     _audioTrack: ?Object,
93
     _audioTrack: ?Object,
93
 
94
 
94
-    /**
95
-     * The current layout of the filmstrip.
96
-     */
97
-    _currentLayout: string,
98
-
99
     /**
95
     /**
100
      * Indicates whether the local video flip feature is disabled or not.
96
      * Indicates whether the local video flip feature is disabled or not.
101
      */
97
      */
189
     _raisedHand: boolean,
185
     _raisedHand: boolean,
190
 
186
 
191
     /**
187
     /**
192
-     * Whether or not the stage filmstrip is disabled.
188
+     * Whether or not the current layout is stage filmstrip layout.
193
      */
189
      */
194
-    _stageFilmstripDisabled: boolean,
190
+    _stageFilmstripLayout: boolean,
195
 
191
 
196
     /**
192
     /**
197
      * Whether or not the participants are displayed on stage.
193
      * Whether or not the participants are displayed on stage.
200
      */
196
      */
201
     _stageParticipantsVisible: boolean,
197
     _stageParticipantsVisible: boolean,
202
 
198
 
199
+    /**
200
+     * The type of thumbnail to display.
201
+     */
202
+    _thumbnailType: string,
203
+
203
     /**
204
     /**
204
      * The video object position for the participant.
205
      * The video object position for the participant.
205
      */
206
      */
447
      */
448
      */
448
     _maybeSendScreenSharingIssueEvents(input) {
449
     _maybeSendScreenSharingIssueEvents(input) {
449
         const {
450
         const {
450
-            _currentLayout,
451
             _isAudioOnly,
451
             _isAudioOnly,
452
-            _isScreenSharing
452
+            _isScreenSharing,
453
+            _thumbnailType
453
         } = this.props;
454
         } = this.props;
454
         const { displayMode } = this.state;
455
         const { displayMode } = this.state;
455
-        const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
456
+        const isTileType = _thumbnailType === THUMBNAIL_TYPE.TILE;
456
 
457
 
457
         if (!(DISPLAY_VIDEO === displayMode)
458
         if (!(DISPLAY_VIDEO === displayMode)
458
-            && tileViewActive
459
+            && isTileType
459
             && _isScreenSharing
460
             && _isScreenSharing
460
             && !_isAudioOnly) {
461
             && !_isAudioOnly) {
461
             sendAnalytics(createScreenSharingIssueEvent({
462
             sendAnalytics(createScreenSharingIssueEvent({
530
      * @returns {void}
531
      * @returns {void}
531
      */
532
      */
532
     _hidePopover() {
533
     _hidePopover() {
533
-        const { _currentLayout } = this.props;
534
+        const { _thumbnailType } = this.props;
534
 
535
 
535
-        if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
536
+        if (_thumbnailType === THUMBNAIL_TYPE.VERTICAL) {
536
             this.setState({
537
             this.setState({
537
                 isHovered: false
538
                 isHovered: false
538
             });
539
             });
550
     _getStyles(): Object {
551
     _getStyles(): Object {
551
         const { canPlayEventReceived } = this.state;
552
         const { canPlayEventReceived } = this.state;
552
         const {
553
         const {
553
-            _currentLayout,
554
             _disableTileEnlargement,
554
             _disableTileEnlargement,
555
             _height,
555
             _height,
556
             _isFakeScreenShareParticipant,
556
             _isFakeScreenShareParticipant,
557
             _isHidden,
557
             _isHidden,
558
             _isScreenSharing,
558
             _isScreenSharing,
559
             _participant,
559
             _participant,
560
+            _thumbnailType,
560
             _videoObjectPosition,
561
             _videoObjectPosition,
561
             _videoTrack,
562
             _videoTrack,
562
             _width,
563
             _width,
564
             style
565
             style
565
         } = this.props;
566
         } = this.props;
566
 
567
 
567
-        const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
568
+        const isTileType = _thumbnailType === THUMBNAIL_TYPE.TILE;
568
         const jitsiVideoTrack = _videoTrack?.jitsiTrack;
569
         const jitsiVideoTrack = _videoTrack?.jitsiTrack;
569
         const track = jitsiVideoTrack?.track;
570
         const track = jitsiVideoTrack?.track;
570
         const isPortraitVideo = ((track && track.getSettings()?.aspectRatio) || 1) < 1;
571
         const isPortraitVideo = ((track && track.getSettings()?.aspectRatio) || 1) < 1;
587
         }
588
         }
588
 
589
 
589
         let videoStyles = null;
590
         let videoStyles = null;
590
-        const doNotStretchVideo = (isPortraitVideo && tileViewActive)
591
+        const doNotStretchVideo = (isPortraitVideo && isTileType)
591
             || _disableTileEnlargement
592
             || _disableTileEnlargement
592
             || _isScreenSharing;
593
             || _isScreenSharing;
593
 
594
 
636
      * @returns {void}
637
      * @returns {void}
637
      */
638
      */
638
     _onClick() {
639
     _onClick() {
639
-        const { _participant, dispatch, _stageFilmstripDisabled } = this.props;
640
+        const { _participant, dispatch, _stageFilmstripLayout } = this.props;
640
         const { id, pinned } = _participant;
641
         const { id, pinned } = _participant;
641
 
642
 
642
-        if (_stageFilmstripDisabled) {
643
-            dispatch(pinParticipant(pinned ? null : id));
644
-        } else {
643
+        if (_stageFilmstripLayout) {
645
             dispatch(togglePinStageParticipant(id));
644
             dispatch(togglePinStageParticipant(id));
645
+        } else {
646
+            dispatch(pinParticipant(pinned ? null : id));
646
         }
647
         }
647
     }
648
     }
648
 
649
 
790
         const {
791
         const {
791
             _isDominantSpeakerDisabled,
792
             _isDominantSpeakerDisabled,
792
             _participant,
793
             _participant,
793
-            _currentLayout,
794
             _raisedHand,
794
             _raisedHand,
795
+            _thumbnailType,
795
             classes
796
             classes
796
         } = this.props;
797
         } = this.props;
797
 
798
 
804
         if (!_isDominantSpeakerDisabled && _participant?.dominantSpeaker) {
805
         if (!_isDominantSpeakerDisabled && _participant?.dominantSpeaker) {
805
             className += ` ${classes.activeSpeaker} dominant-speaker`;
806
             className += ` ${classes.activeSpeaker} dominant-speaker`;
806
         }
807
         }
807
-        if (_currentLayout !== LAYOUTS.TILE_VIEW && _participant?.pinned) {
808
+        if (_thumbnailType !== THUMBNAIL_TYPE.TILE && _participant?.pinned) {
808
             className += ' videoContainerFocused';
809
             className += ' videoContainerFocused';
809
         }
810
         }
810
 
811
 
902
     _renderParticipant(local = false) {
903
     _renderParticipant(local = false) {
903
         const {
904
         const {
904
             _audioTrack,
905
             _audioTrack,
905
-            _currentLayout,
906
             _disableLocalVideoFlip,
906
             _disableLocalVideoFlip,
907
+            _gifSrc,
907
             _isMobile,
908
             _isMobile,
908
             _isMobilePortrait,
909
             _isMobilePortrait,
909
             _isScreenSharing,
910
             _isScreenSharing,
910
             _isTestModeEnabled,
911
             _isTestModeEnabled,
911
             _localFlipX,
912
             _localFlipX,
912
             _participant,
913
             _participant,
914
+            _thumbnailType,
913
             _videoTrack,
915
             _videoTrack,
914
-            _gifSrc,
915
             classes,
916
             classes,
916
             stageFilmstrip
917
             stageFilmstrip
917
         } = this.props;
918
         } = this.props;
975
                 <div
976
                 <div
976
                     className = { clsx(classes.indicatorsContainer,
977
                     className = { clsx(classes.indicatorsContainer,
977
                         classes.indicatorsTopContainer,
978
                         classes.indicatorsTopContainer,
978
-                        _currentLayout === LAYOUTS.TILE_VIEW && 'tile-view-mode'
979
+                        _thumbnailType === THUMBNAIL_TYPE.TILE && 'tile-view-mode'
979
                     ) }>
980
                     ) }>
980
                     <ThumbnailTopIndicators
981
                     <ThumbnailTopIndicators
981
-                        currentLayout = { _currentLayout }
982
                         hidePopover = { this._hidePopover }
982
                         hidePopover = { this._hidePopover }
983
                         indicatorsClassName = { classes.indicatorsBackground }
983
                         indicatorsClassName = { classes.indicatorsBackground }
984
                         isHovered = { isHovered }
984
                         isHovered = { isHovered }
985
                         local = { local }
985
                         local = { local }
986
                         participantId = { id }
986
                         participantId = { id }
987
                         popoverVisible = { popoverVisible }
987
                         popoverVisible = { popoverVisible }
988
-                        showPopover = { this._showPopover } />
988
+                        showPopover = { this._showPopover }
989
+                        thumbnailType = { _thumbnailType } />
989
                 </div>
990
                 </div>
990
                 <div
991
                 <div
991
                     className = { clsx(classes.indicatorsContainer,
992
                     className = { clsx(classes.indicatorsContainer,
992
                         classes.indicatorsBottomContainer,
993
                         classes.indicatorsBottomContainer,
993
-                        _currentLayout === LAYOUTS.TILE_VIEW && 'tile-view-mode'
994
+                        _thumbnailType === THUMBNAIL_TYPE.TILE && 'tile-view-mode'
994
                     ) }>
995
                     ) }>
995
                     <ThumbnailBottomIndicators
996
                     <ThumbnailBottomIndicators
996
                         className = { classes.indicatorsBackground }
997
                         className = { classes.indicatorsBackground }
997
-                        currentLayout = { _currentLayout }
998
                         local = { local }
998
                         local = { local }
999
-                        participantId = { id } />
999
+                        participantId = { id }
1000
+                        thumbnailType = { _thumbnailType } />
1000
                 </div>
1001
                 </div>
1001
                 {!_gifSrc && this._renderAvatar(styles.avatar) }
1002
                 {!_gifSrc && this._renderAvatar(styles.avatar) }
1002
                 { !local && (
1003
                 { !local && (
1103
     }
1104
     }
1104
     const _audioTrack = isLocal
1105
     const _audioTrack = isLocal
1105
         ? getLocalAudioTrack(tracks) : getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantID);
1106
         ? getLocalAudioTrack(tracks) : getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantID);
1106
-    const _currentLayout = stageFilmstrip ? LAYOUTS.TILE_VIEW : getCurrentLayout(state);
1107
+    const _currentLayout = getCurrentLayout(state);
1107
     let size = {};
1108
     let size = {};
1108
     let _isMobilePortrait = false;
1109
     let _isMobilePortrait = false;
1109
     const {
1110
     const {
1116
     const { localFlipX } = state['features/base/settings'];
1117
     const { localFlipX } = state['features/base/settings'];
1117
     const _isMobile = isMobileBrowser();
1118
     const _isMobile = isMobileBrowser();
1118
     const activeParticipants = getActiveParticipantsIds(state);
1119
     const activeParticipants = getActiveParticipantsIds(state);
1120
+    const tileType = getThumbnailTypeFromLayout(_currentLayout, stageFilmstrip);
1121
+
1119
 
1122
 
1120
-    switch (_currentLayout) {
1121
-    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
1122
-    case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW: {
1123
+    switch (tileType) {
1124
+    case THUMBNAIL_TYPE.VERTICAL:
1125
+    case THUMBNAIL_TYPE.HORIZONTAL: {
1123
         const {
1126
         const {
1124
             horizontalViewDimensions = {
1127
             horizontalViewDimensions = {
1125
                 local: {},
1128
                 local: {},
1133
         } = state['features/filmstrip'];
1136
         } = state['features/filmstrip'];
1134
         const _verticalViewGrid = showGridInVerticalView(state);
1137
         const _verticalViewGrid = showGridInVerticalView(state);
1135
         const { local, remote }
1138
         const { local, remote }
1136
-            = _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
1139
+            = tileType === THUMBNAIL_TYPE.VERTICAL
1137
                 ? verticalViewDimensions : horizontalViewDimensions;
1140
                 ? verticalViewDimensions : horizontalViewDimensions;
1138
         const { width, height } = (isLocal ? local : remote) ?? {};
1141
         const { width, height } = (isLocal ? local : remote) ?? {};
1139
 
1142
 
1155
 
1158
 
1156
         break;
1159
         break;
1157
     }
1160
     }
1158
-    case LAYOUTS.TILE_VIEW: {
1161
+    case THUMBNAIL_TYPE.TILE: {
1159
         const { thumbnailSize } = state['features/filmstrip'].tileViewDimensions;
1162
         const { thumbnailSize } = state['features/filmstrip'].tileViewDimensions;
1160
         const {
1163
         const {
1161
             stageFilmstripDimensions = {
1164
             stageFilmstripDimensions = {
1186
 
1189
 
1187
     return {
1190
     return {
1188
         _audioTrack,
1191
         _audioTrack,
1189
-        _currentLayout,
1190
         _defaultLocalDisplayName: defaultLocalDisplayName,
1192
         _defaultLocalDisplayName: defaultLocalDisplayName,
1191
         _disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
1193
         _disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
1192
         _disableTileEnlargement: Boolean(disableTileEnlargement),
1194
         _disableTileEnlargement: Boolean(disableTileEnlargement),
1204
         _localFlipX: Boolean(localFlipX),
1206
         _localFlipX: Boolean(localFlipX),
1205
         _participant: participant,
1207
         _participant: participant,
1206
         _raisedHand: hasRaisedHand(participant),
1208
         _raisedHand: hasRaisedHand(participant),
1207
-        _stageFilmstripDisabled: !isStageFilmstripEnabled(state),
1208
-        _stageParticipantsVisible: shouldDisplayStageFilmstrip(state, 1),
1209
+        _stageFilmstripLayout: isStageFilmstripAvailable(state),
1210
+        _stageParticipantsVisible: _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW,
1211
+        _thumbnailType: tileType,
1209
         _videoObjectPosition: getVideoObjectPosition(state, participant?.id),
1212
         _videoObjectPosition: getVideoObjectPosition(state, participant?.id),
1210
         _videoTrack,
1213
         _videoTrack,
1211
         ...size,
1214
         ...size,

+ 13
- 12
react/features/filmstrip/components/web/ThumbnailBottomIndicators.js Vedi File

6
 
6
 
7
 import { isDisplayNameVisible, isNameReadOnly } from '../../../base/config/functions.any';
7
 import { isDisplayNameVisible, isNameReadOnly } from '../../../base/config/functions.any';
8
 import DisplayName from '../../../display-name/components/web/DisplayName';
8
 import DisplayName from '../../../display-name/components/web/DisplayName';
9
-import { LAYOUTS } from '../../../video-layout';
9
+import { THUMBNAIL_TYPE } from '../../constants';
10
 
10
 
11
 import StatusIndicators from './StatusIndicators';
11
 import StatusIndicators from './StatusIndicators';
12
 
12
 
14
 
14
 
15
 type Props = {
15
 type Props = {
16
 
16
 
17
-    /**
18
-     * The current layout of the filmstrip.
19
-     */
20
-    currentLayout: string,
21
-
22
     /**
17
     /**
23
      * Class name for indicators container.
18
      * Class name for indicators container.
24
      */
19
      */
37
     /**
32
     /**
38
      * Whether or not to show the status indicators.
33
      * Whether or not to show the status indicators.
39
      */
34
      */
40
-    showStatusIndicators: string
35
+    showStatusIndicators: string,
36
+
37
+    /**
38
+     * The type of thumbnail.
39
+     */
40
+    thumbnailType: string
41
 }
41
 }
42
 
42
 
43
 const useStyles = makeStyles(() => {
43
 const useStyles = makeStyles(() => {
61
 
61
 
62
 const ThumbnailBottomIndicators = ({
62
 const ThumbnailBottomIndicators = ({
63
     className,
63
     className,
64
-    currentLayout,
65
     local,
64
     local,
66
     participantId,
65
     participantId,
67
-    showStatusIndicators = true
66
+    showStatusIndicators = true,
67
+    thumbnailType
68
 }: Props) => {
68
 }: Props) => {
69
     const styles = useStyles();
69
     const styles = useStyles();
70
     const _allowEditing = !useSelector(isNameReadOnly);
70
     const _allowEditing = !useSelector(isNameReadOnly);
77
                 audio = { true }
77
                 audio = { true }
78
                 moderator = { true }
78
                 moderator = { true }
79
                 participantID = { participantId }
79
                 participantID = { participantId }
80
-                screenshare = { currentLayout === LAYOUTS.TILE_VIEW } />
80
+                screenshare = { thumbnailType === THUMBNAIL_TYPE.TILE }
81
+                thumbnailType = { thumbnailType } />
81
         }
82
         }
82
         {
83
         {
83
             _showDisplayName && (
84
             _showDisplayName && (
84
                 <span className = { styles.nameContainer }>
85
                 <span className = { styles.nameContainer }>
85
                     <DisplayName
86
                     <DisplayName
86
                         allowEditing = { local ? _allowEditing : false }
87
                         allowEditing = { local ? _allowEditing : false }
87
-                        currentLayout = { currentLayout }
88
                         displayNameSuffix = { local ? _defaultLocalDisplayName : '' }
88
                         displayNameSuffix = { local ? _defaultLocalDisplayName : '' }
89
                         elementID = { local ? 'localDisplayName' : `participant_${participantId}_name` }
89
                         elementID = { local ? 'localDisplayName' : `participant_${participantId}_name` }
90
-                        participantID = { participantId } />
90
+                        participantID = { participantId }
91
+                        thumbnailType = { thumbnailType } />
91
                 </span>
92
                 </span>
92
             )
93
             )
93
         }
94
         }

+ 17
- 16
react/features/filmstrip/components/web/ThumbnailTopIndicators.js Vedi File

8
 import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
8
 import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
9
 import { isMobileBrowser } from '../../../base/environment/utils';
9
 import { isMobileBrowser } from '../../../base/environment/utils';
10
 import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
10
 import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
11
-import { LAYOUTS } from '../../../video-layout';
12
-import { STATS_POPOVER_POSITION } from '../../constants';
11
+import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
13
 import { getIndicatorsTooltipPosition } from '../../functions.web';
12
 import { getIndicatorsTooltipPosition } from '../../functions.web';
14
 
13
 
15
 import PinnedIndicator from './PinnedIndicator';
14
 import PinnedIndicator from './PinnedIndicator';
21
 
20
 
22
 type Props = {
21
 type Props = {
23
 
22
 
24
-    /**
25
-     * The current layout of the filmstrip.
26
-     */
27
-    currentLayout: string,
28
-
29
     /**
23
     /**
30
      * Hide popover callback.
24
      * Hide popover callback.
31
      */
25
      */
64
     /**
58
     /**
65
      * Show popover callback.
59
      * Show popover callback.
66
      */
60
      */
67
-    showPopover: Function
61
+    showPopover: Function,
62
+
63
+    /**
64
+     * The type of thumbnail.
65
+     */
66
+    thumbnailType: string
68
 }
67
 }
69
 
68
 
70
 const useStyles = makeStyles(() => {
69
 const useStyles = makeStyles(() => {
80
 });
79
 });
81
 
80
 
82
 const ThumbnailTopIndicators = ({
81
 const ThumbnailTopIndicators = ({
83
-    currentLayout,
84
     hidePopover,
82
     hidePopover,
85
     indicatorsClassName,
83
     indicatorsClassName,
86
     isFakeScreenShareParticipant,
84
     isFakeScreenShareParticipant,
88
     local,
86
     local,
89
     participantId,
87
     participantId,
90
     popoverVisible,
88
     popoverVisible,
91
-    showPopover
89
+    showPopover,
90
+    thumbnailType
92
 }: Props) => {
91
 }: Props) => {
93
     const styles = useStyles();
92
     const styles = useStyles();
94
 
93
 
111
                         enableStatsDisplay = { true }
110
                         enableStatsDisplay = { true }
112
                         iconSize = { _indicatorIconSize }
111
                         iconSize = { _indicatorIconSize }
113
                         participantId = { participantId }
112
                         participantId = { participantId }
114
-                        statsPopoverPosition = { STATS_POPOVER_POSITION[currentLayout] } />
113
+                        statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
115
                 }
114
                 }
116
             </div>
115
             </div>
117
         );
116
         );
118
     }
117
     }
119
 
118
 
119
+    const tooltipPosition = getIndicatorsTooltipPosition(thumbnailType);
120
+
120
     return (
121
     return (
121
         <>
122
         <>
122
             <div className = { styles.container }>
123
             <div className = { styles.container }>
123
                 <PinnedIndicator
124
                 <PinnedIndicator
124
                     iconSize = { _indicatorIconSize }
125
                     iconSize = { _indicatorIconSize }
125
                     participantId = { participantId }
126
                     participantId = { participantId }
126
-                    tooltipPosition = { getIndicatorsTooltipPosition(currentLayout) } />
127
+                    tooltipPosition = { tooltipPosition } />
127
                 {!_connectionIndicatorDisabled
128
                 {!_connectionIndicatorDisabled
128
                     && <ConnectionIndicator
129
                     && <ConnectionIndicator
129
                         alwaysVisible = { showConnectionIndicator }
130
                         alwaysVisible = { showConnectionIndicator }
130
                         enableStatsDisplay = { true }
131
                         enableStatsDisplay = { true }
131
                         iconSize = { _indicatorIconSize }
132
                         iconSize = { _indicatorIconSize }
132
                         participantId = { participantId }
133
                         participantId = { participantId }
133
-                        statsPopoverPosition = { STATS_POPOVER_POSITION[currentLayout] } />
134
+                        statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
134
                 }
135
                 }
135
                 <RaisedHandIndicator
136
                 <RaisedHandIndicator
136
                     iconSize = { _indicatorIconSize }
137
                     iconSize = { _indicatorIconSize }
137
                     participantId = { participantId }
138
                     participantId = { participantId }
138
-                    tooltipPosition = { getIndicatorsTooltipPosition(currentLayout) } />
139
-                {currentLayout !== LAYOUTS.TILE_VIEW && (
139
+                    tooltipPosition = { tooltipPosition } />
140
+                {thumbnailType !== THUMBNAIL_TYPE.TILE && (
140
                     <div className = { clsx(indicatorsClassName, 'top-indicators') }>
141
                     <div className = { clsx(indicatorsClassName, 'top-indicators') }>
141
                         <StatusIndicators
142
                         <StatusIndicators
142
                             participantID = { participantId }
143
                             participantID = { participantId }
146
             </div>
147
             </div>
147
             <div className = { styles.container }>
148
             <div className = { styles.container }>
148
                 <VideoMenuTriggerButton
149
                 <VideoMenuTriggerButton
149
-                    currentLayout = { currentLayout }
150
                     hidePopover = { hidePopover }
150
                     hidePopover = { hidePopover }
151
                     local = { local }
151
                     local = { local }
152
                     participantId = { participantId }
152
                     participantId = { participantId }
153
                     popoverVisible = { popoverVisible }
153
                     popoverVisible = { popoverVisible }
154
                     showPopover = { showPopover }
154
                     showPopover = { showPopover }
155
+                    thumbnailType = { thumbnailType }
155
                     visible = { isHovered } />
156
                     visible = { isHovered } />
156
             </div>
157
             </div>
157
         </>);
158
         </>);

+ 10
- 10
react/features/filmstrip/components/web/VideoMenuTriggerButton.js Vedi File

6
 
6
 
7
 type Props = {
7
 type Props = {
8
 
8
 
9
-    /**
10
-     * The current layout of the filmstrip.
11
-     */
12
-    currentLayout: string,
13
-
14
     /**
9
     /**
15
      * Hide popover callback.
10
      * Hide popover callback.
16
      */
11
      */
36
      */
31
      */
37
     showPopover: Function,
32
     showPopover: Function,
38
 
33
 
34
+    /**
35
+     * The type of thumbnail.
36
+     */
37
+    thumbnailType: string,
38
+
39
     /**
39
     /**
40
      * Whether or not the component is visible.
40
      * Whether or not the component is visible.
41
      */
41
      */
44
 
44
 
45
 // eslint-disable-next-line no-confusing-arrow
45
 // eslint-disable-next-line no-confusing-arrow
46
 const VideoMenuTriggerButton = ({
46
 const VideoMenuTriggerButton = ({
47
-    currentLayout,
48
     hidePopover,
47
     hidePopover,
49
     local,
48
     local,
50
     participantId,
49
     participantId,
51
     popoverVisible,
50
     popoverVisible,
52
     showPopover,
51
     showPopover,
52
+    thumbnailType,
53
     visible
53
     visible
54
 }: Props) => local
54
 }: Props) => local
55
     ? (
55
     ? (
56
         <span id = 'localvideomenu'>
56
         <span id = 'localvideomenu'>
57
             <LocalVideoMenuTriggerButton
57
             <LocalVideoMenuTriggerButton
58
                 buttonVisible = { visible }
58
                 buttonVisible = { visible }
59
-                currentLayout = { currentLayout }
60
                 hidePopover = { hidePopover }
59
                 hidePopover = { hidePopover }
61
                 popoverVisible = { popoverVisible }
60
                 popoverVisible = { popoverVisible }
62
-                showPopover = { showPopover } />
61
+                showPopover = { showPopover }
62
+                thumbnailType = { thumbnailType } />
63
         </span>
63
         </span>
64
     )
64
     )
65
     : (
65
     : (
66
         <span id = 'remotevideomenu'>
66
         <span id = 'remotevideomenu'>
67
             <RemoteVideoMenuTriggerButton
67
             <RemoteVideoMenuTriggerButton
68
                 buttonVisible = { visible }
68
                 buttonVisible = { visible }
69
-                currentLayout = { currentLayout }
70
                 hidePopover = { hidePopover }
69
                 hidePopover = { hidePopover }
71
                 participantID = { participantId }
70
                 participantID = { participantId }
72
                 popoverVisible = { popoverVisible }
71
                 popoverVisible = { popoverVisible }
73
-                showPopover = { showPopover } />
72
+                showPopover = { showPopover }
73
+                thumbnailType = { thumbnailType } />
74
         </span>
74
         </span>
75
     );
75
     );
76
 
76
 

+ 15
- 7
react/features/filmstrip/constants.js Vedi File

1
 // @flow
1
 // @flow
2
 
2
 
3
 import { BoxModel } from '../base/styles';
3
 import { BoxModel } from '../base/styles';
4
-import { LAYOUTS } from '../video-layout/constants';
5
 
4
 
6
 /**
5
 /**
7
  * The size (height and width) of the small (not tile view) thumbnails.
6
  * The size (height and width) of the small (not tile view) thumbnails.
228
  */
227
  */
229
 export const TILE_MARGIN = 10;
228
 export const TILE_MARGIN = 10;
230
 
229
 
230
+/**
231
+ * The types of thumbnails for filmstrip.
232
+ */
233
+export const THUMBNAIL_TYPE = {
234
+    TILE: 'TILE',
235
+    VERTICAL: 'VERTICAL',
236
+    HORIZONTAL: 'HORIZONTAL'
237
+};
238
+
231
 /**
239
 /**
232
  * The popover position for the connection stats table.
240
  * The popover position for the connection stats table.
233
  */
241
  */
234
 export const STATS_POPOVER_POSITION = {
242
 export const STATS_POPOVER_POSITION = {
235
-    [LAYOUTS.TILE_VIEW]: 'right-start',
236
-    [LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'left-start',
237
-    [LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'top-end'
243
+    [THUMBNAIL_TYPE.TILE]: 'right-start',
244
+    [THUMBNAIL_TYPE.VERTICAL]: 'left-start',
245
+    [THUMBNAIL_TYPE.HORIZONTAL]: 'top-end'
238
 };
246
 };
239
 
247
 
240
 /**
248
 /**
241
  * The tooltip position for the indicators on the thumbnail.
249
  * The tooltip position for the indicators on the thumbnail.
242
  */
250
  */
243
 export const INDICATORS_TOOLTIP_POSITION = {
251
 export const INDICATORS_TOOLTIP_POSITION = {
244
-    [LAYOUTS.TILE_VIEW]: 'right',
245
-    [LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'left',
246
-    [LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'top'
252
+    [THUMBNAIL_TYPE.TILE]: 'right',
253
+    [THUMBNAIL_TYPE.VERTICAL]: 'left',
254
+    [THUMBNAIL_TYPE.HORIZONTAL]: 'top'
247
 };
255
 };
248
 
256
 
249
 /**
257
 /**

+ 2
- 2
react/features/filmstrip/functions.native.js Vedi File

103
 }
103
 }
104
 
104
 
105
 /**
105
 /**
106
- * Whether the stage filmstrip is disabled or not.
106
+ * Whether the stage filmstrip is available or not.
107
  *
107
  *
108
  * @param {Object} state - Redux state.
108
  * @param {Object} state - Redux state.
109
  * @returns {boolean}
109
  * @returns {boolean}
110
  */
110
  */
111
-export function isStageFilmstripEnabled() {
111
+export function isStageFilmstripAvailable() {
112
     return false;
112
     return false;
113
 }
113
 }

+ 52
- 16
react/features/filmstrip/functions.web.js Vedi File

35
     INDICATORS_TOOLTIP_POSITION,
35
     INDICATORS_TOOLTIP_POSITION,
36
     SCROLL_SIZE,
36
     SCROLL_SIZE,
37
     SQUARE_TILE_ASPECT_RATIO,
37
     SQUARE_TILE_ASPECT_RATIO,
38
+    THUMBNAIL_TYPE,
38
     TILE_ASPECT_RATIO,
39
     TILE_ASPECT_RATIO,
39
     TILE_HORIZONTAL_MARGIN,
40
     TILE_HORIZONTAL_MARGIN,
40
     TILE_MIN_HEIGHT_LARGE,
41
     TILE_MIN_HEIGHT_LARGE,
243
  * disabled.
244
  * disabled.
244
  *
245
  *
245
  * @param {Object} state - The redux store state.
246
  * @param {Object} state - The redux store state.
246
- * @param {boolean} stageFilmstrip - Whether the dimensions should be calculated for the stage filmstrip.
247
  * @returns {Object} - The dimensions.
247
  * @returns {Object} - The dimensions.
248
  */
248
  */
249
-export function calculateNonResponsiveTileViewDimensions(state, stageFilmstrip = false) {
249
+export function calculateNonResponsiveTileViewDimensions(state) {
250
     const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
250
     const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
251
     const { disableTileEnlargement } = state['features/base/config'];
251
     const { disableTileEnlargement } = state['features/base/config'];
252
-    const { columns: c, minVisibleRows, rows: r } = getNotResponsiveTileViewGridDimensions(state, stageFilmstrip);
253
-    const filmstripWidth = getVerticalViewMaxWidth(state);
252
+    const { columns: c, minVisibleRows, rows: r } = getNotResponsiveTileViewGridDimensions(state);
254
     const size = calculateThumbnailSizeForTileView({
253
     const size = calculateThumbnailSizeForTileView({
255
         columns: c,
254
         columns: c,
256
         minVisibleRows,
255
         minVisibleRows,
257
-        clientWidth: clientWidth - (stageFilmstrip ? filmstripWidth : 0),
256
+        clientWidth,
258
         clientHeight,
257
         clientHeight,
259
         disableTileEnlargement,
258
         disableTileEnlargement,
260
         disableResponsiveTiles: true
259
         disableResponsiveTiles: true
515
         canPlayEventReceived,
514
         canPlayEventReceived,
516
         isRemoteParticipant,
515
         isRemoteParticipant,
517
         stageParticipantsVisible,
516
         stageParticipantsVisible,
517
+        stageFilmstrip,
518
         tileViewActive
518
         tileViewActive
519
     } = input;
519
     } = input;
520
     const adjustedIsVideoPlayable = input.isVideoPlayable && (!isRemoteParticipant || canPlayEventReceived);
520
     const adjustedIsVideoPlayable = input.isVideoPlayable && (!isRemoteParticipant || canPlayEventReceived);
524
     }
524
     }
525
 
525
 
526
     if (!tileViewActive && ((isScreenSharing && isRemoteParticipant)
526
     if (!tileViewActive && ((isScreenSharing && isRemoteParticipant)
527
-        || (stageParticipantsVisible && isActiveParticipant))) {
527
+        || (stageParticipantsVisible && isActiveParticipant && !stageFilmstrip))) {
528
         return DISPLAY_AVATAR;
528
         return DISPLAY_AVATAR;
529
     } else if (isCurrentlyOnLargeVideo && !tileViewActive) {
529
     } else if (isCurrentlyOnLargeVideo && !tileViewActive) {
530
         // Display name is always and only displayed when user is on the stage
530
         // Display name is always and only displayed when user is on the stage
556
         _isVideoPlayable,
556
         _isVideoPlayable,
557
         _participant,
557
         _participant,
558
         _stageParticipantsVisible,
558
         _stageParticipantsVisible,
559
-        _videoTrack
559
+        _videoTrack,
560
+        stageFilmstrip
560
     } = props;
561
     } = props;
561
     const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
562
     const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
562
     const { canPlayEventReceived } = state;
563
     const { canPlayEventReceived } = state;
574
         isScreenSharing: _isScreenSharing,
575
         isScreenSharing: _isScreenSharing,
575
         isFakeScreenShareParticipant: _isFakeScreenShareParticipant,
576
         isFakeScreenShareParticipant: _isFakeScreenShareParticipant,
576
         stageParticipantsVisible: _stageParticipantsVisible,
577
         stageParticipantsVisible: _stageParticipantsVisible,
578
+        stageFilmstrip,
577
         videoStreamMuted: _videoTrack ? _videoTrack.muted : 'no stream'
579
         videoStreamMuted: _videoTrack ? _videoTrack.muted : 'no stream'
578
     };
580
     };
579
 }
581
 }
581
 /**
583
 /**
582
  * Gets the tooltip position for the thumbnail indicators.
584
  * Gets the tooltip position for the thumbnail indicators.
583
  *
585
  *
584
- * @param {string} currentLayout - The current layout of the app.
586
+ * @param {string} thumbnailType - The current thumbnail type.
585
  * @returns {string}
587
  * @returns {string}
586
  */
588
  */
587
-export function getIndicatorsTooltipPosition(currentLayout: string) {
588
-    return INDICATORS_TOOLTIP_POSITION[currentLayout] || 'top';
589
+export function getIndicatorsTooltipPosition(thumbnailType: string) {
590
+    return INDICATORS_TOOLTIP_POSITION[thumbnailType] || 'top';
589
 }
591
 }
590
 
592
 
591
 /**
593
 /**
599
     const _currentLayout = getCurrentLayout(state);
601
     const _currentLayout = getCurrentLayout(state);
600
 
602
 
601
     return !filmstrip?.disableResizable && !isMobileBrowser()
603
     return !filmstrip?.disableResizable && !isMobileBrowser()
602
-        && _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
604
+        && (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW || _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW);
603
 }
605
 }
604
 
606
 
605
 /**
607
 /**
665
     case LAYOUTS.TILE_VIEW:
667
     case LAYOUTS.TILE_VIEW:
666
         ({ hasScroll = false } = state['features/filmstrip'].tileViewDimensions);
668
         ({ hasScroll = false } = state['features/filmstrip'].tileViewDimensions);
667
         break;
669
         break;
668
-    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
670
+    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
671
+    case LAYOUTS.STAGE_FILMSTRIP_VIEW: {
669
         ({ hasScroll = false } = state['features/filmstrip'].verticalViewDimensions);
672
         ({ hasScroll = false } = state['features/filmstrip'].verticalViewDimensions);
670
         break;
673
         break;
671
     }
674
     }
703
 }
706
 }
704
 
707
 
705
 /**
708
 /**
706
- * Get whether or not the stage filmstrip should be displayed.
709
+ * Get whether or not the stage filmstrip is available (enabled & can be used).
707
  *
710
  *
708
  * @param {Object} state - Redux state.
711
  * @param {Object} state - Redux state.
709
  * @param {number} minParticipantCount - The min number of participants for the stage filmstrip
712
  * @param {number} minParticipantCount - The min number of participants for the stage filmstrip
710
  * to be displayed.
713
  * to be displayed.
711
  * @returns {boolean}
714
  * @returns {boolean}
712
  */
715
  */
713
-export function shouldDisplayStageFilmstrip(state, minParticipantCount = 2) {
716
+export function isStageFilmstripAvailable(state, minParticipantCount = 0) {
714
     const { activeParticipants } = state['features/filmstrip'];
717
     const { activeParticipants } = state['features/filmstrip'];
715
     const { remoteScreenShares } = state['features/video-layout'];
718
     const { remoteScreenShares } = state['features/video-layout'];
716
-    const currentLayout = getCurrentLayout(state);
717
     const sharedVideo = isSharingStatus(state['features/shared-video']?.status);
719
     const sharedVideo = isSharingStatus(state['features/shared-video']?.status);
718
 
720
 
719
     return isStageFilmstripEnabled(state) && remoteScreenShares.length === 0 && !sharedVideo
721
     return isStageFilmstripEnabled(state) && remoteScreenShares.length === 0 && !sharedVideo
720
-        && activeParticipants.length >= minParticipantCount && currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
722
+        && activeParticipants.length >= minParticipantCount;
723
+}
724
+
725
+/**
726
+ * Get whether or not the stage filmstrip should be displayed.
727
+ *
728
+ * @param {Object} state - Redux state.
729
+ * @returns {boolean}
730
+ */
731
+export function shouldDisplayStageFilmstrip(state) {
732
+    return isStageFilmstripAvailable(state, 2);
721
 }
733
 }
722
 
734
 
723
 /**
735
 /**
731
 
743
 
732
     return !(filmstrip?.disableStageFilmstrip ?? true) && interfaceConfig.VERTICAL_FILMSTRIP;
744
     return !(filmstrip?.disableStageFilmstrip ?? true) && interfaceConfig.VERTICAL_FILMSTRIP;
733
 }
745
 }
746
+
747
+/**
748
+ * Gets the thumbnail type by filmstrip type.
749
+ *
750
+ * @param {string} currentLayout - Current app layout.
751
+ * @param {boolean} isStageFilmstrip - Whether the filmstrip is stage filmstrip or not.
752
+ * @returns {string}
753
+ */
754
+export function getThumbnailTypeFromLayout(currentLayout, isStageFilmstrip = false) {
755
+    switch (currentLayout) {
756
+    case LAYOUTS.TILE_VIEW:
757
+        return THUMBNAIL_TYPE.TILE;
758
+    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
759
+        return THUMBNAIL_TYPE.VERTICAL;
760
+    case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
761
+        return THUMBNAIL_TYPE.HORIZONTAL;
762
+    case LAYOUTS.STAGE_FILMSTRIP_VIEW:
763
+        if (isStageFilmstrip) {
764
+            return THUMBNAIL_TYPE.TILE;
765
+        }
766
+
767
+        return THUMBNAIL_TYPE.VERTICAL;
768
+    }
769
+}

+ 19
- 6
react/features/filmstrip/middleware.web.js Vedi File

22
 
22
 
23
 import {
23
 import {
24
     ADD_STAGE_PARTICIPANT,
24
     ADD_STAGE_PARTICIPANT,
25
+    CLEAR_STAGE_PARTICIPANTS,
25
     REMOVE_STAGE_PARTICIPANT,
26
     REMOVE_STAGE_PARTICIPANT,
26
     SET_MAX_STAGE_PARTICIPANTS,
27
     SET_MAX_STAGE_PARTICIPANTS,
27
     SET_USER_FILMSTRIP_WIDTH,
28
     SET_USER_FILMSTRIP_WIDTH,
42
 import {
43
 import {
43
     isFilmstripResizable,
44
     isFilmstripResizable,
44
     updateRemoteParticipants,
45
     updateRemoteParticipants,
45
-    updateRemoteParticipantsOnLeave
46
+    updateRemoteParticipantsOnLeave,
47
+    getActiveParticipantsIds,
48
+    getPinnedActiveParticipants,
49
+    isStageFilmstripAvailable
46
 } from './functions';
50
 } from './functions';
47
 import './subscriber';
51
 import './subscriber';
48
-import { getActiveParticipantsIds, getPinnedActiveParticipants, isStageFilmstripEnabled } from './functions.web';
49
 
52
 
50
 /**
53
 /**
51
  * Map of timers.
54
  * Map of timers.
202
     case DOMINANT_SPEAKER_CHANGED: {
205
     case DOMINANT_SPEAKER_CHANGED: {
203
         const { id } = action.participant;
206
         const { id } = action.participant;
204
         const state = store.getState();
207
         const state = store.getState();
205
-        const stageFilmstrip = isStageFilmstripEnabled(state);
206
-        const currentLayout = getCurrentLayout(state);
208
+        const stageFilmstrip = isStageFilmstripAvailable(state);
207
         const local = getLocalParticipant(state);
209
         const local = getLocalParticipant(state);
210
+        const currentLayout = getCurrentLayout(state);
208
 
211
 
209
-        if (id === local.id) {
212
+        if (id === local.id || currentLayout === LAYOUTS.TILE_VIEW) {
210
             break;
213
             break;
211
         }
214
         }
212
 
215
 
213
-        if (stageFilmstrip && currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
216
+        if (stageFilmstrip) {
214
             const isPinned = getPinnedActiveParticipants(state).some(p => p.participantId === id);
217
             const isPinned = getPinnedActiveParticipants(state).some(p => p.participantId === id);
215
 
218
 
216
             store.dispatch(addStageParticipant(id, Boolean(isPinned)));
219
             store.dispatch(addStageParticipant(id, Boolean(isPinned)));
276
         } else {
279
         } else {
277
             dispatch(addStageParticipant(participantId, true));
280
             dispatch(addStageParticipant(participantId, true));
278
         }
281
         }
282
+        break;
283
+    }
284
+    case CLEAR_STAGE_PARTICIPANTS: {
285
+        const activeParticipants = getActiveParticipantsIds(store.getState());
286
+
287
+        activeParticipants.forEach(pId => {
288
+            const tid = timers.get(pId);
279
 
289
 
290
+            clearTimeout(tid);
291
+            timers.delete(pId);
292
+        });
280
     }
293
     }
281
     }
294
     }
282
 
295
 

+ 8
- 1
react/features/filmstrip/reducer.js Vedi File

18
     SET_VERTICAL_VIEW_DIMENSIONS,
18
     SET_VERTICAL_VIEW_DIMENSIONS,
19
     SET_VISIBLE_REMOTE_PARTICIPANTS,
19
     SET_VISIBLE_REMOTE_PARTICIPANTS,
20
     SET_VOLUME,
20
     SET_VOLUME,
21
-    SET_MAX_STAGE_PARTICIPANTS
21
+    SET_MAX_STAGE_PARTICIPANTS,
22
+    CLEAR_STAGE_PARTICIPANTS
22
 } from './actionTypes';
23
 } from './actionTypes';
23
 
24
 
24
 const DEFAULT_STATE = {
25
 const DEFAULT_STATE = {
273
                 maxStageParticipants: action.maxParticipants
274
                 maxStageParticipants: action.maxParticipants
274
             };
275
             };
275
         }
276
         }
277
+        case CLEAR_STAGE_PARTICIPANTS: {
278
+            return {
279
+                ...state,
280
+                activeParticipants: []
281
+            };
282
+        }
276
         }
283
         }
277
 
284
 
278
         return state;
285
         return state;

+ 9
- 3
react/features/filmstrip/subscriber.web.js Vedi File

1
 // @flow
1
 // @flow
2
 
2
 
3
 import { isMobileBrowser } from '../base/environment/utils';
3
 import { isMobileBrowser } from '../base/environment/utils';
4
-import { getParticipantCountWithFake } from '../base/participants';
4
+import { getParticipantCountWithFake, pinParticipant } from '../base/participants';
5
 import { StateListenerRegistry } from '../base/redux';
5
 import { StateListenerRegistry } from '../base/redux';
6
 import { clientResized } from '../base/responsive-ui';
6
 import { clientResized } from '../base/responsive-ui';
7
 import { shouldHideSelfView } from '../base/settings';
7
 import { shouldHideSelfView } from '../base/settings';
17
     setTileViewDimensions,
17
     setTileViewDimensions,
18
     setVerticalViewDimensions
18
     setVerticalViewDimensions
19
 } from './actions';
19
 } from './actions';
20
+import { clearStageParticipants } from './actions.web';
20
 import {
21
 import {
21
     ASPECT_RATIO_BREAKPOINT,
22
     ASPECT_RATIO_BREAKPOINT,
22
     DISPLAY_DRAWER_THRESHOLD
23
     DISPLAY_DRAWER_THRESHOLD
24
 import {
25
 import {
25
     isFilmstripResizable,
26
     isFilmstripResizable,
26
     isFilmstripScrollVisible,
27
     isFilmstripScrollVisible,
27
-    shouldDisplayStageFilmstrip,
28
     updateRemoteParticipants
28
     updateRemoteParticipants
29
 } from './functions';
29
 } from './functions';
30
 
30
 
74
             break;
74
             break;
75
         case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
75
         case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
76
             store.dispatch(setVerticalViewDimensions());
76
             store.dispatch(setVerticalViewDimensions());
77
+            if (store.getState()['features/filmstrip'].activeParticipants.length > 1) {
78
+                store.dispatch(clearStageParticipants());
79
+            }
80
+            break;
81
+        case LAYOUTS.STAGE_FILMSTRIP_VIEW:
82
+            store.dispatch(pinParticipant(null));
77
             break;
83
             break;
78
         }
84
         }
79
     }, {
85
     }, {
177
         };
183
         };
178
     },
184
     },
179
     /* listener */(_, store) => {
185
     /* listener */(_, store) => {
180
-        if (shouldDisplayStageFilmstrip(store.getState())) {
186
+        if (getCurrentLayout(store.getState()) === LAYOUTS.STAGE_FILMSTRIP_VIEW) {
181
             store.dispatch(setStageFilmstripViewDimensions());
187
             store.dispatch(setStageFilmstripViewDimensions());
182
         }
188
         }
183
     }, {
189
     }, {

+ 7
- 2
react/features/large-video/actions.any.js Vedi File

9
     getPinnedParticipant,
9
     getPinnedParticipant,
10
     getRemoteParticipants
10
     getRemoteParticipants
11
 } from '../base/participants';
11
 } from '../base/participants';
12
-import { isStageFilmstripEnabled } from '../filmstrip/functions';
12
+import { isStageFilmstripAvailable } from '../filmstrip/functions';
13
+import { shouldDisplayStageFilmstrip } from '../filmstrip/functions.web';
13
 
14
 
14
 import {
15
 import {
15
     SELECT_LARGE_VIDEO_PARTICIPANT,
16
     SELECT_LARGE_VIDEO_PARTICIPANT,
30
     return (dispatch: Dispatch<any>, getState: Function) => {
31
     return (dispatch: Dispatch<any>, getState: Function) => {
31
         const state = getState();
32
         const state = getState();
32
 
33
 
34
+        if (shouldDisplayStageFilmstrip(state)) {
35
+            return;
36
+        }
37
+
33
         // Keep Etherpad open.
38
         // Keep Etherpad open.
34
         if (state['features/etherpad'].editing) {
39
         if (state['features/etherpad'].editing) {
35
             return;
40
             return;
103
  * @returns {(string|undefined)}
108
  * @returns {(string|undefined)}
104
  */
109
  */
105
 function _electParticipantInLargeVideo(state) {
110
 function _electParticipantInLargeVideo(state) {
106
-    const stageFilmstrip = isStageFilmstripEnabled(state);
111
+    const stageFilmstrip = isStageFilmstripAvailable(state);
107
     let participant;
112
     let participant;
108
 
113
 
109
     if (!stageFilmstrip) {
114
     if (!stageFilmstrip) {

+ 2
- 1
react/features/video-layout/constants.js Vedi File

6
 export const LAYOUTS = {
6
 export const LAYOUTS = {
7
     HORIZONTAL_FILMSTRIP_VIEW: 'horizontal-filmstrip-view',
7
     HORIZONTAL_FILMSTRIP_VIEW: 'horizontal-filmstrip-view',
8
     TILE_VIEW: 'tile-view',
8
     TILE_VIEW: 'tile-view',
9
-    VERTICAL_FILMSTRIP_VIEW: 'vertical-filmstrip-view'
9
+    VERTICAL_FILMSTRIP_VIEW: 'vertical-filmstrip-view',
10
+    STAGE_FILMSTRIP_VIEW: 'stage-filmstrip-view'
10
 };
11
 };

+ 5
- 0
react/features/video-layout/functions.any.js Vedi File

7
     getParticipantCount,
7
     getParticipantCount,
8
     pinParticipant
8
     pinParticipant
9
 } from '../base/participants';
9
 } from '../base/participants';
10
+import { shouldDisplayStageFilmstrip } from '../filmstrip/functions.web';
10
 import { isVideoPlaying } from '../shared-video/functions';
11
 import { isVideoPlaying } from '../shared-video/functions';
11
 import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';
12
 import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';
12
 
13
 
40
     if (shouldDisplayTileView(state)) {
41
     if (shouldDisplayTileView(state)) {
41
         return LAYOUTS.TILE_VIEW;
42
         return LAYOUTS.TILE_VIEW;
42
     } else if (interfaceConfig.VERTICAL_FILMSTRIP) {
43
     } else if (interfaceConfig.VERTICAL_FILMSTRIP) {
44
+        if (shouldDisplayStageFilmstrip(state)) {
45
+            return LAYOUTS.STAGE_FILMSTRIP_VIEW;
46
+        }
47
+
43
         return LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
48
         return LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
44
     }
49
     }
45
 
50
 

+ 6
- 6
react/features/video-menu/components/web/LocalVideoMenuTriggerButton.js Vedi File

18
 import { getHideSelfView } from '../../../base/settings';
18
 import { getHideSelfView } from '../../../base/settings';
19
 import { getLocalVideoTrack } from '../../../base/tracks';
19
 import { getLocalVideoTrack } from '../../../base/tracks';
20
 import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
20
 import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
21
+import { THUMBNAIL_TYPE } from '../../../filmstrip';
21
 import { isStageFilmstripEnabled } from '../../../filmstrip/functions.web';
22
 import { isStageFilmstripEnabled } from '../../../filmstrip/functions.web';
22
-import { LAYOUTS } from '../../../video-layout';
23
 import { renderConnectionStatus } from '../../actions.web';
23
 import { renderConnectionStatus } from '../../actions.web';
24
 
24
 
25
 import ConnectionStatusButton from './ConnectionStatusButton';
25
 import ConnectionStatusButton from './ConnectionStatusButton';
274
  * @returns {Props}
274
  * @returns {Props}
275
  */
275
  */
276
 function _mapStateToProps(state, ownProps) {
276
 function _mapStateToProps(state, ownProps) {
277
-    const { currentLayout } = ownProps;
277
+    const { thumbnailType } = ownProps;
278
     const localParticipant = getLocalParticipant(state);
278
     const localParticipant = getLocalParticipant(state);
279
     const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
279
     const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
280
     const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
280
     const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
284
 
284
 
285
     let _menuPosition;
285
     let _menuPosition;
286
 
286
 
287
-    switch (currentLayout) {
288
-    case LAYOUTS.TILE_VIEW:
287
+    switch (thumbnailType) {
288
+    case THUMBNAIL_TYPE.TILE:
289
         _menuPosition = 'left-start';
289
         _menuPosition = 'left-start';
290
         break;
290
         break;
291
-    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
291
+    case THUMBNAIL_TYPE.VERTICAL:
292
         _menuPosition = 'left-start';
292
         _menuPosition = 'left-start';
293
         break;
293
         break;
294
-    case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
294
+    case THUMBNAIL_TYPE.HORIZONTAL:
295
         _menuPosition = 'top-start';
295
         _menuPosition = 'top-start';
296
         break;
296
         break;
297
     default:
297
     default:

+ 6
- 6
react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.js Vedi File

14
 import { Popover } from '../../../base/popover';
14
 import { Popover } from '../../../base/popover';
15
 import { connect } from '../../../base/redux';
15
 import { connect } from '../../../base/redux';
16
 import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
16
 import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
17
-import { LAYOUTS } from '../../../video-layout';
17
+import { THUMBNAIL_TYPE } from '../../../filmstrip';
18
 import { renderConnectionStatus } from '../../actions.web';
18
 import { renderConnectionStatus } from '../../actions.web';
19
 
19
 
20
 import ParticipantContextMenu from './ParticipantContextMenu';
20
 import ParticipantContextMenu from './ParticipantContextMenu';
265
  * @returns {Props}
265
  * @returns {Props}
266
  */
266
  */
267
 function _mapStateToProps(state, ownProps) {
267
 function _mapStateToProps(state, ownProps) {
268
-    const { participantID, currentLayout } = ownProps;
268
+    const { participantID, thumbnailType } = ownProps;
269
     let _remoteControlState = null;
269
     let _remoteControlState = null;
270
     const participant = getParticipantById(state, participantID);
270
     const participant = getParticipantById(state, participantID);
271
     const _participantDisplayName = participant?.name;
271
     const _participantDisplayName = participant?.name;
291
 
291
 
292
     let _menuPosition;
292
     let _menuPosition;
293
 
293
 
294
-    switch (currentLayout) {
295
-    case LAYOUTS.TILE_VIEW:
294
+    switch (thumbnailType) {
295
+    case THUMBNAIL_TYPE.TILE:
296
         _menuPosition = 'left-start';
296
         _menuPosition = 'left-start';
297
         break;
297
         break;
298
-    case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
298
+    case THUMBNAIL_TYPE.VERTICAL:
299
         _menuPosition = 'left-end';
299
         _menuPosition = 'left-end';
300
         break;
300
         break;
301
-    case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
301
+    case THUMBNAIL_TYPE.HORIZONTAL:
302
         _menuPosition = 'top';
302
         _menuPosition = 'top';
303
         break;
303
         break;
304
     default:
304
     default:

Loading…
Annulla
Salva