Files
jitsi-meet/react/features/base/media/components/native/VideoTrack.js
Zoltan Bettenbuk cb70c084b3 [RN] "The View is never the target of touch events"
In preparation for "pinch to zoom" support in desktop streams on mobile, make
certain Views not intervene in touch event handling. While the modification is
necessary for "pinch to zoom" which is coming later, it really makes sense for
the modified Views to not be involved in touching because they're used to aid
layout and/or animations and are to behave to the user as if they're not there.
2018-04-10 01:20:52 -05:00

150 lines
4.0 KiB
JavaScript

import React from 'react';
import { Animated, View } from 'react-native';
import { connect } from 'react-redux';
import AbstractVideoTrack from '../AbstractVideoTrack';
import styles from './styles';
/**
* Component that renders video element for a specified video track.
*
* @extends AbstractVideoTrack
*/
class VideoTrack extends AbstractVideoTrack {
/**
* VideoTrack component's property types.
*
* @static
*/
static propTypes = AbstractVideoTrack.propTypes
/**
* Initializes a new VideoTrack instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
/**
* Reference to currently running animation if any.
*
* @private
*/
this._animation = null;
/**
* Extend Component's state with additional animation-related vars.
*
* @type {Object}
*/
this.state = {
...this.state,
fade: new Animated.Value(0)
};
}
/**
* Renders video element with animation.
*
* @override
* @returns {ReactElement}
*/
render() {
const animatedStyles
= [ styles.videoCover, this._getAnimationStyles() ];
return (
<View style = { styles.video } >
{ super.render() }
<Animated.View
pointerEvents = 'none'
style = { animatedStyles } />
</View>
);
}
/**
* Animates setting a new video track to be rendered by this instance.
*
* @param {Track} oldValue - The old video track rendered by this instance.
* @param {Track} newValue - The new video track to be rendered by this
* instance.
* @private
* @returns {Promise}
*/
_animateSetVideoTrack(oldValue, newValue) {
// If we're in the middle of an animation and a new animation is about
// to start, stop the previous one first.
if (this._animation) {
this._animation.stop();
this._animation = null;
this.state.fade.setValue(0);
}
return this._animateVideoTrack(1)
.then(() => {
super._setVideoTrack(newValue);
return this._animateVideoTrack(0);
})
.catch(() => console.log('Animation was stopped'));
}
/**
* Animates the display of the state videoTrack.
*
* @param {number} toValue - The value to which the specified animatedValue
* is to be animated.
* @private
* @returns {Promise}
*/
_animateVideoTrack(toValue) {
return new Promise((resolve, reject) => {
this._animation
= Animated.timing(this.state.fade, { toValue });
this._animation.start(result => {
this._animation = null;
result.finished ? resolve() : reject();
});
});
}
/**
* Returns animation styles for Animated.View.
*
* @private
* @returns {Object}
*/
_getAnimationStyles() {
return {
opacity: this.state.fade
};
}
// eslint-disable-next-line valid-jsdoc
/**
* Animate the setting of the video track to be rendered by this instance.
*
* @inheritdoc
* @protected
*/
_setVideoTrack(videoTrack) {
// If JitsiTrack instance didn't change, that means some other track's
// props were changed and we don't need to animate.
const oldValue = this.state.videoTrack;
const oldJitsiTrack = oldValue ? oldValue.jitsiTrack : null;
const newValue = videoTrack;
const newJitsiTrack = newValue ? newValue.jitsiTrack : null;
if (oldJitsiTrack === newJitsiTrack) {
super._setVideoTrack(newValue);
} else {
this._animateSetVideoTrack(oldValue, newValue);
}
}
}
export default connect()(VideoTrack);