feat(notification-settings) Update Sounds tab in Settings Dialog (#12990)
Rename from Sounds to Notifications Move Notifications settings from More tab to this tab
This commit is contained in:
parent
d550254f31
commit
036286a1d6
|
@ -995,6 +995,7 @@
|
|||
"more": "More",
|
||||
"name": "Name",
|
||||
"noDevice": "None",
|
||||
"notifications": "Notifications",
|
||||
"participantJoined": "Participant Joined",
|
||||
"participantKnocking": "Participant entered lobby",
|
||||
"participantLeft": "Participant Left",
|
||||
|
@ -1005,7 +1006,6 @@
|
|||
"selectCamera": "Camera",
|
||||
"selectMic": "Microphone",
|
||||
"selfView": "Self view",
|
||||
"sounds": "Sounds",
|
||||
"speakers": "Speakers",
|
||||
"startAudioMuted": "Everyone starts muted",
|
||||
"startReactionsMuted": "Mute reaction sounds for everyone",
|
||||
|
|
|
@ -21,8 +21,8 @@ import { LogoutDialog, SettingsDialog } from './components';
|
|||
import {
|
||||
getModeratorTabProps,
|
||||
getMoreTabProps,
|
||||
getProfileTabProps,
|
||||
getSoundsTabProps
|
||||
getNotificationsTabProps,
|
||||
getProfileTabProps
|
||||
} from './functions';
|
||||
|
||||
/**
|
||||
|
@ -96,17 +96,6 @@ export function submitMoreTab(newState: any) {
|
|||
}));
|
||||
}
|
||||
|
||||
const enabledNotifications = newState.enabledNotifications;
|
||||
|
||||
if (enabledNotifications !== currentState.enabledNotifications) {
|
||||
dispatch(updateSettings({
|
||||
userSelectedNotifications: {
|
||||
...getState()['features/base/settings'].userSelectedNotifications,
|
||||
...enabledNotifications
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (newState.currentFramerate !== currentState.currentFramerate) {
|
||||
const frameRate = parseInt(newState.currentFramerate, 10);
|
||||
|
||||
|
@ -183,9 +172,9 @@ export function submitProfileTab(newState: any) {
|
|||
* @param {Object} newState - The new settings.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function submitSoundsTab(newState: any) {
|
||||
export function submitNotificationsTab(newState: any) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const currentState = getSoundsTabProps(getState());
|
||||
const currentState = getNotificationsTabProps(getState());
|
||||
const shouldNotUpdateReactionSounds = getModeratorTabProps(getState()).startReactionsMuted;
|
||||
const shouldUpdate = (newState.soundsIncomingMessage !== currentState.soundsIncomingMessage)
|
||||
|| (newState.soundsParticipantJoined !== currentState.soundsParticipantJoined)
|
||||
|
@ -209,6 +198,17 @@ export function submitSoundsTab(newState: any) {
|
|||
}
|
||||
dispatch(updateSettings(settingsToUpdate));
|
||||
}
|
||||
|
||||
const enabledNotifications = newState.enabledNotifications;
|
||||
|
||||
if (enabledNotifications !== currentState.enabledNotifications) {
|
||||
dispatch(updateSettings({
|
||||
userSelectedNotifications: {
|
||||
...getState()['features/base/settings'].userSelectedNotifications,
|
||||
...enabledNotifications
|
||||
}
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -27,11 +27,6 @@ export type Props = AbstractDialogTabProps & WithTranslation & {
|
|||
*/
|
||||
desktopShareFramerates: Array<number>;
|
||||
|
||||
/**
|
||||
* The types of enabled notifications that can be configured and their specific visibility.
|
||||
*/
|
||||
enabledNotifications: Object;
|
||||
|
||||
/**
|
||||
* Whether or not follow me is currently active (enabled by some other participant).
|
||||
*/
|
||||
|
@ -47,11 +42,6 @@ export type Props = AbstractDialogTabProps & WithTranslation & {
|
|||
*/
|
||||
showModeratorSettings: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not to display notifications settings.
|
||||
*/
|
||||
showNotificationsSettings: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not to show prejoin screen.
|
||||
*/
|
||||
|
@ -90,7 +80,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
|
|||
|
||||
// Bind event handler so it is only bound once for every instance.
|
||||
this._onFramerateItemSelect = this._onFramerateItemSelect.bind(this);
|
||||
this._onEnabledNotificationsChanged = this._onEnabledNotificationsChanged.bind(this);
|
||||
this._onShowPrejoinPageChanged = this._onShowPrejoinPageChanged.bind(this);
|
||||
this._onKeyboardShortcutEnableChanged = this._onKeyboardShortcutEnableChanged.bind(this);
|
||||
this._renderMaxStageParticipantsSelect = this._renderMaxStageParticipantsSelect.bind(this);
|
||||
|
@ -143,24 +132,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
|
|||
super._onChange({ showPrejoinPage: checked });
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked to select if the given type of
|
||||
* notifications should be shown.
|
||||
*
|
||||
* @param {Object} e - The key event to handle.
|
||||
* @param {string} type - The type of the notification.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onEnabledNotificationsChanged({ target: { checked } }: React.ChangeEvent<HTMLInputElement>, type: any) {
|
||||
super._onChange({
|
||||
enabledNotifications: {
|
||||
...this.props.enabledNotifications,
|
||||
[type]: checked
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked to select if global keyboard shortcuts
|
||||
* should be enabled.
|
||||
|
@ -269,37 +240,6 @@ class MoreTab extends AbstractDialogTab<Props, any> {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the React Element for modifying the enabled notifications settings.
|
||||
*
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderNotificationsSettings() {
|
||||
const { t, enabledNotifications } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = 'settings-sub-pane-element'
|
||||
key = 'notifications'>
|
||||
<span className = 'checkbox-label'>
|
||||
{ t('notify.displayNotifications') }
|
||||
</span>
|
||||
{
|
||||
Object.keys(enabledNotifications).map(key => (
|
||||
<Checkbox
|
||||
checked = { Boolean(enabledNotifications[key as keyof typeof enabledNotifications]) }
|
||||
key = { key }
|
||||
label = { t(key) }
|
||||
name = { `show-${key}` }
|
||||
/* eslint-disable-next-line react/jsx-no-bind */
|
||||
onChange = { e => this._onEnabledNotificationsChanged(e, key) } />
|
||||
))
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the React Element for the max stage participants dropdown.
|
||||
*
|
||||
|
@ -357,14 +297,13 @@ class MoreTab extends AbstractDialogTab<Props, any> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderSettingsLeft() {
|
||||
const { showNotificationsSettings, showPrejoinSettings } = this.props;
|
||||
const { showPrejoinSettings } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = 'settings-sub-pane left'
|
||||
key = 'settings-sub-pane-left'>
|
||||
{ showPrejoinSettings && this._renderPrejoinScreenSettings() }
|
||||
{ showNotificationsSettings && this._renderNotificationsSettings() }
|
||||
{ this._renderKeyboardShortcutCheckbox() }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
import { Theme } from '@mui/material';
|
||||
import { withStyles } from '@mui/styles';
|
||||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import AbstractDialogTab, {
|
||||
IProps as AbstractDialogTabProps } from '../../../base/dialog/components/web/AbstractDialogTab';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Checkbox from '../../../base/ui/components/web/Checkbox';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link NotificationsTab}.
|
||||
*/
|
||||
export interface IProps extends AbstractDialogTabProps, WithTranslation {
|
||||
|
||||
/**
|
||||
* CSS classes object.
|
||||
*/
|
||||
classes: any;
|
||||
|
||||
/**
|
||||
* Array of disabled sounds ids.
|
||||
*/
|
||||
disabledSounds: string[];
|
||||
|
||||
/**
|
||||
* Whether or not the reactions feature is enabled.
|
||||
*/
|
||||
enableReactions: Boolean;
|
||||
|
||||
/**
|
||||
* The types of enabled notifications that can be configured and their specific visibility.
|
||||
*/
|
||||
enabledNotifications: Object;
|
||||
|
||||
/**
|
||||
* Whether or not moderator muted the sounds.
|
||||
*/
|
||||
moderatorMutedSoundsReactions: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not to display notifications settings.
|
||||
*/
|
||||
showNotificationsSettings: boolean;
|
||||
|
||||
/**
|
||||
* Whether sound settings should be displayed or not.
|
||||
*/
|
||||
showSoundsSettings: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the incoming message should play.
|
||||
*/
|
||||
soundsIncomingMessage: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant joined should play.
|
||||
*/
|
||||
soundsParticipantJoined: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant entering the lobby should play.
|
||||
*/
|
||||
soundsParticipantKnocking: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant left should play.
|
||||
*/
|
||||
soundsParticipantLeft: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for reactions should play.
|
||||
*/
|
||||
soundsReactions: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the talk while muted notification should play.
|
||||
*/
|
||||
soundsTalkWhileMuted: Boolean;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => {
|
||||
return {
|
||||
container: {
|
||||
display: 'flex',
|
||||
width: '100%'
|
||||
},
|
||||
|
||||
column: {
|
||||
flex: 1,
|
||||
|
||||
'&:first-child:not(:last-child)': {
|
||||
marginRight: theme.spacing(3)
|
||||
}
|
||||
},
|
||||
|
||||
title: {
|
||||
...withPixelLineHeight(theme.typography.heading6),
|
||||
color: `${theme.palette.text01} !important`,
|
||||
marginBottom: theme.spacing(3)
|
||||
},
|
||||
|
||||
checkbox: {
|
||||
marginBottom: theme.spacing(3)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for modifying the local user's sound settings.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class NotificationsTab extends AbstractDialogTab<IProps, any> {
|
||||
/**
|
||||
* Initializes a new {@code SoundsTab} instance.
|
||||
*
|
||||
* @param {IProps} props - The React {@code Component} props to initialize
|
||||
* the new {@code SoundsTab} instance with.
|
||||
*/
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onChange = this._onChange.bind(this);
|
||||
this._onEnabledNotificationsChanged = this._onEnabledNotificationsChanged.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes a sound setting state.
|
||||
*
|
||||
* @param {Object} e - The key event to handle.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onChange({ target }: React.ChangeEvent<HTMLInputElement>) {
|
||||
super._onChange({ [target.name]: target.checked });
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked to select if the given type of
|
||||
* notifications should be shown.
|
||||
*
|
||||
* @param {Object} e - The key event to handle.
|
||||
* @param {string} type - The type of the notification.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onEnabledNotificationsChanged({ target: { checked } }: React.ChangeEvent<HTMLInputElement>, type: any) {
|
||||
super._onChange({
|
||||
enabledNotifications: {
|
||||
...this.props.enabledNotifications,
|
||||
[type]: checked
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
classes,
|
||||
disabledSounds,
|
||||
enabledNotifications,
|
||||
showNotificationsSettings,
|
||||
showSoundsSettings,
|
||||
soundsIncomingMessage,
|
||||
soundsParticipantJoined,
|
||||
soundsParticipantKnocking,
|
||||
soundsParticipantLeft,
|
||||
soundsTalkWhileMuted,
|
||||
soundsReactions,
|
||||
enableReactions,
|
||||
moderatorMutedSoundsReactions,
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = { classes.container }
|
||||
key = 'sounds'>
|
||||
{showSoundsSettings && (
|
||||
<div className = { classes.column }>
|
||||
<h2 className = { classes.title }>
|
||||
{t('settings.playSounds')}
|
||||
</h2>
|
||||
{enableReactions && <Checkbox
|
||||
checked = { soundsReactions && !disabledSounds.includes('REACTION_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { Boolean(moderatorMutedSoundsReactions
|
||||
|| disabledSounds.includes('REACTION_SOUND')) }
|
||||
label = { t('settings.reactions') }
|
||||
name = 'soundsReactions'
|
||||
onChange = { this._onChange } />
|
||||
}
|
||||
<Checkbox
|
||||
checked = { soundsIncomingMessage && !disabledSounds.includes('INCOMING_MSG_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { disabledSounds.includes('INCOMING_MSG_SOUND') }
|
||||
label = { t('settings.incomingMessage') }
|
||||
name = 'soundsIncomingMessage'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantJoined
|
||||
&& !disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
|
||||
label = { t('settings.participantJoined') }
|
||||
name = 'soundsParticipantJoined'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantLeft && !disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
|
||||
label = { t('settings.participantLeft') }
|
||||
name = 'soundsParticipantLeft'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsTalkWhileMuted && !disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
|
||||
label = { t('settings.talkWhileMuted') }
|
||||
name = 'soundsTalkWhileMuted'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantKnocking
|
||||
&& !disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
|
||||
className = { classes.checkbox }
|
||||
disabled = { disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
|
||||
label = { t('settings.participantKnocking') }
|
||||
name = 'soundsParticipantKnocking'
|
||||
onChange = { this._onChange } />
|
||||
</div>
|
||||
)}
|
||||
{showNotificationsSettings && (
|
||||
<div className = { classes.column }>
|
||||
<h2 className = { classes.title }>
|
||||
{t('notify.displayNotifications')}
|
||||
</h2>
|
||||
{
|
||||
Object.keys(enabledNotifications).map(key => (
|
||||
<Checkbox
|
||||
checked = { Boolean(enabledNotifications[key as
|
||||
keyof typeof enabledNotifications]) }
|
||||
className = { classes.checkbox }
|
||||
key = { key }
|
||||
label = { t(key) }
|
||||
name = { `show-${key}` }
|
||||
/* eslint-disable-next-line react/jsx-no-bind */
|
||||
onChange = { e => this._onEnabledNotificationsChanged(e, key) } />
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(translate(NotificationsTab));
|
|
@ -18,23 +18,24 @@ import {
|
|||
import {
|
||||
submitModeratorTab,
|
||||
submitMoreTab,
|
||||
submitProfileTab,
|
||||
submitSoundsTab
|
||||
submitNotificationsTab,
|
||||
submitProfileTab
|
||||
} from '../../actions';
|
||||
import { SETTINGS_TABS } from '../../constants';
|
||||
import {
|
||||
getModeratorTabProps,
|
||||
getMoreTabProps,
|
||||
getProfileTabProps,
|
||||
getSoundsTabProps
|
||||
getNotificationsMap,
|
||||
getNotificationsTabProps,
|
||||
getProfileTabProps
|
||||
} from '../../functions';
|
||||
|
||||
// @ts-ignore
|
||||
import CalendarTab from './CalendarTab';
|
||||
import ModeratorTab from './ModeratorTab';
|
||||
import MoreTab from './MoreTab';
|
||||
import NotificationsTab from './NotificationsTab';
|
||||
import ProfileTab from './ProfileTab';
|
||||
import SoundsTab from './SoundsTab';
|
||||
/* eslint-enable lines-around-comment */
|
||||
|
||||
/**
|
||||
|
@ -148,7 +149,7 @@ const styles = (theme: Theme) => {
|
|||
|
||||
'& .settings-checkbox': {
|
||||
display: 'flex',
|
||||
marginBottom: theme.spacing(2)
|
||||
marginBottom: theme.spacing(3)
|
||||
},
|
||||
|
||||
'& .calendar-tab': {
|
||||
|
@ -248,6 +249,8 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
|
|||
const showCalendarSettings
|
||||
= configuredTabs.includes('calendar') && isCalendarEnabled(state);
|
||||
const showSoundsSettings = configuredTabs.includes('sounds');
|
||||
const enabledNotifications = getNotificationsMap(state);
|
||||
const showNotificationsSettings = Object.keys(enabledNotifications).length > 0;
|
||||
const tabs: IDialogTab[] = [];
|
||||
|
||||
if (showDeviceSettings) {
|
||||
|
@ -276,6 +279,24 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
|
|||
});
|
||||
}
|
||||
|
||||
if (showSoundsSettings || showNotificationsSettings) {
|
||||
tabs.push({
|
||||
name: SETTINGS_TABS.NOTIFICATIONS,
|
||||
component: NotificationsTab,
|
||||
labelKey: 'settings.notifications',
|
||||
propsUpdateFunction: (tabState: any, newProps: any) => {
|
||||
return {
|
||||
...newProps,
|
||||
enabledNotifications: tabState?.enabledNotifications || {}
|
||||
};
|
||||
},
|
||||
props: getNotificationsTabProps(state, showSoundsSettings),
|
||||
className: `settings-pane ${classes.settingsDialog}`,
|
||||
submit: submitNotificationsTab,
|
||||
icon: IconBell
|
||||
});
|
||||
}
|
||||
|
||||
if (showModeratorSettings) {
|
||||
tabs.push({
|
||||
name: SETTINGS_TABS.MODERATOR,
|
||||
|
@ -321,18 +342,6 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
|
|||
});
|
||||
}
|
||||
|
||||
if (showSoundsSettings) {
|
||||
tabs.push({
|
||||
name: SETTINGS_TABS.SOUNDS,
|
||||
component: SoundsTab,
|
||||
labelKey: 'settings.sounds',
|
||||
props: getSoundsTabProps(state),
|
||||
className: `settings-pane ${classes.settingsDialog} profile-pane`,
|
||||
submit: submitSoundsTab,
|
||||
icon: IconBell
|
||||
});
|
||||
}
|
||||
|
||||
if (showMoreTab) {
|
||||
tabs.push({
|
||||
name: SETTINGS_TABS.MORE,
|
||||
|
@ -350,7 +359,6 @@ function _mapStateToProps(state: IReduxState, ownProps: any) {
|
|||
currentLanguage: tabState?.currentLanguage,
|
||||
hideSelfView: tabState?.hideSelfView,
|
||||
showPrejoinPage: tabState?.showPrejoinPage,
|
||||
enabledNotifications: tabState?.enabledNotifications || {},
|
||||
maxStageParticipants: tabState?.maxStageParticipants
|
||||
};
|
||||
},
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
import React from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-ignore
|
||||
import { AbstractDialogTab } from '../../../base/dialog';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import type { Props as AbstractDialogTabProps } from '../../../base/dialog';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Checkbox from '../../../base/ui/components/web/Checkbox';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link SoundsTab}.
|
||||
*/
|
||||
export type Props = AbstractDialogTabProps & WithTranslation & {
|
||||
|
||||
/**
|
||||
* Whether or not the reactions feature is enabled.
|
||||
*/
|
||||
enableReactions: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not moderator muted the sounds.
|
||||
*/
|
||||
moderatorMutedSoundsReactions: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the incoming message should play.
|
||||
*/
|
||||
soundsIncomingMessage: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant joined should play.
|
||||
*/
|
||||
soundsParticipantJoined: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant entering the lobby should play.
|
||||
*/
|
||||
soundsParticipantKnocking: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the participant left should play.
|
||||
*/
|
||||
soundsParticipantLeft: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for reactions should play.
|
||||
*/
|
||||
soundsReactions: Boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the sound for the talk while muted notification should play.
|
||||
*/
|
||||
soundsTalkWhileMuted: Boolean;
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* React {@code Component} for modifying the local user's sound settings.
|
||||
*
|
||||
* @augments Component
|
||||
*/
|
||||
class SoundsTab extends AbstractDialogTab<Props> {
|
||||
/**
|
||||
* Initializes a new {@code SoundsTab} instance.
|
||||
*
|
||||
* @param {Props} props - The React {@code Component} props to initialize
|
||||
* the new {@code SoundsTab} instance with.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
// Bind event handlers so they are only bound once for every instance.
|
||||
this._onChange = this._onChange.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes a sound setting state.
|
||||
*
|
||||
* @param {Object} e - The key event to handle.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_onChange({ target }: React.ChangeEvent<HTMLInputElement>) {
|
||||
super._onChange({ [target.name]: target.checked });
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
disabledSounds,
|
||||
soundsIncomingMessage,
|
||||
soundsParticipantJoined,
|
||||
soundsParticipantKnocking,
|
||||
soundsParticipantLeft,
|
||||
soundsTalkWhileMuted,
|
||||
soundsReactions,
|
||||
enableReactions,
|
||||
moderatorMutedSoundsReactions,
|
||||
t // @ts-ignore
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className = 'settings-sub-pane-element'
|
||||
key = 'sounds'>
|
||||
<h2 className = 'mock-atlaskit-label'>
|
||||
{t('settings.playSounds')}
|
||||
</h2>
|
||||
{enableReactions && <Checkbox
|
||||
checked = { soundsReactions && !disabledSounds.includes('REACTION_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { moderatorMutedSoundsReactions || disabledSounds.includes('REACTION_SOUND') }
|
||||
label = { t('settings.reactions') }
|
||||
name = 'soundsReactions'
|
||||
onChange = { this._onChange } />
|
||||
}
|
||||
<Checkbox
|
||||
checked = { soundsIncomingMessage && !disabledSounds.includes('INCOMING_MSG_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { disabledSounds.includes('INCOMING_MSG_SOUND') }
|
||||
label = { t('settings.incomingMessage') }
|
||||
name = 'soundsIncomingMessage'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantJoined && !disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
|
||||
label = { t('settings.participantJoined') }
|
||||
name = 'soundsParticipantJoined'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantLeft && !disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
|
||||
label = { t('settings.participantLeft') }
|
||||
name = 'soundsParticipantLeft'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsTalkWhileMuted && !disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
|
||||
label = { t('settings.talkWhileMuted') }
|
||||
name = 'soundsTalkWhileMuted'
|
||||
onChange = { this._onChange } />
|
||||
<Checkbox
|
||||
checked = { soundsParticipantKnocking && !disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
|
||||
className = 'settings-checkbox'
|
||||
disabled = { disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
|
||||
label = { t('settings.participantKnocking') }
|
||||
name = 'soundsParticipantKnocking'
|
||||
onChange = { this._onChange } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default translate(SoundsTab);
|
|
@ -3,8 +3,8 @@ export const SETTINGS_TABS = {
|
|||
DEVICES: 'devices_tab',
|
||||
MORE: 'more_tab',
|
||||
MODERATOR: 'moderator-tab',
|
||||
PROFILE: 'profile_tab',
|
||||
SOUNDS: 'sounds_tab'
|
||||
NOTIFICATIONS: 'notifications_tab',
|
||||
PROFILE: 'profile_tab'
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -116,14 +116,11 @@ export function getNotificationsMap(stateful: IStateful) {
|
|||
export function getMoreTabProps(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const framerate = state['features/screen-share'].captureFrameRate ?? SS_DEFAULT_FRAME_RATE;
|
||||
const enabledNotifications = getNotificationsMap(stateful);
|
||||
const stageFilmstripEnabled = isStageFilmstripEnabled(state);
|
||||
|
||||
return {
|
||||
currentFramerate: framerate,
|
||||
desktopShareFramerates: SS_SUPPORTED_FRAMERATES,
|
||||
enabledNotifications,
|
||||
showNotificationsSettings: Object.keys(enabledNotifications).length > 0,
|
||||
showPrejoinPage: !state['features/base/settings'].userSelectedSkipPrejoin,
|
||||
showPrejoinSettings: state['features/base/config'].prejoinConfig?.enabled,
|
||||
maxStageParticipants: state['features/base/settings'].maxStageParticipants,
|
||||
|
@ -225,10 +222,11 @@ export function getProfileTabProps(stateful: IStateful) {
|
|||
*
|
||||
* @param {(Function|Object)} stateful -The (whole) redux state, or redux's
|
||||
* {@code getState} function to be used to retrieve the state.
|
||||
* @param {boolean} showSoundsSettings - Whether to show the sound settings or not.
|
||||
* @returns {Object} - The properties for the "Sounds" tab from settings
|
||||
* dialog.
|
||||
*/
|
||||
export function getSoundsTabProps(stateful: IStateful) {
|
||||
export function getNotificationsTabProps(stateful: IStateful, showSoundsSettings?: boolean) {
|
||||
const state = toState(stateful);
|
||||
const {
|
||||
soundsIncomingMessage,
|
||||
|
@ -240,9 +238,12 @@ export function getSoundsTabProps(stateful: IStateful) {
|
|||
} = state['features/base/settings'];
|
||||
const enableReactions = isReactionsEnabled(state);
|
||||
const moderatorMutedSoundsReactions = state['features/base/conference'].startReactionsMuted ?? false;
|
||||
const enabledNotifications = getNotificationsMap(stateful);
|
||||
|
||||
return {
|
||||
disabledSounds: state['features/base/config'].disabledSounds || [],
|
||||
enabledNotifications,
|
||||
showNotificationsSettings: Object.keys(enabledNotifications).length > 0,
|
||||
soundsIncomingMessage,
|
||||
soundsParticipantJoined,
|
||||
soundsParticipantKnocking,
|
||||
|
@ -250,7 +251,8 @@ export function getSoundsTabProps(stateful: IStateful) {
|
|||
soundsTalkWhileMuted,
|
||||
soundsReactions,
|
||||
enableReactions,
|
||||
moderatorMutedSoundsReactions
|
||||
moderatorMutedSoundsReactions,
|
||||
showSoundsSettings
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue