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.

DeviceSelector.js 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import Select from '@atlaskit/single-select';
  2. import React, { Component } from 'react';
  3. import { translate } from '../../base/i18n';
  4. /**
  5. * React component for selecting a device from a select element. Wraps Select
  6. * with device selection specific logic.
  7. *
  8. * @extends Component
  9. */
  10. class DeviceSelector extends Component {
  11. /**
  12. * DeviceSelector component's property types.
  13. *
  14. * @static
  15. */
  16. static propTypes = {
  17. /**
  18. * MediaDeviceInfos used for display in the select element.
  19. */
  20. devices: React.PropTypes.array,
  21. /**
  22. * If false, will return a selector with no selection options.
  23. */
  24. hasPermission: React.PropTypes.bool,
  25. /**
  26. * If true, will render the selector disabled with a default selection.
  27. */
  28. isDisabled: React.PropTypes.bool,
  29. /**
  30. * The translation key to display as a menu label.
  31. */
  32. label: React.PropTypes.string,
  33. /**
  34. * The callback to invoke when a selection is made.
  35. */
  36. onSelect: React.PropTypes.func,
  37. /**
  38. * The default device to display as selected.
  39. */
  40. selectedDeviceId: React.PropTypes.string,
  41. /**
  42. * Invoked to obtain translated strings.
  43. */
  44. t: React.PropTypes.func
  45. }
  46. /**
  47. * Initializes a new DeviceSelector instance.
  48. *
  49. * @param {Object} props - The read-only React Component props with which
  50. * the new instance is to be initialized.
  51. */
  52. constructor(props) {
  53. super(props);
  54. this._onSelect = this._onSelect.bind(this);
  55. }
  56. /**
  57. * Implements React's {@link Component#render()}.
  58. *
  59. * @inheritdoc
  60. * @returns {ReactElement}
  61. */
  62. render() {
  63. if (!this.props.hasPermission) {
  64. return this._renderNoPermission();
  65. }
  66. if (!this.props.devices.length) {
  67. return this._renderNoDevices();
  68. }
  69. const items = this.props.devices.map(this._createSelectItem);
  70. const defaultSelected = items.find(item =>
  71. item.value === this.props.selectedDeviceId
  72. );
  73. return this._createSelector({
  74. defaultSelected,
  75. isDisabled: this.props.isDisabled,
  76. items,
  77. placeholder: 'deviceSelection.selectADevice'
  78. });
  79. }
  80. /**
  81. * Creates an object in the format expected by Select for an option element.
  82. *
  83. * @param {MediaDeviceInfo} device - An object with a label and a deviceId.
  84. * @private
  85. * @returns {Object} The passed in media device description converted to a
  86. * format recognized as a valid Select item.
  87. */
  88. _createSelectItem(device) {
  89. return {
  90. content: device.label,
  91. value: device.deviceId
  92. };
  93. }
  94. /**
  95. * Creates a Select Component using passed in props and options.
  96. *
  97. * @param {Object} options - Additional configuration for display Select.
  98. * @param {Object} options.defaultSelected - The option that should be set
  99. * as currently chosen.
  100. * @param {boolean} options.isDisabled - If true Select will not open on
  101. * click.
  102. * @param {Array} options.items - All the selectable options to display.
  103. * @param {string} options.placeholder - The translation key to display when
  104. * no selection has been made.
  105. * @private
  106. * @returns {ReactElement}
  107. */
  108. _createSelector(options) {
  109. return (
  110. <Select
  111. defaultSelected = { options.defaultSelected }
  112. isDisabled = { options.isDisabled }
  113. isFirstChild = { true }
  114. items = { [ { items: options.items || [] } ] }
  115. label = { this.props.t(this.props.label) }
  116. noMatchesFound
  117. = { this.props.t('deviceSelection.noOtherDevices') }
  118. onSelected = { this._onSelect }
  119. placeholder = { this.props.t(options.placeholder) }
  120. shouldFitContainer = { true } />
  121. );
  122. }
  123. /**
  124. * Invokes the passed in callback to notify of selection changes.
  125. *
  126. * @param {Object} selection - Event returned from Select.
  127. * @private
  128. * @returns {void}
  129. */
  130. _onSelect(selection) {
  131. this.props.onSelect(selection.item.value);
  132. }
  133. /**
  134. * Creates a Select Component that is disabled and has a placeholder
  135. * indicating there are no devices to select.
  136. *
  137. * @private
  138. * @returns {ReactElement}
  139. */
  140. _renderNoDevices() {
  141. return this._createSelector({
  142. isDisabled: true,
  143. placeholder: 'settings.noDevice'
  144. });
  145. }
  146. /**
  147. * Creates a Select Component that is disabled and has a placeholder stating
  148. * there is no permission to display the devices.
  149. *
  150. * @private
  151. * @returns {ReactElement}
  152. */
  153. _renderNoPermission() {
  154. return this._createSelector({
  155. isDisabled: true,
  156. placeholder: 'settings.noPermission'
  157. });
  158. }
  159. }
  160. export default translate(DeviceSelector);