You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NotificationsTab.tsx 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import { Theme } from '@mui/material';
  2. import { withStyles } from '@mui/styles';
  3. import React from 'react';
  4. import { WithTranslation } from 'react-i18next';
  5. import AbstractDialogTab, {
  6. IProps as AbstractDialogTabProps } from '../../../base/dialog/components/web/AbstractDialogTab';
  7. import { translate } from '../../../base/i18n/functions';
  8. import { withPixelLineHeight } from '../../../base/styles/functions.web';
  9. import Checkbox from '../../../base/ui/components/web/Checkbox';
  10. /**
  11. * The type of the React {@code Component} props of {@link NotificationsTab}.
  12. */
  13. export interface IProps extends AbstractDialogTabProps, WithTranslation {
  14. /**
  15. * CSS classes object.
  16. */
  17. classes: any;
  18. /**
  19. * Array of disabled sounds ids.
  20. */
  21. disabledSounds: string[];
  22. /**
  23. * Whether or not the reactions feature is enabled.
  24. */
  25. enableReactions: Boolean;
  26. /**
  27. * The types of enabled notifications that can be configured and their specific visibility.
  28. */
  29. enabledNotifications: Object;
  30. /**
  31. * Whether or not moderator muted the sounds.
  32. */
  33. moderatorMutedSoundsReactions: Boolean;
  34. /**
  35. * Whether or not to display notifications settings.
  36. */
  37. showNotificationsSettings: boolean;
  38. /**
  39. * Whether sound settings should be displayed or not.
  40. */
  41. showSoundsSettings: boolean;
  42. /**
  43. * Whether or not the sound for the incoming message should play.
  44. */
  45. soundsIncomingMessage: Boolean;
  46. /**
  47. * Whether or not the sound for the participant joined should play.
  48. */
  49. soundsParticipantJoined: Boolean;
  50. /**
  51. * Whether or not the sound for the participant entering the lobby should play.
  52. */
  53. soundsParticipantKnocking: Boolean;
  54. /**
  55. * Whether or not the sound for the participant left should play.
  56. */
  57. soundsParticipantLeft: Boolean;
  58. /**
  59. * Whether or not the sound for reactions should play.
  60. */
  61. soundsReactions: Boolean;
  62. /**
  63. * Whether or not the sound for the talk while muted notification should play.
  64. */
  65. soundsTalkWhileMuted: Boolean;
  66. }
  67. const styles = (theme: Theme) => {
  68. return {
  69. container: {
  70. display: 'flex',
  71. width: '100%'
  72. },
  73. column: {
  74. flex: 1,
  75. '&:first-child:not(:last-child)': {
  76. marginRight: theme.spacing(3)
  77. }
  78. },
  79. title: {
  80. ...withPixelLineHeight(theme.typography.heading6),
  81. color: `${theme.palette.text01} !important`,
  82. marginBottom: theme.spacing(3)
  83. },
  84. checkbox: {
  85. marginBottom: theme.spacing(3)
  86. }
  87. };
  88. };
  89. /**
  90. * React {@code Component} for modifying the local user's sound settings.
  91. *
  92. * @augments Component
  93. */
  94. class NotificationsTab extends AbstractDialogTab<IProps, any> {
  95. /**
  96. * Initializes a new {@code SoundsTab} instance.
  97. *
  98. * @param {IProps} props - The React {@code Component} props to initialize
  99. * the new {@code SoundsTab} instance with.
  100. */
  101. constructor(props: IProps) {
  102. super(props);
  103. // Bind event handlers so they are only bound once for every instance.
  104. this._onChange = this._onChange.bind(this);
  105. this._onEnabledNotificationsChanged = this._onEnabledNotificationsChanged.bind(this);
  106. }
  107. /**
  108. * Changes a sound setting state.
  109. *
  110. * @param {Object} e - The key event to handle.
  111. *
  112. * @returns {void}
  113. */
  114. _onChange({ target }: React.ChangeEvent<HTMLInputElement>) {
  115. super._onChange({ [target.name]: target.checked });
  116. }
  117. /**
  118. * Callback invoked to select if the given type of
  119. * notifications should be shown.
  120. *
  121. * @param {Object} e - The key event to handle.
  122. * @param {string} type - The type of the notification.
  123. *
  124. * @returns {void}
  125. */
  126. _onEnabledNotificationsChanged({ target: { checked } }: React.ChangeEvent<HTMLInputElement>, type: any) {
  127. super._onChange({
  128. enabledNotifications: {
  129. ...this.props.enabledNotifications,
  130. [type]: checked
  131. }
  132. });
  133. }
  134. /**
  135. * Implements React's {@link Component#render()}.
  136. *
  137. * @inheritdoc
  138. * @returns {ReactElement}
  139. */
  140. render() {
  141. const {
  142. classes,
  143. disabledSounds,
  144. enabledNotifications,
  145. showNotificationsSettings,
  146. showSoundsSettings,
  147. soundsIncomingMessage,
  148. soundsParticipantJoined,
  149. soundsParticipantKnocking,
  150. soundsParticipantLeft,
  151. soundsTalkWhileMuted,
  152. soundsReactions,
  153. enableReactions,
  154. moderatorMutedSoundsReactions,
  155. t
  156. } = this.props;
  157. return (
  158. <div
  159. className = { classes.container }
  160. key = 'sounds'>
  161. {showSoundsSettings && (
  162. <div className = { classes.column }>
  163. <h2 className = { classes.title }>
  164. {t('settings.playSounds')}
  165. </h2>
  166. {enableReactions && <Checkbox
  167. checked = { soundsReactions && !disabledSounds.includes('REACTION_SOUND') }
  168. className = { classes.checkbox }
  169. disabled = { Boolean(moderatorMutedSoundsReactions
  170. || disabledSounds.includes('REACTION_SOUND')) }
  171. label = { t('settings.reactions') }
  172. name = 'soundsReactions'
  173. onChange = { this._onChange } />
  174. }
  175. <Checkbox
  176. checked = { soundsIncomingMessage && !disabledSounds.includes('INCOMING_MSG_SOUND') }
  177. className = { classes.checkbox }
  178. disabled = { disabledSounds.includes('INCOMING_MSG_SOUND') }
  179. label = { t('settings.incomingMessage') }
  180. name = 'soundsIncomingMessage'
  181. onChange = { this._onChange } />
  182. <Checkbox
  183. checked = { soundsParticipantJoined
  184. && !disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
  185. className = { classes.checkbox }
  186. disabled = { disabledSounds.includes('PARTICIPANT_JOINED_SOUND') }
  187. label = { t('settings.participantJoined') }
  188. name = 'soundsParticipantJoined'
  189. onChange = { this._onChange } />
  190. <Checkbox
  191. checked = { soundsParticipantLeft && !disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
  192. className = { classes.checkbox }
  193. disabled = { disabledSounds.includes('PARTICIPANT_LEFT_SOUND') }
  194. label = { t('settings.participantLeft') }
  195. name = 'soundsParticipantLeft'
  196. onChange = { this._onChange } />
  197. <Checkbox
  198. checked = { soundsTalkWhileMuted && !disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
  199. className = { classes.checkbox }
  200. disabled = { disabledSounds.includes('TALK_WHILE_MUTED_SOUND') }
  201. label = { t('settings.talkWhileMuted') }
  202. name = 'soundsTalkWhileMuted'
  203. onChange = { this._onChange } />
  204. <Checkbox
  205. checked = { soundsParticipantKnocking
  206. && !disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
  207. className = { classes.checkbox }
  208. disabled = { disabledSounds.includes('KNOCKING_PARTICIPANT_SOUND') }
  209. label = { t('settings.participantKnocking') }
  210. name = 'soundsParticipantKnocking'
  211. onChange = { this._onChange } />
  212. </div>
  213. )}
  214. {showNotificationsSettings && (
  215. <div className = { classes.column }>
  216. <h2 className = { classes.title }>
  217. {t('notify.displayNotifications')}
  218. </h2>
  219. {
  220. Object.keys(enabledNotifications).map(key => (
  221. <Checkbox
  222. checked = { Boolean(enabledNotifications[key as
  223. keyof typeof enabledNotifications]) }
  224. className = { classes.checkbox }
  225. key = { key }
  226. label = { t(key) }
  227. name = { `show-${key}` }
  228. /* eslint-disable-next-line react/jsx-no-bind */
  229. onChange = { e => this._onEnabledNotificationsChanged(e, key) } />
  230. ))
  231. }
  232. </div>
  233. )}
  234. </div>
  235. );
  236. }
  237. }
  238. export default withStyles(styles)(translate(NotificationsTab));