Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

subscriber.web.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // @flow
  2. import { isMobileBrowser } from '../base/environment/utils';
  3. import { getParticipantCountWithFake, pinParticipant } from '../base/participants';
  4. import { StateListenerRegistry } from '../base/redux';
  5. import { clientResized } from '../base/responsive-ui';
  6. import { shouldHideSelfView } from '../base/settings';
  7. import { setFilmstripVisible } from '../filmstrip/actions';
  8. import { selectParticipantInLargeVideo } from '../large-video/actions.any';
  9. import { getParticipantsPaneOpen } from '../participants-pane/functions';
  10. import { setOverflowDrawer } from '../toolbox/actions.web';
  11. import { LAYOUTS, getCurrentLayout, shouldDisplayTileView } from '../video-layout';
  12. import {
  13. clearStageParticipants,
  14. setHorizontalViewDimensions,
  15. setScreenshareFilmstripParticipant,
  16. setScreensharingTileDimensions,
  17. setStageFilmstripViewDimensions,
  18. setTileViewDimensions,
  19. setVerticalViewDimensions
  20. } from './actions.web';
  21. import {
  22. ASPECT_RATIO_BREAKPOINT,
  23. DISPLAY_DRAWER_THRESHOLD
  24. } from './constants';
  25. import {
  26. isFilmstripResizable,
  27. isTopPanelEnabled
  28. } from './functions.web';
  29. import './subscriber.any';
  30. /**
  31. * Listens for changes in the number of participants to calculate the dimensions of the tile view grid and the tiles.
  32. */
  33. StateListenerRegistry.register(
  34. /* selector */ state => {
  35. return {
  36. numberOfParticipants: getParticipantCountWithFake(state),
  37. disableSelfView: shouldHideSelfView(state),
  38. localScreenShare: state['features/base/participants'].localScreenShare
  39. };
  40. },
  41. /* listener */ (currentState, store) => {
  42. const state = store.getState();
  43. const resizableFilmstrip = isFilmstripResizable(state);
  44. if (shouldDisplayTileView(state)) {
  45. store.dispatch(setTileViewDimensions());
  46. }
  47. if (resizableFilmstrip) {
  48. store.dispatch(setVerticalViewDimensions());
  49. }
  50. }, {
  51. deepEquals: true
  52. });
  53. /**
  54. * Listens for changes in the selected layout to calculate the dimensions of the tile view grid and horizontal view.
  55. */
  56. StateListenerRegistry.register(
  57. /* selector */ state => {
  58. const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
  59. return {
  60. layout: getCurrentLayout(state),
  61. height: clientHeight,
  62. width: clientWidth
  63. };
  64. },
  65. /* listener */ ({ layout }, store) => {
  66. switch (layout) {
  67. case LAYOUTS.TILE_VIEW: {
  68. const { pinnedParticipant } = store.getState()['features/base/participants'];
  69. if (pinnedParticipant) {
  70. store.dispatch(pinParticipant(null));
  71. }
  72. store.dispatch(clearStageParticipants());
  73. store.dispatch(setTileViewDimensions());
  74. break;
  75. }
  76. case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
  77. store.dispatch(setHorizontalViewDimensions());
  78. break;
  79. case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
  80. store.dispatch(setVerticalViewDimensions());
  81. if (store.getState()['features/filmstrip'].activeParticipants.length > 1) {
  82. store.dispatch(clearStageParticipants());
  83. }
  84. break;
  85. case LAYOUTS.STAGE_FILMSTRIP_VIEW:
  86. store.dispatch(pinParticipant(null));
  87. break;
  88. }
  89. }, {
  90. deepEquals: true
  91. });
  92. /**
  93. * Listens for changes in the chat state to recompute available width.
  94. */
  95. StateListenerRegistry.register(
  96. /* selector */ state => state['features/chat'].isOpen,
  97. /* listener */ (isChatOpen, store) => {
  98. const { innerWidth, innerHeight } = window;
  99. if (isChatOpen) {
  100. // $FlowFixMe
  101. document.body.classList.add('shift-right');
  102. } else {
  103. // $FlowFixMe
  104. document.body.classList.remove('shift-right');
  105. }
  106. store.dispatch(clientResized(innerWidth, innerHeight));
  107. });
  108. /**
  109. * Listens for changes in the participant pane state to calculate the
  110. * dimensions of the tile view grid and the tiles.
  111. */
  112. StateListenerRegistry.register(
  113. /* selector */ getParticipantsPaneOpen,
  114. /* listener */ (isOpen, store) => {
  115. const { innerWidth, innerHeight } = window;
  116. store.dispatch(clientResized(innerWidth, innerHeight));
  117. });
  118. /**
  119. * Listens for changes in the client width to determine whether the overflow menu(s) should be displayed as drawers.
  120. */
  121. StateListenerRegistry.register(
  122. /* selector */ state => state['features/base/responsive-ui'].clientWidth < DISPLAY_DRAWER_THRESHOLD,
  123. /* listener */ (widthBelowThreshold, store) => {
  124. if (isMobileBrowser()) {
  125. store.dispatch(setOverflowDrawer(widthBelowThreshold));
  126. }
  127. });
  128. /**
  129. * Gracefully hide/show the filmstrip when going past threshold.
  130. */
  131. StateListenerRegistry.register(
  132. /* selector */ state => state['features/base/responsive-ui'].clientWidth < ASPECT_RATIO_BREAKPOINT,
  133. /* listener */ (widthBelowThreshold, store) => {
  134. const state = store.getState();
  135. const { disableFilmstripAutohiding } = state['features/base/config'];
  136. if (!disableFilmstripAutohiding) {
  137. store.dispatch(setFilmstripVisible(!widthBelowThreshold));
  138. }
  139. });
  140. /**
  141. * Listens for changes in the filmstrip width to determine the size of the tiles.
  142. */
  143. StateListenerRegistry.register(
  144. /* selector */ state => state['features/filmstrip'].width?.current,
  145. /* listener */(_, store) => {
  146. store.dispatch(setVerticalViewDimensions());
  147. });
  148. /**
  149. * Listens for changes in the filmstrip config to determine the size of the tiles.
  150. */
  151. StateListenerRegistry.register(
  152. /* selector */ state => state['features/base/config'].filmstrip?.disableResizable,
  153. /* listener */(_, store) => {
  154. store.dispatch(setVerticalViewDimensions());
  155. });
  156. /**
  157. * Listens for changes to determine the size of the stage filmstrip tiles.
  158. */
  159. StateListenerRegistry.register(
  160. /* selector */ state => {
  161. return {
  162. remoteScreenShares: state['features/video-layout'].remoteScreenShares.length,
  163. length: state['features/filmstrip'].activeParticipants.length,
  164. width: state['features/filmstrip'].width?.current,
  165. visible: state['features/filmstrip'].visible,
  166. clientWidth: state['features/base/responsive-ui'].clientWidth,
  167. clientHeight: state['features/base/responsive-ui'].clientHeight,
  168. tileView: state['features/video-layout'].tileViewEnabled,
  169. height: state['features/filmstrip'].topPanelHeight?.current
  170. };
  171. },
  172. /* listener */(_, store) => {
  173. if (getCurrentLayout(store.getState()) === LAYOUTS.STAGE_FILMSTRIP_VIEW) {
  174. store.dispatch(setStageFilmstripViewDimensions());
  175. }
  176. }, {
  177. deepEquals: true
  178. });
  179. /**
  180. * Listens for changes in the active participants count determine the stage participant (when
  181. * there's just one).
  182. */
  183. StateListenerRegistry.register(
  184. /* selector */ state => state['features/filmstrip'].activeParticipants,
  185. /* listener */(activeParticipants, store) => {
  186. if (activeParticipants.length <= 1) {
  187. store.dispatch(selectParticipantInLargeVideo());
  188. }
  189. });
  190. /**
  191. * Listens for changes to determine the size of the screenshare filmstrip.
  192. */
  193. StateListenerRegistry.register(
  194. /* selector */ state => {
  195. return {
  196. length: state['features/video-layout'].remoteScreenShares.length,
  197. clientWidth: state['features/base/responsive-ui'].clientWidth,
  198. clientHeight: state['features/base/responsive-ui'].clientHeight,
  199. height: state['features/filmstrip'].topPanelHeight?.current,
  200. width: state['features/filmstrip'].width?.current,
  201. visible: state['features/filmstrip'].visible,
  202. topPanelVisible: state['features/filmstrip'].topPanelVisible
  203. };
  204. },
  205. /* listener */({ length }, store) => {
  206. if (length >= 1 && isTopPanelEnabled(store.getState())) {
  207. store.dispatch(setScreensharingTileDimensions());
  208. }
  209. }, {
  210. deepEquals: true
  211. });
  212. /**
  213. * Listens for changes to clear invalid data.
  214. */
  215. StateListenerRegistry.register(
  216. /* selector */ state => state['features/video-layout'].remoteScreenShares.length,
  217. /* listener */(length, store) => {
  218. if (length === 0) {
  219. store.dispatch(setScreenshareFilmstripParticipant());
  220. }
  221. }, {
  222. deepEquals: true
  223. });