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.native.ts 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { IReduxState } from '../app/types';
  2. import { IStateful } from '../base/app/types';
  3. import { hasAvailableDevices } from '../base/devices/functions.native';
  4. import { TOOLBOX_ALWAYS_VISIBLE, TOOLBOX_ENABLED } from '../base/flags/constants';
  5. import { getFeatureFlag } from '../base/flags/functions';
  6. import { getParticipantCountWithFake } from '../base/participants/functions';
  7. import { toState } from '../base/redux/functions';
  8. import { isLocalVideoTrackDesktop } from '../base/tracks/functions.native';
  9. import { MAIN_TOOLBAR_BUTTONS_PRIORITY } from './constants';
  10. import { isButtonEnabled } from './functions.any';
  11. import { IGetVisibleNativeButtonsParams, IToolboxNativeButton } from './types';
  12. export * from './functions.any';
  13. /**
  14. * Indicates if the desktop share button is disabled or not.
  15. *
  16. * @param {IReduxState} state - The state from the Redux store.
  17. * @returns {boolean}
  18. */
  19. export function isDesktopShareButtonDisabled(state: IReduxState) {
  20. const { muted, unmuteBlocked } = state['features/base/media'].video;
  21. const videoOrShareInProgress = !muted || isLocalVideoTrackDesktop(state);
  22. return unmuteBlocked && !videoOrShareInProgress;
  23. }
  24. /**
  25. * Returns true if the toolbox is visible.
  26. *
  27. * @param {IStateful} stateful - A function or object that can be
  28. * resolved to Redux state by the function {@code toState}.
  29. * @returns {boolean}
  30. */
  31. export function isToolboxVisible(stateful: IStateful) {
  32. const state = toState(stateful);
  33. const { toolbarConfig } = state['features/base/config'];
  34. const { alwaysVisible } = toolbarConfig || {};
  35. const { enabled, visible } = state['features/toolbox'];
  36. const participantCount = getParticipantCountWithFake(state);
  37. const alwaysVisibleFlag = getFeatureFlag(state, TOOLBOX_ALWAYS_VISIBLE, false);
  38. const enabledFlag = getFeatureFlag(state, TOOLBOX_ENABLED, true);
  39. return enabledFlag && enabled
  40. && (alwaysVisible || visible || participantCount === 1 || alwaysVisibleFlag);
  41. }
  42. /**
  43. * Indicates if the video mute button is disabled or not.
  44. *
  45. * @param {IReduxState} state - The state from the Redux store.
  46. * @returns {boolean}
  47. */
  48. export function isVideoMuteButtonDisabled(state: IReduxState) {
  49. const { muted, unmuteBlocked } = state['features/base/media'].video;
  50. return !hasAvailableDevices(state, 'videoInput')
  51. || (unmuteBlocked && Boolean(muted));
  52. }
  53. /**
  54. * Returns all buttons that need to be rendered.
  55. *
  56. * @param {IGetVisibleButtonsParams} params - The parameters needed to extract the visible buttons.
  57. * @returns {Object} - The visible buttons arrays .
  58. */
  59. export function getVisibleNativeButtons(
  60. { allButtons, clientWidth, mainToolbarButtonsThresholds, toolbarButtons }: IGetVisibleNativeButtonsParams) {
  61. const filteredButtons = Object.keys(allButtons).filter(key =>
  62. typeof key !== 'undefined' // filter invalid buttons that may be coming from config.mainToolbarButtons override
  63. && isButtonEnabled(key, toolbarButtons));
  64. const { order } = mainToolbarButtonsThresholds.find(({ width }) => clientWidth > width)
  65. || mainToolbarButtonsThresholds[mainToolbarButtonsThresholds.length - 1];
  66. const mainToolbarButtonKeysOrder = [
  67. ...order.filter(key => filteredButtons.includes(key)),
  68. ...MAIN_TOOLBAR_BUTTONS_PRIORITY.filter(key => !order.includes(key) && filteredButtons.includes(key)),
  69. ...filteredButtons.filter(key => !order.includes(key) && !MAIN_TOOLBAR_BUTTONS_PRIORITY.includes(key))
  70. ];
  71. const mainButtonsKeys = mainToolbarButtonKeysOrder.slice(0, order.length);
  72. const overflowMenuButtons = filteredButtons.reduce((acc, key) => {
  73. if (!mainButtonsKeys.includes(key)) {
  74. acc.push(allButtons[key]);
  75. }
  76. return acc;
  77. }, [] as IToolboxNativeButton[]);
  78. // if we have 1 button in the overflow menu it is better to directly display it in the main toolbar by replacing
  79. // the "More" menu button with it.
  80. if (overflowMenuButtons.length === 1) {
  81. const button = overflowMenuButtons.shift()?.key;
  82. button && mainButtonsKeys.push(button);
  83. }
  84. const mainMenuButtons
  85. = mainButtonsKeys.map(key => allButtons[key]).sort((a, b) => {
  86. // Native toolbox includes hangup and overflowmenu button keys, too
  87. // hangup goes last, overflowmenu goes second-to-last
  88. if (a.key === 'hangup' || a.key === 'overflowmenu') {
  89. return 1;
  90. }
  91. if (b.key === 'hangup' || b.key === 'overflowmenu') {
  92. return -1;
  93. }
  94. return 0; // other buttons are sorted by priority
  95. });
  96. return {
  97. mainMenuButtons,
  98. overflowMenuButtons
  99. };
  100. }