1+ import React , { useState , useEffect } from "react"
2+ import tw , { css } from "twin.macro"
3+ import ReactPlayer from "react-player/lazy"
4+ import "slick-carousel/slick/slick.css"
5+ import "slick-carousel/slick/slick-theme.css"
6+ import Slider from "react-slick"
7+ import {
8+ SliderContentImageStyle ,
9+ SliderStyle ,
10+ SliderContentStyle ,
11+ getSliderSetting ,
12+ parseVideo
13+ } from "./main-media-util-helper"
14+
15+ const getVideoThumbnailUrl = async url => {
16+ const video = parseVideo ( url )
17+ if ( video . type === "youtube" )
18+ return video . id ? "https://img.youtube.com/vi/" + video . id + "/maxresdefault.jpg" : "#"
19+ if ( video . type === "vimeo" ) {
20+ const fetched = ( async videoId => {
21+ let result = { }
22+ try {
23+ const response = await fetch ( "https://vimeo.com/api/v2/video/" + videoId + ".json" )
24+ result = await response . json ( )
25+ return result [ 0 ] . thumbnail_large
26+ } catch ( e ) {
27+ console . error ( "Error while fetching Vimeo video data" , e )
28+ }
29+ } )
30+ return fetched ( video . id )
31+ }
32+ }
33+
34+ const renderMainMediaDisplayElement = {
35+ video : video => {
36+ return (
37+ < div tw = "h-full text-center" key = { video . key } id = { video . key } css = { video . css } >
38+ < ReactPlayer url = { video . url } width = "100%" controls = { true } />
39+ </ div >
40+ )
41+ } ,
42+ image : image => (
43+ < a href = { image . url } tw = "w-full text-center" css = { image . css }
44+ key = { image . key } id = { image . key } >
45+ < img
46+ alt = { `Screenshot of ${ image . name } website` }
47+ tw = "border-4 max-w-full inline-block"
48+ src = { image . src }
49+ />
50+ </ a >
51+ ) ,
52+ }
53+
54+ const renderMainMediaSliderElement = {
55+ video : video => sliderThumbnail ( video ) ,
56+ image : image => sliderThumbnail ( image )
57+ }
58+
59+ const sliderThumbnail = props => {
60+ props = props || { }
61+ const src = props . src || props . thumbnailSrc || "#"
62+ const alt = props . name || "Thumbnail"
63+ return (
64+ < div css = { [ SliderContentStyle ] }
65+ id = { props . key }
66+ key = { props . key }
67+ onClick = { props . onClick } >
68+ < img
69+ alt = { alt }
70+ id = { props . key + "_img" }
71+ key = { props . key + "_img" }
72+ src = { src }
73+ css = { [
74+ tw `border-4 max-w-full` ,
75+ SliderContentImageStyle
76+ ] }
77+ />
78+ </ div >
79+ )
80+ }
81+
82+ export const MainMediaUtil = ( { data} ) => {
83+ const [ items ] = useState ( data )
84+ const [ index , setIndex ] = useState ( 0 )
85+ const [ isRendered , setIsRendered ] = useState ( false )
86+ const [ hasThumbnails , setHasThumbnails ] = useState ( false )
87+ const sliderSetting = getSliderSetting ( items . length )
88+
89+ const toggleDisplayStatusOfElement = options => {
90+ options = options || { }
91+ const idForElementToDisplay = "#main_media_util_in_display_" + index
92+ const elementToDisplay = document . querySelector ( idForElementToDisplay )
93+ elementToDisplay . setAttribute ( 'style' , options . style || 'display:block' )
94+
95+ if ( isRendered ) return
96+ const idForElementToFocus = "#main_media_util_" + index
97+ const elementToFocus = document . querySelector ( idForElementToFocus )
98+ elementToFocus . focus ( { preventScroll : true } )
99+ setIsRendered ( true )
100+ }
101+
102+ const populateVideoThumbnails = async ( ) => {
103+ items . map ( async item => {
104+ if ( item . type !== "video" ) return
105+ const url = await getVideoThumbnailUrl ( item . source . url )
106+ const target = document . querySelector ( "#" + item . source . key + "_img" )
107+ target . setAttribute ( "src" , url )
108+ } )
109+ setHasThumbnails ( true )
110+ }
111+
112+ useEffect ( ( ) => {
113+ if ( items . length > 1 ) toggleDisplayStatusOfElement ( )
114+ if ( ! hasThumbnails ) populateVideoThumbnails ( )
115+ } )
116+
117+ return items && items . length > 1 ? (
118+ < >
119+ < div tw = "items-center h-full mb-1" >
120+ { items . map ( ( item , itemIndex ) => {
121+ item . source . key = "main_media_util_in_display_" + itemIndex
122+ item . source . css = css `display : none;`
123+ return renderMainMediaDisplayElement [ item . type ] ( item . source )
124+ } ) }
125+ </ div >
126+ < div tw = "items-center h-full ml-2 mr-2" >
127+ < Slider { ...sliderSetting } css = { [ SliderStyle ] } >
128+ { items . map ( ( item , itemIndex ) => {
129+ item . source . key = "main_media_util_" + itemIndex
130+ item . source . onClick = ( ) => {
131+ if ( itemIndex === index ) return
132+ toggleDisplayStatusOfElement ( { style : 'display:none' } )
133+ setIndex ( itemIndex )
134+ }
135+ return renderMainMediaSliderElement [ item . type ] ( item . source )
136+ } ) }
137+ </ Slider >
138+ </ div >
139+ </ >
140+ ) : (
141+ < div tw = "flex justify-center items-center h-full mb-5 pb-4" >
142+ { items && items . map ( item => {
143+ item . source . key = "main_media_util_in_display_0"
144+ return renderMainMediaDisplayElement [ item . type ] ( item . source )
145+ } ) }
146+ </ div >
147+ )
148+ }
0 commit comments