|
@@ -1,5 +1,6 @@
|
|
-import React, { useCallback, useEffect, useState } from 'react'
|
|
|
|
|
|
+import React, { useCallback, useEffect, useState, useRef, useMemo } from 'react'
|
|
import { RouteComponentProps, useParams } from '@reach/router'
|
|
import { RouteComponentProps, useParams } from '@reach/router'
|
|
|
|
+import { debounce } from 'lodash'
|
|
import {
|
|
import {
|
|
ChannelContainer,
|
|
ChannelContainer,
|
|
Container,
|
|
Container,
|
|
@@ -21,7 +22,9 @@ import { ADD_VIDEO_VIEW, GET_VIDEO } from '@/api/queries'
|
|
import { GetVideo, GetVideoVariables } from '@/api/queries/__generated__/GetVideo'
|
|
import { GetVideo, GetVideoVariables } from '@/api/queries/__generated__/GetVideo'
|
|
import { formatVideoViewsAndDate } from '@/utils/video'
|
|
import { formatVideoViewsAndDate } from '@/utils/video'
|
|
import { AddVideoView, AddVideoViewVariables } from '@/api/queries/__generated__/AddVideoView'
|
|
import { AddVideoView, AddVideoViewVariables } from '@/api/queries/__generated__/AddVideoView'
|
|
|
|
+
|
|
import { ChannelLink, InfiniteVideoGrid } from '@/components'
|
|
import { ChannelLink, InfiniteVideoGrid } from '@/components'
|
|
|
|
+import { usePersonalData } from '@/hooks'
|
|
|
|
|
|
const VideoView: React.FC<RouteComponentProps> = () => {
|
|
const VideoView: React.FC<RouteComponentProps> = () => {
|
|
const { id } = useParams()
|
|
const { id } = useParams()
|
|
@@ -29,11 +32,21 @@ const VideoView: React.FC<RouteComponentProps> = () => {
|
|
variables: { id },
|
|
variables: { id },
|
|
})
|
|
})
|
|
const [addVideoView] = useMutation<AddVideoView, AddVideoViewVariables>(ADD_VIDEO_VIEW)
|
|
const [addVideoView] = useMutation<AddVideoView, AddVideoViewVariables>(ADD_VIDEO_VIEW)
|
|
|
|
+ const { state, updateWatchedVideos } = usePersonalData()
|
|
|
|
+
|
|
|
|
+ const [startTimestamp, setStartTimestamp] = useState<number>()
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ if (startTimestamp != null) {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ const currentVideo = state.watchedVideos.find((v) => v.id === data?.video?.id)
|
|
|
|
+ setStartTimestamp(currentVideo?.__typename === 'INTERRUPTED' ? currentVideo.timestamp : 0)
|
|
|
|
+ }, [data?.video?.id, state.watchedVideos, startTimestamp])
|
|
|
|
|
|
- const videoId = data?.video?.id
|
|
|
|
const channelId = data?.video?.channel.id
|
|
const channelId = data?.video?.channel.id
|
|
|
|
+ const videoId = data?.video?.id
|
|
|
|
|
|
- const [playing, setPlaying] = useState<boolean>(true)
|
|
|
|
|
|
+ const [playing, setPlaying] = useState(true)
|
|
const handleUserKeyPress = useCallback((event: Event) => {
|
|
const handleUserKeyPress = useCallback((event: Event) => {
|
|
const { keyCode } = event as KeyboardEvent
|
|
const { keyCode } = event as KeyboardEvent
|
|
if (keyCode === 32) {
|
|
if (keyCode === 32) {
|
|
@@ -72,6 +85,31 @@ const VideoView: React.FC<RouteComponentProps> = () => {
|
|
})
|
|
})
|
|
}, [addVideoView, videoId, channelId])
|
|
}, [addVideoView, videoId, channelId])
|
|
|
|
|
|
|
|
+ // Save the video timestamp
|
|
|
|
+ // disabling eslint for this line since debounce is an external fn and eslint can't figure out its args, so it will complain.
|
|
|
|
+ // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
+ const handleTimeUpdate = useCallback(
|
|
|
|
+ debounce((time) => {
|
|
|
|
+ if (data?.video?.id) {
|
|
|
|
+ updateWatchedVideos('INTERRUPTED', data.video.id, time)
|
|
|
|
+ }
|
|
|
|
+ }, 5000),
|
|
|
|
+ [data?.video?.id]
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ const handleVideoEnd = useCallback(() => {
|
|
|
|
+ if (data?.video?.id) {
|
|
|
|
+ updateWatchedVideos('COMPLETED', data?.video?.id)
|
|
|
|
+ }
|
|
|
|
+ }, [data?.video?.id, updateWatchedVideos])
|
|
|
|
+
|
|
|
|
+ const handlePlay = useCallback(() => {
|
|
|
|
+ setPlaying(true)
|
|
|
|
+ }, [])
|
|
|
|
+ const handlePause = useCallback(() => {
|
|
|
|
+ setPlaying(false)
|
|
|
|
+ }, [])
|
|
|
|
+
|
|
if (error) {
|
|
if (error) {
|
|
throw error
|
|
throw error
|
|
}
|
|
}
|
|
@@ -88,9 +126,13 @@ const VideoView: React.FC<RouteComponentProps> = () => {
|
|
<VideoPlayer
|
|
<VideoPlayer
|
|
playing={playing}
|
|
playing={playing}
|
|
src={data.video.media.location}
|
|
src={data.video.media.location}
|
|
- autoplay
|
|
|
|
fill
|
|
fill
|
|
posterUrl={data.video.thumbnailUrl}
|
|
posterUrl={data.video.thumbnailUrl}
|
|
|
|
+ onEnd={handleVideoEnd}
|
|
|
|
+ onTimeUpdated={handleTimeUpdate}
|
|
|
|
+ onPlay={handlePlay}
|
|
|
|
+ onPause={handlePause}
|
|
|
|
+ startTime={startTimestamp}
|
|
/>
|
|
/>
|
|
) : (
|
|
) : (
|
|
<PlayerPlaceholder />
|
|
<PlayerPlaceholder />
|