Ott 892 match profile imprs (#327)
* refactor(892): split match players into 2 components (#324) * Ott 892 part 2 (#325) * fix(892): micro fix * fix(892): hls player ui impr. * fix(892): finished match player ui impr. (#326) * fix(892): rewind btw episodes (#334) * refactor(892): removed resuming from MultiSourcePlayer (#335)keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
e3a683f37d
commit
20e58e7c5a
|
After Width: | Height: | Size: 418 B |
|
After Width: | Height: | Size: 436 B |
@ -0,0 +1,91 @@ |
||||
import { useEffect } from 'react' |
||||
|
||||
import isEqual from 'lodash/isEqual' |
||||
|
||||
import type { MatchInfo } from 'requests' |
||||
|
||||
import { |
||||
useSportNameParam, |
||||
usePageId, |
||||
useToggle, |
||||
} from 'hooks' |
||||
|
||||
import type { Settings } from 'features/MatchPopup' |
||||
import { useMatchPopupStore } from 'features/MatchPopup' |
||||
import { usePlayerProgressReporter } from 'features/MatchPage/hooks/usePlayerProgressReporter' |
||||
|
||||
import { useEpisodes } from './useEpisodes' |
||||
import { useChapters } from './useChapters' |
||||
|
||||
export type Props = { |
||||
profile: MatchInfo, |
||||
} |
||||
|
||||
export const useFinishedMatch = ({ profile }: Props) => { |
||||
const { |
||||
actions, |
||||
fetchMatchPlaylists, |
||||
handlePlaylistClick, |
||||
matchPlaylists, |
||||
selectedPlaylist, |
||||
setMatch, |
||||
setSettings, |
||||
settings, |
||||
} = useMatchPopupStore() |
||||
const { sportType } = useSportNameParam() |
||||
const matchId = usePageId() |
||||
const { |
||||
close: closeSettingsPopup, |
||||
isOpen: isSettingsPopupOpen, |
||||
open: openSettingsPopup, |
||||
} = useToggle() |
||||
|
||||
const { episodes } = useEpisodes() |
||||
|
||||
useEffect(() => { |
||||
if (profile) { |
||||
const match = { |
||||
calc: false, |
||||
id: matchId, |
||||
live: false, |
||||
sportType, |
||||
team1: profile.team1, |
||||
team2: profile.team2, |
||||
} |
||||
setMatch(match) |
||||
fetchMatchPlaylists(match) |
||||
} |
||||
}, [ |
||||
matchId, |
||||
profile, |
||||
setMatch, |
||||
sportType, |
||||
fetchMatchPlaylists, |
||||
]) |
||||
|
||||
const setEpisodesSettings = (newSettings: Settings) => { |
||||
const settingsChanged = !isEqual(newSettings, settings) |
||||
if (settingsChanged) { |
||||
setSettings(newSettings) |
||||
} |
||||
closeSettingsPopup() |
||||
} |
||||
|
||||
return { |
||||
actions, |
||||
closeSettingsPopup, |
||||
isSettingsPopupOpen, |
||||
onPlaylistSelect: handlePlaylistClick, |
||||
openSettingsPopup, |
||||
playlists: matchPlaylists, |
||||
profile, |
||||
selectedPlaylist, |
||||
setEpisodesSettings, |
||||
settings, |
||||
...useChapters({ |
||||
episodes, |
||||
selectedPlaylist, |
||||
}), |
||||
...usePlayerProgressReporter(), |
||||
} |
||||
} |
||||
@ -0,0 +1,72 @@ |
||||
import { Fragment } from 'react' |
||||
|
||||
import isEmpty from 'lodash/isEmpty' |
||||
|
||||
import { MatchSidePlaylists } from 'features/MatchSidePlaylists' |
||||
import { MultiSourcePlayer } from 'features/MultiSourcePlayer' |
||||
|
||||
import { MatchProfileCard } from '../MatchProfileCard' |
||||
import { SettingsPopup } from '../SettingsPopup' |
||||
|
||||
import type { Props } from './hooks' |
||||
import { useFinishedMatch } from './hooks' |
||||
import { Container } from '../../styled' |
||||
import { Modal } from './styled' |
||||
|
||||
export const FinishedMatch = (props: Props) => { |
||||
const { profile } = props |
||||
const { |
||||
actions, |
||||
chapters, |
||||
closeSettingsPopup, |
||||
isSettingsPopupOpen, |
||||
onPlayerProgressChange, |
||||
onPlayingChange, |
||||
onPlaylistSelect, |
||||
openSettingsPopup, |
||||
playlists, |
||||
selectedPlaylist, |
||||
setEpisodesSettings, |
||||
settings, |
||||
} = useFinishedMatch(props) |
||||
|
||||
return ( |
||||
<Fragment> |
||||
<Modal |
||||
close={closeSettingsPopup} |
||||
isOpen={isSettingsPopupOpen} |
||||
withCloseButton={false} |
||||
> |
||||
<SettingsPopup |
||||
actions={actions} |
||||
onWatchEpisodesClick={setEpisodesSettings} |
||||
settings={settings} |
||||
closePopup={closeSettingsPopup} |
||||
profile={profile} |
||||
selectedPlaylist={selectedPlaylist} |
||||
/> |
||||
</Modal> |
||||
|
||||
<Container> |
||||
<MatchProfileCard profile={profile} /> |
||||
{!isEmpty(chapters) && ( |
||||
<MultiSourcePlayer |
||||
chapters={chapters} |
||||
onPlayingChange={onPlayingChange} |
||||
onProgressChange={onPlayerProgressChange} |
||||
/> |
||||
)} |
||||
</Container> |
||||
|
||||
{playlists && ( |
||||
<MatchSidePlaylists |
||||
playlists={playlists} |
||||
selectedPlaylist={selectedPlaylist} |
||||
onSelect={onPlaylistSelect} |
||||
profile={profile} |
||||
openPopup={openSettingsPopup} |
||||
/> |
||||
)} |
||||
</Fragment> |
||||
) |
||||
} |
||||
@ -0,0 +1,27 @@ |
||||
import styled from 'styled-components/macro' |
||||
|
||||
import { devices } from 'config/devices' |
||||
|
||||
import { Modal as BaseModal } from 'features/Modal' |
||||
import { ModalWindow } from 'features/Modal/styled' |
||||
|
||||
export const Modal = styled(BaseModal)` |
||||
background-color: rgba(0, 0, 0, 0.7); |
||||
|
||||
${ModalWindow} { |
||||
width: 1222px; |
||||
padding: 20px 0; |
||||
background-color: #3F3F3F; |
||||
border-radius: 5px; |
||||
|
||||
@media ${devices.tablet} { |
||||
width: 100vw; |
||||
} |
||||
|
||||
@media ${devices.mobile} { |
||||
height: 100vh; |
||||
padding: 0; |
||||
background-color: transparent; |
||||
} |
||||
} |
||||
` |
||||
@ -0,0 +1,30 @@ |
||||
import { useEffect, useState } from 'react' |
||||
|
||||
import type { LiveVideos } from 'requests' |
||||
import { getLiveVideos } from 'requests' |
||||
|
||||
import { |
||||
useSportNameParam, |
||||
usePageId, |
||||
} from 'hooks' |
||||
|
||||
import { usePlayerProgressReporter } from 'features/MatchPage/hooks/usePlayerProgressReporter' |
||||
import { useLastPlayPosition } from 'features/MatchPage/hooks/useLastPlayPosition' |
||||
|
||||
export const useLiveMatch = () => { |
||||
const { sportType } = useSportNameParam() |
||||
const matchId = usePageId() |
||||
|
||||
const [liveVideos, setLiveVideos] = useState<LiveVideos>([]) |
||||
|
||||
useEffect(() => { |
||||
getLiveVideos(sportType, matchId).then(setLiveVideos) |
||||
}, |
||||
[sportType, matchId]) |
||||
|
||||
return { |
||||
matchUrl: liveVideos[0] || '', |
||||
...usePlayerProgressReporter(), |
||||
...useLastPlayPosition(), |
||||
} |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
import type { MatchInfo } from 'requests' |
||||
|
||||
import { StreamPlayer } from 'features/StreamPlayer' |
||||
|
||||
import { useLiveMatch } from './hooks' |
||||
import { MatchProfileCard } from '../MatchProfileCard' |
||||
import { Container } from '../../styled' |
||||
|
||||
type Props = { |
||||
profile: MatchInfo, |
||||
} |
||||
|
||||
export const LiveMatch = ({ profile }: Props) => { |
||||
const { |
||||
lastPlayPosition, |
||||
matchUrl, |
||||
onPlayerProgressChange, |
||||
onPlayingChange, |
||||
} = useLiveMatch() |
||||
|
||||
return ( |
||||
<Container marginRight={320}> |
||||
<MatchProfileCard profile={profile} /> |
||||
<StreamPlayer |
||||
url={matchUrl} |
||||
onPlayingChange={onPlayingChange} |
||||
onProgressChange={onPlayerProgressChange} |
||||
resumeFrom={lastPlayPosition.second} |
||||
/> |
||||
</Container> |
||||
) |
||||
} |
||||
@ -1,115 +0,0 @@ |
||||
import { useEffect, useState } from 'react' |
||||
|
||||
import isEqual from 'lodash/isEqual' |
||||
|
||||
import type { LiveVideos } from 'requests' |
||||
import { getLiveVideos } from 'requests' |
||||
import { |
||||
useSportNameParam, |
||||
usePageId, |
||||
useToggle, |
||||
} from 'hooks' |
||||
import { Settings, useMatchPopupStore } from 'features/MatchPopup' |
||||
|
||||
import { useLastPlayPosition } from './useLastPlayPosition' |
||||
import { useEpisodes } from './useEpisodes' |
||||
import { useChapters } from './useChapters' |
||||
import { useMatchProfile } from './useMatchProfile' |
||||
|
||||
export const useMatchPage = () => { |
||||
const { |
||||
actions, |
||||
closePopup, |
||||
fetchMatchPlaylists, |
||||
handlePlaylistClick, |
||||
matchPlaylists, |
||||
selectedPlaylist, |
||||
setMatch, |
||||
setSettings, |
||||
settings, |
||||
} = useMatchPopupStore() |
||||
const [isFinishedMatch, setFinishedMatch] = useState(Boolean(selectedPlaylist)) |
||||
const [liveVideos, setLiveVideos] = useState<LiveVideos>([]) |
||||
const profile = useMatchProfile() |
||||
const { sportType } = useSportNameParam() |
||||
const matchId = usePageId() |
||||
|
||||
const { |
||||
close, |
||||
isOpen, |
||||
open, |
||||
} = useToggle() |
||||
|
||||
const { episodes } = useEpisodes() |
||||
|
||||
useEffect(() => { |
||||
if (!isFinishedMatch) { |
||||
getLiveVideos(sportType, matchId) |
||||
.then(setLiveVideos) |
||||
.catch(() => setFinishedMatch(true)) |
||||
} |
||||
}, |
||||
[ |
||||
isFinishedMatch, |
||||
sportType, |
||||
matchId, |
||||
]) |
||||
|
||||
useEffect(() => { |
||||
if (profile && isFinishedMatch) { |
||||
const match = { |
||||
calc: false, |
||||
id: matchId, |
||||
live: false, |
||||
sportType, |
||||
team1: profile.team1, |
||||
team2: profile.team2, |
||||
} |
||||
setMatch(match) |
||||
fetchMatchPlaylists(match) |
||||
} |
||||
}, [ |
||||
matchId, |
||||
profile, |
||||
setMatch, |
||||
sportType, |
||||
isFinishedMatch, |
||||
fetchMatchPlaylists, |
||||
]) |
||||
|
||||
const setEpisodesSettings = (values: Settings) => { |
||||
const isSettingsChanged = !isEqual(values, settings) |
||||
if (isSettingsChanged) { |
||||
setSettings({ |
||||
episodeDuration: values.episodeDuration, |
||||
selectedActions: values.selectedActions, |
||||
selectedFormat: values.selectedFormat, |
||||
}) |
||||
} |
||||
close() |
||||
} |
||||
|
||||
useEffect(() => { |
||||
closePopup() |
||||
}, [closePopup]) |
||||
|
||||
return { |
||||
actions, |
||||
closeSettingsPopup: close, |
||||
isOpen, |
||||
onPlaylistSelect: handlePlaylistClick, |
||||
openSettingsPopup: open, |
||||
playlists: matchPlaylists, |
||||
profile, |
||||
selectedPlaylist, |
||||
setEpisodesSettings, |
||||
settings, |
||||
url: liveVideos[0] || '', |
||||
...useChapters({ |
||||
episodes, |
||||
isFinishedMatch, |
||||
selectedPlaylist, |
||||
}), |
||||
...useLastPlayPosition(), |
||||
} |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
export const REWIND_SECONDS = 5 |
||||
|
||||
export const HOUR_IN_MILLISECONDS = 60 * 60 * 1000 |
||||
@ -0,0 +1,32 @@ |
||||
import styled from 'styled-components/macro' |
||||
|
||||
import { ButtonBase } from 'features/StreamPlayer/styled' |
||||
|
||||
export const ChaptersText = styled.span` |
||||
margin: 0 14px; |
||||
font-weight: 500; |
||||
font-size: 16px; |
||||
color: #fff; |
||||
text-align: center; |
||||
` |
||||
|
||||
type PrevProps = { |
||||
disabled?: boolean, |
||||
} |
||||
|
||||
export const Prev = styled(ButtonBase)<PrevProps>` |
||||
width: 29px; |
||||
height: 28px; |
||||
background-image: url(/images/player-prev.svg); |
||||
|
||||
${({ disabled }) => ( |
||||
disabled |
||||
? 'opacity: 0.5;' |
||||
: '' |
||||
)} |
||||
` |
||||
|
||||
export const Next = styled(Prev)` |
||||
margin-right: 24px; |
||||
transform: rotate(180deg); |
||||
` |
||||
Loading…
Reference in new issue