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

functions.js 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /* @flow */
  2. import SideContainerToggler
  3. from '../../../modules/UI/side_pannels/SideContainerToggler';
  4. import { appNavigate } from '../app';
  5. import { toggleAudioMuted, toggleVideoMuted } from '../base/media';
  6. import defaultToolbarButtons from './defaultToolbarButtons';
  7. declare var $: Function;
  8. declare var AJS: Object;
  9. declare var interfaceConfig: Object;
  10. import type { Dispatch } from 'redux-thunk';
  11. type MapOfAttributes = { [key: string]: * };
  12. /**
  13. * Maps actions to React component props.
  14. *
  15. * @param {Function} dispatch - Redux action dispatcher.
  16. * @returns {{
  17. * _onHangup: Function,
  18. * _onToggleAudio: Function,
  19. * _onToggleVideo: Function
  20. * }}
  21. * @private
  22. */
  23. export function abstractMapDispatchToProps(dispatch: Dispatch<*>): Object {
  24. return {
  25. /**
  26. * Dispatches action to leave the current conference.
  27. *
  28. * @private
  29. * @returns {void}
  30. * @type {Function}
  31. */
  32. _onHangup() {
  33. // XXX We don't know here which value is effectively/internally
  34. // used when there's no valid room name to join. It isn't our
  35. // business to know that anyway. The undefined value is our
  36. // expression of (1) the lack of knowledge & (2) the desire to no
  37. // longer have a valid room name to join.
  38. return dispatch(appNavigate(undefined));
  39. },
  40. /**
  41. * Dispatches an action to toggle the mute state of the
  42. * audio/microphone.
  43. *
  44. * @private
  45. * @returns {Object} - Dispatched action.
  46. * @type {Function}
  47. */
  48. _onToggleAudio() {
  49. return dispatch(toggleAudioMuted());
  50. },
  51. /**
  52. * Dispatches an action to toggle the mute state of the video/camera.
  53. *
  54. * @private
  55. * @returns {Object} - Dispatched action.
  56. * @type {Function}
  57. */
  58. _onToggleVideo() {
  59. return dispatch(toggleVideoMuted());
  60. }
  61. };
  62. }
  63. /**
  64. * Maps parts of media state to component props.
  65. *
  66. * @param {Object} state - Redux state.
  67. * @protected
  68. * @returns {{
  69. * _audioMuted: boolean,
  70. * _videoMuted: boolean,
  71. * _visible: boolean
  72. * }}
  73. */
  74. export function abstractMapStateToProps(state: Object): Object {
  75. const media = state['features/base/media'];
  76. const { visible } = state['features/toolbar'];
  77. return {
  78. /**
  79. * Flag showing that audio is muted.
  80. *
  81. * @protected
  82. * @type {boolean}
  83. */
  84. _audioMuted: media.audio.muted,
  85. /**
  86. * Flag showing whether video is muted.
  87. *
  88. * @protected
  89. * @type {boolean}
  90. */
  91. _videoMuted: media.video.muted,
  92. /**
  93. * Flag showing whether toolbar is visible.
  94. *
  95. * @protected
  96. * @type {boolean}
  97. */
  98. _visible: visible
  99. };
  100. }
  101. /**
  102. * Takes toolbar button props and maps them to HTML attributes to set.
  103. *
  104. * @param {Object} props - Props set to the React component.
  105. * @returns {Object}
  106. */
  107. export function getButtonAttributesByProps(props: Object): MapOfAttributes {
  108. const classNames = [ ...props.classNames ];
  109. props.toggled && classNames.push('toggled');
  110. props.unclickable && classNames.push('unclickable');
  111. const result: MapOfAttributes = {
  112. className: classNames.join(' '),
  113. 'data-container': 'body',
  114. 'data-placement': 'bottom',
  115. id: props.id
  116. };
  117. if (!props.enabled) {
  118. result.disabled = 'disabled';
  119. }
  120. if (props.hidden) {
  121. result.style = { display: 'none' };
  122. }
  123. return result;
  124. }
  125. /**
  126. * Returns object containing default buttons for the primary and secondary
  127. * toolbars.
  128. *
  129. * @returns {Object}
  130. */
  131. export function getDefaultToolbarButtons(): Object {
  132. let toolbarButtons = {
  133. primaryToolbarButtons: new Map(),
  134. secondaryToolbarButtons: new Map()
  135. };
  136. if (typeof interfaceConfig !== 'undefined'
  137. && interfaceConfig.TOOLBAR_BUTTONS) {
  138. toolbarButtons = interfaceConfig.TOOLBAR_BUTTONS.reduce(
  139. (acc, buttonName) => {
  140. const button = defaultToolbarButtons[buttonName];
  141. if (button) {
  142. const place = _getToolbarButtonPlace(buttonName);
  143. button.buttonName = buttonName;
  144. acc[place].set(buttonName, button);
  145. }
  146. return acc;
  147. }, toolbarButtons);
  148. }
  149. return toolbarButtons;
  150. }
  151. /**
  152. * Get place for toolbar button.
  153. * Now it can be in main toolbar or in extended (left) toolbar.
  154. *
  155. * @param {string} btn - Button name.
  156. * @private
  157. * @returns {string}
  158. */
  159. function _getToolbarButtonPlace(btn) {
  160. return (
  161. interfaceConfig.MAIN_TOOLBAR_BUTTONS.includes(btn)
  162. ? 'primaryToolbarButtons'
  163. : 'secondaryToolbarButtons');
  164. }
  165. /**
  166. * Returns toolbar class names to add while rendering.
  167. *
  168. * @param {Object} props - Props object pass to React component.
  169. * @returns {Object}
  170. * @private
  171. */
  172. export function getToolbarClassNames(props: Object) {
  173. const primaryToolbarClassNames = [ 'toolbar_primary' ];
  174. const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
  175. if (props._visible) {
  176. const slideInAnimation
  177. = SideContainerToggler.isVisible ? 'slideInExtX' : 'slideInX';
  178. primaryToolbarClassNames.push('fadeIn');
  179. secondaryToolbarClassNames.push(slideInAnimation);
  180. } else {
  181. const slideOutAnimation
  182. = SideContainerToggler.isVisible ? 'slideOutExtX' : 'slideOutX';
  183. primaryToolbarClassNames.push('fadeOut');
  184. secondaryToolbarClassNames.push(slideOutAnimation);
  185. }
  186. return {
  187. primaryToolbarClassName: primaryToolbarClassNames.join(' '),
  188. secondaryToolbarClassName: secondaryToolbarClassNames.join(' ')
  189. };
  190. }
  191. /**
  192. * Show custom popup/tooltip for a specified button.
  193. *
  194. * @param {string} popupSelectorID - The selector id of the popup to show.
  195. * @param {boolean} show - True or false/show or hide the popup.
  196. * @param {number} timeout - The time to show the popup.
  197. * @returns {void}
  198. */
  199. export function showCustomToolbarPopup(
  200. popupSelectorID: string,
  201. show: boolean,
  202. timeout: number) {
  203. AJS.$(popupSelectorID).tooltip({
  204. gravity: $(popupSelectorID).attr('data-popup'),
  205. html: true,
  206. title: 'title',
  207. trigger: 'manual'
  208. });
  209. if (show) {
  210. AJS.$(popupSelectorID).tooltip('show');
  211. setTimeout(
  212. () => {
  213. // hide the tooltip
  214. AJS.$(popupSelectorID).tooltip('hide');
  215. },
  216. timeout);
  217. } else {
  218. AJS.$(popupSelectorID).tooltip('hide');
  219. }
  220. }