瀏覽代碼

feat(DominantSpeakerName): Implement

master
Mihai-Andrei Uscat 3 年之前
父節點
當前提交
7263829763

+ 7
- 3
css/_toolbars.scss 查看文件

@@ -105,12 +105,15 @@
105 105
     margin: 0 auto;
106 106
     max-width: 100%;
107 107
     pointer-events: all;
108
-    background-color: #131519;
109
-    padding-bottom: env(safe-area-inset-bottom, 0);
110
-    box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
111 108
     border-radius: 6px;
112 109
 }
113 110
 
111
+.toolbox-content-wrapper::after {
112
+    content: '';
113
+    background: $newToolbarBackgroundColor;
114
+    padding-bottom: env(safe-area-inset-bottom, 0);
115
+}
116
+
114 117
 .toolbox-content-items {
115 118
     background: $newToolbarBackgroundColor;
116 119
     border-radius: 6px;
@@ -118,6 +121,7 @@
118 121
     padding: 6px;
119 122
     text-align: center;
120 123
     pointer-events: all;
124
+    box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
121 125
 
122 126
     >div {
123 127
         margin-left: 8px;

+ 2
- 2
css/_transcription-subtitles.scss 查看文件

@@ -16,8 +16,8 @@
16 16
     z-index: $subtitlesZ;
17 17
 
18 18
     &.lifted {
19
-        // Lift subtitle above toolbar+invite box.
20
-        bottom: $newToolbarSize + 112px + 40px;
19
+        // Lift subtitle above toolbar+dominant speaker box.
20
+        bottom: $newToolbarSize + 36px + 40px;
21 21
     }
22 22
 
23 23
     span {

+ 45
- 0
react/features/display-name/components/web/DisplayNameBadge.js 查看文件

@@ -0,0 +1,45 @@
1
+// @flow
2
+
3
+import { makeStyles } from '@material-ui/core/styles';
4
+import React from 'react';
5
+
6
+type Props = {
7
+
8
+    /**
9
+     * The name to be displayed within the badge.
10
+     */
11
+    name: string
12
+}
13
+
14
+const useStyles = makeStyles(theme => {
15
+    return {
16
+        badge: {
17
+            background: 'rgba(0, 0, 0, 0.6)',
18
+            borderRadius: '3px',
19
+            color: theme.palette.text01,
20
+            maxWidth: '50%',
21
+            overflow: 'hidden',
22
+            padding: '2px 16px',
23
+            textOverflow: 'ellipsis',
24
+            whiteSpace: 'nowrap'
25
+        }
26
+    };
27
+});
28
+
29
+/**
30
+ * Component that displays a name badge.
31
+ *
32
+ * @param {Props} props - The props of the component.
33
+ * @returns {ReactElement}
34
+ */
35
+const DisplayNameBadge = ({ name }: Props) => {
36
+    const classes = useStyles();
37
+
38
+    return (
39
+        <div className = { classes.badge }>
40
+            {name}
41
+        </div>
42
+    );
43
+};
44
+
45
+export default DisplayNameBadge;

+ 60
- 0
react/features/display-name/components/web/DominantSpeakerName.js 查看文件

@@ -0,0 +1,60 @@
1
+// @flow
2
+
3
+import { makeStyles } from '@material-ui/core/styles';
4
+import React from 'react';
5
+import { useSelector } from 'react-redux';
6
+
7
+import { getLocalParticipant } from '../../../base/participants';
8
+import { withPixelLineHeight } from '../../../base/styles/functions.web';
9
+import { getLargeVideoParticipant } from '../../../large-video/functions';
10
+import { isToolboxVisible } from '../../../toolbox/functions.web';
11
+import { isLayoutTileView } from '../../../video-layout';
12
+
13
+import DisplayNameBadge from './DisplayNameBadge';
14
+
15
+const useStyles = makeStyles(theme => {
16
+    return {
17
+        badgeContainer: {
18
+            ...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
19
+            alignItems: 'center',
20
+            display: 'flex',
21
+            justifyContent: 'center',
22
+            marginBottom: theme.spacing(2),
23
+            transition: 'margin-bottom 0.3s'
24
+        },
25
+        containerElevated: {
26
+            marginBottom: theme.spacing(7)
27
+        }
28
+    };
29
+});
30
+
31
+/**
32
+ * Component that renders the dominant speaker's name as a badge above the toolbar in stage view.
33
+ *
34
+ * @returns {ReactElement|null}
35
+ */
36
+const DominantSpeakerName = () => {
37
+    const classes = useStyles();
38
+    const largeVideoParticipant = useSelector(getLargeVideoParticipant);
39
+    const nameToDisplay = largeVideoParticipant?.name;
40
+    const selectedId = largeVideoParticipant?.id;
41
+
42
+    const localParticipant = useSelector(getLocalParticipant);
43
+    const localId = localParticipant?.id;
44
+
45
+    const isTileView = useSelector(isLayoutTileView);
46
+    const toolboxVisible = useSelector(isToolboxVisible);
47
+
48
+    if (nameToDisplay && selectedId !== localId && !isTileView) {
49
+        return (
50
+            <div
51
+                className = { `${classes.badgeContainer}${toolboxVisible ? '' : ` ${classes.containerElevated}`}` }>
52
+                <DisplayNameBadge name = { nameToDisplay } />
53
+            </div>
54
+        );
55
+    }
56
+
57
+    return null;
58
+};
59
+
60
+export default DominantSpeakerName;

+ 1
- 0
react/features/display-name/components/web/index.js 查看文件

@@ -3,3 +3,4 @@
3 3
 export { default as DisplayName } from './DisplayName';
4 4
 export { default as DisplayNameLabel } from './DisplayNameLabel';
5 5
 export { default as DisplayNamePrompt } from './DisplayNamePrompt';
6
+export { default as DominantSpeakerName } from './DominantSpeakerName';

+ 15
- 0
react/features/large-video/functions.js 查看文件

@@ -0,0 +1,15 @@
1
+// @flow
2
+
3
+import { getParticipantById } from '../base/participants';
4
+
5
+/**
6
+ * Selector for the participant currently displaying on the large video.
7
+ *
8
+ * @param {Object} state - The redux state.
9
+ * @returns {Object}
10
+ */
11
+export function getLargeVideoParticipant(state: Object) {
12
+    const { participantId } = state['features/large-video'];
13
+
14
+    return getParticipantById(state, participantId);
15
+}

+ 8
- 2
react/features/subtitles/components/Captions.web.js 查看文件

@@ -2,8 +2,10 @@
2 2
 
3 3
 import React from 'react';
4 4
 
5
-import { getParticipantCountWithFake } from '../../base/participants';
5
+import { getLocalParticipant } from '../../base/participants';
6 6
 import { connect } from '../../base/redux';
7
+import { getLargeVideoParticipant } from '../../large-video/functions';
8
+import { isLayoutTileView } from '../../video-layout';
7 9
 
8 10
 import {
9 11
     _abstractMapStateToProps,
@@ -74,9 +76,13 @@ class Captions
74 76
  * @returns {Object}
75 77
  */
76 78
 function mapStateToProps(state) {
79
+    const isTileView = isLayoutTileView(state);
80
+    const largeVideoParticipant = getLargeVideoParticipant(state);
81
+    const localParticipant = getLocalParticipant(state);
82
+
77 83
     return {
78 84
         ..._abstractMapStateToProps(state),
79
-        _isLifted: getParticipantCountWithFake(state) < 2
85
+        _isLifted: largeVideoParticipant && largeVideoParticipant?.id !== localParticipant?.id && !isTileView
80 86
     };
81 87
 }
82 88
 

+ 2
- 0
react/features/toolbox/components/web/Toolbox.js 查看文件

@@ -24,6 +24,7 @@ import { connect } from '../../../base/redux';
24 24
 import { getLocalVideoTrack } from '../../../base/tracks';
25 25
 import { toggleChat } from '../../../chat';
26 26
 import { ChatButton } from '../../../chat/components';
27
+import { DominantSpeakerName } from '../../../display-name';
27 28
 import { EmbedMeetingButton } from '../../../embed-meeting';
28 29
 import { SharedDocumentButton } from '../../../etherpad';
29 30
 import { FeedbackButton } from '../../../feedback';
@@ -1145,6 +1146,7 @@ class Toolbox extends Component<Props> {
1145 1146
                     onFocus = { this._onTabIn }
1146 1147
                     onMouseOut = { this._onMouseOut }
1147 1148
                     onMouseOver = { this._onMouseOver }>
1149
+                    <DominantSpeakerName />
1148 1150
                     <div className = 'toolbox-content-items'>
1149 1151
                         {mainMenuButtons.map(({ Content, key, ...rest }) => Content !== Separator && (
1150 1152
                             <Content

+ 10
- 0
react/features/video-layout/functions.js 查看文件

@@ -208,3 +208,13 @@ export function updateAutoPinnedParticipant(
208 208
         dispatch(pinParticipant(latestScreenShareParticipantId));
209 209
     }
210 210
 }
211
+
212
+/**
213
+ * Selector for whether we are currently in tile view.
214
+ *
215
+ * @param {Object} state - The redux state.
216
+ * @returns {boolean}
217
+ */
218
+export function isLayoutTileView(state: Object) {
219
+    return getCurrentLayout(state) === LAYOUTS.TILE_VIEW;
220
+}

Loading…
取消
儲存