[RN] Don't press on Conference in preparation for 'pinch to zoom'
TouchableWithoutFeedback and TouchableHighlight interfere with the implementation of 'pinch to zoom' to come. We prepare for it by driving the onClick/onPress handler(s) out of Conference, through LargeVideo and ParticipantView into Video itself where the bulk of 'pinch to zoom' will be implemented.
This commit is contained in:
parent
cb70c084b3
commit
decbcefbd4
|
@ -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 {
|
|||
<Video
|
||||
mirror = { videoTrack && videoTrack.mirror }
|
||||
onPlaying = { this._onVideoPlaying }
|
||||
onPress = { this.props.onPress }
|
||||
stream = { stream }
|
||||
zOrder = { this.props.zOrder } />
|
||||
);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<RTCView
|
||||
mirror = { this.props.mirror }
|
||||
objectFit = { objectFit }
|
||||
streamURL = { streamURL }
|
||||
style = { style }
|
||||
zOrder = { this.props.zOrder } />
|
||||
<Pressable onPress = { this.props.onPress }>
|
||||
<RTCView
|
||||
mirror = { this.props.mirror }
|
||||
objectFit = { objectFit }
|
||||
streamURL = { streamURL }
|
||||
style = { style }
|
||||
zOrder = { this.props.zOrder } />
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Props> {
|
|||
*/
|
||||
render() {
|
||||
const {
|
||||
onPress,
|
||||
_avatar: avatar,
|
||||
_connectionStatus: connectionStatus,
|
||||
_videoTrack: videoTrack
|
||||
|
@ -190,16 +196,26 @@ class ParticipantView extends Component<Props> {
|
|||
// 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<Props> {
|
|||
|
||||
return (
|
||||
<Container
|
||||
onClick = { renderVideo ? undefined : onPress }
|
||||
style = {{
|
||||
...styles.participantView,
|
||||
...this.props.style
|
||||
}}>
|
||||
}}
|
||||
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)
|
||||
&& <VideoTrack
|
||||
onPress = { renderVideo ? onPress : undefined }
|
||||
videoTrack = { videoTrack }
|
||||
waitForVideoStarted = { waitForVideoStarted }
|
||||
zOrder = { this.props.zOrder } /> }
|
||||
|
||||
{ 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)
|
||||
&& <Avatar
|
||||
size = { this.props.avatarSize }
|
||||
uri = { avatar } /> }
|
||||
|
|
|
@ -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<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {React$Node}
|
||||
*/
|
||||
render() {
|
||||
// onPress
|
||||
const { children, onPress } = this.props;
|
||||
|
||||
if (onPress) {
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress = { onPress }>
|
||||
{ children }
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
}
|
||||
|
||||
// A Pressable without an onPress is a "no-op".
|
||||
return children;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -190,9 +190,7 @@ class Conference extends Component<Props> {
|
|||
<Container
|
||||
accessibilityLabel = 'Conference'
|
||||
accessible = { false }
|
||||
onClick = { this._onClick }
|
||||
style = { styles.conference }
|
||||
touchFeedback = { false }>
|
||||
style = { styles.conference }>
|
||||
<StatusBar
|
||||
hidden = { true }
|
||||
translucent = { true } />
|
||||
|
@ -200,7 +198,7 @@ class Conference extends Component<Props> {
|
|||
{/*
|
||||
* The LargeVideo is the lowermost stacking layer.
|
||||
*/}
|
||||
<LargeVideo />
|
||||
<LargeVideo onPress = { this._onClick } />
|
||||
|
||||
{/*
|
||||
* If there is a ringing call, show the callee's info.
|
||||
|
|
|
@ -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<Props, State> {
|
|||
avatarSize,
|
||||
useConnectivityInfoLabel
|
||||
} = this.state;
|
||||
const {
|
||||
onPress,
|
||||
_participantId
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<DimensionsDetector
|
||||
onDimensionsChanged = { this._onDimensionsChanged } >
|
||||
onDimensionsChanged = { this._onDimensionsChanged }>
|
||||
<ParticipantView
|
||||
avatarSize = { avatarSize }
|
||||
participantId = { this.props._participantId }
|
||||
onPress = { onPress }
|
||||
participantId = { _participantId }
|
||||
style = { styles.largeVideo }
|
||||
useConnectivityInfoLabel = { useConnectivityInfoLabel }
|
||||
zOrder = { 0 } />
|
||||
|
|
Loading…
Reference in New Issue