VideoView.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import React, { useEffect } from 'react'
  2. import { navigate, RouteComponentProps, useParams } from '@reach/router'
  3. import {
  4. Container,
  5. DescriptionContainer,
  6. InfoContainer,
  7. Meta,
  8. MoreVideosContainer,
  9. MoreVideosHeader,
  10. PlayerContainer,
  11. StyledChannelAvatar,
  12. Title,
  13. TitleActionsContainer,
  14. } from './VideoView.style'
  15. import { VideoGrid } from '@/components'
  16. import { VideoPlayer } from '@/shared/components'
  17. import { useMutation, useQuery } from '@apollo/client'
  18. import { ADD_VIDEO_VIEW, GET_VIDEO_WITH_CHANNEL_VIDEOS } from '@/api/queries'
  19. import { GetVideo, GetVideoVariables } from '@/api/queries/__generated__/GetVideo'
  20. import routes from '@/config/routes'
  21. import { formatVideoViewsAndDate } from '@/utils/video'
  22. import { AddVideoView, AddVideoViewVariables } from '@/api/queries/__generated__/AddVideoView'
  23. const VideoView: React.FC<RouteComponentProps> = () => {
  24. const { id } = useParams()
  25. const { loading, data } = useQuery<GetVideo, GetVideoVariables>(GET_VIDEO_WITH_CHANNEL_VIDEOS, {
  26. variables: { id },
  27. })
  28. const [addVideoView] = useMutation<AddVideoView, AddVideoViewVariables>(ADD_VIDEO_VIEW)
  29. const videoID = data?.video?.id
  30. useEffect(() => {
  31. if (!videoID) {
  32. return
  33. }
  34. addVideoView({
  35. variables: { id: videoID },
  36. update: (cache, mutationResult) => {
  37. cache.modify({
  38. id: cache.identify({
  39. __typename: 'Video',
  40. id: videoID,
  41. }),
  42. fields: {
  43. views: () => mutationResult.data?.addVideoView.views,
  44. },
  45. })
  46. },
  47. }).catch((error) => {
  48. console.warn('Failed to increase video views', { error })
  49. })
  50. }, [addVideoView, videoID])
  51. if (loading || !data) {
  52. return <p>Loading</p>
  53. }
  54. if (!data.video) {
  55. return <p>Video not found</p>
  56. }
  57. const { title, views, publishedOnJoystreamAt, channel, description } = data.video
  58. const descriptionLines = description.split('\n')
  59. return (
  60. <Container>
  61. <PlayerContainer>
  62. <VideoPlayer src={data.video.media.location} height={700} autoplay />
  63. </PlayerContainer>
  64. <InfoContainer>
  65. <TitleActionsContainer>
  66. <Title>{title}</Title>
  67. </TitleActionsContainer>
  68. <Meta>{formatVideoViewsAndDate(views, publishedOnJoystreamAt, { fullViews: true })}</Meta>
  69. <StyledChannelAvatar
  70. name={channel.handle}
  71. avatarUrl={channel.avatarPhotoURL}
  72. onClick={() => navigate(routes.channel(channel.id))}
  73. />
  74. <DescriptionContainer>
  75. {descriptionLines.map((line, idx) => (
  76. <p key={idx}>{line}</p>
  77. ))}
  78. </DescriptionContainer>
  79. <MoreVideosContainer>
  80. <MoreVideosHeader>More from {channel.handle}</MoreVideosHeader>
  81. <VideoGrid videos={channel.videos} showChannel={false} />
  82. </MoreVideosContainer>
  83. </InfoContainer>
  84. </Container>
  85. )
  86. }
  87. export default VideoView