feat(toolbox): Add polls and file sharing buttons to overflow menu

Adds dedicated buttons for polls and file sharing in the toolbar overflow menu, following the pattern of the CC button. Both buttons open the chat panel with their respective tab selected when clicked.
This commit is contained in:
Hristo Terezov
2025-10-28 16:30:31 -05:00
parent 3fd9ce5f11
commit e02c4e8f7f
9 changed files with 177 additions and 0 deletions

View File

@@ -1429,6 +1429,7 @@
"exitFullScreen": "Exit full screen",
"exitTileView": "Exit tile view",
"feedback": "Leave feedback",
"fileSharing": "File sharing",
"giphy": "Toggle GIPHY menu",
"hangup": "Leave the meeting",
"help": "Help",
@@ -1464,6 +1465,7 @@
"openReactionsMenu": "Open reactions menu",
"participants": "Participants",
"pip": "Enter Picture-in-Picture mode",
"polls": "Polls",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Raise your hand",

View File

@@ -220,6 +220,34 @@ export function openCCPanel() {
};
}
/**
* Opens the chat panel with polls tab active.
*
* @returns {Object} The redux action.
*/
export function openPollsPanel() {
return async (dispatch: IStore['dispatch']) => {
dispatch(setFocusedTab(ChatTabs.POLLS));
dispatch({
type: OPEN_CHAT
});
};
}
/**
* Opens the chat panel with file sharing tab active.
*
* @returns {Object} The redux action.
*/
export function openFileSharingPanel() {
return async (dispatch: IStore['dispatch']) => {
dispatch(setFocusedTab(ChatTabs.FILE_SHARING));
dispatch({
type: OPEN_CHAT
});
};
}
/**
* Initiates the sending of messages between a moderator and a lobby attendee.

View File

@@ -0,0 +1,45 @@
import { connect } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconShareDoc } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { openFileSharingPanel } from '../../../chat/actions.any';
import { isFileSharingEnabled } from '../../functions.any';
/**
* Component that renders a button to open the file sharing panel.
*
* @augments AbstractButton
*/
class FileSharingButton extends AbstractButton<AbstractButtonProps> {
override icon = IconShareDoc;
override label = 'toolbar.fileSharing';
override tooltip = 'toolbar.fileSharing';
/**
* Handles clicking the button to open the file sharing panel.
*
* @private
* @returns {void}
*/
override _handleClick() {
const { dispatch } = this.props;
dispatch(openFileSharingPanel());
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {IReduxState} state - The Redux state.
* @returns {Object} - Mapped props.
*/
function mapStateToProps(state: IReduxState) {
return {
visible: isFileSharingEnabled(state)
};
}
export default translate(connect(mapStateToProps)(FileSharingButton));

View File

@@ -0,0 +1,23 @@
import { useSelector } from 'react-redux';
import FileSharingButton from './components/web/FileSharingButton';
import { isFileSharingEnabled } from './functions.any';
const fileSharing = {
key: 'filesharing',
Content: FileSharingButton,
group: 2
};
/**
* A hook that returns the file sharing button if it is enabled and undefined otherwise.
*
* @returns {Object | undefined} - The file sharing button object or undefined.
*/
export function useFileSharingButton() {
const isEnabled = useSelector(isFileSharingEnabled);
if (isEnabled) {
return fileSharing;
}
}

View File

@@ -0,0 +1,45 @@
import { connect } from 'react-redux';
import { IReduxState } from '../../../app/types';
import { translate } from '../../../base/i18n/functions';
import { IconInfo } from '../../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { openPollsPanel } from '../../../chat/actions.any';
import { arePollsDisabled } from '../../../conference/functions.any';
/**
* Component that renders a button to open the polls panel.
*
* @augments AbstractButton
*/
class PollsButton extends AbstractButton<AbstractButtonProps> {
override icon = IconInfo;
override label = 'toolbar.polls';
override tooltip = 'toolbar.polls';
/**
* Handles clicking the button to open the polls panel.
*
* @private
* @returns {void}
*/
override _handleClick() {
const { dispatch } = this.props;
dispatch(openPollsPanel());
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {IReduxState} state - The Redux state.
* @returns {Object} - Mapped props.
*/
function mapStateToProps(state: IReduxState) {
return {
visible: !arePollsDisabled(state)
};
}
export default translate(connect(mapStateToProps)(PollsButton));

View File

@@ -0,0 +1,24 @@
import { useSelector } from 'react-redux';
import { arePollsDisabled } from '../conference/functions.any';
import PollsButton from './components/web/PollsButton';
const polls = {
key: 'polls',
Content: PollsButton,
group: 2
};
/**
* A hook that returns the polls button if it is enabled and undefined otherwise.
*
* @returns {Object | undefined} - The polls button object or undefined.
*/
export function usePollsButton() {
const isPollsDisabled = useSelector(arePollsDisabled);
if (!isPollsDisabled) {
return polls;
}
}

View File

@@ -151,6 +151,7 @@ export const TOOLBAR_BUTTONS: ToolbarButton[] = [
'embedmeeting',
'etherpad',
'feedback',
'filesharing',
'filmstrip',
'fullscreen',
'hangup',
@@ -163,6 +164,7 @@ export const TOOLBAR_BUTTONS: ToolbarButton[] = [
'mute-everyone',
'mute-video-everyone',
'participants-pane',
'polls',
'profile',
'raisehand',
'recording',

View File

@@ -17,6 +17,7 @@ import ChatButton from '../chat/components/web/ChatButton';
import { useEmbedButton } from '../embed-meeting/hooks';
import { useEtherpadButton } from '../etherpad/hooks';
import { useFeedbackButton } from '../feedback/hooks.web';
import { useFileSharingButton } from '../file-sharing/hooks.web';
import { setGifMenuVisibility } from '../gifs/actions';
import { isGifEnabled } from '../gifs/function.any';
import InviteButton from '../invite/components/add-people-dialog/web/InviteButton';
@@ -32,6 +33,7 @@ import {
isParticipantsPaneEnabled
} from '../participants-pane/functions';
import { useParticipantPaneButton } from '../participants-pane/hooks.web';
import { usePollsButton } from '../polls/hooks.web';
import { addReactionToBuffer } from '../reactions/actions.any';
import { toggleReactionsMenuVisibility } from '../reactions/actions.web';
import RaiseHandContainerButton from '../reactions/components/web/RaiseHandContainerButtons';
@@ -278,6 +280,8 @@ export function useToolboxButtons(
const participants = useParticipantPaneButton();
const tileview = useTileViewButton();
const cc = useClosedCaptionButton();
const polls = usePollsButton();
const filesharing = useFileSharingButton();
const recording = useRecordingButton();
const liveStreaming = useLiveStreamingButton();
const linktosalesforce = useLinkToSalesforceButton();
@@ -309,6 +313,8 @@ export function useToolboxButtons(
fullscreen: _fullscreen,
security,
closedcaptions: cc,
polls,
filesharing,
recording,
livestreaming: liveStreaming,
linktosalesforce,

View File

@@ -24,6 +24,7 @@ export type ToolbarButton = 'camera' |
'embedmeeting' |
'etherpad' |
'feedback' |
'filesharing' |
'filmstrip' |
'fullscreen' |
'hangup' |
@@ -38,6 +39,7 @@ export type ToolbarButton = 'camera' |
'noisesuppression' |
'overflowmenu' |
'participants-pane' |
'polls' |
'profile' |
'raisehand' |
'reactions' |