"Fossies" - the Fresh Open Source Software Archive

Member "jitsi-meet-7319/react/features/video-menu/components/web/RemoteVideoMenuTriggerButton.tsx" (6 Jun 2023, 8069 Bytes) of package /linux/misc/jitsi-meet-7319.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. See also the last Fossies "Diffs" side-by-side code changes report for "RemoteVideoMenuTriggerButton.tsx": jitsi-meet_8319_vs_jitsi-meet_8615.

    1 import React, { useCallback } from 'react';
    2 import { useTranslation } from 'react-i18next';
    3 import { batch, connect } from 'react-redux';
    4 import { makeStyles } from 'tss-react/mui';
    5 
    6 import { IReduxState, IStore } from '../../../app/types';
    7 import { isMobileBrowser } from '../../../base/environment/utils';
    8 import { IconDotsHorizontal } from '../../../base/icons/svg';
    9 import { getLocalParticipant, getParticipantById } from '../../../base/participants/functions';
   10 import { IParticipant } from '../../../base/participants/types';
   11 import Popover from '../../../base/popover/components/Popover.web';
   12 import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
   13 import Button from '../../../base/ui/components/web/Button';
   14 import ConnectionIndicatorContent from
   15     '../../../connection-indicator/components/web/ConnectionIndicatorContent';
   16 import { THUMBNAIL_TYPE } from '../../../filmstrip/constants';
   17 import { renderConnectionStatus } from '../../actions.web';
   18 
   19 import FakeParticipantContextMenu from './FakeParticipantContextMenu';
   20 import ParticipantContextMenu from './ParticipantContextMenu';
   21 import { REMOTE_CONTROL_MENU_STATES } from './RemoteControlButton';
   22 
   23 /**
   24  * The type of the React {@code Component} props of
   25  * {@link RemoteVideoMenuTriggerButton}.
   26  */
   27 interface IProps {
   28 
   29     /**
   30      * Whether the remote video context menu is disabled.
   31      */
   32     _disabled: Boolean;
   33 
   34     /**
   35      * Shared video local participant owner.
   36      */
   37     _localVideoOwner?: boolean;
   38 
   39     /**
   40      * The position relative to the trigger the remote menu should display
   41      * from.
   42      */
   43     _menuPosition: string;
   44 
   45     /**
   46      * Participant reference.
   47      */
   48     _participant: IParticipant;
   49 
   50     /**
   51      * The ID for the participant on which the remote video menu will act.
   52      */
   53     _participantDisplayName: string;
   54 
   55     /**
   56      * The current state of the participant's remote control session.
   57      */
   58     _remoteControlState?: number;
   59 
   60     /**
   61      * Whether the popover should render the Connection Info stats.
   62      */
   63     _showConnectionInfo: Boolean;
   64 
   65     /**
   66      * Whether or not the button should be visible.
   67      */
   68     buttonVisible: boolean;
   69 
   70     /**
   71      * The redux dispatch function.
   72      */
   73     dispatch: IStore['dispatch'];
   74 
   75     /**
   76      * Hides popover.
   77      */
   78     hidePopover?: Function;
   79 
   80     /**
   81      * The ID for the participant on which the remote video menu will act.
   82      */
   83     participantID: string;
   84 
   85     /**
   86      * Whether the popover is visible or not.
   87      */
   88     popoverVisible?: boolean;
   89 
   90     /**
   91      * Shows popover.
   92      */
   93     showPopover?: Function;
   94 
   95     /**
   96      * The type of the thumbnail.
   97      */
   98     thumbnailType: string;
   99 }
  100 
  101 const useStyles = makeStyles()(() => {
  102     return {
  103         triggerButton: {
  104             padding: '3px !important',
  105             borderRadius: '4px',
  106 
  107             '& svg': {
  108                 width: '18px',
  109                 height: '18px'
  110             }
  111         },
  112 
  113         contextMenu: {
  114             position: 'relative',
  115             marginTop: 0,
  116             right: 'auto',
  117             marginRight: '4px',
  118             marginBottom: '4px'
  119         }
  120     };
  121 });
  122 
  123 const RemoteVideoMenuTriggerButton = ({
  124     _disabled,
  125     _localVideoOwner,
  126     _menuPosition,
  127     _participant,
  128     _participantDisplayName,
  129     _remoteControlState,
  130     _showConnectionInfo,
  131     buttonVisible,
  132     dispatch,
  133     hidePopover,
  134     participantID,
  135     popoverVisible,
  136     showPopover
  137 }: IProps) => {
  138     const { classes } = useStyles();
  139     const { t } = useTranslation();
  140 
  141     const _onPopoverOpen = useCallback(() => {
  142         showPopover?.();
  143         dispatch(setParticipantContextMenuOpen(true));
  144     }, []);
  145 
  146     const _onPopoverClose = useCallback(() => {
  147         hidePopover?.();
  148         batch(() => {
  149             dispatch(setParticipantContextMenuOpen(false));
  150             dispatch(renderConnectionStatus(false));
  151         });
  152     }, []);
  153 
  154     // eslint-disable-next-line react/no-multi-comp
  155     const _renderRemoteVideoMenu = () => {
  156         const props = {
  157             className: classes.contextMenu,
  158             onSelect: _onPopoverClose,
  159             participant: _participant,
  160             thumbnailMenu: true
  161         };
  162 
  163         if (_participant?.fakeParticipant) {
  164             return (
  165                 <FakeParticipantContextMenu
  166                     { ...props }
  167                     localVideoOwner = { _localVideoOwner } />
  168             );
  169         }
  170 
  171         return (
  172             <ParticipantContextMenu
  173                 { ...props }
  174                 remoteControlState = { _remoteControlState } />
  175         );
  176     };
  177 
  178     let content;
  179 
  180     if (_showConnectionInfo) {
  181         content = <ConnectionIndicatorContent participantId = { participantID } />;
  182     } else if (!_disabled) {
  183         content = _renderRemoteVideoMenu();
  184     }
  185 
  186     if (!content) {
  187         return null;
  188     }
  189 
  190     const username = _participantDisplayName;
  191 
  192     return (
  193         <Popover
  194             content = { content }
  195             headingLabel = { t('dialog.remoteUserControls', { username }) }
  196             id = 'remote-video-menu-trigger'
  197             onPopoverClose = { _onPopoverClose }
  198             onPopoverOpen = { _onPopoverOpen }
  199             position = { _menuPosition }
  200             visible = { Boolean(popoverVisible) }>
  201             {buttonVisible && !_disabled && (
  202                 !isMobileBrowser() && <Button
  203                     accessibilityLabel = { t('dialog.remoteUserControls', { username }) }
  204                     className = { classes.triggerButton }
  205                     icon = { IconDotsHorizontal }
  206                     size = 'small' />
  207             )}
  208         </Popover>
  209     );
  210 };
  211 
  212 /**
  213  * Maps (parts of) the Redux state to the associated {@code RemoteVideoMenuTriggerButton}'s props.
  214  *
  215  * @param {Object} state - The Redux state.
  216  * @param {Object} ownProps - The own props of the component.
  217  * @private
  218  * @returns {IProps}
  219  */
  220 function _mapStateToProps(state: IReduxState, ownProps: Partial<IProps>) {
  221     const { participantID, thumbnailType } = ownProps;
  222     let _remoteControlState;
  223     const localParticipantId = getLocalParticipant(state)?.id;
  224     const participant = getParticipantById(state, participantID ?? '');
  225     const _participantDisplayName = participant?.name;
  226     const _isRemoteControlSessionActive = participant?.remoteControlSessionStatus ?? false;
  227     const _supportsRemoteControl = participant?.supportsRemoteControl ?? false;
  228     const { active, controller } = state['features/remote-control'];
  229     const { requestedParticipant, controlled } = controller;
  230     const activeParticipant = requestedParticipant || controlled;
  231     const { showConnectionInfo } = state['features/base/connection'];
  232     const { remoteVideoMenu } = state['features/base/config'];
  233     const { ownerId } = state['features/shared-video'];
  234 
  235     if (_supportsRemoteControl
  236             && ((!active && !_isRemoteControlSessionActive) || activeParticipant === participantID)) {
  237         if (requestedParticipant === participantID) {
  238             _remoteControlState = REMOTE_CONTROL_MENU_STATES.REQUESTING;
  239         } else if (controlled) {
  240             _remoteControlState = REMOTE_CONTROL_MENU_STATES.STARTED;
  241         } else {
  242             _remoteControlState = REMOTE_CONTROL_MENU_STATES.NOT_STARTED;
  243         }
  244     }
  245 
  246     let _menuPosition;
  247 
  248     switch (thumbnailType) {
  249     case THUMBNAIL_TYPE.TILE:
  250         _menuPosition = 'left-start';
  251         break;
  252     case THUMBNAIL_TYPE.VERTICAL:
  253         _menuPosition = 'left-end';
  254         break;
  255     case THUMBNAIL_TYPE.HORIZONTAL:
  256         _menuPosition = 'top';
  257         break;
  258     default:
  259         _menuPosition = 'auto';
  260     }
  261 
  262     return {
  263         _disabled: Boolean(remoteVideoMenu?.disabled),
  264         _localVideoOwner: Boolean(ownerId === localParticipantId),
  265         _menuPosition,
  266         _participant: participant ?? { id: '' },
  267         _participantDisplayName: _participantDisplayName ?? '',
  268         _remoteControlState,
  269         _showConnectionInfo: Boolean(showConnectionInfo)
  270     };
  271 }
  272 
  273 export default connect(_mapStateToProps)(RemoteVideoMenuTriggerButton);