From d5e2964e1914b987a4f522c2178642d6d2575236 Mon Sep 17 00:00:00 2001 From: Andrei Dekterev Date: Sat, 8 Apr 2023 23:40:33 +0700 Subject: [PATCH] Revert "fix(#462): match watch second to LS" This reverts commit b59c5ce832d92539699a97be30c4d94bd9697cdc. --- src/config/procedures.tsx | 2 + .../components/LiveMatch/hooks/index.tsx | 24 +++++------ .../LiveMatch/hooks/useLastPlayPosition.tsx | 37 ++++++++++++++++ .../hooks/usePlayerProgressReporter.tsx | 32 ++++---------- .../LiveMatch/hooks/useUrlParam.tsx | 23 ++++++++++ .../store/hooks/useTournamentData.tsx | 5 +-- .../components/LiveMatchPlaylist/index.tsx | 22 ++-------- .../components/LiveMatchPopup/styled.tsx | 1 + src/features/StreamPlayer/hooks/index.tsx | 43 ++++--------------- src/requests/getMatchLastWatchSeconds.tsx | 43 +++++++++++++++++++ src/requests/index.tsx | 2 + src/requests/reportPlayerProgress.tsx | 38 ++++++++++++++++ 12 files changed, 178 insertions(+), 94 deletions(-) create mode 100644 src/features/MatchPage/components/LiveMatch/hooks/useLastPlayPosition.tsx create mode 100644 src/features/MatchPage/components/LiveMatch/hooks/useUrlParam.tsx create mode 100644 src/requests/getMatchLastWatchSeconds.tsx create mode 100644 src/requests/reportPlayerProgress.tsx diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx index de9aa619..834ef537 100644 --- a/src/config/procedures.tsx +++ b/src/config/procedures.tsx @@ -21,6 +21,7 @@ export const PROCEDURES = { get_user_agreemens: 'get_user_agreemens', get_user_favorites: 'get_user_favorites', get_user_info: 'get_user_info', + get_user_match_second: 'get_user_match_second', get_user_payments: 'get_user_payments', get_user_preferences: 'get_user_preferences', get_user_subscribes: 'get_user_subscribes', @@ -36,6 +37,7 @@ export const PROCEDURES = { save_user_custom_subscription: 'save_user_custom_subscription', save_user_favorite: 'save_user_favorite', save_user_info: 'save_user_info', + save_user_match_second: 'save_user_match_second', save_user_page: 'save_user_page', save_user_preferences: 'save_user_preferences', save_user_subscription: 'save_user_subscription', diff --git a/src/features/MatchPage/components/LiveMatch/hooks/index.tsx b/src/features/MatchPage/components/LiveMatch/hooks/index.tsx index 1f3a5919..e41669e7 100644 --- a/src/features/MatchPage/components/LiveMatch/hooks/index.tsx +++ b/src/features/MatchPage/components/LiveMatch/hooks/index.tsx @@ -4,11 +4,11 @@ import { API_ROOT } from 'config' import { readToken } from 'helpers/token' -import { usePageParams } from 'hooks' +import { usePageParams } from 'hooks/usePageParams' import { useMatchPageStore } from 'features/MatchPage/store' -import { MatchSecondType, usePlayerProgressReporter } from './usePlayerProgressReporter' +import { usePlayerProgressReporter } from './usePlayerProgressReporter' import { useResumeUrlParam } from './useResumeUrlParam' import { useChapters } from './useChapters' import { usePlaylistLogger } from './usePlaylistLogger' @@ -21,17 +21,15 @@ export const useLiveMatch = () => { setFullMatchPlaylistDuration, } = useMatchPageStore() const { profileId: matchId, sportType } = usePageParams() - const resumeFromParam = useResumeUrlParam() + const resume = useResumeUrlParam() - const resumeFromLocalStorage = useMemo(() => { - const lastSecondLS = localStorage.getItem('matchLastWatchSecond') - const matchesLastWatchSecond: MatchSecondType | null = lastSecondLS && JSON.parse(lastSecondLS) - // undefined означает, что юзер будет смотреть лайв - return profile && !profile.live - ? matchesLastWatchSecond?.[sportType]?.[matchId]?.lastWatchSecond || 0 - : undefined - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [profile]) + const fromStartIfStreamPaused = useMemo( + () => (profile && !profile.live ? 0 : undefined), + // deps намеренно оставляем пустым, + // не нужно реагировать на изменение live когда пользователь смотрит матч + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ) const { chapters } = useChapters({ profile, @@ -71,7 +69,7 @@ export const useLiveMatch = () => { onPlayerProgressChange, onPlayingChange, onPlaylistSelect, - resume: resumeFromParam ?? resumeFromLocalStorage, + resume: resume ?? fromStartIfStreamPaused, streamUrl: `${API_ROOT}/video/stream/${sportType}/${matchId}.m3u8`, } } diff --git a/src/features/MatchPage/components/LiveMatch/hooks/useLastPlayPosition.tsx b/src/features/MatchPage/components/LiveMatch/hooks/useLastPlayPosition.tsx new file mode 100644 index 00000000..885f0470 --- /dev/null +++ b/src/features/MatchPage/components/LiveMatch/hooks/useLastPlayPosition.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react' + +import type { LastPlayPosition } from 'requests' +import { getMatchLastWatchSeconds } from 'requests' + +import { usePageParams } from 'hooks/usePageParams' +import { useRequest } from 'hooks/useRequest' + +const initialPosition = { + half: 0, + second: 0, +} + +export const useLastPlayPosition = () => { + const { profileId: matchId, sportType } = usePageParams() + const [ + lastPlayPosition, + setPosition, + ] = useState(initialPosition) + const { + isFetching: isLastPlayPositionFetching, + request: requestLastPlayPosition, + } = useRequest(getMatchLastWatchSeconds) + + useEffect(() => { + requestLastPlayPosition(sportType, matchId).then(setPosition) + }, [ + sportType, + matchId, + requestLastPlayPosition, + ]) + + return { + isLastPlayPositionFetching, + lastPlayPosition, + } +} diff --git a/src/features/MatchPage/components/LiveMatch/hooks/usePlayerProgressReporter.tsx b/src/features/MatchPage/components/LiveMatch/hooks/usePlayerProgressReporter.tsx index 52272ad9..b393f8f3 100644 --- a/src/features/MatchPage/components/LiveMatch/hooks/usePlayerProgressReporter.tsx +++ b/src/features/MatchPage/components/LiveMatch/hooks/usePlayerProgressReporter.tsx @@ -1,41 +1,25 @@ import { useCallback, useRef } from 'react' +import { reportPlayerProgress } from 'requests' + import { usePageParams } from 'hooks/usePageParams' import { useInterval } from 'hooks/useInterval' const reportRequestInterval = 30000 -export type MatchSecondType = { - [sportType: number]: { - [matchId: number]: { - lastWatchSecond: number, - period: number, - }, - }, -} - export const usePlayerProgressReporter = () => { const { profileId: matchId, sportType } = usePageParams() const playerData = useRef({ period: 0, seconds: 0 }) const intervalCallback = () => { const { period, seconds } = playerData.current - - const matchSecond = localStorage.getItem('matchLastWatchSecond') - const matchSecondParsed: MatchSecondType = matchSecond ? JSON.parse(matchSecond) : {} - - localStorage.setItem('matchLastWatchSecond', JSON.stringify({ - ...matchSecondParsed, - [sportType]: { - ...matchSecondParsed?.[sportType], - [matchId]: { - lastWatchSecond: seconds, - period, - }, - }, - })) + reportPlayerProgress({ + half: period, + matchId, + seconds, + sport: sportType, + }) } - const { start, stop } = useInterval({ callback: intervalCallback, intervalDuration: reportRequestInterval, diff --git a/src/features/MatchPage/components/LiveMatch/hooks/useUrlParam.tsx b/src/features/MatchPage/components/LiveMatch/hooks/useUrlParam.tsx new file mode 100644 index 00000000..158b1fba --- /dev/null +++ b/src/features/MatchPage/components/LiveMatch/hooks/useUrlParam.tsx @@ -0,0 +1,23 @@ +import { useMemo } from 'react' +import { useLocation } from 'react-router' + +import isNumber from 'lodash/isNumber' + +export const RESUME_KEY = 'resume' + +const readResumeParam = (search: string) => { + const params = new URLSearchParams(search) + const rawValue = params.get(RESUME_KEY) + if (!rawValue) return undefined + + const value = JSON.parse(rawValue) + return isNumber(value) ? value : 0 +} + +export const useUrlParam = () => { + const { search } = useLocation() + + const resume = useMemo(() => readResumeParam(search), [search]) + + return resume +} diff --git a/src/features/MatchPage/store/hooks/useTournamentData.tsx b/src/features/MatchPage/store/hooks/useTournamentData.tsx index e2450632..5dca4d7c 100644 --- a/src/features/MatchPage/store/hooks/useTournamentData.tsx +++ b/src/features/MatchPage/store/hooks/useTournamentData.tsx @@ -11,7 +11,6 @@ import sortBy from 'lodash/sortBy' import type { Match } from 'features/Matches' import { prepareMatches } from 'features/Matches/helpers/prepareMatches' -import { useAuthStore } from 'features/AuthStore' import type { MatchInfo } from 'requests' import { getTournamentMatches } from 'requests' @@ -24,7 +23,6 @@ import { TournamentData } from '../../types' export const useTournamentData = (matchProfile: MatchInfo) => { const { sportType } = usePageParams() - const { user } = useAuthStore() const [tournamentMatches, setTournamentMatches] = useState>([]) const [matchDates, setMatchDates] = useState>([]) @@ -46,7 +44,7 @@ export const useTournamentData = (matchProfile: MatchInfo) => { )).sort((a, b) => a.getTime() - b.getTime()) setMatchDates(sortedUniq(matchDateList.map((date) => format(date, 'yyyy-MM-dd')))) - setTournamentMatches(sortBy(prepareMatches(matchesBySection.broadcast, user), ['date'])) + setTournamentMatches(sortBy(prepareMatches(matchesBySection.broadcast), ['date'])) })() } }, [ @@ -54,7 +52,6 @@ export const useTournamentData = (matchProfile: MatchInfo) => { sportType, matchProfile?.live, matchProfile?.c_match_calc_status, - user, ]) const tournamentData: TournamentData = useMemo(() => ({ diff --git a/src/features/MatchPopup/components/LiveMatchPlaylist/index.tsx b/src/features/MatchPopup/components/LiveMatchPlaylist/index.tsx index 72c02503..264f1ed6 100644 --- a/src/features/MatchPopup/components/LiveMatchPlaylist/index.tsx +++ b/src/features/MatchPopup/components/LiveMatchPlaylist/index.tsx @@ -3,38 +3,22 @@ import { useState, useEffect } from 'react' import { PAGES } from 'config' import { isMobileDevice } from 'config/userAgent' import { getSportLexic } from 'helpers' +import { getMatchLastWatchSeconds, LastPlayPosition } from 'requests' import { useMatchPopupStore } from 'features/MatchPopup/store' -import type { MatchSecondType } from 'features/MatchPage/components/LiveMatch/hooks/usePlayerProgressReporter' - -import { useLocalStore } from 'hooks' import { SimplePlaylistButton } from '../SimplePlaylistButton' import { List, Item } from './styled' -type LastPlayPosition = { - half: number, - second: number, -} - export const LiveMatchPlaylist = () => { const [lastPlayPosition, setLastPlayPosition] = useState(null) const { match } = useMatchPopupStore() - const [lastWatchSecond] = useLocalStore({ - key: 'matchLastWatchSecond', - }) - useEffect(() => { if (match) { - const matchTime = lastWatchSecond?.[match.sportType]?.[match.id] - - setLastPlayPosition({ - half: matchTime?.period || 0, - second: matchTime?.lastWatchSecond || 0, - }) + getMatchLastWatchSeconds(match?.sportType, match?.id) + .then((lastPlayPositionSecond) => setLastPlayPosition(lastPlayPositionSecond)) } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [match]) if (!match) return null diff --git a/src/features/MatchPopup/components/LiveMatchPopup/styled.tsx b/src/features/MatchPopup/components/LiveMatchPopup/styled.tsx index 1072d709..08055a9e 100644 --- a/src/features/MatchPopup/components/LiveMatchPopup/styled.tsx +++ b/src/features/MatchPopup/components/LiveMatchPopup/styled.tsx @@ -11,6 +11,7 @@ export const Modal = styled(BaseModal)` ${ModalWindow} { width: 27.22rem; + min-height: 14.859rem; padding: 1.416rem 0.71rem; border-radius: 5px; diff --git a/src/features/StreamPlayer/hooks/index.tsx b/src/features/StreamPlayer/hooks/index.tsx index 0aebd25a..784a5a8e 100644 --- a/src/features/StreamPlayer/hooks/index.tsx +++ b/src/features/StreamPlayer/hooks/index.tsx @@ -1,6 +1,5 @@ +import type { MouseEvent } from 'react' import { - MouseEvent, - useMemo, useRef, useCallback, useEffect, @@ -12,7 +11,6 @@ import { useTour } from '@reactour/tour' import size from 'lodash/size' import isNumber from 'lodash/isNumber' import isEmpty from 'lodash/isEmpty' -import isUndefined from 'lodash/isUndefined' import Hls from 'hls.js' @@ -113,23 +111,14 @@ export const useVideoPlayer = ({ /** время для сохранения статистики просмотра матча */ const timeForStatistics = useRef(0) - const resumeTimeWithOffset = useMemo(() => { - const chapterWithOffset = chapters[0].startOffsetMs / 1000 - return !isUndefined(resumeFrom) && isLive && chapters[0].isFullMatchChapter - ? resumeFrom + chapterWithOffset - : resumeFrom - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [resumeFrom]) - const { url } = chapters[0] ?? { url: '' } const numberOfChapters = size(chapters) const { hls, videoRef } = useHlsPlayer({ isLive, - resumeFrom: resumeTimeWithOffset, + resumeFrom, src: url, }) - // временно закоментил, если ничего не сломается, удалю - // const [isLivePlaying, setIsLivePlaying] = useState(false) + const [isLivePlaying, setIsLivePlaying] = useState(false) const [isPausedTime, setIsPausedTime] = useState(false) const [pausedProgress, setPausedProgress] = useState(0) @@ -264,12 +253,12 @@ export const useVideoPlayer = ({ if (selectedPlaylist?.id !== FULL_GAME_KEY) { restartVideo() - // setIsLivePlaying(true) + setIsLivePlaying(true) } const liveProgressMs = Math.max(fullMatchDuration - BUFFERING_TIME, 0) setPlayerState({ playedProgress: liveProgressMs, seek: liveProgressMs / 1000 }) - // if (liveProgressMs > 0) setIsLivePlaying(false) + if (liveProgressMs > 0) setIsLivePlaying(false) // eslint-disable-next-line react-hooks/exhaustive-deps }, [ duration, @@ -307,11 +296,11 @@ export const useVideoPlayer = ({ }, [selectedPlaylist]) useEffect(() => { - if (duration && isUndefined(resumeFrom) && chaptersProps[0]?.isFullMatchChapter) { + if (duration && isLivePlaying && chapters[0]?.isFullMatchChapter) { backToLive() } // eslint-disable-next-line - }, [chaptersProps]) + }, [duration, isLivePlaying]) useEffect(() => { if (duration @@ -339,16 +328,12 @@ export const useVideoPlayer = ({ }, [seek, setPlayerState]) useEffect(() => { - onPlayingChange(selectedPlaylist?.id === FULL_GAME_KEY ? playing : false) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [playing, selectedPlaylist]) - - useEffect(() => { + onPlayingChange(playing) if (playing) { setPlayerState({ buffering: false }) } // eslint-disable-next-line - }, [playing]) + }, [playing, onPlayingChange]) const regURL = /\d{6,20}/gi @@ -368,16 +353,6 @@ export const useVideoPlayer = ({ && chapters[0]?.url.match(regURL)?.[0] === chaptersProps[0]?.url.match(regURL)?.[0]) || (isEmpty(chapters) || isEmpty(chaptersProps))) return - if (!isUndefined(resumeFrom) && chaptersProps[0].isFullMatchChapter) { - setPlayerState({ - ...initialState, - chapters: chaptersProps, - playing: true, - seek: resumeFrom + chaptersProps[0].startOffsetMs / 1000, - }) - return - } - setPlayerState({ ...initialState, chapters: chaptersProps, diff --git a/src/requests/getMatchLastWatchSeconds.tsx b/src/requests/getMatchLastWatchSeconds.tsx new file mode 100644 index 00000000..6f976130 --- /dev/null +++ b/src/requests/getMatchLastWatchSeconds.tsx @@ -0,0 +1,43 @@ +import { + DATA_URL, + PROCEDURES, + +} from 'config' +import { callApi } 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: number, + matchId: number, +) => { + const config = { + body: { + params: { + _p_match_id: matchId, + _p_sport: sportType, + }, + proc, + }, + } + + const response: Response = await callApi({ + config, + url: DATA_URL, + }) + + return { + half: response?._p_half ?? 0, + second: response?._p_second ?? 0, + } +} diff --git a/src/requests/index.tsx b/src/requests/index.tsx index a2cff564..494e9a3a 100644 --- a/src/requests/index.tsx +++ b/src/requests/index.tsx @@ -14,8 +14,10 @@ export * from './getUserInfo' export * from './getMatchInfo' export * from './getVideos' export * from './getUnauthenticatedMatch' +export * from './reportPlayerProgress' export * from './saveUserInfo' export * from './getPlayerInfo' +export * from './getMatchLastWatchSeconds' export * from './getMatchesPreviewImages' export * from './getSportActions' export * from './getMatchEvents' diff --git a/src/requests/reportPlayerProgress.tsx b/src/requests/reportPlayerProgress.tsx new file mode 100644 index 00000000..48155428 --- /dev/null +++ b/src/requests/reportPlayerProgress.tsx @@ -0,0 +1,38 @@ +import { + DATA_URL, + PROCEDURES, +} from 'config' +import { callApi } from 'helpers' + +const proc = PROCEDURES.save_user_match_second + +type Args = { + half?: number, + matchId: number, + seconds: number, + sport: number, +} + +export const reportPlayerProgress = ({ + half, + matchId, + seconds, + sport, +}: Args) => { + const config = { + body: { + params: { + _p_half: half, + _p_match_id: matchId, + _p_second: seconds, + _p_sport: sport, + }, + proc, + }, + } + + callApi({ + config, + url: DATA_URL, + }) +}