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.

SettingsDialog.js 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { getAvailableDevices } from '../../../base/devices';
  5. import { DialogWithTabs, hideDialog } from '../../../base/dialog';
  6. import {
  7. DeviceSelection,
  8. getDeviceSelectionDialogProps,
  9. submitDeviceSelectionTab
  10. } from '../../../device-selection';
  11. import MoreTab from './MoreTab';
  12. import ProfileTab from './ProfileTab';
  13. import { getMoreTabProps, getProfileTabProps } from '../../functions';
  14. import { submitMoreTab, submitProfileTab } from '../../actions';
  15. import { SETTINGS_TABS } from '../../constants';
  16. declare var APP: Object;
  17. declare var interfaceConfig: Object;
  18. /**
  19. * The type of the React {@code Component} props of
  20. * {@link ConnectedSettingsDialog}.
  21. */
  22. type Props = {
  23. /**
  24. * Which settings tab should be initially displayed. If not defined then
  25. * the first tab will be displayed.
  26. */
  27. defaultTab: string,
  28. /**
  29. * Information about the tabs to be rendered.
  30. */
  31. _tabs: Array<Object>,
  32. /**
  33. * Invoked to save changed settings.
  34. */
  35. dispatch: Function,
  36. };
  37. /**
  38. * A React {@code Component} for displaying a dialog to modify local settings
  39. * and conference-wide (moderator) settings. This version is connected to
  40. * redux to get the current settings.
  41. *
  42. * @extends Component
  43. */
  44. class SettingsDialog extends Component<Props> {
  45. /**
  46. * Initializes a new {@code ConnectedSettingsDialog} instance.
  47. *
  48. * @param {Props} props - The React {@code Component} props to initialize
  49. * the new {@code ConnectedSettingsDialog} instance with.
  50. */
  51. constructor(props: Props) {
  52. super(props);
  53. // Bind event handlers so they are only bound once for every instance.
  54. this._closeDialog = this._closeDialog.bind(this);
  55. }
  56. /**
  57. * Implements React's {@link Component#render()}.
  58. *
  59. * @inheritdoc
  60. * @returns {ReactElement}
  61. */
  62. render() {
  63. const { _tabs, defaultTab, dispatch } = this.props;
  64. const onSubmit = this._closeDialog;
  65. const defaultTabIdx
  66. = _tabs.findIndex(({ name }) => name === defaultTab);
  67. const tabs = _tabs.map(tab => {
  68. return {
  69. ...tab,
  70. onMount: tab.onMount
  71. ? (...args) => dispatch(tab.onMount(...args))
  72. : undefined,
  73. submit: (...args) => dispatch(tab.submit(...args))
  74. };
  75. });
  76. return (
  77. <DialogWithTabs
  78. closeDialog = { this._closeDialog }
  79. defaultTab = {
  80. defaultTabIdx === -1 ? undefined : defaultTabIdx
  81. }
  82. onSubmit = { onSubmit }
  83. tabs = { tabs } />
  84. );
  85. }
  86. _closeDialog: () => void;
  87. /**
  88. * Callback invoked to close the dialog without saving changes.
  89. *
  90. * @private
  91. * @returns {void}
  92. */
  93. _closeDialog() {
  94. this.props.dispatch(hideDialog());
  95. }
  96. }
  97. /**
  98. * Maps (parts of) the Redux state to the associated props for the
  99. * {@code ConnectedSettingsDialog} component.
  100. *
  101. * @param {Object} state - The Redux state.
  102. * @private
  103. * @returns {{
  104. * tabs: Array<Object>
  105. * }}
  106. */
  107. function _mapStateToProps(state) {
  108. const configuredTabs = interfaceConfig.SETTINGS_SECTIONS || [];
  109. const jwt = state['features/base/jwt'];
  110. // The settings sections to display.
  111. const showDeviceSettings = configuredTabs.includes('devices');
  112. const moreTabProps = getMoreTabProps(state);
  113. const { showModeratorSettings, showLanguageSettings } = moreTabProps;
  114. const showProfileSettings
  115. = configuredTabs.includes('profile') && jwt.isGuest;
  116. const tabs = [];
  117. if (showDeviceSettings) {
  118. tabs.push({
  119. name: SETTINGS_TABS.DEVICES,
  120. component: DeviceSelection,
  121. label: 'settings.devices',
  122. onMount: getAvailableDevices,
  123. props: getDeviceSelectionDialogProps(state),
  124. propsUpdateFunction: (tabState, newProps) => {
  125. // Ensure the device selection tab gets updated when new devices
  126. // are found by taking the new props and only preserving the
  127. // current user selected devices. If this were not done, the
  128. // tab would keep using a copy of the initial props it received,
  129. // leaving the device list to become stale.
  130. return {
  131. ...newProps,
  132. selectedAudioInputId: tabState.selectedAudioInputId,
  133. selectedAudioOutputId: tabState.selectedAudioOutputId,
  134. selectedVideoInputId: tabState.selectedVideoInputId
  135. };
  136. },
  137. styles: 'settings-pane devices-pane',
  138. submit: submitDeviceSelectionTab
  139. });
  140. }
  141. if (showProfileSettings) {
  142. tabs.push({
  143. name: SETTINGS_TABS.PROFILE,
  144. component: ProfileTab,
  145. label: 'profile.title',
  146. props: getProfileTabProps(state),
  147. styles: 'settings-pane profile-pane',
  148. submit: submitProfileTab
  149. });
  150. }
  151. if (showModeratorSettings || showLanguageSettings) {
  152. tabs.push({
  153. name: SETTINGS_TABS.MORE,
  154. component: MoreTab,
  155. label: 'settings.more',
  156. props: moreTabProps,
  157. styles: 'settings-pane more-pane',
  158. submit: submitMoreTab
  159. });
  160. }
  161. return { _tabs: tabs };
  162. }
  163. export default connect(_mapStateToProps)(SettingsDialog);