diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx
index b90d06c6..b7bf6ccc 100644
--- a/src/config/procedures.tsx
+++ b/src/config/procedures.tsx
@@ -15,6 +15,7 @@ export const PROCEDURES = {
get_tournament_matches: 'get_tournament_matches',
get_user_favorites: 'get_user_favorites',
get_user_info: 'get_user_info',
+ get_user_match_second: 'get_user_match_second',
logout_user: 'logout_user',
lst_c_country: 'lst_c_country',
param_lexical: 'param_lexical',
diff --git a/src/features/MatchCard/CardLiveHover/index.tsx b/src/features/MatchCard/CardLiveHover/index.tsx
index 38b166d3..62a4ad11 100644
--- a/src/features/MatchCard/CardLiveHover/index.tsx
+++ b/src/features/MatchCard/CardLiveHover/index.tsx
@@ -3,6 +3,7 @@ import React from 'react'
import { Link } from 'react-router-dom'
+import { RESUME_KEY } from 'features/MatchPage/hooks/useLastPlayPosition'
import { OutsideClick } from 'features/OutsideClick'
import {
@@ -44,7 +45,7 @@ export const CardLiveHover = ({
-
+
diff --git a/src/features/MatchPage/hooks/useLastPlayPosition.tsx b/src/features/MatchPage/hooks/useLastPlayPosition.tsx
new file mode 100644
index 00000000..ebebf0fa
--- /dev/null
+++ b/src/features/MatchPage/hooks/useLastPlayPosition.tsx
@@ -0,0 +1,65 @@
+import {
+ useEffect,
+ useState,
+ useMemo,
+} from 'react'
+import { useLocation } from 'react-router'
+
+import isBoolean from 'lodash/isBoolean'
+
+import type { LastPlayPosition } from 'requests'
+import { getMatchLastWatchSeconds } from 'requests'
+
+import {
+ useSportNameParam,
+ usePageId,
+ useRequest,
+} from 'hooks'
+
+export const RESUME_KEY = 'resume'
+
+const readResumeParam = (search: string) => {
+ const params = new URLSearchParams(search)
+ const rawValue = params.get(RESUME_KEY)
+ if (!rawValue) return false
+
+ const value = JSON.parse(rawValue)
+ return isBoolean(value) && Boolean(value)
+}
+
+const initialPosition = {
+ half: 0,
+ second: 0,
+}
+
+export const useLastPlayPosition = () => {
+ const { search } = useLocation()
+ const { sportType } = useSportNameParam()
+ const matchId = usePageId()
+ const [
+ lastPlayPosition,
+ setPosition,
+ ] = useState(initialPosition)
+ const {
+ isFetching: isLastPlayPositionFetching,
+ request: requestLastPlayPosition,
+ } = useRequest(getMatchLastWatchSeconds)
+
+ const resume = useMemo(() => readResumeParam(search), [search])
+
+ useEffect(() => {
+ if (resume) {
+ requestLastPlayPosition(sportType, matchId).then(setPosition)
+ }
+ }, [
+ sportType,
+ matchId,
+ resume,
+ requestLastPlayPosition,
+ ])
+
+ return {
+ isLastPlayPositionFetching,
+ lastPlayPosition,
+ }
+}
diff --git a/src/features/MatchPage/hooks/useVideoData.tsx b/src/features/MatchPage/hooks/useVideoData.tsx
index ea76b245..c8e2c2e5 100644
--- a/src/features/MatchPage/hooks/useVideoData.tsx
+++ b/src/features/MatchPage/hooks/useVideoData.tsx
@@ -6,6 +6,8 @@ import { getLiveVideos, getVideos } from 'requests'
import { useSportNameParam, usePageId } from 'hooks'
import { isNull } from 'lodash'
+import { useLastPlayPosition } from './useLastPlayPosition'
+
export const useVideoData = () => {
const [videos, setVideos] = useState([])
const [liveVideos, setLiveVideos] = useState([])
@@ -32,5 +34,6 @@ export const useVideoData = () => {
return {
url: liveVideos[0] || '',
videos,
+ ...useLastPlayPosition(),
}
}
diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx
index b4e2f20c..523550e5 100644
--- a/src/features/MatchPage/index.tsx
+++ b/src/features/MatchPage/index.tsx
@@ -13,11 +13,16 @@ import { MainWrapper, Container } from './styled'
export const MatchPage = () => {
const profile = useMatchProfile()
- const { url, videos } = useVideoData()
+ const {
+ isLastPlayPositionFetching,
+ lastPlayPosition,
+ url,
+ videos,
+ } = useVideoData()
const { onPlayerProgressChange, onPlayingChange } = usePlayerProgressReporter()
- const isLiveMatch = Boolean(url)
- const isFinishedMatch = !isEmpty(videos)
+ const isLiveMatch = Boolean(url) && !isLastPlayPositionFetching
+ const isFinishedMatch = !isEmpty(videos) && !isLastPlayPositionFetching
return (
@@ -29,6 +34,7 @@ export const MatchPage = () => {
url={url}
onPlayingChange={onPlayingChange}
onProgressChange={onPlayerProgressChange}
+ resumeFrom={lastPlayPosition.second}
/>
)
}
@@ -38,6 +44,7 @@ export const MatchPage = () => {
videos={videos}
onPlayingChange={onPlayingChange}
onProgressChange={onPlayerProgressChange}
+ resumeFrom={lastPlayPosition}
/>
)
}
diff --git a/src/features/MultiSourcePlayer/helpers/index.tsx b/src/features/MultiSourcePlayer/helpers/index.tsx
index f1b24072..c4b4097b 100644
--- a/src/features/MultiSourcePlayer/helpers/index.tsx
+++ b/src/features/MultiSourcePlayer/helpers/index.tsx
@@ -5,24 +5,23 @@ import findIndex from 'lodash/findIndex'
import type { Chapters } from '../types'
type Args = {
- resume?: boolean,
+ from?: number,
url: string,
videoRef: RefObject,
}
export const preparePlayer = ({
- resume = false,
+ from = 0,
url,
videoRef,
}: Args) => {
const video = videoRef?.current
if (!video) return
- const wasAtTime = video.currentTime
// eslint-disable-next-line no-param-reassign
video.src = url
- if (resume) {
- video.currentTime = wasAtTime
+ if (from) {
+ video.currentTime = from
}
video.load()
}
diff --git a/src/features/MultiSourcePlayer/hooks/index.tsx b/src/features/MultiSourcePlayer/hooks/index.tsx
index df3bdad9..ed9245e0 100644
--- a/src/features/MultiSourcePlayer/hooks/index.tsx
+++ b/src/features/MultiSourcePlayer/hooks/index.tsx
@@ -8,7 +8,7 @@ import {
import size from 'lodash/size'
-import type { Videos } from 'requests'
+import type { LastPlayPosition, Videos } from 'requests'
import { useEventListener } from 'hooks'
import { useFullscreen } from 'features/StreamPlayer/hooks/useFullscreen'
@@ -25,16 +25,18 @@ export type Props = {
onError?: () => void,
onPlayingChange: (playing: boolean) => void,
onProgressChange: (seconds: number, period: number) => void,
+ resumeFrom: LastPlayPosition,
videos: Videos,
}
export const useMultiSourcePlayer = ({
+ resumeFrom,
onError = () => {},
videos,
onPlayingChange,
onProgressChange: onProgressChangeCallback,
}: Props) => {
- const activeChapterIndex = useRef(0)
+ const activeChapterIndex = useRef(resumeFrom.half)
const wrapperRef = useRef(null)
const videoRef = useRef(null)
const [loadedProgress, setLoadedProgress] = useState(0)
@@ -67,13 +69,18 @@ export const useMultiSourcePlayer = ({
videoRef,
})
- const getCurrentChapterUrl = useCallback((quality: string = selectedQuality) => (
+ const getActiveChapterUrl = useCallback((quality: string = selectedQuality) => (
chapters[activeChapterIndex.current].urls[quality]
), [selectedQuality, chapters])
+ const getActiveChapterStart = useCallback(() => (
+ chapters[activeChapterIndex.current]?.startMs || 0
+ ), [chapters])
+
const onQualitySelect = (quality: string) => {
+ const from = videoRef.current?.currentTime
setSelectedQuality(quality)
- continuePlaying(getCurrentChapterUrl(quality), true)
+ continuePlaying(getActiveChapterUrl(quality), from)
}
const playNextChapter = () => {
@@ -81,9 +88,9 @@ export const useMultiSourcePlayer = ({
const isLastChapterPlayed = activeChapterIndex.current === size(chapters)
if (isLastChapterPlayed) {
activeChapterIndex.current = 0
- stopPlaying(getCurrentChapterUrl())
+ stopPlaying(getActiveChapterUrl())
} else {
- continuePlaying(getCurrentChapterUrl())
+ continuePlaying(getActiveChapterUrl())
}
}
@@ -93,10 +100,6 @@ export const useMultiSourcePlayer = ({
}
}
- const getActiveChapterStart = () => (
- chapters[activeChapterIndex.current]?.startMs || 0
- )
-
const onLoadedChange = (loadedMs: number) => {
const chapterStart = getActiveChapterStart()
setLoadedProgress(chapterStart + loadedMs)
@@ -108,13 +111,17 @@ export const useMultiSourcePlayer = ({
}
useEffect(() => {
- const url = getCurrentChapterUrl()
+ const url = getActiveChapterUrl()
+ const chapterStartMs = getActiveChapterStart()
+ const from = resumeFrom.second - (chapterStartMs / 1000)
if (url && firstTimeStart) {
- startPlaying(url)
+ startPlaying(url, from)
}
}, [
firstTimeStart,
- getCurrentChapterUrl,
+ resumeFrom,
+ getActiveChapterUrl,
+ getActiveChapterStart,
startPlaying,
])
diff --git a/src/features/MultiSourcePlayer/hooks/usePlayingState.tsx b/src/features/MultiSourcePlayer/hooks/usePlayingState.tsx
index 0b677755..ecc21f17 100644
--- a/src/features/MultiSourcePlayer/hooks/usePlayingState.tsx
+++ b/src/features/MultiSourcePlayer/hooks/usePlayingState.tsx
@@ -27,8 +27,12 @@ export const usePlayingState = (videoRef: RefObject) => {
setPlaying(false)
}, [videoRef])
- const startPlaying = useCallback((url: string) => {
- preparePlayer({ url, videoRef })
+ const startPlaying = useCallback((url: string, from?: number) => {
+ preparePlayer({
+ from,
+ url,
+ videoRef,
+ })
videoRef.current?.play()
setFirstTimeStart(false)
setPlaying(true)
@@ -36,10 +40,10 @@ export const usePlayingState = (videoRef: RefObject) => {
const continuePlaying = useCallback((
url: string,
- rememberTime: boolean = false,
+ from?: number,
) => {
preparePlayer({
- resume: rememberTime,
+ from,
url,
videoRef,
})
diff --git a/src/features/StreamPlayer/hooks/index.tsx b/src/features/StreamPlayer/hooks/index.tsx
index a60f65f4..feda4add 100644
--- a/src/features/StreamPlayer/hooks/index.tsx
+++ b/src/features/StreamPlayer/hooks/index.tsx
@@ -22,6 +22,7 @@ type ProgressState = {
export type Props = {
onPlayingChange: (playing: boolean) => void,
onProgressChange: (seconds: number) => void,
+ resumeFrom: number,
url: string,
}
@@ -30,12 +31,13 @@ const toMilliSeconds = (seconds: number) => seconds * 1000
export const useVideoPlayer = ({
onPlayingChange,
onProgressChange: progressChangeCallback,
+ resumeFrom,
}: Props) => {
const [ready, setReady] = useState(false)
const [playing, setPlaying] = useState(false)
const [duration, setDuration] = useState(0)
const [loadedProgress, setLoadedProgress] = useState(0)
- const [playedProgress, setPlayedProgress] = useState(0)
+ const [playedProgress, setPlayedProgress] = useState(toMilliSeconds(resumeFrom))
const wrapperRef = useRef(null)
const playerRef = useRef(null)
diff --git a/src/requests/getMatchLastWatchSeconds.tsx b/src/requests/getMatchLastWatchSeconds.tsx
new file mode 100644
index 00000000..47aa00d3
--- /dev/null
+++ b/src/requests/getMatchLastWatchSeconds.tsx
@@ -0,0 +1,43 @@
+import {
+ DATA_URL,
+ PROCEDURES,
+ SportTypes,
+} from 'config'
+import { callApi, getResponseData } from 'helpers'
+
+const proc = PROCEDURES.get_user_match_second
+
+type Response = {
+ _p_half: number | null,
+ _p_second: number | null,
+}
+
+export type LastPlayPosition = {
+ half: number,
+ second: number,
+}
+
+export const getMatchLastWatchSeconds = async (
+ sportType: SportTypes,
+ matchId: number,
+) => {
+ const config = {
+ body: {
+ params: {
+ _p_match_id: matchId,
+ _p_sport: sportType,
+ },
+ proc,
+ },
+ }
+
+ const response: Response = await callApi({
+ config,
+ url: DATA_URL,
+ }).then(getResponseData(proc))
+
+ return {
+ half: response?._p_half ?? 0,
+ second: response?._p_second ?? 0,
+ }
+}
diff --git a/src/requests/index.tsx b/src/requests/index.tsx
index 265a7fd9..170f59d1 100644
--- a/src/requests/index.tsx
+++ b/src/requests/index.tsx
@@ -18,3 +18,4 @@ export * from './getVideos'
export * from './saveUserInfo'
export * from './getPlayerInfo'
export * from './getLiveVideos'
+export * from './getMatchLastWatchSeconds'