diff --git a/react/features/base/media/components/AbstractVideoTrack.js b/react/features/base/media/components/AbstractVideoTrack.js
index db0b99c9b..721a531f6 100644
--- a/react/features/base/media/components/AbstractVideoTrack.js
+++ b/react/features/base/media/components/AbstractVideoTrack.js
@@ -21,6 +21,12 @@ export default class AbstractVideoTrack extends Component {
static propTypes = {
dispatch: PropTypes.func,
+ /**
+ * Callback to invoke when the {@link Video} of
+ * {@code AbstractVideoTrack} is clicked/pressed.
+ */
+ onPress: PropTypes.func,
+
videoTrack: PropTypes.object,
waitForVideoStarted: PropTypes.bool,
@@ -106,6 +112,7 @@ export default class AbstractVideoTrack extends Component {
);
@@ -120,8 +127,7 @@ export default class AbstractVideoTrack extends Component {
_onVideoPlaying() {
const videoTrack = this.props.videoTrack;
- if (videoTrack
- && !videoTrack.videoStarted) {
+ if (videoTrack && !videoTrack.videoStarted) {
this.props.dispatch(trackVideoStarted(videoTrack.jitsiTrack));
}
}
diff --git a/react/features/base/media/components/native/Video.js b/react/features/base/media/components/native/Video.js
index d8c2b15e1..f3dd668cf 100644
--- a/react/features/base/media/components/native/Video.js
+++ b/react/features/base/media/components/native/Video.js
@@ -1,9 +1,11 @@
-/* @flow */
+// @flow
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { RTCView } from 'react-native-webrtc';
+import { Pressable } from '../../../react';
+
import styles from './styles';
/**
@@ -19,7 +21,14 @@ export default class Video extends Component<*> {
*/
static propTypes = {
mirror: PropTypes.bool,
+
onPlaying: PropTypes.func,
+
+ /**
+ * Callback to invoke when the {@code Video} is clicked/pressed.
+ */
+ onPress: PropTypes.func,
+
stream: PropTypes.object,
/**
@@ -82,14 +91,15 @@ export default class Video extends Component<*> {
const style = styles.video;
const objectFit = (style && style.objectFit) || 'cover';
- // eslint-disable-next-line no-extra-parens
return (
-
+
+
+
);
}
diff --git a/react/features/base/participants/components/ParticipantView.native.js b/react/features/base/participants/components/ParticipantView.native.js
index 72b314b22..a1ef61f7b 100644
--- a/react/features/base/participants/components/ParticipantView.native.js
+++ b/react/features/base/participants/components/ParticipantView.native.js
@@ -70,6 +70,11 @@ type Props = {
*/
avatarSize: number,
+ /**
+ * Callback to invoke when the {@code ParticipantView} is clicked/pressed.
+ */
+ onPress: Function,
+
/**
* The ID of the participant (to be) depicted by {@link ParticipantView}.
*
@@ -176,6 +181,7 @@ class ParticipantView extends Component {
*/
render() {
const {
+ onPress,
_avatar: avatar,
_connectionStatus: connectionStatus,
_videoTrack: videoTrack
@@ -190,16 +196,26 @@ class ParticipantView extends Component {
// doesn't retain the last frame forever, so we would end up with a
// black screen.
const waitForVideoStarted = false;
- const renderVideo
+ let renderVideo
= !this.props._audioOnly
&& (connectionStatus
=== JitsiParticipantConnectionStatus.ACTIVE)
&& shouldRenderVideoTrack(videoTrack, waitForVideoStarted);
// Is the avatar to be rendered?
- const renderAvatar = Boolean(!renderVideo && avatar);
+ let renderAvatar = Boolean(!renderVideo && avatar);
- // If the connection has problems we will "tint" the video / avatar.
+ // The consumer of this ParticipantView is allowed to forbid showing the
+ // video if the private logic of this ParticipantView determines that
+ // the video could be rendered.
+ renderVideo = renderVideo && _toBoolean(this.props.showVideo, true);
+
+ // The consumer of this ParticipantView is allowed to forbid showing the
+ // avatar if the private logic of this ParticipantView determines that
+ // the avatar could be rendered.
+ renderAvatar = renderAvatar && _toBoolean(this.props.showAvatar, true);
+
+ // If the connection has problems, we will "tint" the video / avatar.
const useTint
= connectionStatus === JitsiParticipantConnectionStatus.INACTIVE
|| connectionStatus
@@ -207,30 +223,21 @@ class ParticipantView extends Component {
return (
+ }}
+ touchFeedback = { false }>
{ renderVideo
-
- // The consumer of this ParticipantView is allowed to forbid
- // showing the video if the private logic of this
- // ParticipantView determines that the video could be
- // rendered.
- && _toBoolean(this.props.showVideo, true)
&& }
{ renderAvatar
-
- // The consumer of this ParticipantView is allowed to forbid
- // showing the avatar if the private logic of this
- // ParticipantView determines that the avatar could be
- // rendered.
- && _toBoolean(this.props.showAvatar, true)
&& }
diff --git a/react/features/base/react/components/native/Pressable.js b/react/features/base/react/components/native/Pressable.js
new file mode 100644
index 000000000..339c8b933
--- /dev/null
+++ b/react/features/base/react/components/native/Pressable.js
@@ -0,0 +1,46 @@
+// @flow
+
+import React, { Component } from 'react';
+import { TouchableWithoutFeedback } from 'react-native';
+
+/**
+ * The type of the React {@link Component} props of {@link Pressable}.
+ */
+type Props = {
+ children: React$Node,
+
+ /**
+ * Called when the touch is released, but not if cancelled (e.g. by a scroll
+ * that steals the responder lock).
+ */
+ onPress: Function
+};
+
+/**
+ * Adds support for {@code onPress} to a child React {@link Component} (which
+ * should probably not support the prop in question; otherwise, there's little
+ * point of using {@code Pressable} then in the first place).
+ */
+export default class Pressable extends Component {
+ /**
+ * Implements React's {@link Component#render()}.
+ *
+ * @inheritdoc
+ * @returns {React$Node}
+ */
+ render() {
+ // onPress
+ const { children, onPress } = this.props;
+
+ if (onPress) {
+ return (
+
+ { children }
+
+ );
+ }
+
+ // A Pressable without an onPress is a "no-op".
+ return children;
+ }
+}
diff --git a/react/features/base/react/components/native/index.js b/react/features/base/react/components/native/index.js
index 786a1c4e9..20cb0ab24 100644
--- a/react/features/base/react/components/native/index.js
+++ b/react/features/base/react/components/native/index.js
@@ -3,6 +3,7 @@ export { default as Header } from './Header';
export { default as NavigateSectionList } from './NavigateSectionList';
export { default as Link } from './Link';
export { default as LoadingIndicator } from './LoadingIndicator';
+export { default as Pressable } from './Pressable';
export { default as SideBar } from './SideBar';
export { default as Text } from './Text';
export { default as TintedView } from './TintedView';
diff --git a/react/features/conference/components/Conference.native.js b/react/features/conference/components/Conference.native.js
index e4d85b5d4..9effb913c 100644
--- a/react/features/conference/components/Conference.native.js
+++ b/react/features/conference/components/Conference.native.js
@@ -190,9 +190,7 @@ class Conference extends Component {
+ style = { styles.conference }>
@@ -200,7 +198,7 @@ class Conference extends Component {
{/*
* The LargeVideo is the lowermost stacking layer.
*/}
-
+
{/*
* If there is a ringing call, show the callee's info.
diff --git a/react/features/large-video/components/LargeVideo.native.js b/react/features/large-video/components/LargeVideo.native.js
index d965acfdb..b75e6437e 100644
--- a/react/features/large-video/components/LargeVideo.native.js
+++ b/react/features/large-video/components/LargeVideo.native.js
@@ -13,6 +13,11 @@ import styles, { AVATAR_SIZE } from './styles';
*/
type Props = {
+ /**
+ * Callback to invoke when the {@code LargeVideo} is clicked/pressed.
+ */
+ onPress: Function,
+
/**
* The ID of the participant (to be) depicted by LargeVideo.
*
@@ -107,13 +112,18 @@ class LargeVideo extends Component {
avatarSize,
useConnectivityInfoLabel
} = this.state;
+ const {
+ onPress,
+ _participantId
+ } = this.props;
return (
+ onDimensionsChanged = { this._onDimensionsChanged }>