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.

ThumbnailWrapper.js 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* @flow */
  2. import React, { Component } from 'react';
  3. import { shouldComponentUpdate } from 'react-window';
  4. import { connect } from '../../../base/redux';
  5. import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
  6. import Thumbnail from './Thumbnail';
  7. /**
  8. * The type of the React {@code Component} props of {@link ThumbnailWrapper}.
  9. */
  10. type Props = {
  11. /**
  12. * The horizontal offset in px for the thumbnail. Used to center the thumbnails in the last row in tile view.
  13. */
  14. _horizontalOffset: number,
  15. /**
  16. * The ID of the participant associated with the Thumbnail.
  17. */
  18. _participantID: ?string,
  19. /**
  20. * The index of the column in tile view.
  21. */
  22. columnIndex?: number,
  23. /**
  24. * The index of the ThumbnailWrapper in stage view.
  25. */
  26. index?: number,
  27. /**
  28. * The index of the row in tile view.
  29. */
  30. rowIndex?: number,
  31. /**
  32. * The styles comming from react-window.
  33. */
  34. style: Object
  35. };
  36. /**
  37. * A wrapper Component for the Thumbnail that translates the react-window specific props
  38. * to the Thumbnail Component's props.
  39. */
  40. class ThumbnailWrapper extends Component<Props> {
  41. /**
  42. * Creates new ThumbnailWrapper instance.
  43. *
  44. * @param {Props} props - The props of the component.
  45. */
  46. constructor(props: Props) {
  47. super(props);
  48. this.shouldComponentUpdate = shouldComponentUpdate.bind(this);
  49. }
  50. shouldComponentUpdate: Props => boolean;
  51. /**
  52. * Implements React's {@link Component#render()}.
  53. *
  54. * @inheritdoc
  55. * @returns {ReactElement}
  56. */
  57. render() {
  58. const { _participantID, style, _horizontalOffset = 0 } = this.props;
  59. if (typeof _participantID !== 'string') {
  60. return null;
  61. }
  62. if (_participantID === 'local') {
  63. return (
  64. <Thumbnail
  65. horizontalOffset = { _horizontalOffset }
  66. key = 'local'
  67. style = { style } />);
  68. }
  69. return (
  70. <Thumbnail
  71. horizontalOffset = { _horizontalOffset }
  72. key = { `remote_${_participantID}` }
  73. participantID = { _participantID }
  74. style = { style } />);
  75. }
  76. }
  77. /**
  78. * Maps (parts of) the Redux state to the associated {@code ThumbnailWrapper}'s props.
  79. *
  80. * @param {Object} state - The Redux state.
  81. * @param {Object} ownProps - The props passed to the component.
  82. * @private
  83. * @returns {Props}
  84. */
  85. function _mapStateToProps(state, ownProps) {
  86. const _currentLayout = getCurrentLayout(state);
  87. const { remoteParticipants } = state['features/filmstrip'];
  88. const remoteParticipantsLength = remoteParticipants.length;
  89. const { testing = {} } = state['features/base/config'];
  90. const enableThumbnailReordering = testing.enableThumbnailReordering ?? true;
  91. if (_currentLayout === LAYOUTS.TILE_VIEW) {
  92. const { columnIndex, rowIndex } = ownProps;
  93. const { gridDimensions = {}, thumbnailSize } = state['features/filmstrip'].tileViewDimensions;
  94. const { columns, rows } = gridDimensions;
  95. const index = (rowIndex * columns) + columnIndex;
  96. let horizontalOffset;
  97. if (rowIndex === rows - 1) { // center the last row
  98. const { width: thumbnailWidth } = thumbnailSize;
  99. const { iAmRecorder } = state['features/base/config'];
  100. const partialLastRowParticipantsNumber = (remoteParticipantsLength + (iAmRecorder ? 0 : 1)) % columns;
  101. if (partialLastRowParticipantsNumber > 0) {
  102. horizontalOffset = Math.floor((columns - partialLastRowParticipantsNumber) * (thumbnailWidth + 4) / 2);
  103. }
  104. }
  105. if (index > remoteParticipantsLength) {
  106. return {};
  107. }
  108. // When the thumbnails are reordered, local participant is inserted at index 0.
  109. const localIndex = enableThumbnailReordering ? 0 : remoteParticipantsLength;
  110. const remoteIndex = enableThumbnailReordering ? index - 1 : index;
  111. if (index === localIndex) {
  112. return {
  113. _participantID: 'local',
  114. _horizontalOffset: horizontalOffset
  115. };
  116. }
  117. return {
  118. _participantID: remoteParticipants[remoteIndex],
  119. _horizontalOffset: horizontalOffset
  120. };
  121. }
  122. const { index } = ownProps;
  123. if (typeof index !== 'number' || remoteParticipantsLength <= index) {
  124. return {};
  125. }
  126. return {
  127. _participantID: remoteParticipants[index]
  128. };
  129. }
  130. export default connect(_mapStateToProps)(ThumbnailWrapper);