import React , { useCallback , useContext , useEffect , useMemo , useRef , useState , } from 'react' ; import { CardMediaModel } from '../../../models/TimelineMediaModel' ; import { GlobalContext } from '../../GlobalContext' ; import { MemoSubTitle , MemoTitle } from '../memoized' ; import { CardImage , CardVideo , ErrorMessage , IFrameVideo , MediaDetailsWrapper , MediaWrapper , } from './timeline-card-media.styles' ; interface ErrorMessageModel { message : string ; } const CardMedia = ( { active , id , onMediaStateChange , theme , title , content , media , slideshowActive , hideMedia = false , cardHeight , } ) => { const videoRef = useRef < HTMLVideoElement > ( null ) ; const [ loadFailed , setLoadFailed ] = useState ( false ) ; const { mode } = useContext ( GlobalContext ) ; useEffect ( ( ) => { if ( ! videoRef ) { return ; } if ( active ) { videoRef . current && videoRef . current . play ( ) ; } else { videoRef . current && videoRef . current . pause ( ) ; } } , [ active ] ) ; const [ mediaLoaded , setMediaLoaded ] = useState ( false ) ; const handleMediaLoaded = useCallback ( ( ) => { setMediaLoaded ( true ) ; } , [ ] ) ; const handleError = useCallback ( ( ) => { setLoadFailed ( true ) ; onMediaStateChange ( { id , paused : false , playing : false , } ) ; } , [ ] ) ; const ErrorMessageMem = React . memo ( ( { message } ) => ( < ErrorMessage > { message } < /ErrorMessage>)); const isYouTube = useMemo ( ( ) => /^(https?\:\/\/)?(www\.youtube\.com|youtu\.?be)\/.+$/ . test ( media . source . url ) , [ ] ) ; const IFrameYouTube = useMemo ( ( ) => ( < IFrameVideo frameBorder = "0" allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen src = { `${ media . source . url }${ active ? '?autoplay=1&enablejsapi=1' : '?enablejsapi=1' }` } />), [active]); const Video = useMemo ( ( ) => { return ( < CardVideo controls autoPlay = { active } ref = { videoRef } onLoadedData = { handleMediaLoaded } onPlay = { ( ) => onMediaStateChange ( { id , paused : false , playing : true , } ) } onPause = { ( ) => onMediaStateChange ( { id , paused : true , playing : false , } ) } onEnded = { ( ) => onMediaStateChange ( { id , paused : false , playing : false , } ) } onError = { handleError } > < source src = { media . source . url } > < /source> < /CardVideo>); } , [ active ] ) ; const Image = useMemo ( ( ) => { return ( < CardImage src = { media . source . url } mode = { mode } onLoad = { handleMediaLoaded } onError = { handleError } visible = { mediaLoaded } active = { active } alt = { media . name } loading = { 'lazy' } / > ) ; } , [ active , mediaLoaded ] ) ; ErrorMessageMem . displayName = 'Error Message' ; return ( < > < MediaWrapper theme = { theme } active = { active } mode = { mode } slideShowActive = { slideshowActive } className = "card-media-wrapper" cardHeight = { cardHeight } > { media . type === 'VIDEO' && ! isYouTube && ( ! loadFailed ? ( Video ) : ( < ErrorMessageMem message = "Failed to load the video" / > ) ) } { media . type === 'VIDEO' && isYouTube && IFrameYouTube } { media . type === 'IMAGE' && ( ! loadFailed ? ( Image ) : ( < ErrorMessageMem message = "Failed to load the image." / > ) ) } < /MediaWrapper> < MediaDetailsWrapper mode = { mode } > < MemoTitle title = { title } theme = { theme } active = { active } / > < MemoSubTitle content = { content } /> < /MediaDetailsWrapper> < />); } ; export default CardMedia ;