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.

functions.js 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. import type { Dispatch } from 'redux-thunk';
  8. type MapOfAttributes = { [key: string]: * };
  9. declare var $: Function;
  10. declare var AJS: Object;
  11. declare var interfaceConfig: Object;
  12. /**
  13. * Maps (redux) 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/toolbox'];
  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 toolbox is visible.
  94. *
  95. * @protected
  96. * @type {boolean}
  97. */
  98. _visible: visible
  99. };
  100. }
  101. /* eslint-disable flowtype/space-before-type-colon */
  102. /**
  103. * Takes toolbar button props and maps them to HTML attributes to set.
  104. *
  105. * @param {Object} props - Props set to the React component.
  106. * @returns {MapOfAttributes}
  107. */
  108. export function getButtonAttributesByProps(props: Object = {})
  109. : MapOfAttributes {
  110. let classNames = props.classNames;
  111. if (classNames) {
  112. // XXX Make sure to not modify props.classNames because that'd be bad
  113. // practice.
  114. classNames = [ ...classNames ];
  115. }
  116. props.toggled && classNames.push('toggled');
  117. props.unclickable && classNames.push('unclickable');
  118. const result: MapOfAttributes = {
  119. className: classNames.join(' '),
  120. 'data-container': 'body',
  121. 'data-placement': 'bottom',
  122. id: props.id
  123. };
  124. if (!props.enabled) {
  125. result.disabled = 'disabled';
  126. }
  127. if (props.hidden) {
  128. result.style = { display: 'none' };
  129. }
  130. return result;
  131. }
  132. /* eslint-enable flowtype/space-before-type-colon */
  133. /**
  134. * Returns an object which contains the default buttons for the primary and
  135. * secondary toolbars.
  136. *
  137. * @returns {Object}
  138. */
  139. export function getDefaultToolboxButtons(): Object {
  140. let toolbarButtons = {
  141. primaryToolbarButtons: new Map(),
  142. secondaryToolbarButtons: new Map()
  143. };
  144. if (typeof interfaceConfig !== 'undefined'
  145. && interfaceConfig.TOOLBAR_BUTTONS) {
  146. const { filmStripOnly } = interfaceConfig;
  147. toolbarButtons
  148. = interfaceConfig.TOOLBAR_BUTTONS.reduce(
  149. (acc, buttonName) => {
  150. const button = defaultToolbarButtons[buttonName];
  151. if (button) {
  152. const place = _getToolbarButtonPlace(buttonName);
  153. button.buttonName = buttonName;
  154. // In filmstrip-only mode we only add a button if it's
  155. // filmstrip-only enabled.
  156. if (!filmStripOnly || button.filmstripOnlyEnabled) {
  157. acc[place].set(buttonName, button);
  158. }
  159. }
  160. return acc;
  161. },
  162. toolbarButtons);
  163. }
  164. return toolbarButtons;
  165. }
  166. /**
  167. * Get place for toolbar button. Now it can be in the primary Toolbar or in the
  168. * secondary Toolbar.
  169. *
  170. * @param {string} btn - Button name.
  171. * @private
  172. * @returns {string}
  173. */
  174. function _getToolbarButtonPlace(btn) {
  175. return (
  176. interfaceConfig.MAIN_TOOLBAR_BUTTONS.includes(btn)
  177. ? 'primaryToolbarButtons'
  178. : 'secondaryToolbarButtons');
  179. }
  180. /**
  181. * Returns toolbar class names to add while rendering.
  182. *
  183. * @param {Object} props - Props object pass to React component.
  184. * @returns {Object}
  185. * @private
  186. */
  187. export function getToolbarClassNames(props: Object) {
  188. const primaryToolbarClassNames = [
  189. interfaceConfig.filmStripOnly
  190. ? 'toolbar_filmstrip-only'
  191. : 'toolbar_primary'
  192. ];
  193. const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
  194. if (props._visible) {
  195. const slideInAnimation
  196. = SideContainerToggler.isVisible ? 'slideInExtX' : 'slideInX';
  197. primaryToolbarClassNames.push('fadeIn');
  198. secondaryToolbarClassNames.push(slideInAnimation);
  199. } else {
  200. const slideOutAnimation
  201. = SideContainerToggler.isVisible ? 'slideOutExtX' : 'slideOutX';
  202. primaryToolbarClassNames.push('fadeOut');
  203. secondaryToolbarClassNames.push(slideOutAnimation);
  204. }
  205. return {
  206. primaryToolbarClassName: primaryToolbarClassNames.join(' '),
  207. secondaryToolbarClassName: secondaryToolbarClassNames.join(' ')
  208. };
  209. }
  210. /**
  211. * Show custom popup/tooltip for a specified button.
  212. *
  213. * @param {string} popupSelectorID - The selector id of the popup to show.
  214. * @param {boolean} show - True or false/show or hide the popup.
  215. * @param {number} timeout - The time to show the popup.
  216. * @returns {void}
  217. */
  218. export function showCustomToolbarPopup(
  219. popupSelectorID: string,
  220. show: boolean,
  221. timeout: number) {
  222. AJS.$(popupSelectorID).tooltip({
  223. gravity: $(popupSelectorID).attr('data-popup'),
  224. html: true,
  225. title: 'title',
  226. trigger: 'manual'
  227. });
  228. if (show) {
  229. AJS.$(popupSelectorID).tooltip('show');
  230. setTimeout(
  231. () => {
  232. // hide the tooltip
  233. AJS.$(popupSelectorID).tooltip('hide');
  234. },
  235. timeout);
  236. } else {
  237. AJS.$(popupSelectorID).tooltip('hide');
  238. }
  239. }