jitsi-meet/react/features/video-menu/components/web/FakeParticipantContextMenu.tsx
theluyuan 38ba663466
Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled
init
2025-09-02 14:49:16 +08:00

179 lines
5.7 KiB
TypeScript

import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import TogglePinToStageButton from '../../../../features/video-menu/components/web/TogglePinToStageButton';
import Avatar from '../../../base/avatar/components/Avatar';
import { IconPlay } from '../../../base/icons/svg';
import { isWhiteboardParticipant } from '../../../base/participants/functions';
import { IParticipant } from '../../../base/participants/types';
import ContextMenu from '../../../base/ui/components/web/ContextMenu';
import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
import { stopSharedVideo } from '../../../shared-video/actions';
import { getParticipantMenuButtonsWithNotifyClick, showOverflowDrawer } from '../../../toolbox/functions.web';
import { NOTIFY_CLICK_MODE } from '../../../toolbox/types';
import { setWhiteboardOpen } from '../../../whiteboard/actions';
import { WHITEBOARD_ID } from '../../../whiteboard/constants';
import { PARTICIPANT_MENU_BUTTONS as BUTTONS } from '../../constants';
interface IProps {
/**
* Class name for the context menu.
*/
className?: string;
/**
* Closes a drawer if open.
*/
closeDrawer?: () => void;
/**
* The participant for which the drawer is open.
* It contains the displayName & participantID.
*/
drawerParticipant?: {
displayName: string;
participantID: string;
};
/**
* Shared video local participant owner.
*/
localVideoOwner?: boolean;
/**
* Target elements against which positioning calculations are made.
*/
offsetTarget?: HTMLElement;
/**
* Callback for the mouse entering the component.
*/
onEnter?: (e?: React.MouseEvent) => void;
/**
* Callback for the mouse leaving the component.
*/
onLeave?: (e?: React.MouseEvent) => void;
/**
* Callback for making a selection in the menu.
*/
onSelect: (value?: boolean | React.MouseEvent) => void;
/**
* Participant reference.
*/
participant: IParticipant;
/**
* Whether or not the menu is displayed in the thumbnail remote video menu.
*/
thumbnailMenu?: boolean;
}
const FakeParticipantContextMenu = ({
className,
closeDrawer,
drawerParticipant,
localVideoOwner,
offsetTarget,
onEnter,
onLeave,
onSelect,
participant,
thumbnailMenu
}: IProps) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
const buttonsWithNotifyClick = useSelector(getParticipantMenuButtonsWithNotifyClick);
const notifyClick = useCallback(
(buttonKey: string, participantId?: string) => {
const notifyMode = buttonsWithNotifyClick?.get(buttonKey);
if (!notifyMode) {
return;
}
APP.API.notifyParticipantMenuButtonClicked(
buttonKey,
participantId,
notifyMode === NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
);
}, [ buttonsWithNotifyClick ]);
const clickHandler = useCallback(() => onSelect(true), [ onSelect ]);
const _onStopSharedVideo = useCallback(() => {
clickHandler();
dispatch(stopSharedVideo());
}, [ stopSharedVideo ]);
const _onHideWhiteboard = useCallback(() => {
clickHandler();
dispatch(setWhiteboardOpen(false));
}, [ setWhiteboardOpen ]);
const _getActions = useCallback(() => {
if (isWhiteboardParticipant(participant)) {
return [ {
accessibilityLabel: t('toolbar.hideWhiteboard'),
icon: IconPlay,
onClick: _onHideWhiteboard,
text: t('toolbar.hideWhiteboard')
} ];
}
if (localVideoOwner) {
return [ {
accessibilityLabel: t('toolbar.stopSharedVideo'),
icon: IconPlay,
onClick: _onStopSharedVideo,
text: t('toolbar.stopSharedVideo')
} ];
}
}, [ localVideoOwner, participant.fakeParticipant ]);
return (
<ContextMenu
className = { className }
entity = { participant }
hidden = { thumbnailMenu ? false : undefined }
inDrawer = { thumbnailMenu && _overflowDrawer }
isDrawerOpen = { Boolean(drawerParticipant) }
offsetTarget = { offsetTarget }
onClick = { onSelect }
onDrawerClose = { thumbnailMenu ? onSelect : closeDrawer }
onMouseEnter = { onEnter }
onMouseLeave = { onLeave }>
{!thumbnailMenu && _overflowDrawer && drawerParticipant && <ContextMenuItemGroup
actions = { [ {
accessibilityLabel: drawerParticipant.displayName,
customIcon: <Avatar
participantId = { drawerParticipant.participantID }
size = { 20 } />,
text: drawerParticipant.displayName
} ] } />}
<ContextMenuItemGroup
actions = { _getActions() }>
{isWhiteboardParticipant(participant) && (
<TogglePinToStageButton
key = 'pinToStage'
// eslint-disable-next-line react/jsx-no-bind
notifyClick = { () => notifyClick(BUTTONS.PIN_TO_STAGE, WHITEBOARD_ID) }
notifyMode = { buttonsWithNotifyClick?.get(BUTTONS.PIN_TO_STAGE) }
participantID = { WHITEBOARD_ID } />
)}
</ContextMenuItemGroup>
</ContextMenu>
);
};
export default FakeParticipantContextMenu;