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.

actions.web.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /* @flow */
  2. import { compose } from 'redux';
  3. import Recording from '../../../modules/UI/recording/Recording';
  4. import SideContainerToggler
  5. from '../../../modules/UI/side_pannels/SideContainerToggler';
  6. import UIEvents from '../../../service/UI/UIEvents';
  7. import UIUtil from '../../../modules/UI/util/UIUtil';
  8. import {
  9. changeLocalRaiseHand,
  10. clearToolboxTimeout,
  11. setSubjectSlideIn,
  12. setToolbarButton,
  13. setToolboxTimeout,
  14. setToolboxTimeoutMS,
  15. setToolboxVisible,
  16. toggleFullScreen,
  17. toggleToolbarButton
  18. } from './actions.native';
  19. import { SET_DEFAULT_TOOLBOX_BUTTONS } from './actionTypes';
  20. import { getDefaultToolboxButtons } from './functions';
  21. declare var $: Function;
  22. declare var APP: Object;
  23. declare var config: Object;
  24. declare var interfaceConfig: Object;
  25. export * from './actions.native';
  26. /**
  27. * Checks whether desktop sharing is enabled and whether
  28. * we have params to start automatically sharing.
  29. *
  30. * @returns {Function}
  31. */
  32. export function checkAutoEnableDesktopSharing(): Function {
  33. return () => {
  34. // XXX Should use dispatcher to toggle screensharing but screensharing
  35. // hasn't been React-ified yet.
  36. if (UIUtil.isButtonEnabled('desktop')
  37. && config.autoEnableDesktopSharing) {
  38. APP.UI.eventEmitter.emit(UIEvents.TOGGLE_SCREENSHARING);
  39. }
  40. };
  41. }
  42. /**
  43. * Docks/undocks the Toolbox.
  44. *
  45. * @param {boolean} dock - True if dock, false otherwise.
  46. * @returns {Function}
  47. */
  48. export function dockToolbox(dock: boolean): Function {
  49. return (dispatch: Dispatch<*>, getState: Function) => {
  50. if (interfaceConfig.filmStripOnly) {
  51. return;
  52. }
  53. const state = getState();
  54. const { timeoutMS, visible } = state['features/toolbox'];
  55. if (dock) {
  56. // First make sure the toolbox is shown.
  57. visible || dispatch(showToolbox());
  58. dispatch(clearToolboxTimeout());
  59. } else if (visible) {
  60. dispatch(
  61. setToolboxTimeout(
  62. () => dispatch(hideToolbox()),
  63. timeoutMS));
  64. } else {
  65. dispatch(showToolbox());
  66. }
  67. };
  68. }
  69. /**
  70. * Returns button on mount/unmount handlers with dispatch function stored in
  71. * closure.
  72. *
  73. * @param {Function} dispatch - Redux action dispatcher.
  74. * @param {Function} getState - The function fetching the Redux state.
  75. * @returns {Object} Button on mount/unmount handlers.
  76. * @private
  77. */
  78. function _getButtonHandlers(dispatch, getState) {
  79. const { isGuest } = getState()['features/jwt'];
  80. const localRaiseHandHandler = compose(dispatch, changeLocalRaiseHand);
  81. const toggleFullScreenHandler = compose(dispatch, toggleFullScreen);
  82. return {
  83. /**
  84. * Mount handler for desktop button.
  85. *
  86. * @type {Object}
  87. */
  88. desktop: {
  89. onMount: () => dispatch(showDesktopSharingButton())
  90. },
  91. /**
  92. * Mount/Unmount handler for toggling fullscreen button.
  93. *
  94. * @type {Object}
  95. */
  96. fullscreen: {
  97. onMount: () =>
  98. APP.UI.addListener(
  99. UIEvents.FULLSCREEN_TOGGLED,
  100. toggleFullScreenHandler),
  101. onUnmount: () =>
  102. APP.UI.removeListener(
  103. UIEvents.FULLSCREEN_TOGGLED,
  104. toggleFullScreenHandler)
  105. },
  106. /**
  107. * Mount handler for profile button.
  108. *
  109. * @type {Object}
  110. */
  111. profile: {
  112. onMount: () =>
  113. isGuest
  114. || dispatch(setProfileButtonUnclickable(true))
  115. },
  116. /**
  117. * Mount/Unmount handlers for raisehand button.
  118. *
  119. * @type {button}
  120. */
  121. raisehand: {
  122. onMount: () =>
  123. APP.UI.addListener(
  124. UIEvents.LOCAL_RAISE_HAND_CHANGED,
  125. localRaiseHandHandler),
  126. onUnmount: () =>
  127. APP.UI.removeListener(
  128. UIEvents.LOCAL_RAISE_HAND_CHANGED,
  129. localRaiseHandHandler)
  130. },
  131. /**
  132. * Mount handler for recording button.
  133. *
  134. * @type {Object}
  135. */
  136. recording: {
  137. onMount: () =>
  138. config.enableRecording
  139. && dispatch(showRecordingButton())
  140. }
  141. };
  142. }
  143. /**
  144. * Hides the toolbox.
  145. *
  146. * @param {boolean} force - True to force the hiding of the toolbox without
  147. * caring about the extended toolbar side panels.
  148. * @returns {Function}
  149. */
  150. export function hideToolbox(force: boolean = false): Function {
  151. return (dispatch: Dispatch<*>, getState: Function) => {
  152. const state = getState();
  153. const {
  154. alwaysVisible,
  155. hovered,
  156. timeoutMS
  157. } = state['features/toolbox'];
  158. if (alwaysVisible) {
  159. return;
  160. }
  161. dispatch(clearToolboxTimeout());
  162. if (!force
  163. && (hovered
  164. || APP.UI.isRingOverlayVisible()
  165. || SideContainerToggler.isVisible())) {
  166. dispatch(
  167. setToolboxTimeout(
  168. () => dispatch(hideToolbox()),
  169. timeoutMS));
  170. } else {
  171. dispatch(setToolboxVisible(false));
  172. dispatch(setSubjectSlideIn(false));
  173. }
  174. };
  175. }
  176. /**
  177. * Sets the default toolbar buttons of the Toolbox.
  178. *
  179. * @returns {Function}
  180. */
  181. export function setDefaultToolboxButtons(): Function {
  182. return (dispatch: Dispatch, getState: Function) => {
  183. // Save dispatch function in closure.
  184. const buttonHandlers = _getButtonHandlers(dispatch, getState);
  185. const toolboxButtons = getDefaultToolboxButtons(buttonHandlers);
  186. dispatch({
  187. type: SET_DEFAULT_TOOLBOX_BUTTONS,
  188. ...toolboxButtons
  189. });
  190. };
  191. }
  192. /**
  193. * Signals that unclickable property of profile button should change its value.
  194. *
  195. * @param {boolean} unclickable - Shows whether button is unclickable.
  196. * @returns {Function}
  197. */
  198. export function setProfileButtonUnclickable(unclickable: boolean): Function {
  199. return (dispatch: Dispatch<*>) => {
  200. const buttonName = 'profile';
  201. dispatch(setToolbarButton(buttonName, {
  202. unclickable
  203. }));
  204. UIUtil.removeTooltip(document.getElementById('toolbar_button_profile'));
  205. };
  206. }
  207. /**
  208. * Shows desktop sharing button.
  209. *
  210. * @returns {Function}
  211. */
  212. export function showDesktopSharingButton(): Function {
  213. return (dispatch: Dispatch<*>) => {
  214. const buttonName = 'desktop';
  215. const visible
  216. = APP.conference.isDesktopSharingEnabled
  217. && UIUtil.isButtonEnabled(buttonName);
  218. dispatch(setToolbarButton(buttonName, {
  219. hidden: !visible
  220. }));
  221. };
  222. }
  223. /**
  224. * Shows or hides the dialpad button.
  225. *
  226. * @param {boolean} show - Flag showing whether to show button or not.
  227. * @returns {Function}
  228. */
  229. export function showDialPadButton(show: boolean): Function {
  230. return (dispatch: Dispatch<*>) => {
  231. const buttonName = 'dialpad';
  232. if (show && UIUtil.isButtonEnabled(buttonName)) {
  233. dispatch(setToolbarButton(buttonName, {
  234. hidden: false
  235. }));
  236. }
  237. };
  238. }
  239. /**
  240. * Shows recording button.
  241. *
  242. * @returns {Function}
  243. */
  244. export function showRecordingButton(): Function {
  245. return (dispatch: Dispatch<*>) => {
  246. dispatch(setToolbarButton('recording', {
  247. hidden: false
  248. }));
  249. Recording.initRecordingButton();
  250. };
  251. }
  252. /**
  253. * Shows or hides the 'shared video' button.
  254. *
  255. * @returns {Function}
  256. */
  257. export function showSharedVideoButton(): Function {
  258. return (dispatch: Dispatch<*>) => {
  259. const buttonName = 'sharedvideo';
  260. if (UIUtil.isButtonEnabled(buttonName)
  261. && !config.disableThirdPartyRequests) {
  262. dispatch(setToolbarButton(buttonName, {
  263. hidden: false
  264. }));
  265. }
  266. };
  267. }
  268. /**
  269. * Shows the dial out button if it's required and appropriate
  270. * flag is passed.
  271. *
  272. * @param {boolean} show - Flag showing whether to show button or not.
  273. * @returns {Function}
  274. */
  275. export function showDialOutButton(show: boolean): Function {
  276. return (dispatch: Dispatch<*>, getState: Function) => {
  277. const buttonName = 'dialout';
  278. if (show
  279. && APP.conference.sipGatewayEnabled()
  280. && UIUtil.isButtonEnabled(buttonName)
  281. && (!config.enableUserRolesBasedOnToken
  282. || !getState()['features/jwt'].isGuest)) {
  283. dispatch(setToolbarButton(buttonName, {
  284. hidden: false
  285. }));
  286. }
  287. };
  288. }
  289. /**
  290. * Shows the toolbox for specified timeout.
  291. *
  292. * @param {number} timeout - Timeout for showing the toolbox.
  293. * @returns {Function}
  294. */
  295. export function showToolbox(timeout: number = 0): Object {
  296. return (dispatch: Dispatch<*>, getState: Function) => {
  297. const state = getState();
  298. const {
  299. alwaysVisible,
  300. enabled,
  301. timeoutMS,
  302. visible
  303. } = state['features/toolbox'];
  304. if (enabled && !visible) {
  305. dispatch(setToolboxVisible(true));
  306. dispatch(setSubjectSlideIn(true));
  307. // If the Toolbox is always visible, there's no need for a timeout
  308. // to toggle its visibility.
  309. if (!alwaysVisible) {
  310. dispatch(
  311. setToolboxTimeout(
  312. () => dispatch(hideToolbox()),
  313. timeout || timeoutMS));
  314. dispatch(setToolboxTimeoutMS(interfaceConfig.TOOLBAR_TIMEOUT));
  315. }
  316. }
  317. };
  318. }
  319. /**
  320. * Event handler for side toolbar container toggled event.
  321. *
  322. * @param {string} containerId - ID of the container.
  323. * @returns {Function}
  324. */
  325. export function toggleSideToolbarContainer(containerId: string): Function {
  326. return (dispatch: Dispatch, getState: Function) => {
  327. const state = getState();
  328. const { secondaryToolbarButtons } = state['features/toolbox'];
  329. for (const key of secondaryToolbarButtons.keys()) {
  330. const isButtonEnabled = UIUtil.isButtonEnabled(key);
  331. const button = secondaryToolbarButtons.get(key);
  332. if (isButtonEnabled
  333. && button.sideContainerId
  334. && button.sideContainerId === containerId) {
  335. dispatch(toggleToolbarButton(key));
  336. break;
  337. }
  338. }
  339. };
  340. }