您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

DesktopPicker.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /* global config */
  2. import Tabs from '@atlaskit/tabs';
  3. import React, { Component } from 'react';
  4. import { connect } from 'react-redux';
  5. import { Dialog, hideDialog } from '../../base/dialog';
  6. import { translate } from '../../base/i18n';
  7. import {
  8. resetDesktopSources,
  9. obtainDesktopSources
  10. } from '../actions';
  11. import DesktopPickerPane from './DesktopPickerPane';
  12. const updateInterval = 1000;
  13. const thumbnailSize = {
  14. height: 300,
  15. width: 300
  16. };
  17. const tabConfigurations = [
  18. {
  19. label: 'dialog.yourEntireScreen',
  20. type: 'screen',
  21. isDefault: true
  22. },
  23. {
  24. label: 'dialog.applicationWindow',
  25. type: 'window'
  26. }
  27. ];
  28. const validTypes = tabConfigurations.map(configuration => configuration.type);
  29. const configuredTypes = config.desktopSharingChromeSources || [];
  30. const tabsToPopulate = tabConfigurations.filter(configuration =>
  31. configuredTypes.includes(configuration.type)
  32. && validTypes.includes(configuration.type)
  33. );
  34. const typesToFetch = tabsToPopulate.map(configuration => configuration.type);
  35. /**
  36. * React component for DesktopPicker.
  37. *
  38. * @extends Component
  39. */
  40. class DesktopPicker extends Component {
  41. /**
  42. * DesktopPicker component's property types.
  43. *
  44. * @static
  45. */
  46. static propTypes = {
  47. /**
  48. * Used to request DesktopCapturerSources.
  49. */
  50. dispatch: React.PropTypes.func,
  51. /**
  52. * The callback to be invoked when the component is closed or
  53. * when a DesktopCapturerSource has been chosen.
  54. */
  55. onSourceChoose: React.PropTypes.func,
  56. /**
  57. * An object with arrays of DesktopCapturerSources. The key
  58. * should be the source type.
  59. */
  60. sources: React.PropTypes.object,
  61. /**
  62. * Used to obtain translations.
  63. */
  64. t: React.PropTypes.func
  65. }
  66. /**
  67. * Initializes a new DesktopPicker instance.
  68. *
  69. * @param {Object} props - The read-only properties with which the new
  70. * instance is to be initialized.
  71. */
  72. constructor(props) {
  73. super(props);
  74. this.state = {
  75. selectedSourceId: ''
  76. };
  77. this._poller = null;
  78. this._onCloseModal = this._onCloseModal.bind(this);
  79. this._onPreviewClick = this._onPreviewClick.bind(this);
  80. this._onSubmit = this._onSubmit.bind(this);
  81. this._updateSources = this._updateSources.bind(this);
  82. }
  83. /**
  84. * Perform an immediate update request for DesktopCapturerSources and
  85. * begin requesting updates at an interval.
  86. *
  87. * @inheritdoc
  88. */
  89. componentWillMount() {
  90. this._updateSources();
  91. this._startPolling();
  92. }
  93. /**
  94. * Clean up component and DesktopCapturerSource store state.
  95. *
  96. * @inheritdoc
  97. */
  98. componentWillUnmount() {
  99. this._stopPolling();
  100. this.props.dispatch(resetDesktopSources());
  101. }
  102. /**
  103. * Notifies this mounted React Component that it will receive new props.
  104. * Sets a default selected source if one is not already set.
  105. *
  106. * @inheritdoc
  107. * @param {Object} nextProps - The read-only React Component props that this
  108. * instance will receive.
  109. * @returns {void}
  110. */
  111. componentWillReceiveProps(nextProps) {
  112. if (!this.state.selectedSourceId
  113. && nextProps.sources.screen.length) {
  114. this.setState({ selectedSourceId: nextProps.sources.screen[0].id });
  115. }
  116. }
  117. /**
  118. * Implements React's {@link Component#render()}.
  119. *
  120. * @inheritdoc
  121. */
  122. render() {
  123. return (
  124. <Dialog
  125. isModal = { false }
  126. okTitleKey = 'dialog.Share'
  127. onCancel = { this._onCloseModal }
  128. onSubmit = { this._onSubmit }
  129. titleKey = 'dialog.shareYourScreen'
  130. width = 'medium' >
  131. { this._renderTabs() }
  132. </Dialog>);
  133. }
  134. /**
  135. * Dispatches an action to get currently available DesktopCapturerSources.
  136. *
  137. * @private
  138. * @returns {void}
  139. */
  140. _updateSources() {
  141. this.props.dispatch(obtainDesktopSources(
  142. typesToFetch,
  143. {
  144. thumbnailSize
  145. }
  146. ));
  147. }
  148. /**
  149. * Create an interval to update knwon available DesktopCapturerSources.
  150. *
  151. * @private
  152. * @returns {void}
  153. */
  154. _startPolling() {
  155. this._stopPolling();
  156. this._poller = window.setInterval(this._updateSources,
  157. updateInterval);
  158. }
  159. /**
  160. * Cancels the interval to update DesktopCapturerSources.
  161. *
  162. * @private
  163. * @returns {void}
  164. */
  165. _stopPolling() {
  166. window.clearInterval(this._poller);
  167. this._poller = null;
  168. }
  169. /**
  170. * Sets the currently selected DesktopCapturerSource.
  171. *
  172. * @param {string} id - The id of DesktopCapturerSource.
  173. * @returns {void}
  174. */
  175. _onPreviewClick(id) {
  176. this.setState({ selectedSourceId: id });
  177. }
  178. /**
  179. * Request to close the modal and execute callbacks
  180. * with the selected source id.
  181. *
  182. * @returns {void}
  183. */
  184. _onSubmit() {
  185. this._onCloseModal(this.state.selectedSourceId);
  186. }
  187. /**
  188. * Dispatches an action to hide the DesktopPicker and invokes
  189. * the passed in callback with a selectedSourceId, if any.
  190. *
  191. * @param {string} id - The id of the DesktopCapturerSource to pass into
  192. * the onSourceChoose callback.
  193. * @returns {void}
  194. */
  195. _onCloseModal(id = '') {
  196. this.props.onSourceChoose(id);
  197. this.props.dispatch(hideDialog());
  198. }
  199. /**
  200. * Configures and renders the tabs for display.
  201. *
  202. * @returns {ReactElement}
  203. * @private
  204. */
  205. _renderTabs() {
  206. const tabs = tabsToPopulate.map(tabConfig => {
  207. const type = tabConfig.type;
  208. return {
  209. label: this.props.t(tabConfig.label),
  210. defaultSelected: tabConfig.isDefault,
  211. content: <DesktopPickerPane
  212. key = { type }
  213. onClick = { this._onPreviewClick }
  214. onDoubleClick = { this._onCloseModal }
  215. selectedSourceId = { this.state.selectedSourceId }
  216. sources = { this.props.sources[type] || [] }
  217. type = { type } />
  218. };
  219. });
  220. return <Tabs tabs = { tabs } />;
  221. }
  222. }
  223. /**
  224. * Maps (parts of) the Redux state to the associated DesktopPicker's props.
  225. *
  226. * @param {Object} state - Redux state.
  227. * @protected
  228. * @returns {{
  229. * sources: Object
  230. * }}
  231. */
  232. function mapStateToProps(state) {
  233. return {
  234. sources: state['features/desktop-picker/sources']
  235. };
  236. }
  237. export default translate(connect(mapStateToProps)(DesktopPicker));