feat(stage-name-label): Don't show for SS when toolbar is hidden

pull/15141/head jitsi-meet_9746
Hristo Terezov 8 months ago
parent e328b15fcd
commit 1152073b57
  1. 60
      react/features/display-name/components/web/StageParticipantNameLabel.tsx
  2. 36
      react/features/display-name/functions.ts
  3. 23
      react/features/subtitles/components/web/Captions.tsx
  4. 31
      react/features/toolbox/functions.web.ts

@ -3,17 +3,17 @@ import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { IReduxState } from '../../../app/types';
import { isDisplayNameVisible } from '../../../base/config/functions.any';
import {
getLocalParticipant,
getParticipantDisplayName,
isWhiteboardParticipant
} from '../../../base/participants/functions';
import { getParticipantDisplayName, isScreenShareParticipant } from '../../../base/participants/functions';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
import { getVideospaceFloatingElementsBottomSpacing } from '../../../base/ui/functions.web';
import { getLargeVideoParticipant } from '../../../large-video/functions';
import { getTransitionParamsForElementsAboveToolbox, isToolboxVisible } from '../../../toolbox/functions.web';
import { isLayoutTileView } from '../../../video-layout/functions.web';
import {
getTransitionParamsForElementsAboveToolbox,
isToolboxVisible,
toCSSTransitionValue
} from '../../../toolbox/functions.web';
import { isLayoutTileView } from '../../../video-layout/functions.any';
import { shouldDisplayStageParticipantBadge } from '../../functions';
import DisplayNameBadge from './DisplayNameBadge';
import {
@ -27,7 +27,7 @@ interface IOptions {
clientHeight?: number;
}
const useStyles = makeStyles<IOptions>()((theme, options: IOptions = {}) => {
const useStyles = makeStyles<IOptions, 'screenSharing'>()((theme, options: IOptions = {}, classes) => {
const typography = {
...getStageParticipantTypography(theme)
};
@ -42,6 +42,15 @@ const useStyles = makeStyles<IOptions>()((theme, options: IOptions = {}) => {
typography.lineHeight = getStageParticipantNameLabelLineHeight(theme, clientHeight);
}
const toolbarVisibleTransitionProps = getTransitionParamsForElementsAboveToolbox(true);
const toolbarHiddenTransitionProps = getTransitionParamsForElementsAboveToolbox(false);
const showTransitionDuration = toolbarVisibleTransitionProps.delay + toolbarVisibleTransitionProps.duration;
const hideTransitionDuration = toolbarHiddenTransitionProps.delay + toolbarHiddenTransitionProps.duration;
const showTransition = `opacity ${showTransitionDuration}s ${toolbarVisibleTransitionProps.easingFunction}`;
const hideTransition = `opacity ${hideTransitionDuration}s ${toolbarHiddenTransitionProps.easingFunction}`;
const moveUpTransition = `margin-bottom ${toCSSTransitionValue(toolbarVisibleTransitionProps)}`;
const moveDownTransition = `margin-bottom ${toCSSTransitionValue(toolbarHiddenTransitionProps)}`;
return {
badgeContainer: {
...withPixelLineHeight(typography),
@ -49,7 +58,7 @@ const useStyles = makeStyles<IOptions>()((theme, options: IOptions = {}) => {
display: 'inline-flex',
justifyContent: 'center',
marginBottom: getVideospaceFloatingElementsBottomSpacing(theme, false),
transition: `margin-bottom ${getTransitionParamsForElementsAboveToolbox(false)}`,
transition: moveDownTransition,
pointerEvents: 'none',
position: 'absolute',
bottom: 0,
@ -59,7 +68,15 @@ const useStyles = makeStyles<IOptions>()((theme, options: IOptions = {}) => {
},
containerElevated: {
marginBottom: getVideospaceFloatingElementsBottomSpacing(theme, true),
transition: `margin-bottom ${getTransitionParamsForElementsAboveToolbox(true)}`
transition: moveUpTransition,
[`&.${classes.screenSharing}`]: {
opacity: 1,
transition: `${showTransition}, ${moveUpTransition}`
}
},
screenSharing: {
opacity: 0,
transition: `${hideTransition}, ${moveDownTransition}`
}
};
});
@ -75,25 +92,20 @@ const StageParticipantNameLabel = () => {
const largeVideoParticipant = useSelector(getLargeVideoParticipant);
const selectedId = largeVideoParticipant?.id;
const nameToDisplay = useSelector((state: IReduxState) => getParticipantDisplayName(state, selectedId ?? ''));
const localParticipant = useSelector(getLocalParticipant);
const localId = localParticipant?.id;
const isTileView = useSelector(isLayoutTileView);
const toolboxVisible: boolean = useSelector(isToolboxVisible);
const showDisplayName = useSelector(isDisplayNameVisible);
const visible = useSelector(shouldDisplayStageParticipantBadge);
const isTileView = useSelector(isLayoutTileView);
const _isScreenShareParticipant = isScreenShareParticipant(largeVideoParticipant);
if (showDisplayName
&& nameToDisplay
&& selectedId !== localId
&& !isTileView
&& !isWhiteboardParticipant(largeVideoParticipant)
) {
if (visible || (_isScreenShareParticipant && !isTileView)) {
// For stage participant visibility is true only when the toolbar is visible but we need to keep the element
// in the DOM in order to make it disappear with an animation.
return (
<div
className = { cx(
classes.badgeContainer,
toolboxVisible && classes.containerElevated
toolboxVisible && classes.containerElevated,
_isScreenShareParticipant && classes.screenSharing
) }>
<DisplayNameBadge name = { nameToDisplay } />
</div>

@ -1,5 +1,15 @@
import { IStore } from '../app/types';
import { IReduxState, IStore } from '../app/types';
import { isDisplayNameVisible } from '../base/config/functions.any';
import {
getLocalParticipant,
getParticipantDisplayName,
isScreenShareParticipant,
isWhiteboardParticipant
} from '../base/participants/functions';
import { updateSettings } from '../base/settings/actions';
import { getLargeVideoParticipant } from '../large-video/functions';
import { isToolboxVisible } from '../toolbox/functions.web';
import { isLayoutTileView } from '../video-layout/functions.any';
/**
* Appends a suffix to the display name.
@ -42,3 +52,27 @@ export function onSetDisplayName(dispatch: IStore['dispatch'], onPostSubmit?: Fu
return true;
};
}
/**
* Returns true if the stage participant badge should be displayed and false otherwise.
*
* @param {IReduxState} state - The redux state.
* @returns {boolean} - True if the stage participant badge should be displayed and false otherwise.
*/
export function shouldDisplayStageParticipantBadge(state: IReduxState) {
const largeVideoParticipant = getLargeVideoParticipant(state);
const selectedId = largeVideoParticipant?.id;
const nameToDisplay = getParticipantDisplayName(state, selectedId ?? '');
const localId = getLocalParticipant(state)?.id;
const isTileView = isLayoutTileView(state);
const toolboxVisible: boolean = isToolboxVisible(state);
const showDisplayName = isDisplayNameVisible(state);
return Boolean(showDisplayName
&& nameToDisplay
&& selectedId !== localId
&& !isTileView
&& !isWhiteboardParticipant(largeVideoParticipant)
&& (!isScreenShareParticipant(largeVideoParticipant) || toolboxVisible)
);
}

@ -4,12 +4,14 @@ import { connect } from 'react-redux';
import { withStyles } from 'tss-react/mui';
import { IReduxState } from '../../../app/types';
import { getLocalParticipant } from '../../../base/participants/functions';
import { getVideospaceFloatingElementsBottomSpacing } from '../../../base/ui/functions.web';
import { getStageParticipantNameLabelHeight } from '../../../display-name/components/web/styles';
import { getLargeVideoParticipant } from '../../../large-video/functions';
import { getTransitionParamsForElementsAboveToolbox, isToolboxVisible } from '../../../toolbox/functions.web';
import { isLayoutTileView } from '../../../video-layout/functions.web';
import { shouldDisplayStageParticipantBadge } from '../../../display-name/functions';
import {
getTransitionParamsForElementsAboveToolbox,
isToolboxVisible,
toCSSTransitionValue
} from '../../../toolbox/functions.web';
import { calculateSubtitlesFontSize } from '../../functions.web';
import {
AbstractCaptions,
@ -53,7 +55,7 @@ const styles = (theme: Theme, props: IProps) => {
// Normally we would use 0.2 * fontSize in order to cover the background gap from line-height: 1.2 but it seems
// the current font is a little bit larger than it is supposed to be.
const padding = 0.1 * fontSize;
const bottom = getVideospaceFloatingElementsBottomSpacing(theme, _toolboxVisible);
let bottom = getVideospaceFloatingElementsBottomSpacing(theme, _toolboxVisible);
let marginBottom = 0;
// This is the case where we display the onstage participant display name
@ -61,7 +63,7 @@ const styles = (theme: Theme, props: IProps) => {
if (_isLifted) {
// 10px is the space between the onstage participant display name label and subtitles. We also need
// to add the padding of the subtitles because it will decrease the gap between the label and subtitles.
marginBottom += getStageParticipantNameLabelHeight(theme, _clientHeight) + 10 + padding;
bottom += getStageParticipantNameLabelHeight(theme, _clientHeight) + 10 + padding;
}
if (_shiftUp) {
@ -72,7 +74,7 @@ const styles = (theme: Theme, props: IProps) => {
return {
transcriptionSubtitles: {
bottom: `${bottom}px`,
marginBottom,
marginBottom: `${marginBottom}px`,
fontSize: `${fontSize}px`,
left: '50%',
maxWidth: '50vw',
@ -87,7 +89,7 @@ const styles = (theme: Theme, props: IProps) => {
transform: 'translateX(-50%)',
zIndex: 7, // The popups are with z-index 8. This z-index has to be lower.
lineHeight: 1.2,
transition: `bottom ${getTransitionParamsForElementsAboveToolbox(_toolboxVisible)}`,
transition: `bottom ${toCSSTransitionValue(getTransitionParamsForElementsAboveToolbox(_toolboxVisible))}`,
span: {
color: '#fff',
@ -153,14 +155,11 @@ class Captions extends AbstractCaptions<IProps> {
* @returns {Object}
*/
function mapStateToProps(state: IReduxState) {
const isTileView = isLayoutTileView(state);
const largeVideoParticipant = getLargeVideoParticipant(state);
const localParticipant = getLocalParticipant(state);
const { clientHeight } = state['features/base/responsive-ui'];
return {
..._abstractMapStateToProps(state),
_isLifted: Boolean(largeVideoParticipant && largeVideoParticipant?.id !== localParticipant?.id && !isTileView),
_isLifted: shouldDisplayStageParticipantBadge(state),
_clientHeight: clientHeight,
_shiftUp: state['features/toolbox'].shiftUp,
_toolboxVisible: isToolboxVisible(state)

@ -250,16 +250,41 @@ export function getParticipantMenuButtonsWithNotifyClick(state: IReduxState): Ma
return state['features/toolbox'].participantMenuButtonsWithNotifyClick;
}
interface ICSSTransitionObject {
delay: number;
duration: number;
easingFunction: string;
}
/**
* Returns the time, timing function and delay for elements that are position above the toolbar and need to move along
* with the toolbar.
*
* @param {boolean} isToolbarVisible - Whether the toolbar is visible or not.
* @returns {string}
* @returns {ICSSTransitionObject}
*/
export function getTransitionParamsForElementsAboveToolbox(isToolbarVisible: boolean) {
export function getTransitionParamsForElementsAboveToolbox(isToolbarVisible: boolean): ICSSTransitionObject {
// The transistion time and delay is different to account for the time when the toolbar is about to hide/show but
// the elements don't have to move.
return isToolbarVisible ? '0.15s ease-in 0.15s' : '0.24s ease-in 0s';
return isToolbarVisible ? {
duration: 0.15,
easingFunction: 'ease-in',
delay: 0.15
} : {
duration: 0.24,
easingFunction: 'ease-in',
delay: 0
};
}
/**
* Converts a given object to a css transition value string.
*
* @param {ICSSTransitionObject} object - The object.
* @returns {string}
*/
export function toCSSTransitionValue(object: ICSSTransitionObject) {
const { delay, duration, easingFunction } = object;
return `${duration}s ${easingFunction} ${delay}s`;
}

Loading…
Cancel
Save