feat(sound-settings) Added ability to control sounds

pull/9593/head jitsi-meet_6096
robertpin 3 years ago committed by GitHub
parent 251eec19cd
commit c10805f81b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      config.js
  2. 2
      interface_config.js
  3. 6
      lang/main.json
  4. 1
      react/features/base/config/configWhitelist.js
  5. 6
      react/features/base/participants/middleware.js
  6. 4
      react/features/base/settings/reducer.js
  7. 4
      react/features/chat/middleware.js
  8. 27
      react/features/settings/actions.js
  9. 17
      react/features/settings/components/web/SettingsDialog.js
  10. 123
      react/features/settings/components/web/SoundsTab.js
  11. 3
      react/features/settings/constants.js
  12. 26
      react/features/settings/functions.js
  13. 7
      react/features/talk-while-muted/middleware.js

@ -603,6 +603,9 @@ var config = {
// conference (if set to true, these sounds will not be played).
// disableJoinLeaveSounds: false,
// Disables the sounds that play when a chat message is received.
// disableIncomingMessageSound: false,
// Information for the chrome extension banner
// chromeExtensionBanner: {
// // The chrome extension to be installed address

@ -174,7 +174,7 @@ var interfaceConfig = {
RECENT_LIST_ENABLED: true,
REMOTE_THUMBNAIL_RATIO: 1, // 1:1
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar', 'sounds' ],
/**
* Specify which sharing features should be displayed. If the value is not set

@ -744,6 +744,7 @@
"devices": "Devices",
"followMe": "Everyone follows me",
"framesPerSecond": "frames-per-second",
"incomingMessage": "Incoming message",
"language": "Language",
"loggedIn": "Logged in as {{name}}",
"microphones": "Microphones",
@ -751,13 +752,18 @@
"more": "More",
"name": "Name",
"noDevice": "None",
"participantJoined": "Participant Joined",
"participantLeft": "Participant Left",
"playSounds": "Play sound on",
"sameAsSystem": "Same as system ({{label}})",
"selectAudioOutput": "Audio output",
"selectCamera": "Camera",
"selectMic": "Microphone",
"sounds": "Sounds",
"speakers": "Speakers",
"startAudioMuted": "Everyone starts muted",
"startVideoMuted": "Everyone starts hidden",
"talkWhileMuted": "Talk while muted",
"title": "Settings"
},
"settingsView": {

@ -87,6 +87,7 @@ export default [
'disableH264',
'disableHPF',
'disableInviteFunctions',
'disableIncomingMessageSound',
'disableJoinLeaveSounds',
'disableLocalVideoFlip',
'disableNS',

@ -371,6 +371,7 @@ function _localParticipantLeft({ dispatch }, next, action) {
function _maybePlaySounds({ getState, dispatch }, action) {
const state = getState();
const { startAudioMuted, disableJoinLeaveSounds } = state['features/base/config'];
const { soundsParticipantJoined: joinSound, soundsParticipantLeft: leftSound } = state['features/base/settings'];
// If we have join/leave sounds disabled, don't play anything.
if (disableJoinLeaveSounds) {
@ -387,13 +388,16 @@ function _maybePlaySounds({ getState, dispatch }, action) {
const { isReplacing, isReplaced } = action.participant;
if (action.type === PARTICIPANT_JOINED) {
if (!joinSound) {
return;
}
const { presence } = action.participant;
// The sounds for the poltergeist are handled by features/invite.
if (presence !== INVITED && presence !== CALLING && !isReplacing) {
dispatch(playSound(PARTICIPANT_JOINED_SOUND_ID));
}
} else if (action.type === PARTICIPANT_LEFT && !isReplaced) {
} else if (action.type === PARTICIPANT_LEFT && !isReplaced && leftSound) {
dispatch(playSound(PARTICIPANT_LEFT_SOUND_ID));
}
}

@ -27,6 +27,10 @@ const DEFAULT_STATE = {
micDeviceId: undefined,
serverURL: undefined,
hideShareAudioHelper: false,
soundsIncomingMessage: true,
soundsParticipantJoined: true,
soundsParticipantLeft: true,
soundsTalkWhileMuted: true,
startAudioOnly: false,
startWithAudioMuted: false,
startWithVideoMuted: false,

@ -305,8 +305,10 @@ function _handleReceivedMessage({ dispatch, getState },
// Logic for all platforms:
const state = getState();
const { isOpen: isChatOpen } = state['features/chat'];
const { disableIncomingMessageSound } = state['features/base/config'];
const { soundsIncomingMessage: soundEnabled } = state['features/base/settings'];
if (shouldPlaySound && !isChatOpen) {
if (!disableIncomingMessageSound && soundEnabled && shouldPlaySound && !isChatOpen) {
dispatch(playSound(INCOMING_MSG_SOUND_ID));
}

@ -12,7 +12,7 @@ import {
SET_VIDEO_SETTINGS_VISIBILITY
} from './actionTypes';
import { LogoutDialog, SettingsDialog } from './components';
import { getMoreTabProps, getProfileTabProps } from './functions';
import { getMoreTabProps, getProfileTabProps, getSoundsTabProps } from './functions';
declare var APP: Object;
@ -129,6 +129,31 @@ export function submitProfileTab(newState: Object): Function {
};
}
/**
* Submits the settings from the "Sounds" tab of the settings dialog.
*
* @param {Object} newState - The new settings.
* @returns {Function}
*/
export function submitSoundsTab(newState: Object): Function {
return (dispatch, getState) => {
const currentState = getSoundsTabProps(getState());
const shouldUpdate = (newState.soundsIncomingMessage !== currentState.soundsIncomingMessage)
|| (newState.soundsParticipantJoined !== currentState.soundsParticipantJoined)
|| (newState.soundsParticipantLeft !== currentState.soundsParticipantLeft)
|| (newState.soundsTalkWhileMuted !== currentState.soundsTalkWhileMuted);
if (shouldUpdate) {
dispatch(updateSettings({
soundsIncomingMessage: newState.soundsIncomingMessage,
soundsParticipantJoined: newState.soundsParticipantJoined,
soundsParticipantLeft: newState.soundsParticipantLeft,
soundsTalkWhileMuted: newState.soundsTalkWhileMuted
}));
}
};
}
/**
* Toggles the visibility of the audio settings.
*

@ -11,13 +11,14 @@ import {
getDeviceSelectionDialogProps,
submitDeviceSelectionTab
} from '../../../device-selection';
import { submitMoreTab, submitProfileTab } from '../../actions';
import { submitMoreTab, submitProfileTab, submitSoundsTab } from '../../actions';
import { SETTINGS_TABS } from '../../constants';
import { getMoreTabProps, getProfileTabProps } from '../../functions';
import { getMoreTabProps, getProfileTabProps, getSoundsTabProps } from '../../functions';
import CalendarTab from './CalendarTab';
import MoreTab from './MoreTab';
import ProfileTab from './ProfileTab';
import SoundsTab from './SoundsTab';
declare var APP: Object;
declare var interfaceConfig: Object;
@ -135,6 +136,7 @@ function _mapStateToProps(state) {
= configuredTabs.includes('profile') && !state['features/base/config'].disableProfile;
const showCalendarSettings
= configuredTabs.includes('calendar') && isCalendarEnabled(state);
const showSoundsSettings = configuredTabs.includes('sounds');
const tabs = [];
if (showDeviceSettings) {
@ -183,6 +185,17 @@ function _mapStateToProps(state) {
});
}
if (showSoundsSettings) {
tabs.push({
name: SETTINGS_TABS.SOUNDS,
component: SoundsTab,
label: 'settings.sounds',
props: getSoundsTabProps(state),
styles: 'settings-pane profile-pane',
submit: submitSoundsTab
});
}
if (showModeratorSettings || showLanguageSettings || showPrejoinSettings) {
tabs.push({
name: SETTINGS_TABS.MORE,

@ -0,0 +1,123 @@
// @flow
import Checkbox from '@atlaskit/checkbox';
import React from 'react';
import { AbstractDialogTab } from '../../../base/dialog';
import type { Props as AbstractDialogTabProps } from '../../../base/dialog';
import { translate } from '../../../base/i18n';
declare var APP: Object;
/**
* The type of the React {@code Component} props of {@link SoundsTab}.
*/
export type Props = {
...$Exact<AbstractDialogTabProps>,
/**
* 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 left should play.
*/
soundsParticipantLeft: 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.
*
* @extends 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);
}
_onChange: (Object) => void;
/**
* Changes a sound setting state.
*
* @param {Object} e - The key event to handle.
*
* @returns {void}
*/
_onChange({ target }) {
super._onChange({ [target.name]: target.checked });
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const {
soundsIncomingMessage,
soundsParticipantJoined,
soundsParticipantLeft,
soundsTalkWhileMuted,
t
} = this.props;
return (
<div
className = 'settings-sub-pane-element'
key = 'sounds'>
<h2 className = 'mock-atlaskit-label'>
{t('settings.playSounds')}
</h2>
<Checkbox
isChecked = { soundsIncomingMessage }
label = { t('settings.incomingMessage') }
name = 'soundsIncomingMessage'
onChange = { this._onChange } />
<Checkbox
isChecked = { soundsParticipantJoined }
label = { t('settings.participantJoined') }
name = 'soundsParticipantJoined'
onChange = { this._onChange } />
<Checkbox
isChecked = { soundsParticipantLeft }
label = { t('settings.participantLeft') }
name = 'soundsParticipantLeft'
onChange = { this._onChange } />
<Checkbox
isChecked = { soundsTalkWhileMuted }
label = { t('settings.talkWhileMuted') }
name = 'soundsTalkWhileMuted'
onChange = { this._onChange } />
</div>
);
}
}
export default translate(SoundsTab);

@ -2,7 +2,8 @@ export const SETTINGS_TABS = {
CALENDAR: 'calendar_tab',
DEVICES: 'devices_tab',
MORE: 'more_tab',
PROFILE: 'profile_tab'
PROFILE: 'profile_tab',
SOUNDS: 'sounds_tab'
};
/**

@ -156,6 +156,32 @@ export function getProfileTabProps(stateful: Object | Function) {
};
}
/**
* Returns the properties for the "Sounds" tab from settings dialog from Redux
* state.
*
* @param {(Function|Object)} stateful -The (whole) redux state, or redux's
* {@code getState} function to be used to retrieve the state.
* @returns {Object} - The properties for the "Sounds" tab from settings
* dialog.
*/
export function getSoundsTabProps(stateful: Object | Function) {
const state = toState(stateful);
const {
soundsIncomingMessage,
soundsParticipantJoined,
soundsParticipantLeft,
soundsTalkWhileMuted
} = state['features/base/settings'];
return {
soundsIncomingMessage,
soundsParticipantJoined,
soundsParticipantLeft,
soundsTalkWhileMuted
};
}
/**
* Returns a promise which resolves with a list of objects containing
* all the video jitsiTracks and appropriate errors for the given device ids.

@ -47,7 +47,12 @@ MiddlewareRegistry.register(store => next => action => {
customActionHandler: () => dispatch(setAudioMuted(false))
}));
dispatch(playSound(TALK_WHILE_MUTED_SOUND_ID));
const { soundsTalkWhileMuted } = getState()['features/base/settings'];
if (soundsTalkWhileMuted) {
dispatch(playSound(TALK_WHILE_MUTED_SOUND_ID));
}
if (notification) {
// we store the last start muted notification id that we showed,

Loading…
Cancel
Save