snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { isScreenShareParticipantById } from '../../../base/participants/functions';
|
||||
import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
|
||||
import SendToSecondScreenIcon from '../../../multi-screen/components/SendToSecondScreenIcon';
|
||||
import { ISecondScreenSource } from '../../../multi-screen/types';
|
||||
import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
|
||||
import { getIndicatorsTooltipPosition } from '../../functions.web';
|
||||
|
||||
import PinnedIndicator from './PinnedIndicator';
|
||||
import RaisedHandIndicator from './RaisedHandIndicator';
|
||||
import StatusIndicators from './StatusIndicators';
|
||||
import VideoMenuTriggerButton from './VideoMenuTriggerButton';
|
||||
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Whether to hide the connection indicator.
|
||||
*/
|
||||
disableConnectionIndicator?: boolean;
|
||||
|
||||
/**
|
||||
* Hide popover callback.
|
||||
*/
|
||||
hidePopover?: Function;
|
||||
|
||||
/**
|
||||
* Class name for the status indicators container.
|
||||
*/
|
||||
indicatorsClassName?: string;
|
||||
|
||||
/**
|
||||
* Whether or not the thumbnail is hovered.
|
||||
*/
|
||||
isHovered: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the indicators are for the local participant.
|
||||
*/
|
||||
local?: boolean;
|
||||
|
||||
/**
|
||||
* Id of the participant for which the component is displayed.
|
||||
*/
|
||||
participantId: string;
|
||||
|
||||
/**
|
||||
* Whether popover is visible or not.
|
||||
*/
|
||||
popoverVisible?: boolean;
|
||||
|
||||
/**
|
||||
* Show popover callback.
|
||||
*/
|
||||
showPopover?: Function;
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles()(() => {
|
||||
return {
|
||||
container: {
|
||||
display: 'flex',
|
||||
|
||||
'& > *:not(:last-child)': {
|
||||
marginRight: '4px'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const ThumbnailTopIndicators = ({
|
||||
disableConnectionIndicator,
|
||||
hidePopover,
|
||||
indicatorsClassName,
|
||||
isHovered,
|
||||
local,
|
||||
participantId,
|
||||
popoverVisible,
|
||||
showPopover,
|
||||
thumbnailType
|
||||
}: IProps) => {
|
||||
const { classes: styles, cx } = useStyles();
|
||||
|
||||
const _isMobile = isMobileBrowser();
|
||||
const { NORMAL = 16 } = interfaceConfig.INDICATOR_FONT_SIZES || {};
|
||||
const _indicatorIconSize = NORMAL;
|
||||
const _connectionIndicatorAutoHideEnabled = Boolean(
|
||||
useSelector((state: IReduxState) => state['features/base/config'].connectionIndicators?.autoHide) ?? true);
|
||||
const _connectionIndicatorDisabled = _isMobile || disableConnectionIndicator
|
||||
|| Boolean(useSelector((state: IReduxState) => state['features/base/config'].connectionIndicators?.disabled));
|
||||
const showConnectionIndicator = isHovered || !_connectionIndicatorAutoHideEnabled;
|
||||
const isVirtualScreenshareParticipant = useSelector(
|
||||
(state: IReduxState) => isScreenShareParticipantById(state, participantId)
|
||||
);
|
||||
|
||||
// Kept stable so the trigger's click handler is too: this thumbnail
|
||||
// re-renders on every hover and every connection-stats tick.
|
||||
const screenshareSource: ISecondScreenSource = useMemo(
|
||||
() => ({ participant: participantId,
|
||||
role: 'screenshare' }),
|
||||
[ participantId ]);
|
||||
|
||||
if (isVirtualScreenshareParticipant) {
|
||||
return (
|
||||
<div className = { styles.container }>
|
||||
{!_connectionIndicatorDisabled
|
||||
&& <ConnectionIndicator
|
||||
alwaysVisible = { showConnectionIndicator }
|
||||
enableStatsDisplay = { true }
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
|
||||
}
|
||||
|
||||
{/* This thumbnail has no menu to add an entry to, so the second
|
||||
screen gets its own button, where the menu trigger would be. */}
|
||||
<SendToSecondScreenIcon
|
||||
source = { screenshareSource }
|
||||
visible = { isHovered } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const tooltipPosition = getIndicatorsTooltipPosition(thumbnailType);
|
||||
|
||||
return (<>
|
||||
<div className = { styles.container }>
|
||||
<PinnedIndicator
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{!_connectionIndicatorDisabled
|
||||
&& <ConnectionIndicator
|
||||
alwaysVisible = { showConnectionIndicator }
|
||||
enableStatsDisplay = { true }
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
|
||||
}
|
||||
<RaisedHandIndicator
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{thumbnailType !== THUMBNAIL_TYPE.TILE && (
|
||||
<div className = { cx(indicatorsClassName, 'top-indicators') }>
|
||||
<StatusIndicators
|
||||
participantID = { participantId }
|
||||
screenshare = { false } />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className = { styles.container }>
|
||||
<VideoMenuTriggerButton
|
||||
hidePopover = { hidePopover }
|
||||
local = { local }
|
||||
participantId = { participantId }
|
||||
popoverVisible = { popoverVisible }
|
||||
showPopover = { showPopover }
|
||||
thumbnailType = { thumbnailType }
|
||||
visible = { isHovered } />
|
||||
</div>
|
||||
</>);
|
||||
};
|
||||
|
||||
export default ThumbnailTopIndicators;
|
||||
Reference in New Issue
Block a user