// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import { Alert, Platform, StyleSheet, TouchableOpacity, View, } from 'react-native'; import Video from 'react-native-video'; import RNFetchBlob from 'rn-fetch-blob'; import {intlShape} from 'react-intl'; import EventEmitter from 'mattermost-redux/utils/event_emitter'; import VideoControls, {PLAYER_STATE} from 'app/components/video_controls'; import {DeviceTypes} from 'app/constants/'; import {getLocalFilePathFromFile} from 'app/utils/file'; import Downloader from './downloader.ios'; const {VIDEOS_PATH} = DeviceTypes; export default class VideoPreview extends PureComponent { static propTypes = { deviceHeight: PropTypes.number.isRequired, deviceWidth: PropTypes.number.isRequired, file: PropTypes.object.isRequired, onFullScreen: PropTypes.func.isRequired, onSeeking: PropTypes.func, theme: PropTypes.object.isRequired, }; static contextTypes = { intl: intlShape, }; constructor(props) { super(props); let path = null; const {file} = props; if (file && file.data && file.data.localPath) { path = file.data.localPath; } this.state = { isLoading: true, isFullScreen: false, playerState: PLAYER_STATE.PAUSED, paused: true, currentTime: 0, duration: 0, path, showDownloader: true, }; } componentWillMount() { EventEmitter.on('stop-video-playback', this.stopPlayback); this.initializeComponent(); } componentWillUnmount() { EventEmitter.off('stop-video-playback', this.stopPlayback); } async initializeComponent() { const {file} = this.props; const prefix = Platform.OS === 'android' ? 'file:/' : ''; const path = getLocalFilePathFromFile(VIDEOS_PATH, file); const exist = await RNFetchBlob.fs.exists(`${prefix}${path}`); if (exist) { this.setState({path}); } } exitFullScreen = () => { this.setState({isFullScreen: false}); this.props.onFullScreen(true); }; enterFullScreen = () => { this.setState({isFullScreen: true}); this.props.onFullScreen(false); }; onDownloadSuccess = () => { const {file} = this.props; const path = file.data.localPath || getLocalFilePathFromFile(VIDEOS_PATH, file); this.setState({showDownloader: false, path}); }; onEnd = () => { if (this.state.isFullScreen) { this.props.onFullScreen(true); } this.setState({playerState: PLAYER_STATE.ENDED, isFullScreen: false, paused: true}); }; onError = () => { const {intl} = this.context; Alert.alert( intl.formatMessage({ id: 'mobile.video_playback.failed_title', defaultMessage: 'Video playback failed', }), intl.formatMessage({ id: 'mobile.video_playback.failed_description', defaultMessage: 'An error occurred while trying to play the video.\n', }), [{ text: intl.formatMessage({ id: 'mobile.server_upgrade.button', defaultMessage: 'OK', }), }] ); }; onFullScreen = () => { if (this.state.isFullScreen) { this.exitFullScreen(); } else { this.enterFullScreen(); } }; onLoad = (data) => { this.setState({duration: data.duration, isLoading: false}); }; onLoadStart = () => { this.setState({isLoading: true}); }; onPaused = () => { this.setState({ paused: !this.state.paused, playerState: this.state.paused ? PLAYER_STATE.PLAYING : PLAYER_STATE.PAUSED, }); }; onProgress = (data) => { if (this.state.isLoading || this.state.playerState !== PLAYER_STATE.PLAYING) { return; } this.setState({currentTime: data.currentTime}); }; onReplay = () => { if (this.refs.videoPlayer) { this.setState({playerState: PLAYER_STATE.PLAYING, paused: false}); this.refs.videoPlayer.seek(0); } }; onSeek = (seek) => { if (this.refs.videoPlayer) { this.setState({currentTime: seek}, () => { this.refs.videoPlayer.seek(seek); }); } }; stopPlayback = () => { if (!this.state.paused) { this.onPaused(); } }; render() { const { deviceHeight, deviceWidth, file, onSeeking, theme, } = this.props; const {currentTime, duration, isFullScreen, isLoading, path, paused, playerState, showDownloader} = this.state; if (!path) { return ( ); } return ( this.refs.controls.fadeInControls()} > ); } }