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.

Filmstrip.native.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { ScrollView } from 'react-native';
  4. import { connect } from 'react-redux';
  5. import { Container } from '../../base/react';
  6. import {
  7. isNarrowAspectRatio,
  8. makeAspectRatioAware
  9. } from '../../base/responsive-ui';
  10. import styles from './styles';
  11. import Thumbnail from './Thumbnail';
  12. /**
  13. * Filmstrip component's property types.
  14. */
  15. type Props = {
  16. /**
  17. * The indicator which determines whether the filmstrip is enabled.
  18. *
  19. * @private
  20. */
  21. _enabled: boolean,
  22. /**
  23. * The participants in the conference.
  24. *
  25. * @private
  26. */
  27. _participants: Array<any>,
  28. /**
  29. * The indicator which determines whether the filmstrip is visible.
  30. *
  31. * @private
  32. */
  33. _visible: boolean
  34. };
  35. /**
  36. * Implements a React {@link Component} which represents the filmstrip on
  37. * mobile/React Native.
  38. *
  39. * @extends Component
  40. */
  41. class Filmstrip extends Component<Props> {
  42. /**
  43. * Implements React's {@link Component#render()}.
  44. *
  45. * @inheritdoc
  46. * @returns {ReactElement}
  47. */
  48. render() {
  49. if (!this.props._enabled) {
  50. return null;
  51. }
  52. const isNarrowAspectRatio_ = isNarrowAspectRatio(this);
  53. const filmstripStyle
  54. = isNarrowAspectRatio_
  55. ? styles.filmstripNarrow
  56. : styles.filmstripWide;
  57. return (
  58. <Container
  59. style = { filmstripStyle }
  60. visible = { this.props._visible }>
  61. <ScrollView
  62. horizontal = { isNarrowAspectRatio_ }
  63. showsHorizontalScrollIndicator = { false }
  64. showsVerticalScrollIndicator = { false }>
  65. {
  66. /* eslint-disable react/jsx-wrap-multilines */
  67. this._sort(
  68. this.props._participants,
  69. isNarrowAspectRatio_)
  70. .map(p =>
  71. <Thumbnail
  72. key = { p.id }
  73. participant = { p } />)
  74. /* eslint-enable react/jsx-wrap-multilines */
  75. }
  76. </ScrollView>
  77. </Container>
  78. );
  79. }
  80. /**
  81. * Sorts a specific array of {@code Participant}s in display order.
  82. *
  83. * @param {Participant[]} participants - The array of {@code Participant}s
  84. * to sort in display order.
  85. * @param {boolean} isNarrowAspectRatio_ - Indicates if the aspect ratio is
  86. * wide or narrow.
  87. * @private
  88. * @returns {Participant[]} A new array containing the elements of the
  89. * specified {@code participants} array sorted in display order.
  90. */
  91. _sort(participants, isNarrowAspectRatio_) {
  92. // XXX Array.prototype.sort() is not appropriate because (1) it operates
  93. // in place and (2) it is not necessarily stable.
  94. const sortedParticipants = [
  95. // First put the local participant.
  96. ...participants.filter(p => p.local),
  97. // Then the remote participants, which are sorted by join order.
  98. ...participants.filter(p => !p.local)
  99. ];
  100. if (isNarrowAspectRatio_) {
  101. // When the narrow aspect ratio is used, we want to have the remote
  102. // participants from right to left with the newest added/joined to
  103. // the leftmost side. The local participant is the leftmost item.
  104. sortedParticipants.reverse();
  105. }
  106. return sortedParticipants;
  107. }
  108. }
  109. /**
  110. * Maps (parts of) the redux state to the associated {@code Filmstrip}'s props.
  111. *
  112. * @param {Object} state - The redux state.
  113. * @private
  114. * @returns {{
  115. * _participants: Participant[],
  116. * _visible: boolean
  117. * }}
  118. */
  119. function _mapStateToProps(state) {
  120. const participants = state['features/base/participants'];
  121. const { enabled, visible } = state['features/filmstrip'];
  122. return {
  123. /**
  124. * The indicator which determines whether the filmstrip is enabled.
  125. *
  126. * @private
  127. * @type {boolean}
  128. */
  129. _enabled: enabled,
  130. /**
  131. * The participants in the conference.
  132. *
  133. * @private
  134. * @type {Participant[]}
  135. */
  136. _participants: participants,
  137. /**
  138. * The indicator which determines whether the filmstrip is visible. The
  139. * mobile/react-native Filmstrip is visible when there are at least 2
  140. * participants in the conference (including the local one).
  141. *
  142. * @private
  143. * @type {boolean}
  144. */
  145. _visible: visible && participants.length > 1
  146. };
  147. }
  148. export default connect(_mapStateToProps)(makeAspectRatioAware(Filmstrip));