Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)
};
Expand All @@ -42,14 +42,23 @@ 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),
alignItems: 'center',
display: 'inline-flex',
justifyContent: 'center',
marginBottom: getVideospaceFloatingElementsBottomSpacing(theme, false),
transition: `margin-bottom ${getTransitionParamsForElementsAboveToolbox(false)}`,
transition: moveDownTransition,
pointerEvents: 'none',
position: 'absolute',
bottom: 0,
Expand All @@ -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}`
}
};
});
Expand All @@ -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>
Expand Down
36 changes: 35 additions & 1 deletion react/features/display-name/functions.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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)
);
}
23 changes: 11 additions & 12 deletions react/features/subtitles/components/web/Captions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -53,15 +55,15 @@ 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
// below the subtitles.
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) {
Expand All @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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)
Expand Down
31 changes: 28 additions & 3 deletions react/features/toolbox/functions.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
}