bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/settings/component.jsx

320 lines
10 KiB
React
Raw Normal View History

import React, { Component } from 'react';
import ModalFullscreen from '/imports/ui/components/common/modal/fullscreen/component';
import { defineMessages, injectIntl } from 'react-intl';
import DataSaving from '/imports/ui/components/settings/submenus/data-saving/component';
import Application from '/imports/ui/components/settings/submenus/application/component';
2020-03-19 22:19:40 +08:00
import Notification from '/imports/ui/components/settings/submenus/notification/component';
2023-02-17 21:17:19 +08:00
import { clone } from 'radash';
import PropTypes from 'prop-types';
2021-11-05 20:10:12 +08:00
import Styled from './styles';
2022-09-09 01:25:29 +08:00
import { formatLocaleCode } from '/imports/utils/string-utils';
import { setUseCurrentLocale } from '../../core/local-states/useCurrentLocale';
2017-01-27 23:41:11 +08:00
2017-04-18 02:19:27 +08:00
const intlMessages = defineMessages({
appTabLabel: {
id: 'app.settings.applicationTab.label',
description: 'label for application tab',
},
audioTabLabel: {
id: 'app.settings.audioTab.label',
description: 'label for audio tab',
},
videoTabLabel: {
id: 'app.settings.videoTab.label',
description: 'label for video tab',
},
usersTabLabel: {
id: 'app.settings.usersTab.label',
description: 'label for participants tab',
},
2017-04-28 23:56:27 +08:00
SettingsLabel: {
id: 'app.settings.main.label',
description: 'General settings label',
},
CancelLabel: {
id: 'app.settings.main.cancel.label',
description: 'Discard the changes and close the settings menu',
},
CancelLabelDesc: {
id: 'app.settings.main.cancel.label.description',
description: 'Settings modal cancel button description',
},
2017-04-28 23:56:27 +08:00
SaveLabel: {
id: 'app.settings.main.save.label',
description: 'Save the changes and close the settings menu',
},
SaveLabelDesc: {
id: 'app.settings.main.save.label.description',
description: 'Settings modal save button label',
},
notificationLabel: {
id: 'app.submenu.notification.SectionTitle', // set menu label identical to section title
description: 'label for notification tab',
},
2018-02-01 19:31:17 +08:00
dataSavingLabel: {
id: 'app.settings.dataSavingTab.label',
2018-01-30 19:20:51 +08:00
description: 'label for data savings tab',
},
2019-05-08 23:50:00 +08:00
savedAlertLabel: {
id: 'app.settings.save-notification.label',
description: 'label shown in toast when settings are saved',
},
2021-05-01 03:06:28 +08:00
on: {
id: 'app.switch.onLabel',
description: 'label for toggle switch on state',
},
off: {
id: 'app.switch.offLabel',
description: 'label for toggle switch off state',
},
2017-04-18 02:19:27 +08:00
});
2017-01-27 23:41:11 +08:00
const propTypes = {
intl: PropTypes.shape({
formatMessage: PropTypes.func.isRequired,
}).isRequired,
dataSaving: PropTypes.shape({
viewParticipantsWebcams: PropTypes.bool,
viewScreenshare: PropTypes.bool,
}).isRequired,
application: PropTypes.shape({
chatAudioAlerts: PropTypes.bool,
chatPushAlerts: PropTypes.bool,
2019-11-06 04:08:26 +08:00
userJoinAudioAlerts: PropTypes.bool,
2021-08-21 01:15:29 +08:00
userLeaveAudioAlerts: PropTypes.bool,
userLeavePushAlerts: PropTypes.bool,
guestWaitingAudioAlerts: PropTypes.bool,
guestWaitingPushAlerts: PropTypes.bool,
paginationEnabled: PropTypes.bool,
2022-04-09 03:05:29 +08:00
darkTheme: PropTypes.bool,
fallbackLocale: PropTypes.string,
fontSize: PropTypes.string,
locale: PropTypes.string,
microphoneConstraints: PropTypes.objectOf(Object),
}).isRequired,
updateSettings: PropTypes.func.isRequired,
availableLocales: PropTypes.objectOf(PropTypes.array).isRequired,
2021-05-01 03:06:28 +08:00
showToggleLabel: PropTypes.bool.isRequired,
isReactionsEnabled: PropTypes.bool.isRequired,
2017-01-27 23:41:11 +08:00
};
2016-05-06 05:14:39 +08:00
2017-04-18 02:19:27 +08:00
class Settings extends Component {
2017-10-11 06:08:51 +08:00
static setHtmlFontSize(size) {
document.getElementsByTagName('html')[0].style.fontSize = size;
}
2016-05-06 05:14:39 +08:00
constructor(props) {
super(props);
2017-12-19 19:13:37 +08:00
const {
dataSaving, application, selectedTab,
2017-12-19 19:13:37 +08:00
} = props;
2017-03-09 22:34:33 +08:00
2017-01-27 23:41:11 +08:00
this.state = {
current: {
2023-02-17 21:17:19 +08:00
dataSaving: clone(dataSaving),
application: clone(application),
2017-01-27 23:41:11 +08:00
},
saved: {
2023-02-17 21:17:19 +08:00
dataSaving: clone(dataSaving),
application: clone(application),
},
2023-02-17 21:17:19 +08:00
selectedTab: Number.isFinite(selectedTab) && selectedTab >= 0 && selectedTab <= 2
2021-10-19 04:52:59 +08:00
? selectedTab
: 0,
2016-05-06 05:14:39 +08:00
};
2017-03-29 02:41:48 +08:00
this.updateSettings = props.updateSettings;
2017-01-27 23:41:11 +08:00
this.handleUpdateSettings = this.handleUpdateSettings.bind(this);
this.handleSelectTab = this.handleSelectTab.bind(this);
2021-05-01 03:06:28 +08:00
this.displaySettingsStatus = this.displaySettingsStatus.bind(this);
2016-07-12 01:43:42 +08:00
}
2020-05-14 01:05:59 +08:00
componentDidMount() {
const { availableLocales } = this.props;
availableLocales.then((locales) => {
this.setState({ allLocales: locales.filter((locale) => locale?.name !== 'index') });
2017-04-06 20:36:59 +08:00
});
}
2017-01-27 23:41:11 +08:00
handleUpdateSettings(key, newSettings) {
2017-06-03 03:25:02 +08:00
const settings = this.state;
2017-01-27 23:41:11 +08:00
settings.current[key] = newSettings;
this.setState(settings);
2017-01-27 23:41:11 +08:00
}
handleSelectTab(tab) {
2017-01-27 23:41:11 +08:00
this.setState({
selectedTab: tab,
});
}
displaySettingsStatus(status, textOnly = false) {
2021-05-01 03:06:28 +08:00
const { intl } = this.props;
if (textOnly) {
return status ? intl.formatMessage(intlMessages.on)
2023-05-17 01:39:56 +08:00
: intl.formatMessage(intlMessages.off);
}
2021-05-01 03:06:28 +08:00
return (
<Styled.ToggleLabel aria-hidden>
2021-05-01 03:06:28 +08:00
{status ? intl.formatMessage(intlMessages.on)
: intl.formatMessage(intlMessages.off)}
2021-11-05 20:10:12 +08:00
</Styled.ToggleLabel>
2021-05-01 03:06:28 +08:00
);
}
2017-01-27 23:41:11 +08:00
renderModalContent() {
const {
intl,
isModerator,
2022-02-26 01:56:03 +08:00
isPresenter,
showGuestNotification,
2021-05-01 03:06:28 +08:00
showToggleLabel,
2021-08-05 19:03:24 +08:00
layoutContextDispatch,
2021-06-22 04:28:51 +08:00
selectedLayout,
isScreenSharingEnabled,
isVideoEnabled,
isReactionsEnabled,
paginationToggleEnabled,
} = this.props;
const {
selectedTab,
current,
allLocales,
} = this.state;
const isDataSavingTabEnabled = isScreenSharingEnabled || isVideoEnabled;
2017-01-27 23:41:11 +08:00
return (
2021-11-05 20:10:12 +08:00
<Styled.SettingsTabs
onSelect={this.handleSelectTab}
selectedIndex={selectedTab}
2017-04-18 02:19:27 +08:00
role="presentation"
2017-01-27 23:41:11 +08:00
>
2021-11-05 20:10:12 +08:00
<Styled.SettingsTabList>
<Styled.SettingsTabSelector
2017-12-19 19:13:37 +08:00
aria-labelledby="appTab"
2021-11-05 20:10:12 +08:00
selectedClassName="is-selected"
2017-12-19 19:13:37 +08:00
>
2021-11-05 20:10:12 +08:00
<Styled.SettingsIcon iconName="application" />
2017-04-18 02:19:27 +08:00
<span id="appTab">{intl.formatMessage(intlMessages.appTabLabel)}</span>
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabSelector>
<Styled.SettingsTabSelector
selectedClassName="is-selected"
2020-03-19 22:19:40 +08:00
>
2021-11-05 20:10:12 +08:00
<Styled.SettingsIcon iconName="alert" />
<span id="notificationTab">{intl.formatMessage(intlMessages.notificationLabel)}</span>
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabSelector>
{isDataSavingTabEnabled
? (
<Styled.SettingsTabSelector
aria-labelledby="dataSavingTab"
selectedClassName="is-selected"
>
<Styled.SettingsIcon iconName="network" />
<span id="dataSaving">{intl.formatMessage(intlMessages.dataSavingLabel)}</span>
</Styled.SettingsTabSelector>
)
: null}
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabList>
<Styled.SettingsTabPanel selectedClassName="is-selected">
2017-03-09 22:34:33 +08:00
<Application
allLocales={allLocales}
2017-03-09 22:34:33 +08:00
handleUpdateSettings={this.handleUpdateSettings}
settings={current.application}
2021-05-01 03:06:28 +08:00
showToggleLabel={showToggleLabel}
displaySettingsStatus={this.displaySettingsStatus}
2021-08-05 19:03:24 +08:00
layoutContextDispatch={layoutContextDispatch}
2021-06-22 04:28:51 +08:00
selectedLayout={selectedLayout}
2022-02-26 01:56:03 +08:00
isPresenter={isPresenter}
isReactionsEnabled={isReactionsEnabled}
paginationToggleEnabled={paginationToggleEnabled}
2017-06-03 03:25:02 +08:00
/>
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabPanel>
<Styled.SettingsTabPanel selectedClassName="is-selected">
2020-03-19 22:19:40 +08:00
<Notification
handleUpdateSettings={this.handleUpdateSettings}
settings={current.application}
showGuestNotification={showGuestNotification}
2021-05-01 03:06:28 +08:00
showToggleLabel={showToggleLabel}
displaySettingsStatus={this.displaySettingsStatus}
{...{ isModerator }}
2020-03-19 22:19:40 +08:00
/>
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabPanel>
{isDataSavingTabEnabled
? (
<Styled.SettingsTabPanel selectedClassName="is-selected">
<DataSaving
settings={current.dataSaving}
handleUpdateSettings={this.handleUpdateSettings}
showToggleLabel={showToggleLabel}
displaySettingsStatus={this.displaySettingsStatus}
isScreenSharingEnabled={isScreenSharingEnabled}
isVideoEnabled={isVideoEnabled}
/>
</Styled.SettingsTabPanel>
)
: null}
2021-11-05 20:10:12 +08:00
</Styled.SettingsTabs>
2017-01-27 23:41:11 +08:00
);
}
2017-10-11 06:08:51 +08:00
render() {
const {
intl,
setIsOpen,
isOpen,
priority,
2024-01-30 21:03:11 +08:00
setLocalSettings,
} = this.props;
const {
current,
saved,
} = this.state;
2017-10-11 06:08:51 +08:00
return (
<ModalFullscreen
2017-10-11 06:08:51 +08:00
title={intl.formatMessage(intlMessages.SettingsLabel)}
confirm={{
callback: () => {
2024-01-30 21:03:11 +08:00
this.updateSettings(current, intlMessages.savedAlertLabel, setLocalSettings);
2022-09-09 01:25:29 +08:00
if (saved.application.locale !== current.application.locale) {
const { language } = formatLocaleCode(saved.application.locale);
2024-04-25 02:41:49 +08:00
const newLanguage = current.application.locale;
setUseCurrentLocale(newLanguage);
2022-09-09 01:25:29 +08:00
document.body.classList.remove(`lang-${language}`);
}
/* We need to use setIsOpen(false) here to prevent submenu state updates,
2018-04-17 23:06:19 +08:00
* from re-opening the modal.
*/
setIsOpen(false);
},
2017-10-11 06:08:51 +08:00
label: intl.formatMessage(intlMessages.SaveLabel),
description: intl.formatMessage(intlMessages.SaveLabelDesc),
}}
dismiss={{
callback: () => {
Settings.setHtmlFontSize(saved.application.fontSize);
document.getElementsByTagName('html')[0].lang = saved.application.locale;
setIsOpen(false);
},
2017-10-11 06:08:51 +08:00
label: intl.formatMessage(intlMessages.CancelLabel),
description: intl.formatMessage(intlMessages.CancelLabelDesc),
}}
{...{
isOpen,
priority,
}}
2017-10-11 06:08:51 +08:00
>
{this.renderModalContent()}
</ModalFullscreen>
2017-10-11 06:08:51 +08:00
);
}
2017-01-27 23:41:11 +08:00
}
2017-02-16 02:49:40 +08:00
Settings.propTypes = propTypes;
export default injectIntl(Settings);