VideoGallery.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import React, { useCallback, useMemo, useState } from 'react'
  2. import { css, SerializedStyles } from '@emotion/core'
  3. import styled from '@emotion/styled'
  4. import { Gallery, MAX_VIDEO_PREVIEW_WIDTH, VideoPreviewBase } from '@/shared/components'
  5. import VideoPreview from './VideoPreviewWithNavigation'
  6. import { VideoFields } from '@/api/queries/__generated__/VideoFields'
  7. import { CAROUSEL_CONTROL_SIZE } from '@/shared/components/Carousel'
  8. type VideoGalleryProps = {
  9. title: string
  10. action?: string
  11. videos?: VideoFields[]
  12. loading?: boolean
  13. }
  14. const PLACEHOLDERS_COUNT = 12
  15. const VideoGallery: React.FC<VideoGalleryProps> = ({ title, action, videos, loading }) => {
  16. const [posterSize, setPosterSize] = useState(0)
  17. const [galleryControlCss, setGalleryControlCss] = useState<SerializedStyles>(css``)
  18. useMemo(() => {
  19. if (!posterSize) {
  20. return
  21. }
  22. const topPx = posterSize / 2 - CAROUSEL_CONTROL_SIZE / 2
  23. setGalleryControlCss(css`
  24. top: ${topPx}px;
  25. `)
  26. }, [posterSize])
  27. const displayPlaceholders = loading || !videos
  28. const imgRef = useCallback((node: HTMLImageElement) => {
  29. if (node != null) {
  30. setPosterSize(node.clientHeight)
  31. }
  32. }, [])
  33. return (
  34. <Gallery
  35. title={title}
  36. action={action}
  37. leftControlCss={galleryControlCss}
  38. rightControlCss={galleryControlCss}
  39. disableControls={displayPlaceholders}
  40. >
  41. {displayPlaceholders
  42. ? Array.from({ length: PLACEHOLDERS_COUNT }).map((_, idx) => (
  43. <StyledVideoPreviewBase key={`video-placeholder-${idx}`} />
  44. ))
  45. : videos!.map((video, idx) => (
  46. <StyledVideoPreview
  47. id={video.id}
  48. channelId={video.channel.id}
  49. title={video.title}
  50. channelName={video.channel.handle}
  51. channelAvatarURL={video.channel.avatarPhotoURL}
  52. views={video.views}
  53. createdAt={video.publishedOnJoystreamAt}
  54. duration={video.duration}
  55. posterURL={video.thumbnailURL}
  56. imgRef={idx === 0 ? imgRef : null}
  57. key={video.id}
  58. />
  59. ))}
  60. </Gallery>
  61. )
  62. }
  63. const StyledVideoPreviewBase = styled(VideoPreviewBase)`
  64. & + & {
  65. margin-left: 1.25rem;
  66. }
  67. width: ${MAX_VIDEO_PREVIEW_WIDTH};
  68. `
  69. const StyledVideoPreview = styled(VideoPreview)`
  70. & + & {
  71. margin-left: 1.25rem;
  72. }
  73. width: ${MAX_VIDEO_PREVIEW_WIDTH};
  74. `
  75. export default VideoGallery