Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

DeviceSelector.web.tsx 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { Theme } from '@mui/material';
  2. import { withStyles } from '@mui/styles';
  3. import React, { Component } from 'react';
  4. import { WithTranslation } from 'react-i18next';
  5. import { translate } from '../../base/i18n/functions';
  6. import { withPixelLineHeight } from '../../base/styles/functions.web';
  7. import Select from '../../base/ui/components/web/Select';
  8. /**
  9. * The type of the React {@code Component} props of {@link DeviceSelector}.
  10. */
  11. interface IProps extends WithTranslation {
  12. /**
  13. * CSS classes object.
  14. */
  15. classes: any;
  16. /**
  17. * MediaDeviceInfos used for display in the select element.
  18. */
  19. devices: Array<MediaDeviceInfo> | undefined;
  20. /**
  21. * If false, will return a selector with no selection options.
  22. */
  23. hasPermission: boolean;
  24. /**
  25. * CSS class for the icon to the left of the dropdown trigger.
  26. */
  27. icon: string;
  28. /**
  29. * The id of the dropdown element.
  30. */
  31. id: string;
  32. /**
  33. * If true, will render the selector disabled with a default selection.
  34. */
  35. isDisabled: boolean;
  36. /**
  37. * The translation key to display as a menu label.
  38. */
  39. label: string;
  40. /**
  41. * The callback to invoke when a selection is made.
  42. */
  43. onSelect: Function;
  44. /**
  45. * The default device to display as selected.
  46. */
  47. selectedDeviceId: string;
  48. }
  49. const styles = (theme: Theme) => {
  50. return {
  51. textSelector: {
  52. width: '100%',
  53. boxSizing: 'border-box',
  54. borderRadius: theme.shape.borderRadius,
  55. backgroundColor: theme.palette.uiBackground,
  56. padding: '10px 16px',
  57. textAlign: 'center',
  58. ...withPixelLineHeight(theme.typography.bodyShortRegular),
  59. border: `1px solid ${theme.palette.ui03}`
  60. }
  61. };
  62. };
  63. /**
  64. * React component for selecting a device from a select element. Wraps
  65. * AKDropdownMenu with device selection specific logic.
  66. *
  67. * @augments Component
  68. */
  69. class DeviceSelector extends Component<IProps> {
  70. /**
  71. * Initializes a new DeviceSelector instance.
  72. *
  73. * @param {Object} props - The read-only React Component props with which
  74. * the new instance is to be initialized.
  75. */
  76. constructor(props: IProps) {
  77. super(props);
  78. this._onSelect = this._onSelect.bind(this);
  79. this._createDropdown = this._createDropdown.bind(this);
  80. }
  81. /**
  82. * Implements React's {@link Component#render()}.
  83. *
  84. * @inheritdoc
  85. * @returns {ReactElement}
  86. */
  87. render() {
  88. if (this.props.hasPermission === undefined) {
  89. return null;
  90. }
  91. if (!this.props.hasPermission) {
  92. return this._renderNoPermission();
  93. }
  94. if (!this.props.devices || !this.props.devices.length) {
  95. return this._renderNoDevices();
  96. }
  97. const items = this.props.devices.map(device => {
  98. return {
  99. value: device.deviceId,
  100. label: device.label || device.deviceId
  101. };
  102. });
  103. const defaultSelected = this.props.devices.find(item =>
  104. item.deviceId === this.props.selectedDeviceId
  105. );
  106. return this._createDropdown({
  107. defaultSelected,
  108. isDisabled: this.props.isDisabled,
  109. items,
  110. placeholder: this.props.t('deviceSelection.selectADevice')
  111. });
  112. }
  113. /**
  114. * Creates a AKDropdownMenu Component using passed in props and options. If
  115. * the dropdown needs to be disabled, then only the AKDropdownMenu trigger
  116. * element is returned to simulate a disabled state.
  117. *
  118. * @param {Object} options - Additional configuration for display.
  119. * @param {Object} options.defaultSelected - The option that should be set
  120. * as currently chosen.
  121. * @param {boolean} options.isDisabled - If true, only the AKDropdownMenu
  122. * trigger component will be returned to simulate a disabled dropdown.
  123. * @param {Array} options.items - All the selectable options to display.
  124. * @param {string} options.placeholder - The translation key to display when
  125. * no selection has been made.
  126. * @private
  127. * @returns {ReactElement}
  128. */
  129. _createDropdown(options: { defaultSelected?: MediaDeviceInfo; isDisabled: boolean;
  130. items?: Array<{ label: string; value: string; }>; placeholder: string; }) {
  131. const triggerText
  132. = (options.defaultSelected && (options.defaultSelected.label || options.defaultSelected.deviceId))
  133. || options.placeholder;
  134. const { classes } = this.props;
  135. if (options.isDisabled || !options.items?.length) {
  136. return (
  137. <div className = { classes.textSelector }>
  138. {triggerText}
  139. </div>
  140. );
  141. }
  142. return (
  143. <Select
  144. label = { this.props.t(this.props.label) }
  145. onChange = { this._onSelect }
  146. options = { options.items }
  147. value = { this.props.selectedDeviceId } />
  148. );
  149. }
  150. /**
  151. * Invokes the passed in callback to notify of selection changes.
  152. *
  153. * @param {Object} e - The key event to handle.
  154. *
  155. * @private
  156. * @returns {void}
  157. */
  158. _onSelect(e: React.ChangeEvent<HTMLSelectElement>) {
  159. const deviceId = e.target.value;
  160. if (this.props.selectedDeviceId !== deviceId) {
  161. this.props.onSelect(deviceId);
  162. }
  163. }
  164. /**
  165. * Creates a Select Component that is disabled and has a placeholder
  166. * indicating there are no devices to select.
  167. *
  168. * @private
  169. * @returns {ReactElement}
  170. */
  171. _renderNoDevices() {
  172. return this._createDropdown({
  173. isDisabled: true,
  174. placeholder: this.props.t('settings.noDevice')
  175. });
  176. }
  177. /**
  178. * Creates a AKDropdownMenu Component that is disabled and has a placeholder
  179. * stating there is no permission to display the devices.
  180. *
  181. * @private
  182. * @returns {ReactElement}
  183. */
  184. _renderNoPermission() {
  185. return this._createDropdown({
  186. isDisabled: true,
  187. placeholder: this.props.t('deviceSelection.noPermission')
  188. });
  189. }
  190. }
  191. export default withStyles(styles)(translate(DeviceSelector));