mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-16 23:17:46 +00:00
Currently if a button in the main toolbar is not visible, the button is not replaced by another button from the overflow menu.
252 lines
8.5 KiB
TypeScript
252 lines
8.5 KiB
TypeScript
import { IReduxState } from '../app/types';
|
|
import { hasAvailableDevices } from '../base/devices/functions';
|
|
import { MEET_FEATURES } from '../base/jwt/constants';
|
|
import { isJwtFeatureEnabled } from '../base/jwt/functions';
|
|
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 { IMainToolbarButtonThresholds, IToolboxButton, NOTIFY_CLICK_MODE } from './types';
|
|
|
|
export * from './functions.any';
|
|
|
|
/**
|
|
* Helper for getting the height of the toolbox.
|
|
*
|
|
* @returns {number} The height of the toolbox.
|
|
*/
|
|
export function getToolboxHeight() {
|
|
const toolbox = document.getElementById('new-toolbox');
|
|
|
|
return toolbox?.clientHeight || 0;
|
|
}
|
|
|
|
/**
|
|
* Checks if the specified button is enabled.
|
|
*
|
|
* @param {string} buttonName - The name of the button. See {@link interfaceConfig}.
|
|
* @param {Object|Array<string>} state - The redux state or the array with the enabled buttons.
|
|
* @returns {boolean} - True if the button is enabled and false otherwise.
|
|
*/
|
|
export function isButtonEnabled(buttonName: string, state: IReduxState | Array<string>) {
|
|
const buttons = Array.isArray(state) ? state : state['features/toolbox'].toolbarButtons || [];
|
|
|
|
return buttons.includes(buttonName);
|
|
}
|
|
|
|
/**
|
|
* Indicates if the toolbox is visible or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean} - True to indicate that the toolbox is visible, false -
|
|
* otherwise.
|
|
*/
|
|
export function isToolboxVisible(state: IReduxState) {
|
|
const { iAmRecorder, iAmSipGateway, toolbarConfig } = state['features/base/config'];
|
|
const { alwaysVisible } = toolbarConfig || {};
|
|
const {
|
|
timeoutID,
|
|
visible
|
|
} = state['features/toolbox'];
|
|
const { audioSettingsVisible, videoSettingsVisible } = state['features/settings'];
|
|
const whiteboardVisible = isWhiteboardVisible(state);
|
|
|
|
return Boolean(!iAmRecorder && !iAmSipGateway
|
|
&& (
|
|
timeoutID
|
|
|| visible
|
|
|| alwaysVisible
|
|
|| audioSettingsVisible
|
|
|| videoSettingsVisible
|
|
|| whiteboardVisible
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Indicates if the audio settings button is disabled or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function isAudioSettingsButtonDisabled(state: IReduxState) {
|
|
|
|
return !(hasAvailableDevices(state, 'audioInput')
|
|
|| hasAvailableDevices(state, 'audioOutput'))
|
|
|| state['features/base/config'].startSilent;
|
|
}
|
|
|
|
/**
|
|
* Indicates if the desktop share button is disabled or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function isDesktopShareButtonDisabled(state: IReduxState) {
|
|
const { muted, unmuteBlocked } = state['features/base/media'].video;
|
|
const videoOrShareInProgress = !muted || isScreenMediaShared(state);
|
|
const enabledInJwt = isJwtFeatureEnabled(state, MEET_FEATURES.SCREEN_SHARING, true, true);
|
|
|
|
return !enabledInJwt || (unmuteBlocked && !videoOrShareInProgress);
|
|
}
|
|
|
|
/**
|
|
* Indicates if the video settings button is disabled or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function isVideoSettingsButtonDisabled(state: IReduxState) {
|
|
return !hasAvailableDevices(state, 'videoInput');
|
|
}
|
|
|
|
/**
|
|
* Indicates if the video mute button is disabled or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function isVideoMuteButtonDisabled(state: IReduxState) {
|
|
const { muted, unmuteBlocked, gumPending } = state['features/base/media'].video;
|
|
|
|
return !hasAvailableDevices(state, 'videoInput')
|
|
|| (unmuteBlocked && Boolean(muted))
|
|
|| gumPending !== IGUMPendingState.NONE;
|
|
}
|
|
|
|
/**
|
|
* If an overflow drawer should be displayed or not.
|
|
* This is usually done for mobile devices or on narrow screens.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function showOverflowDrawer(state: IReduxState) {
|
|
return state['features/toolbox'].overflowDrawer;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the overflow menu button is displayed and false otherwise.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean} - True if the overflow menu button is displayed and false otherwise.
|
|
*/
|
|
export function showOverflowMenu(state: IReduxState) {
|
|
return state['features/toolbox'].overflowMenuVisible;
|
|
}
|
|
|
|
/**
|
|
* Indicates whether the toolbox is enabled or not.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {boolean}
|
|
*/
|
|
export function isToolboxEnabled(state: IReduxState) {
|
|
return state['features/toolbox'].enabled;
|
|
}
|
|
|
|
/**
|
|
* Returns the toolbar timeout from config or the default value.
|
|
*
|
|
* @param {IReduxState} state - The state from the Redux store.
|
|
* @returns {number} - Toolbar timeout in milliseconds.
|
|
*/
|
|
export function getToolbarTimeout(state: IReduxState) {
|
|
const { toolbarConfig } = state['features/base/config'];
|
|
|
|
return toolbarConfig?.timeout || TOOLBAR_TIMEOUT;
|
|
}
|
|
|
|
/**
|
|
* Sets the notify click mode for the buttons.
|
|
*
|
|
* @param {Object} buttons - The list of toolbar buttons.
|
|
* @param {Map} buttonsWithNotifyClick - The buttons notify click configuration.
|
|
* @returns {void}
|
|
*/
|
|
function setButtonsNotifyClickMode(buttons: Object, buttonsWithNotifyClick: Map<string, NOTIFY_CLICK_MODE>) {
|
|
if (typeof APP === 'undefined' || (buttonsWithNotifyClick?.size ?? 0) <= 0) {
|
|
return;
|
|
}
|
|
|
|
Object.values(buttons).forEach((button: any) => {
|
|
if (typeof button === 'object') {
|
|
button.notifyMode = buttonsWithNotifyClick.get(button.key);
|
|
}
|
|
});
|
|
}
|
|
|
|
interface IGetVisibleButtonsParams {
|
|
allButtons: { [key: string]: IToolboxButton; };
|
|
buttonsWithNotifyClick: Map<string, NOTIFY_CLICK_MODE>;
|
|
clientWidth: number;
|
|
jwtDisabledButtons: string[];
|
|
mainToolbarButtonsThresholds: IMainToolbarButtonThresholds;
|
|
toolbarButtons: string[];
|
|
}
|
|
|
|
/**
|
|
* Returns all buttons that need to be rendered.
|
|
*
|
|
* @param {IGetVisibleButtonsParams} params - The parameters needed to extract the visible buttons.
|
|
* @returns {Object} - The visible buttons arrays .
|
|
*/
|
|
export function getVisibleButtons({
|
|
allButtons,
|
|
buttonsWithNotifyClick,
|
|
toolbarButtons,
|
|
clientWidth,
|
|
jwtDisabledButtons,
|
|
mainToolbarButtonsThresholds
|
|
}: IGetVisibleButtonsParams) {
|
|
setButtonsNotifyClickMode(allButtons, buttonsWithNotifyClick);
|
|
|
|
const filteredButtons = Object.keys(allButtons).filter(key =>
|
|
typeof key !== 'undefined' // filter invalid buttons that may be comming from config.mainToolbarButtons
|
|
// override
|
|
&& !jwtDisabledButtons.includes(key)
|
|
&& isButtonEnabled(key, toolbarButtons));
|
|
|
|
|
|
const { order } = mainToolbarButtonsThresholds.find(({ width }) => clientWidth > width)
|
|
|| mainToolbarButtonsThresholds[mainToolbarButtonsThresholds.length - 1];
|
|
|
|
const mainToolbarButtonKeysOrder = [
|
|
...order.filter(key => filteredButtons.includes(key)),
|
|
...MAIN_TOOLBAR_BUTTONS_PRIORITY.filter(key => !order.includes(key) && filteredButtons.includes(key)),
|
|
...filteredButtons.filter(key => !order.includes(key) && !MAIN_TOOLBAR_BUTTONS_PRIORITY.includes(key))
|
|
];
|
|
|
|
const mainButtonsKeys = mainToolbarButtonKeysOrder.slice(0, order.length);
|
|
const overflowMenuButtons = filteredButtons.reduce((acc, key) => {
|
|
if (!mainButtonsKeys.includes(key)) {
|
|
acc.push(allButtons[key]);
|
|
}
|
|
|
|
return acc;
|
|
}, [] as IToolboxButton[]);
|
|
|
|
// if we have 1 button in the overflow menu it is better to directly display it in the main toolbar by replacing
|
|
// the "More" menu button with it.
|
|
if (overflowMenuButtons.length === 1) {
|
|
const button = overflowMenuButtons.shift()?.key;
|
|
|
|
button && mainButtonsKeys.push(button);
|
|
}
|
|
|
|
return {
|
|
mainMenuButtons: mainButtonsKeys.map(key => allButtons[key]),
|
|
overflowMenuButtons
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Returns the list of participant menu buttons that have that notify the api when clicked.
|
|
*
|
|
* @param {Object} state - The redux state.
|
|
* @returns {Map<string, NOTIFY_CLICK_MODE>} - The list of participant menu buttons.
|
|
*/
|
|
export function getParticipantMenuButtonsWithNotifyClick(state: IReduxState): Map<string, NOTIFY_CLICK_MODE> {
|
|
return state['features/toolbox'].participantMenuButtonsWithNotifyClick;
|
|
}
|