diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
index 47d5f9d34b..b70a205db1 100755
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
@@ -14,7 +14,7 @@ import browserInfo from '/imports/utils/browserInfo';
import deviceInfo from '/imports/utils/deviceInfo';
import { PANELS, ACTIONS } from '../layout/enums';
import { isEqual } from 'radash';
-import LeaveMeetingButton from './leave-meeting-button/component';
+import LeaveMeetingButtonContainer from './leave-meeting-button/container';
const intlMessages = defineMessages({
toggleUserListLabel: {
@@ -37,10 +37,6 @@ const intlMessages = defineMessages({
id: 'app.createBreakoutRoom.room',
description: 'default breakout room name',
},
- leaveMeetingLabel: {
- id: 'app.navBar.leaveMeetingBtnLabel',
- description: 'Leave meeting button label',
- },
});
const propTypes = {
@@ -253,7 +249,7 @@ class NavBar extends Component {
{ConnectionStatusService.isEnabled() ? : null}
{isDirectLeaveButtonEnabled && isMeteorConnected
- ?
+ ?
: null}
{
- const leaveSession = () => {
+const defaultProps = {
+ amIModerator: false,
+ isBreakoutRoom: false,
+ isDropdownOpen: false,
+};
+
+class LeaveMeetingButton extends PureComponent {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ isEndMeetingConfirmationModalOpen: false,
+ };
+
+ // Set the logout code to 680 because it's not a real code and can be matched on the other side
+ this.LOGOUT_CODE = '680';
+
+ this.setEndMeetingConfirmationModalIsOpen = this.setEndMeetingConfirmationModalIsOpen.bind(this);
+ this.leaveSession = this.leaveSession.bind(this);
+ }
+
+ setEndMeetingConfirmationModalIsOpen(value) {
+ this.setState({isEndMeetingConfirmationModalOpen: value})
+ }
+
+ leaveSession() {
makeCall('userLeftMeeting');
// we don't check askForFeedbackOnLogout here,
// it is checked in meeting-ended component
- Session.set('codeError', LOGOUT_CODE);
- };
+ Session.set('codeError', this.LOGOUT_CODE);
+ }
+
+ renderMenuItems() {
+ const {
+ intl, amIModerator, isBreakoutRoom, isMeteorConnected,
+ } = this.props;
- return (
- leaveSession()}
- icon="logout"
- />
- );
-};
+ const allowedToEndMeeting = amIModerator && !isBreakoutRoom;
+
+ const { allowLogout: allowLogoutSetting } = Meteor.settings.public.app;
+
+ this.menuItems = [];
+
+ if (allowLogoutSetting && isMeteorConnected) {
+ this.menuItems.push(
+ {
+ key: 'list-item-logout',
+ dataTest: 'logout-button',
+ icon: 'logout',
+ label: intl.formatMessage(intlMessages.leaveSessionLabel),
+ description: intl.formatMessage(intlMessages.leaveSessionDesc),
+ onClick: () => this.leaveSession(),
+ },
+ );
+ }
+
+ if (allowedToEndMeeting && isMeteorConnected) {
+ const customStyles = { background: colorDanger, color: colorWhite };
+
+ this.menuItems.push(
+ {
+ key: 'list-item-end-meeting',
+ icon: 'application',
+ label: intl.formatMessage(intlMessages.endMeetingLabel),
+ description: intl.formatMessage(intlMessages.endMeetingDesc),
+ customStyles,
+ onClick: () => this.setEndMeetingConfirmationModalIsOpen(true),
+ },
+ );
+ }
+
+ return this.menuItems;
+ }
+
+ renderModal(isOpen, setIsOpen, priority, Component, otherOptions) {
+ return isOpen ? setIsOpen(false),
+ priority,
+ setIsOpen,
+ isOpen
+ }}
+ /> : null
+ }
+
+ render() {
+ const {
+ intl,
+ isDropdownOpen,
+ isMobile,
+ isRTL,
+ } = this.props;
+
+ const { isEndMeetingConfirmationModalOpen } = this.state;
+
+ const customStyles = { top: '1rem' };
+
+ return (
+ <>
+ null}
+ />
+ )}
+ actions={this.renderMenuItems()}
+ opts={{
+ id: 'app-leave-meeting-menu',
+ keepMounted: true,
+ transitionDuration: 0,
+ elevation: 3,
+ getcontentanchorel: null,
+ fullwidth: 'true',
+ anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'left' : 'right' },
+ transformorigin: { vertical: 'top', horizontal: isRTL ? 'left' : 'right' },
+ }}
+ />
+ {this.renderModal(isEndMeetingConfirmationModalOpen, this.setEndMeetingConfirmationModalIsOpen,
+ "low", EndMeetingConfirmationContainer)}
+ >
+ );
+ }
+}
LeaveMeetingButton.propTypes = propTypes;
-
-export default LeaveMeetingButton;
+LeaveMeetingButton.defaultProps = defaultProps;
+export default injectIntl(LeaveMeetingButton);
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/container.jsx
new file mode 100644
index 0000000000..f175b65efb
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/container.jsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { withTracker } from 'meteor/react-meteor-data';
+import deviceInfo from '/imports/utils/deviceInfo';
+import LeaveMeetingButton from './component';
+import { meetingIsBreakout } from '/imports/ui/components/app/service';
+import { layoutSelectInput, layoutSelect } from '../../layout/context';
+import { SMALL_VIEWPORT_BREAKPOINT } from '../../layout/enums';
+
+const LeaveMeetingButtonContainer = (props) => {
+ const { width: browserWidth } = layoutSelectInput((i) => i.browser);
+ const isMobile = browserWidth <= SMALL_VIEWPORT_BREAKPOINT;
+ const isRTL = layoutSelect((i) => i.isRTL);
+
+ return (
+
+ );
+};
+
+export default withTracker((props) => {
+ return {
+ amIModerator: props.amIModerator,
+ isMobile: deviceInfo.isMobile,
+ isMeteorConnected: Meteor.status().connected,
+ isBreakoutRoom: meetingIsBreakout(),
+ isDropdownOpen: Session.get('dropdownOpen'),
+ };
+})(LeaveMeetingButtonContainer);
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/styles.js b/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/styles.js
index 1382548cc3..c40e98fc58 100644
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/styles.js
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/leave-meeting-button/styles.js
@@ -1,12 +1,22 @@
import styled from 'styled-components';
+import { smallOnly } from '/imports/ui/stylesheets/styled-components/breakpoints';
import Button from '/imports/ui/components/common/button/component';
const LeaveButton = styled(Button)`
- border-radius: 1.1rem;
- margin: 0.5rem;
- font-size: 1rem;
- line-height: 1.1rem;
- font-weight: 400;
+ ${({ state }) => state === 'open' && `
+ @media ${smallOnly} {
+ display: none;
+ }
+ `}
+
+ ${({ state }) => state === 'closed' && `
+ border-radius: 1.1rem;
+ margin: 0.5rem;
+ font-size: 1rem;
+ line-height: 1.1rem;
+ font-weight: 400;
+ z-index: 3;
+ `}
`;
export default {