feat(in-263): return to full match after playing episodes

pull/66/head
Ruslan Khayrullin 3 years ago
parent 94463a558e
commit 5fbcf1e20d
  1. 3
      src/features/MatchCard/styled.tsx
  2. 1
      src/features/MatchPage/components/FinishedMatch/helpers.tsx
  3. 14
      src/features/MatchPage/components/FinishedMatch/hooks/index.tsx
  4. 4
      src/features/MatchPage/components/FinishedMatch/index.tsx
  5. 29
      src/features/MatchPage/helpers/getHalfTime.tsx
  6. 3
      src/features/MatchPage/store/hooks/index.tsx
  7. 27
      src/features/MatchPage/store/hooks/useStatsTab.tsx
  8. 2
      src/features/MatchSidePlaylists/components/Matches/index.tsx
  9. 2
      src/features/MatchSidePlaylists/components/PlayersTable/styled.tsx
  10. 1
      src/features/MatchSidePlaylists/components/TabEvents/styled.tsx
  11. 2
      src/features/MatchSidePlaylists/components/TabWatch/index.tsx
  12. 2
      src/features/MatchSidePlaylists/components/TeamsStatsTable/styled.tsx
  13. 2
      src/features/MatchSidePlaylists/hooks.tsx
  14. 9
      src/features/MatchSidePlaylists/styled.tsx
  15. 50
      src/features/MultiSourcePlayer/hooks/index.tsx
  16. 1
      src/features/MultiSourcePlayer/types.tsx
  17. 34
      src/features/StreamPlayer/hooks/index.tsx

@ -243,13 +243,14 @@ export const Team = styled.span<CardProps>`
justify-content: space-between;
align-items: center;
font-weight: 600;
font-size: 13px;
font-size: 0.85rem;
line-height: 1.14rem;
color: #fff;
${({ isMatchPage }) => (
isMatchPage
? css`
font-size: 18px;
line-height: 28px;
`
: ''

@ -69,6 +69,7 @@ const getFullMatchChapters = (videos: Array<Video>) => {
duration: video.duration,
endMs,
endOffsetMs: endMs,
isFullMatchChapter: true,
period: video.period,
startMs: prevVideoEndMs,
startOffsetMs: 0,

@ -1,6 +1,6 @@
import { useEffect } from 'react'
import { useToggle } from 'hooks/useToggle'
import { useToggle, useObjectState } from 'hooks'
import type { Settings } from 'features/MatchPopup'
import { useMatchPopupStore } from 'features/MatchPopup'
@ -10,7 +10,17 @@ import { usePlayerLogger } from './usePlayerLogger'
import { useEpisodes } from './useEpisodes'
import { useChapters } from './useChapters'
const initPausedData = {
activeChapterIndex: 0,
activePlayer: 0 || 1,
playedProgress: 0,
}
export type PausedData = typeof initPausedData
export const useFinishedMatch = () => {
const [pausedData, setPausedData] = useObjectState<PausedData>(initPausedData)
const { setChapters, setSettings } = useMatchPopupStore()
const {
handlePlaylistClick,
@ -51,8 +61,10 @@ export const useFinishedMatch = () => {
onPlayingChange,
onPlaylistSelect,
openSettingsPopup,
pausedData,
playlists: matchPlaylists,
selectedPlaylist,
setEpisodesSettings,
setPausedData,
}
}

@ -25,8 +25,10 @@ export const FinishedMatch = () => {
isSettingsPopupOpen,
onPlayingChange,
onPlaylistSelect,
pausedData,
selectedPlaylist,
setEpisodesSettings,
setPausedData,
} = useFinishedMatch()
return (
@ -48,6 +50,8 @@ export const FinishedMatch = () => {
{!isEmpty(chapters) && (
<Fragment>
<MultiSourcePlayer
pausedData={pausedData}
setPausedData={setPausedData}
access={access}
isOpenPopup={isOpenFiltersPopup}
chapters={chapters}

@ -10,19 +10,19 @@ export const getHalfTime = (videoBounds: VideoBounds, currentTime: number) => {
const matchSecond = (Number(firstBound?.s) || 0) + currentTime
if (matchSecond > (Number(lastBound?.e) || 0)) {
return {}
}
let period = 1
let second = 1
if (matchSecond < Number(videoBounds[1].s)) {
if (firstBound === lastBound || matchSecond < (Number(videoBounds[1]?.s || 0))) {
return {
period: 1,
second: 1,
period,
second,
}
}
let period = 1
let second = 1
if (lastBound?.e && matchSecond > (Number(lastBound.e))) {
return {}
}
for (let i = 1; i < videoBounds.length; i++) {
const { e, s } = videoBounds[i]
@ -30,16 +30,17 @@ export const getHalfTime = (videoBounds: VideoBounds, currentTime: number) => {
if (inRange(
matchSecond,
Number(s),
Number(e) + 1,
Number(e || 1e5) + 1,
)) {
period = i
second = matchSecond - Number(videoBounds[i].s)
break
} else if (inRange(
matchSecond,
Number(e) + 1,
Number(videoBounds[i + 1].s),
)) {
} else if (
videoBounds[i + 1] && inRange(
matchSecond,
Number(e) + 1,
Number(videoBounds[i + 1].s),
)) {
period = i + 1
break
}

@ -83,7 +83,6 @@ export const useMatchPage = () => {
matchPlaylists,
selectedPlaylist,
setFullMatchPlaylistDuration,
setSelectedPlaylist,
} = useMatchData(matchProfile)
const profile = matchProfile
@ -195,8 +194,8 @@ export const useMatchPage = () => {
} = useStatsTab({
disablePlayingEpisodes,
handlePlaylistClick,
matchProfile,
selectedPlaylist,
setSelectedPlaylist,
})
const { teamsStats } = useTeamsStats({

@ -1,15 +1,13 @@
import type { Dispatch, SetStateAction } from 'react'
import { useState } from 'react'
import { useState, useEffect } from 'react'
import map from 'lodash/map'
import isEqual from 'lodash/isEqual'
import { isIOS } from 'config'
import type {
Episode,
Episodes,
Events,
MatchInfo,
} from 'requests'
import type { EventPlaylistOption, PlaylistOption } from 'features/MatchPage/types'
@ -21,8 +19,8 @@ import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/confi
type UseStatsTabArgs = {
disablePlayingEpisodes: () => void,
handlePlaylistClick: (playlist: PlaylistOption) => void,
matchProfile: MatchInfo,
selectedPlaylist?: PlaylistOption,
setSelectedPlaylist: Dispatch<SetStateAction<PlaylistOption | undefined>>,
}
type PlayNextEpisodeArgs = {
@ -45,8 +43,8 @@ const addOffset = ({
export const useStatsTab = ({
disablePlayingEpisodes,
handlePlaylistClick,
matchProfile,
selectedPlaylist,
setSelectedPlaylist,
}: UseStatsTabArgs) => {
const [statsType, setStatsType] = useState<StatsType>(StatsType.FINAL_STATS)
const [isPlayersStatsFetching, setIsPlayersStatsFetching] = useState(false)
@ -108,17 +106,6 @@ export const useStatsTab = ({
const episodesToPlay = getEpisodesToPlay(episodes)
/**
* на ios видео иногда не останавлвается после завершения эпизода,
* данный хак исправляет проблему
*/
if (isIOS) {
setSelectedPlaylist({
...episodesToPlay[0],
episodes: [addOffset(episodesToPlay[0].episodes[0])],
})
}
setEpisodesToPlay(episodesToPlay)
setFilteredEvents(episodes as Events)
@ -129,6 +116,12 @@ export const useStatsTab = ({
playNextEpisode({ episodesToPlay, order: 0 })
}
useEffect(() => {
if (matchProfile?.live) {
setStatsType(StatsType.CURRENT_STATS)
}
}, [matchProfile?.live])
return {
circleAnimation,
filteredEvents,

@ -66,7 +66,7 @@ export const Matches = ({
return (
<Fragment>
{playListFilter > 1 && <Title t='other_games' />}
{playListFilter > 0 && <Title t='other_games' />}
<MatchesWrapper
ref={ref}
hasScroll={overflow}

@ -160,7 +160,7 @@ export const CellContainer = styled.td.attrs(({ clickable }: CellContainerProps)
width: ${({ columnWidth }) => (columnWidth ? `${columnWidth}px` : 'auto')};
min-width: 30px;
font-size: 11px;
font-weight: ${({ sorted }) => (sorted ? 'bold' : 'normal')};
font-weight: ${({ clickable }) => (clickable ? 600 : 400)};
color: ${({ clickable, theme }) => (clickable ? '#5EB2FF' : theme.colors.white)};
white-space: nowrap;
background-color: var(--bgColor);

@ -159,6 +159,7 @@ export const Tab = styled.span<TTab>`
cursor: pointer;
width: 13px;
height: 13px;
display: inline-block;
:nth-child(2) {
margin-left: 3px;

@ -50,7 +50,7 @@ export const TabWatch = ({
return (
<Fragment>
{playListFilter > 1 && (
{playListFilter > 0 && (
<MatchPlaylists
ref={matchPlaylistsRef}
playlists={filteredPlayListByDuration}

@ -94,7 +94,7 @@ export const ParamValue = styled.span.attrs(({ clickable }: TParamValue) => ({
height: 15px;
text-align: center;
position: relative;
font-weight: 600;
font-weight: ${({ clickable }) => (clickable ? 600 : 400)};
color: ${({ clickable, theme }) => (clickable ? '#5EB2FF' : theme.colors.white)};
${({ clickable }) => (clickable

@ -32,7 +32,7 @@ export const useMatchSidePlaylists = () => {
), [playlists.match])
const isWatchTabVisible = useMemo(() => (
playListFilter > 1 || tournamentData.matchDates.length > 1
playListFilter > 0 || tournamentData.matchDates.length > 1
), [playListFilter, tournamentData.matchDates.length])
const isEventTabVisible = useMemo(() => (

@ -49,11 +49,6 @@ export const TabsGroup = styled.div.attrs({ role: 'tablist' })<TabsGroupProps>`
}
`
: '')}
${isMobileDevice
? css`
`
: ''};
`
export const TabTitle = styled(T9n)`
@ -82,6 +77,10 @@ export const Tab = styled.button.attrs({ role: 'tab' })`
font-weight: 600;
}
}
:only-child {
cursor: unset;
}
`
type TabIconProps = {

@ -12,6 +12,7 @@ import { useFullscreen } from 'features/StreamPlayer/hooks/useFullscreen'
import { useVolume } from 'features/VideoPlayer/hooks/useVolume'
import { useNoNetworkPopupStore } from 'features/NoNetworkPopup'
import { useMatchPageStore } from 'features/MatchPage/store'
import { FULL_GAME_KEY } from 'features/MatchPage/helpers/buildPlaylists'
import {
useEventListener,
@ -19,6 +20,7 @@ import {
useObjectState,
usePageParams,
} from 'hooks'
import type { SetPartialState } from 'hooks'
import {
MatchInfo,
@ -26,6 +28,8 @@ import {
VIEW_INTERVAL_MS,
} from 'requests'
import type { PausedData } from 'features/MatchPage/components/FinishedMatch/hooks'
import { useProgressChangeHandler } from './useProgressChangeHandler'
import { usePlayingHandlers } from './usePlayingHandlers'
import { useVideoQuality } from './useVideoQuality'
@ -57,17 +61,24 @@ export type Props = {
isOpenPopup?: boolean,
onError?: () => void,
onPlayingChange: (playing: boolean) => void,
pausedData: PausedData,
profile: MatchInfo,
setPausedData: SetPartialState<PausedData>,
}
export const useMultiSourcePlayer = ({
chapters,
onError,
onPlayingChange,
pausedData,
setPausedData,
}: Props) => {
const {
handlePlaylistClick,
isPlayFilterEpisodes,
matchPlaylists,
playNextEpisode,
selectedPlaylist,
setCircleAnimation,
setPlayingProgress,
} = useMatchPageStore()
@ -202,8 +213,39 @@ export const useMultiSourcePlayer = ({
setPlayerState({ playedProgress: value })
setPlayingProgress(Math.floor(value / 1000))
if (chapter.isFullMatchChapter) {
setPausedData({
activeChapterIndex,
activePlayer,
playedProgress: value,
})
}
}
const backToPausedTime = useCallback(() => {
if (selectedPlaylist?.id !== FULL_GAME_KEY) {
handlePlaylistClick(matchPlaylists.match[0])
}
setTimeout(() => {
setPlayerState((state) => ({
activeChapterIndex: pausedData.activeChapterIndex,
playedProgress: pausedData.playedProgress,
seek: {
...state.seek,
[pausedData.activePlayer]: pausedData.playedProgress / 1000,
},
}))
}, 0)
}, [
selectedPlaylist?.id,
pausedData,
handlePlaylistClick,
matchPlaylists.match,
setPlayerState,
])
const onEnded = () => {
playNextChapter()
}
@ -248,7 +290,11 @@ export const useMultiSourcePlayer = ({
playNextEpisode()
}
if (playedProgress >= chapterDuration && !seeking && !isPlayFilterEpisodes) {
playNextChapter()
if (isLastChapterPlaying) {
backToPausedTime()
} else {
playNextChapter()
}
}
}, [
isPlayFilterEpisodes,
@ -258,6 +304,8 @@ export const useMultiSourcePlayer = ({
seeking,
playNextChapter,
setPlayerState,
isLastChapterPlaying,
backToPausedTime,
])
useEventListener({

@ -4,6 +4,7 @@ export type Chapter = {
duration: number,
endMs: number,
endOffsetMs: number,
isFullMatchChapter?: boolean,
period: number,
startMs: number,
startOffsetMs: number,

@ -25,6 +25,7 @@ import { useNoNetworkPopupStore } from 'features/NoNetworkPopup'
import { useLiveMatch } from 'features/MatchPage/components/LiveMatch/hooks'
import { useLexicsStore } from 'features/LexicsStore'
import { useMatchPageStore } from 'features/MatchPage/store'
import { FULL_GAME_KEY } from 'features/MatchPage/helpers/buildPlaylists'
import { VIEW_INTERVAL_MS, saveMatchStats } from 'requests'
@ -91,6 +92,7 @@ export const useVideoPlayer = ({
const { profileId, sportType } = usePageParams()
const {
isPlayFilterEpisodes,
matchPlaylists,
playNextEpisode,
selectedPlaylist,
setCircleAnimation,
@ -187,7 +189,7 @@ export const useVideoPlayer = ({
}
const onWaiting = () => {
setPlayerState({ buffering: !ready })
setPlayerState({ buffering: true })
}
const onPlaying = () => {
@ -232,14 +234,8 @@ export const useVideoPlayer = ({
const backToLive = useCallback(() => {
if (!duration) return
if (selectedPlaylist?.id !== 'full_game') {
onPlaylistSelect({
duration: 0,
episodes: [],
id: 'full_game',
lexic: 13028,
type: 0,
})
if (selectedPlaylist?.id !== FULL_GAME_KEY) {
onPlaylistSelect(matchPlaylists.match[0])
setIsLiveTime(true)
}
@ -251,19 +247,14 @@ export const useVideoPlayer = ({
onPlaylistSelect,
selectedPlaylist,
setPlayerState,
matchPlaylists.match,
])
const backToPausedTime = useCallback(() => {
if (!duration) return
if (selectedPlaylist?.id !== 'full_game') {
onPlaylistSelect({
duration: 0,
episodes: [],
id: 'full_game',
lexic: 13028,
type: 0,
})
if (selectedPlaylist?.id !== FULL_GAME_KEY) {
onPlaylistSelect(matchPlaylists.match[0])
setIsPausedTime(true)
}
@ -276,11 +267,12 @@ export const useVideoPlayer = ({
onPlaylistSelect,
selectedPlaylist,
setPlayerState,
matchPlaylists.match,
])
useEffect(() => {
if (chapters[0]?.isFullMatchChapter) {
setPausedProgress(playedProgress)
setPausedProgress(playedProgress + chapters[0].startOffsetMs)
}
// eslint-disable-next-line
}, [selectedPlaylist])
@ -357,11 +349,11 @@ export const useVideoPlayer = ({
])
useEffect(() => {
if ((isLive && chapters[0]?.isFullMatchChapter) || isEmpty(chapters)) return
if ((chapters[0]?.isFullMatchChapter) || isEmpty(chapters)) return
const { duration: chapterDuration } = getActiveChapter()
if (playedProgress >= chapterDuration && !seeking && !isPlayFilterEpisodes) {
if (isLive && isLastChapterPlaying) {
if (isLastChapterPlaying) {
backToPausedTime()
} else {
playNextChapter()
@ -406,7 +398,7 @@ export const useVideoPlayer = ({
useEffect(() => {
if (!navigator.serviceWorker || !isIOS) return undefined
const listener = (event: MessageEvent) => {
const listener = (event: MessageEvent<{ duration: number }>) => {
setPlayerState({ duration: toMilliSeconds(event.data.duration) })
}

Loading…
Cancel
Save