"Fossies" - the Fresh Open Source Software Archive 
Member "jitsi-meet-7555/react/features/video-menu/components/web/LocalVideoMenuTriggerButton.tsx" (28 Sep 2023, 10089 Bytes) of package /linux/misc/jitsi-meet-7555.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) TSX (TypeScript with React) source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1 import React, { useCallback } from 'react';
2 import { useTranslation } from 'react-i18next';
3 import { batch, connect, useSelector } from 'react-redux';
4 import { makeStyles } from 'tss-react/mui';
5
6 import { IReduxState, IStore } from '../../../app/types';
7 import { getButtonNotifyMode, getParticipantMenuButtonsWithNotifyClick } from '../../../base/config/functions.web';
8 import { isMobileBrowser } from '../../../base/environment/utils';
9 import { IconDotsHorizontal } from '../../../base/icons/svg';
10 import { getLocalParticipant } from '../../../base/participants/functions';
11 import Popover from '../../../base/popover/components/Popover.web';
12 import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
13 import { getHideSelfView } from '../../../base/settings/functions.web';
14 import { getLocalVideoTrack } from '../../../base/tracks/functions';
15 import Button from '../../../base/ui/components/web/Button';
16 import ContextMenu from '../../../base/ui/components/web/ContextMenu';
17 import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
18 import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
19 import { THUMBNAIL_TYPE } from '../../../filmstrip/constants';
20 import { isStageFilmstripAvailable } from '../../../filmstrip/functions.web';
21 import { NOTIFY_CLICK_MODE } from '../../../toolbox/constants';
22 import { renderConnectionStatus } from '../../actions.web';
23 import { PARTICIPANT_MENU_BUTTONS as BUTTONS } from '../../constants';
24
25 import ConnectionStatusButton from './ConnectionStatusButton';
26 import FlipLocalVideoButton from './FlipLocalVideoButton';
27 import HideSelfViewVideoButton from './HideSelfViewVideoButton';
28 import TogglePinToStageButton from './TogglePinToStageButton';
29
30 /**
31 * The type of the React {@code Component} props of
32 * {@link LocalVideoMenuTriggerButton}.
33 */
34 interface IProps {
35
36 /**
37 * The id of the local participant.
38 */
39 _localParticipantId: string;
40
41 /**
42 * The position relative to the trigger the local video menu should display
43 * from.
44 */
45 _menuPosition: string;
46
47 /**
48 * Whether to display the Popover as a drawer.
49 */
50 _overflowDrawer: boolean;
51
52 /**
53 * Whether to render the connection info pane.
54 */
55 _showConnectionInfo: boolean;
56
57 /**
58 * Whether to render the hide self view button.
59 */
60 _showHideSelfViewButton: boolean;
61
62 /**
63 * Shows/hides the local video flip button.
64 */
65 _showLocalVideoFlipButton: boolean;
66
67 /**
68 * Whether to render the pin to stage button.
69 */
70 _showPinToStage: boolean;
71
72 /**
73 * Whether or not the button should be visible.
74 */
75 buttonVisible: boolean;
76
77 /**
78 * The redux dispatch function.
79 */
80 dispatch: IStore['dispatch'];
81
82 /**
83 * Hides popover.
84 */
85 hidePopover?: Function;
86
87 /**
88 * Whether the popover is visible or not.
89 */
90 popoverVisible?: boolean;
91
92 /**
93 * Shows popover.
94 */
95 showPopover?: Function;
96
97 /**
98 * The type of the thumbnail.
99 */
100 thumbnailType: string;
101 }
102
103 const useStyles = makeStyles()(() => {
104 return {
105 triggerButton: {
106 padding: '3px !important',
107 borderRadius: '4px',
108
109 '& svg': {
110 width: '18px',
111 height: '18px'
112 }
113 },
114
115 contextMenu: {
116 position: 'relative',
117 marginTop: 0,
118 right: 'auto',
119 padding: '0',
120 minWidth: '200px'
121 },
122
123 flipText: {
124 marginLeft: '36px'
125 }
126 };
127 });
128
129 const LocalVideoMenuTriggerButton = ({
130 _localParticipantId,
131 _menuPosition,
132 _overflowDrawer,
133 _showConnectionInfo,
134 _showHideSelfViewButton,
135 _showLocalVideoFlipButton,
136 _showPinToStage,
137 buttonVisible,
138 dispatch,
139 hidePopover,
140 showPopover,
141 popoverVisible
142 }: IProps) => {
143 const { classes } = useStyles();
144 const { t } = useTranslation();
145 const buttonsWithNotifyClick = useSelector(getParticipantMenuButtonsWithNotifyClick);
146
147 const notifyClick = useCallback(
148 (buttonKey: string) => {
149 const notifyMode = getButtonNotifyMode(buttonKey, buttonsWithNotifyClick);
150
151 if (!notifyMode) {
152 return;
153 }
154
155 APP.API.notifyParticipantMenuButtonClicked(
156 buttonKey,
157 _localParticipantId,
158 notifyMode === NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
159 );
160 }, [ buttonsWithNotifyClick, getButtonNotifyMode ]);
161
162 const _onPopoverOpen = useCallback(() => {
163 showPopover?.();
164 dispatch(setParticipantContextMenuOpen(true));
165 }, []);
166
167 const _onPopoverClose = useCallback(() => {
168 hidePopover?.();
169 batch(() => {
170 dispatch(setParticipantContextMenuOpen(false));
171 dispatch(renderConnectionStatus(false));
172 });
173 }, []);
174
175 const content = _showConnectionInfo
176 ? <ConnectionIndicatorContent participantId = { _localParticipantId } />
177 : (
178 <ContextMenu
179 className = { classes.contextMenu }
180 hidden = { false }
181 inDrawer = { _overflowDrawer }>
182 <ContextMenuItemGroup>
183 {_showLocalVideoFlipButton
184 && <FlipLocalVideoButton
185 className = { _overflowDrawer ? classes.flipText : '' }
186 // eslint-disable-next-line react/jsx-no-bind
187 notifyClick = { () => notifyClick(BUTTONS.FLIP_LOCAL_VIDEO) }
188 notifyMode = { getButtonNotifyMode(BUTTONS.FLIP_LOCAL_VIDEO, buttonsWithNotifyClick) }
189 onClick = { hidePopover } />
190 }
191 {_showHideSelfViewButton
192 && <HideSelfViewVideoButton
193 className = { _overflowDrawer ? classes.flipText : '' }
194 // eslint-disable-next-line react/jsx-no-bind
195 notifyClick = { () => notifyClick(BUTTONS.HIDE_SELF_VIEW) }
196 notifyMode = { getButtonNotifyMode(BUTTONS.HIDE_SELF_VIEW, buttonsWithNotifyClick) }
197 onClick = { hidePopover } />
198 }
199 {
200 _showPinToStage && <TogglePinToStageButton
201 className = { _overflowDrawer ? classes.flipText : '' }
202 noIcon = { true }
203 // eslint-disable-next-line react/jsx-no-bind
204 notifyClick = { () => notifyClick(BUTTONS.PIN_TO_STAGE) }
205 notifyMode = { getButtonNotifyMode(BUTTONS.PIN_TO_STAGE, buttonsWithNotifyClick) }
206 onClick = { hidePopover }
207 participantID = { _localParticipantId } />
208 }
209 {
210 isMobileBrowser() && <ConnectionStatusButton
211 // eslint-disable-next-line react/jsx-no-bind
212 notifyClick = { () => notifyClick(BUTTONS.CONN_STATUS) }
213 notifyMode = { getButtonNotifyMode(BUTTONS.CONN_STATUS, buttonsWithNotifyClick) }
214 participantID = { _localParticipantId } />
215 }
216 </ContextMenuItemGroup>
217 </ContextMenu>
218 );
219
220 return (
221 isMobileBrowser() || _showLocalVideoFlipButton || _showHideSelfViewButton
222 ? <Popover
223 content = { content }
224 headingLabel = { t('dialog.localUserControls') }
225 id = 'local-video-menu-trigger'
226 onPopoverClose = { _onPopoverClose }
227 onPopoverOpen = { _onPopoverOpen }
228 position = { _menuPosition }
229 visible = { Boolean(popoverVisible) }>
230 {buttonVisible && !isMobileBrowser() && (
231 <Button
232 accessibilityLabel = { t('dialog.localUserControls') }
233 className = { classes.triggerButton }
234 icon = { IconDotsHorizontal }
235 size = 'small' />
236 )}
237 </Popover>
238 : null
239 );
240 };
241
242 /**
243 * Maps (parts of) the Redux state to the associated {@code LocalVideoMenuTriggerButton}'s props.
244 *
245 * @param {Object} state - The Redux state.
246 * @param {Object} ownProps - The own props of the component.
247 * @private
248 * @returns {IProps}
249 */
250 function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
251 const { thumbnailType } = ownProps;
252 const localParticipant = getLocalParticipant(state);
253 const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
254 const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
255 const { overflowDrawer } = state['features/toolbox'];
256 const { showConnectionInfo } = state['features/base/connection'];
257 const showHideSelfViewButton = !disableSelfViewSettings && !getHideSelfView(state);
258
259 let _menuPosition;
260
261 switch (thumbnailType) {
262 case THUMBNAIL_TYPE.TILE:
263 _menuPosition = 'left-start';
264 break;
265 case THUMBNAIL_TYPE.VERTICAL:
266 _menuPosition = 'left-start';
267 break;
268 case THUMBNAIL_TYPE.HORIZONTAL:
269 _menuPosition = 'top-start';
270 break;
271 default:
272 _menuPosition = 'auto';
273 }
274
275 return {
276 _menuPosition,
277 _showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
278 _showHideSelfViewButton: showHideSelfViewButton,
279 _overflowDrawer: overflowDrawer,
280 _localParticipantId: localParticipant?.id ?? '',
281 _showConnectionInfo: Boolean(showConnectionInfo),
282 _showPinToStage: isStageFilmstripAvailable(state)
283 };
284 }
285
286 export default connect(_mapStateToProps)(LocalVideoMenuTriggerButton);