2018-03-26 23:32:43 +02:00
// @flow
2019-08-02 08:28:14 +02:00
import React , { Fragment , useEffect , useCallback } from 'react' ;
2018-03-26 23:32:43 +02:00
import classnames from 'classnames' ;
2018-07-05 04:49:12 +02:00
import LoadingScreen from 'component/common/loading-screen' ;
2019-08-02 08:28:14 +02:00
import Button from 'component/button' ;
import FileRender from 'component/fileRender' ;
import isUserTyping from 'util/detect-typing' ;
2019-04-03 07:56:58 +02:00
2018-05-16 21:34:38 +02:00
const SPACE _BAR _KEYCODE = 32 ;
2018-03-26 23:32:43 +02:00
type Props = {
2019-08-02 08:28:14 +02:00
play : ( string , boolean ) => void ,
mediaType : string ,
2018-03-26 23:32:43 +02:00
isLoading : boolean ,
2019-08-02 08:28:14 +02:00
isPlaying : boolean ,
2019-08-06 05:25:33 +02:00
fileInfo : FileListItem ,
2018-03-26 23:32:43 +02:00
uri : string ,
2019-08-02 08:28:14 +02:00
obscurePreview : boolean ,
2019-04-03 06:17:00 +02:00
insufficientCredits : boolean ,
2019-08-02 08:28:14 +02:00
isStreamable : boolean ,
thumbnail ? : string ,
streamingUrl ? : string ,
2018-03-26 23:32:43 +02:00
} ;
2017-04-23 11:56:50 +02:00
2019-08-02 08:28:14 +02:00
export default function FileViewer ( props : Props ) {
const {
play ,
mediaType ,
isPlaying ,
fileInfo ,
uri ,
obscurePreview ,
insufficientCredits ,
thumbnail ,
streamingUrl ,
isStreamable ,
} = props ;
const isPlayable = [ 'audio' , 'video' ] . indexOf ( mediaType ) !== - 1 ;
const fileStatus = fileInfo && fileInfo . status ;
const isReadyToPlay = ( isStreamable && streamingUrl ) || ( fileInfo && fileInfo . completed ) ;
const loadingMessage =
! isStreamable && fileInfo && fileInfo . blobs _completed >= 1 && ( ! fileInfo . download _path || ! fileInfo . written _bytes )
? _ _ ( "It looks like you deleted or moved this file. We're rebuilding it now. It will only take a few seconds." )
: _ _ ( 'Loading' ) ;
// Wrap this in useCallback because we need to use it to the keyboard effect
// If we don't a new instance will be created for every render and react will think the dependencies have change, which will add/remove the listener for every render
const viewFile = useCallback (
( e : SyntheticInputEvent < * > | KeyboardEvent ) => {
e . stopPropagation ( ) ;
// Check for user setting here
const saveFile = ! isStreamable ;
play ( uri , saveFile ) ;
} ,
[ play , uri , isStreamable ]
) ;
useEffect ( ( ) => {
// This is just for beginning to download a file
// Play/Pause/Fullscreen will be handled by the respective viewers because not every file type should behave the same
function handleKeyDown ( e : KeyboardEvent ) {
if ( ! isUserTyping ( ) && e . keyCode === SPACE _BAR _KEYCODE ) {
e . preventDefault ( ) ;
if ( ! isPlaying || fileStatus === 'stopped' ) {
viewFile ( e ) ;
}
2018-08-03 17:54:10 +02:00
}
}
2019-08-02 08:28:14 +02:00
window . addEventListener ( 'keydown' , handleKeyDown ) ;
return ( ) => {
window . removeEventListener ( 'keydown' , handleKeyDown ) ;
} ;
} , [ isPlaying , fileStatus , viewFile ] ) ;
return (
< div
onClick = { viewFile }
style = { ! obscurePreview && thumbnail ? { backgroundImage : ` url(" ${ thumbnail } ") ` } : { } }
className = { classnames ( 'video content__cover content__embedded' , {
'card__media--nsfw' : obscurePreview ,
'card__media--disabled' : ! fileInfo && insufficientCredits ,
} ) }
>
{ isPlaying && (
< Fragment > { isReadyToPlay ? < FileRender uri = { uri } / > : < LoadingScreen status = { loadingMessage } / > } < / Fragment >
) }
{ ! isPlaying && (
< Button
onClick = { viewFile }
iconSize = { 30 }
title = { isPlayable ? _ _ ( 'Play' ) : _ _ ( 'View' ) }
className = { classnames ( 'button--icon' , {
'button--play' : isPlayable ,
'button--view' : ! isPlayable ,
} ) }
/ >
) }
< / div >
) ;
2017-04-23 11:56:50 +02:00
}