mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 11:22:31 +00:00
feat(conference): apply reduce ui for web (#16763)
* Change stage view and use newly reducedUImainToolbarButtons config to show different custom buttons as main toolbar buttons for when web is in reduced UI.
This commit is contained in:
@@ -924,6 +924,11 @@ var config = {
|
||||
// [ 'microphone', 'camera' ]
|
||||
// ],
|
||||
|
||||
// Overrides the buttons displayed in the main toolbar for reduced UI.
|
||||
// When there isn't an override for a certain configuration the default jitsi-meet configuration will be used.
|
||||
// The order of the buttons in the array is preserved.
|
||||
// reducedUImainToolbarButtons: [ 'microphone', 'camera' ],
|
||||
|
||||
// Toolbar buttons which have their click/tap event exposed through the API on
|
||||
// `toolbarButtonClicked`. Passing a string for the button key will
|
||||
// prevent execution of the click/tap routine; passing an object with `key` and
|
||||
|
||||
@@ -559,6 +559,7 @@ export interface IConfig {
|
||||
skipConsentInMeeting?: boolean;
|
||||
suggestRecording?: boolean;
|
||||
};
|
||||
reducedUImainToolbarButtons?: Array<string>;
|
||||
remoteVideoMenu?: {
|
||||
disableDemote?: boolean;
|
||||
disableGrantModerator?: boolean;
|
||||
|
||||
@@ -215,6 +215,7 @@ export default [
|
||||
'recordings.showPrejoinWarning',
|
||||
'recordings.showRecordingLink',
|
||||
'recordings.suggestRecording',
|
||||
'reducedUImainToolbarButtons',
|
||||
'replaceParticipant',
|
||||
'resolution',
|
||||
'screenshotCapture',
|
||||
|
||||
@@ -24,6 +24,7 @@ import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants';
|
||||
* determine whether and how to render it.
|
||||
*/
|
||||
const REDUCED_UI_THRESHOLD = 300;
|
||||
const WEB_REDUCED_UI_THRESHOLD = 320;
|
||||
|
||||
/**
|
||||
* Indicates a resize of the window.
|
||||
@@ -49,6 +50,8 @@ export function clientResized(clientWidth: number, clientHeight: number) {
|
||||
}
|
||||
|
||||
availableWidth -= getParticipantsPaneWidth(state);
|
||||
|
||||
dispatch(setReducedUI(availableWidth, clientHeight));
|
||||
}
|
||||
|
||||
batch(() => {
|
||||
@@ -106,7 +109,10 @@ export function setAspectRatio(width: number, height: number) {
|
||||
*/
|
||||
export function setReducedUI(width: number, height: number) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const reducedUI = Math.min(width, height) < REDUCED_UI_THRESHOLD;
|
||||
const threshold = navigator.product === 'ReactNative'
|
||||
? REDUCED_UI_THRESHOLD
|
||||
: WEB_REDUCED_UI_THRESHOLD;
|
||||
const reducedUI = Math.min(width, height) < threshold;
|
||||
|
||||
if (reducedUI !== getState()['features/base/responsive-ui'].reducedUI) {
|
||||
return dispatch({
|
||||
|
||||
@@ -78,6 +78,11 @@ interface IProps extends AbstractProps {
|
||||
*/
|
||||
_isResizing: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the UI is reduced.
|
||||
*/
|
||||
_reducedUI: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not to block chat access with a nickname input form.
|
||||
*/
|
||||
@@ -227,6 +232,7 @@ const Chat = ({
|
||||
_focusedTab,
|
||||
_isResizing,
|
||||
_messages,
|
||||
_reducedUI,
|
||||
_unreadMessagesCount,
|
||||
_unreadPollsCount,
|
||||
_unreadFilesCount,
|
||||
@@ -567,6 +573,10 @@ const Chat = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (_reducedUI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
_isOpen ? <div
|
||||
className = { classes.container }
|
||||
@@ -623,6 +633,7 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
const { isOpen, messages, unreadMessagesCount, unreadFilesCount, width, isResizing } = state['features/chat'];
|
||||
const { unreadPollsCount } = state['features/polls'];
|
||||
const _localParticipant = getLocalParticipant(state);
|
||||
const { reducedUI } = state['features/base/responsive-ui'];
|
||||
|
||||
return {
|
||||
_isModal: window.innerWidth <= SMALL_WIDTH_THRESHOLD,
|
||||
@@ -633,6 +644,7 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
_isFileSharingTabEnabled: isFileSharingEnabled(state),
|
||||
_focusedTab: getFocusedTab(state),
|
||||
_messages: messages,
|
||||
_reducedUI: reducedUI,
|
||||
_unreadMessagesCount: unreadMessagesCount,
|
||||
_unreadPollsCount: unreadPollsCount,
|
||||
_unreadFilesCount: unreadFilesCount,
|
||||
|
||||
@@ -90,6 +90,11 @@ interface IProps extends AbstractProps, WithTranslation {
|
||||
*/
|
||||
_overflowDrawer: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the UI is reduced.
|
||||
*/
|
||||
_reducedUI: boolean;
|
||||
|
||||
/**
|
||||
* Name for this conference room.
|
||||
*/
|
||||
@@ -226,12 +231,45 @@ class Conference extends AbstractConference<IProps, any> {
|
||||
_layoutClassName,
|
||||
_notificationsVisible,
|
||||
_overflowDrawer,
|
||||
_reducedUI,
|
||||
_showLobby,
|
||||
_showPrejoin,
|
||||
_showVisitorsQueue,
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
if (_reducedUI) {
|
||||
return (
|
||||
<div
|
||||
id = 'layout_wrapper'
|
||||
onMouseEnter = { this._onMouseEnter }
|
||||
onMouseLeave = { this._onMouseLeave }
|
||||
onMouseMove = { this._onMouseMove }
|
||||
ref = { this._setBackground }>
|
||||
<Chat />
|
||||
<div
|
||||
className = { _layoutClassName }
|
||||
id = 'videoconference_page'
|
||||
onMouseMove = { isMobileBrowser() ? undefined : this._onShowToolbar }>
|
||||
<ConferenceInfo />
|
||||
<Notice />
|
||||
<div
|
||||
id = 'videospace'
|
||||
onTouchStart = { this._onVideospaceTouchStart }>
|
||||
<LargeVideo />
|
||||
</div>
|
||||
<span
|
||||
aria-level = { 1 }
|
||||
className = 'sr-only'
|
||||
role = 'heading'>
|
||||
{ t('toolbar.accessibilityLabel.heading') }
|
||||
</span>
|
||||
<Toolbox />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id = 'layout_wrapper'
|
||||
@@ -418,6 +456,7 @@ class Conference extends AbstractConference<IProps, any> {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const { backgroundAlpha, mouseMoveCallbackInterval } = state['features/base/config'];
|
||||
const { overflowDrawer } = state['features/toolbox'];
|
||||
const { reducedUI } = state['features/base/responsive-ui'];
|
||||
|
||||
return {
|
||||
...abstractMapStateToProps(state),
|
||||
@@ -426,6 +465,7 @@ function _mapStateToProps(state: IReduxState) {
|
||||
_layoutClassName: LAYOUT_CLASSNAMES[getCurrentLayout(state) ?? ''],
|
||||
_mouseMoveCallbackInterval: mouseMoveCallbackInterval,
|
||||
_overflowDrawer: overflowDrawer,
|
||||
_reducedUI: reducedUI,
|
||||
_roomName: getConferenceNameForTitle(state),
|
||||
_showLobby: getIsLobbyVisible(state),
|
||||
_showPrejoin: isPrejoinPageVisible(state),
|
||||
|
||||
@@ -34,6 +34,11 @@ interface IProps {
|
||||
autoHide?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the UI is reduced.
|
||||
*/
|
||||
_reducedUI: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the component should be visible or not.
|
||||
*/
|
||||
@@ -194,6 +199,12 @@ class ConferenceInfo extends Component<IProps> {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
override render() {
|
||||
const { _reducedUI } = this.props;
|
||||
|
||||
if (_reducedUI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className = 'details-container'
|
||||
@@ -217,9 +228,12 @@ class ConferenceInfo extends Component<IProps> {
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const { reducedUI } = state['features/base/responsive-ui'];
|
||||
|
||||
return {
|
||||
_conferenceInfo: getConferenceInfo(state),
|
||||
_reducedUI: reducedUI,
|
||||
_visible: isToolboxVisible(state),
|
||||
_conferenceInfo: getConferenceInfo(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
const Notice = () => {
|
||||
const message = useSelector((state: IReduxState) => state['features/base/config'].noticeMessage);
|
||||
const { reducedUI } = useSelector((state: IReduxState) => state['features/base/responsive-ui']);
|
||||
const { classes } = useStyles();
|
||||
|
||||
if (!message) {
|
||||
if (!message || reducedUI) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import {
|
||||
getJwtDisabledButtons,
|
||||
getVisibleButtons,
|
||||
getVisibleButtonsForReducedUI,
|
||||
isButtonEnabled,
|
||||
isToolboxVisible
|
||||
} from '../../functions.web';
|
||||
@@ -82,8 +83,7 @@ export default function Toolbox({
|
||||
const isNarrowLayout = useSelector((state: IReduxState) => state['features/base/responsive-ui'].isNarrowLayout);
|
||||
const videoSpaceWidth = useSelector((state: IReduxState) => state['features/base/responsive-ui'].videoSpaceWidth);
|
||||
const isModerator = useSelector(isLocalParticipantModerator);
|
||||
const customToolbarButtons = useSelector(
|
||||
(state: IReduxState) => state['features/base/config'].customToolbarButtons);
|
||||
const customToolbarButtons = useSelector((state: IReduxState) => state['features/base/config'].customToolbarButtons);
|
||||
const iAmRecorder = useSelector((state: IReduxState) => state['features/base/config'].iAmRecorder);
|
||||
const iAmSipGateway = useSelector((state: IReduxState) => state['features/base/config'].iAmSipGateway);
|
||||
const overflowDrawer = useSelector((state: IReduxState) => state['features/toolbox'].overflowDrawer);
|
||||
@@ -110,6 +110,8 @@ export default function Toolbox({
|
||||
const toolbarVisible = useSelector(isToolboxVisible);
|
||||
const mainToolbarButtonsThresholds
|
||||
= useSelector((state: IReduxState) => state['features/toolbox'].mainToolbarButtonsThresholds);
|
||||
const { reducedUImainToolbarButtons } = useSelector((state: IReduxState) => state['features/base/config']);
|
||||
const reducedUI = useSelector((state: IReduxState) => state['features/base/responsive-ui'].reducedUI);
|
||||
const allButtons = useToolboxButtons(customToolbarButtons);
|
||||
const isMobile = isMobileBrowser();
|
||||
const endConferenceSupported = Boolean(conference?.isEndConferenceSupported() && isModerator);
|
||||
@@ -233,7 +235,7 @@ export default function Toolbox({
|
||||
const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
|
||||
const containerClassName = `toolbox-content${isMobile || isNarrowLayout ? ' toolbox-content-mobile' : ''}`;
|
||||
|
||||
const { mainMenuButtons, overflowMenuButtons } = getVisibleButtons({
|
||||
const normalUIButtons = getVisibleButtons({
|
||||
allButtons,
|
||||
buttonsWithNotifyClick,
|
||||
toolbarButtons: toolbarButtonsToUse,
|
||||
@@ -241,6 +243,20 @@ export default function Toolbox({
|
||||
jwtDisabledButtons,
|
||||
mainToolbarButtonsThresholds
|
||||
});
|
||||
|
||||
const reducedUIButtons = getVisibleButtonsForReducedUI({
|
||||
allButtons,
|
||||
buttonsWithNotifyClick,
|
||||
jwtDisabledButtons,
|
||||
reducedUImainToolbarButtons,
|
||||
});
|
||||
|
||||
const mainMenuButtons = reducedUI
|
||||
? reducedUIButtons.mainMenuButtons
|
||||
: normalUIButtons.mainMenuButtons;
|
||||
const overflowMenuButtons = reducedUI
|
||||
? []
|
||||
: normalUIButtons.overflowMenuButtons;
|
||||
const raiseHandInOverflowMenu = overflowMenuButtons.some(({ key }) => key === 'raisehand');
|
||||
const showReactionsInOverflowMenu = _shouldDisplayReactionsButtons
|
||||
&& (
|
||||
|
||||
@@ -12,6 +12,8 @@ export const DUMMY_9_BUTTONS_THRESHOLD_VALUE = Symbol('9_BUTTONS_THRESHOLD_VALUE
|
||||
*/
|
||||
export const DUMMY_10_BUTTONS_THRESHOLD_VALUE = Symbol('10_BUTTONS_THRESHOLD_VALUE');
|
||||
|
||||
export const DEFAULT_REDUCED_UI_MAIN_TOOLBAR_BUTTONS = [ 'microphone', 'camera' ];
|
||||
|
||||
/**
|
||||
* Thresholds for displaying toolbox buttons.
|
||||
*/
|
||||
|
||||
@@ -6,9 +6,9 @@ import { IGUMPendingState } from '../base/media/types';
|
||||
import { isScreenMediaShared } from '../screen-share/functions';
|
||||
import { isWhiteboardVisible } from '../whiteboard/functions';
|
||||
|
||||
import { MAIN_TOOLBAR_BUTTONS_PRIORITY, TOOLBAR_TIMEOUT } from './constants';
|
||||
import { DEFAULT_REDUCED_UI_MAIN_TOOLBAR_BUTTONS, MAIN_TOOLBAR_BUTTONS_PRIORITY, TOOLBAR_TIMEOUT } from './constants';
|
||||
import { isButtonEnabled } from './functions.any';
|
||||
import { IGetVisibleButtonsParams, IToolboxButton, NOTIFY_CLICK_MODE } from './types';
|
||||
import { IGetVisibleButtonsForReducedUIParams, IGetVisibleButtonsParams, IToolboxButton, NOTIFY_CLICK_MODE } from './types';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
@@ -201,6 +201,41 @@ export function getVisibleButtons({
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns buttons that need to be rendered for reduced UI mode.
|
||||
*
|
||||
* @param {IGetVisibleButtonsForReducedUIParams} params - The parameters needed to extract the visible buttons.
|
||||
* @returns {Object} - The visible buttons for reduced ui.
|
||||
*/
|
||||
export function getVisibleButtonsForReducedUI({
|
||||
allButtons,
|
||||
buttonsWithNotifyClick,
|
||||
jwtDisabledButtons,
|
||||
reducedUImainToolbarButtons
|
||||
}: IGetVisibleButtonsForReducedUIParams) {
|
||||
setButtonsNotifyClickMode(allButtons, buttonsWithNotifyClick);
|
||||
|
||||
if (!Array.isArray(reducedUImainToolbarButtons) || reducedUImainToolbarButtons.length === 0) {
|
||||
const defaultButtons = DEFAULT_REDUCED_UI_MAIN_TOOLBAR_BUTTONS.map(key => allButtons[key]);
|
||||
|
||||
return {
|
||||
mainMenuButtons: defaultButtons
|
||||
};
|
||||
}
|
||||
|
||||
const filteredButtons = reducedUImainToolbarButtons.filter(key =>
|
||||
typeof key !== 'undefined'
|
||||
&& !jwtDisabledButtons.includes(key)
|
||||
&& isButtonEnabled(key, reducedUImainToolbarButtons)
|
||||
&& allButtons[key]);
|
||||
|
||||
const mainMenuButtons = filteredButtons.map(key => allButtons[key]);
|
||||
|
||||
return {
|
||||
mainMenuButtons
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of participant menu buttons that have that notify the api when clicked.
|
||||
*
|
||||
|
||||
@@ -107,3 +107,10 @@ export interface IGetVisibleButtonsParams {
|
||||
mainToolbarButtonsThresholds: IMainToolbarButtonThresholds;
|
||||
toolbarButtons: string[];
|
||||
}
|
||||
|
||||
export interface IGetVisibleButtonsForReducedUIParams {
|
||||
allButtons: { [key: string]: IToolboxButton; };
|
||||
buttonsWithNotifyClick: Map<string, NOTIFY_CLICK_MODE>;
|
||||
jwtDisabledButtons: string[];
|
||||
reducedUImainToolbarButtons?: string[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user