Ott 1731 live match procs polling (#519)
* refactor(1731): added SubscriptionGuard component (#516) * Ott 1731 part 2 (#518) * refactor(1731): events and playlists polling, wip * fix(1731): 0 duration on playlist buttonkeep-around/af30b88d367751c9e05a735e4a0467a96238ef47
parent
c63149f34f
commit
e467cd64d1
@ -1,41 +0,0 @@ |
|||||||
import styled from 'styled-components/macro' |
|
||||||
|
|
||||||
import { devices, MATCH_SIDE_PLAYLIST_WIDTH } from 'config' |
|
||||||
|
|
||||||
import { T9n } from 'features/T9n' |
|
||||||
import { Tab, TabsGroup } from 'features/Common' |
|
||||||
|
|
||||||
const Wrapper = styled.div`` |
|
||||||
|
|
||||||
const Container = styled.div` |
|
||||||
margin-left: 14px; |
|
||||||
margin-right: 18px; |
|
||||||
|
|
||||||
@media ${devices.tablet} { |
|
||||||
width: 80%; |
|
||||||
margin: 0 auto; |
|
||||||
padding: 18px 12px 20px 12px; |
|
||||||
} |
|
||||||
|
|
||||||
@media ${devices.mobile} { |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
` |
|
||||||
|
|
||||||
export const LiveMatchSidePlaylists = () => ( |
|
||||||
<Wrapper> |
|
||||||
<Container> |
|
||||||
<TabsGroup buttons={3}> |
|
||||||
<Tab width={MATCH_SIDE_PLAYLIST_WIDTH[0]} selected> |
|
||||||
<T9n t='watch' /> |
|
||||||
</Tab> |
|
||||||
<Tab width={MATCH_SIDE_PLAYLIST_WIDTH[1]}> |
|
||||||
<T9n t='actions' /> |
|
||||||
</Tab> |
|
||||||
<Tab width={MATCH_SIDE_PLAYLIST_WIDTH[2]}> |
|
||||||
<T9n t='commentators' /> |
|
||||||
</Tab> |
|
||||||
</TabsGroup> |
|
||||||
</Container> |
|
||||||
</Wrapper> |
|
||||||
) |
|
||||||
@ -0,0 +1,42 @@ |
|||||||
|
import type { ReactNode } from 'react' |
||||||
|
import { Fragment, useEffect } from 'react' |
||||||
|
|
||||||
|
import type { MatchInfo } from 'requests/getMatchInfo' |
||||||
|
|
||||||
|
import { usePageParams } from 'hooks/usePageParams' |
||||||
|
|
||||||
|
import { useBuyMatchPopupStore } from 'features/BuyMatchPopup' |
||||||
|
|
||||||
|
import { prepareMatchProfile } from '../../helpers/prepareMatchProfile' |
||||||
|
|
||||||
|
type Props = { |
||||||
|
children: ReactNode, |
||||||
|
matchProfile: MatchInfo, |
||||||
|
} |
||||||
|
|
||||||
|
export const SubscriptionGuard = ({ children, matchProfile }: Props) => { |
||||||
|
const { open: openBuyMatchPopup } = useBuyMatchPopupStore() |
||||||
|
const { profileId: matchId, sportType } = usePageParams() |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (matchProfile && !matchProfile.sub) { |
||||||
|
const profile = prepareMatchProfile({ |
||||||
|
matchId, |
||||||
|
profile: matchProfile, |
||||||
|
sportType, |
||||||
|
}) |
||||||
|
openBuyMatchPopup(profile) |
||||||
|
} |
||||||
|
}, [ |
||||||
|
matchId, |
||||||
|
openBuyMatchPopup, |
||||||
|
matchProfile, |
||||||
|
sportType, |
||||||
|
]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Fragment> |
||||||
|
{matchProfile?.sub ? children : null} |
||||||
|
</Fragment> |
||||||
|
) |
||||||
|
} |
||||||
@ -1 +0,0 @@ |
|||||||
export const MATCH_UPDATE_INTERVAL = 20000 |
|
||||||
@ -0,0 +1,64 @@ |
|||||||
|
import { useEffect, useMemo } from 'react' |
||||||
|
|
||||||
|
import debounce from 'lodash/debounce' |
||||||
|
|
||||||
|
import { usePageParams } from 'hooks/usePageParams' |
||||||
|
import { useInterval } from 'hooks/useInterval' |
||||||
|
|
||||||
|
import { useMatchPopupStore } from 'features/MatchPopup' |
||||||
|
|
||||||
|
import { useEvents } from './useEvents' |
||||||
|
|
||||||
|
const MATCH_DATA_POLL_INTERVAL = 60000 |
||||||
|
const MATCH_PLAYLISTS_DELAY = 5000 |
||||||
|
|
||||||
|
export const useMatchData = (live: boolean = false) => { |
||||||
|
const { profileId: matchId, sportType } = usePageParams() |
||||||
|
const { fetchMatchPlaylists, matchPlaylists } = useMatchPopupStore() |
||||||
|
const { events, fetchMatchEvents } = useEvents() |
||||||
|
|
||||||
|
const fetchPlaylistsDebounced = useMemo( |
||||||
|
() => debounce(fetchMatchPlaylists, MATCH_PLAYLISTS_DELAY), |
||||||
|
[fetchMatchPlaylists], |
||||||
|
) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
fetchMatchPlaylists({ |
||||||
|
id: matchId, |
||||||
|
sportType, |
||||||
|
withFullMatchDuration: !live, |
||||||
|
}) |
||||||
|
fetchMatchEvents() |
||||||
|
}, [ |
||||||
|
live, |
||||||
|
matchId, |
||||||
|
sportType, |
||||||
|
fetchMatchPlaylists, |
||||||
|
fetchMatchEvents, |
||||||
|
]) |
||||||
|
|
||||||
|
const intervalCallback = () => { |
||||||
|
fetchPlaylistsDebounced({ |
||||||
|
id: matchId, |
||||||
|
sportType, |
||||||
|
withFullMatchDuration: !live, |
||||||
|
}) |
||||||
|
fetchMatchEvents() |
||||||
|
} |
||||||
|
|
||||||
|
const { start, stop } = useInterval({ |
||||||
|
callback: intervalCallback, |
||||||
|
intervalDuration: MATCH_DATA_POLL_INTERVAL, |
||||||
|
startImmediate: false, |
||||||
|
}) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (live) { |
||||||
|
start() |
||||||
|
} else { |
||||||
|
stop() |
||||||
|
} |
||||||
|
}, [live, start, stop]) |
||||||
|
|
||||||
|
return { events, matchPlaylists } |
||||||
|
} |
||||||
@ -1,44 +1,53 @@ |
|||||||
import { |
import { |
||||||
useCallback, |
|
||||||
useEffect, |
useEffect, |
||||||
useState, |
useState, |
||||||
|
useMemo, |
||||||
} from 'react' |
} from 'react' |
||||||
|
|
||||||
import type { MatchInfo } from 'requests' |
import type { MatchInfo } from 'requests' |
||||||
import { getMatchInfo } from 'requests' |
import { getMatchInfo } from 'requests' |
||||||
|
|
||||||
import { usePageParams } from 'hooks/usePageParams' |
import { usePageParams } from 'hooks/usePageParams' |
||||||
import { useInterval } from 'hooks/useInterval' |
|
||||||
|
|
||||||
import { MATCH_UPDATE_INTERVAL } from '../config' |
import type { Playlists } from '../types' |
||||||
|
import { useMatchData } from './useMatchData' |
||||||
|
|
||||||
|
const addScoresFromPlaylists = ( |
||||||
|
profile: MatchInfo, |
||||||
|
playlists: Playlists, |
||||||
|
): MatchInfo => ( |
||||||
|
profile |
||||||
|
? { |
||||||
|
...profile, |
||||||
|
team1: { |
||||||
|
...profile?.team1, |
||||||
|
score: playlists.score1, |
||||||
|
}, |
||||||
|
team2: { |
||||||
|
...profile?.team2, |
||||||
|
score: playlists.score2, |
||||||
|
}, |
||||||
|
} |
||||||
|
: null |
||||||
|
) |
||||||
|
|
||||||
export const useMatchProfile = () => { |
export const useMatchProfile = () => { |
||||||
const [matchProfile, setMatchProfile] = useState<MatchInfo>(null) |
const [matchProfile, setMatchProfile] = useState<MatchInfo>(null) |
||||||
const { profileId: matchId, sportType } = usePageParams() |
const { profileId: matchId, sportType } = usePageParams() |
||||||
|
|
||||||
const fetchMatchProfile = useCallback(() => { |
useEffect(() => { |
||||||
getMatchInfo(sportType, matchId).then(setMatchProfile) |
getMatchInfo(sportType, matchId).then(setMatchProfile) |
||||||
}, |
}, [sportType, matchId]) |
||||||
[sportType, matchId]) |
|
||||||
|
|
||||||
const { start, stop } = useInterval({ |
const { events, matchPlaylists } = useMatchData(matchProfile?.live) |
||||||
callback: fetchMatchProfile, |
|
||||||
intervalDuration: MATCH_UPDATE_INTERVAL, |
|
||||||
startImmediate: false, |
|
||||||
}) |
|
||||||
|
|
||||||
useEffect(fetchMatchProfile, [fetchMatchProfile]) |
const profile = useMemo( |
||||||
useEffect(() => { |
() => addScoresFromPlaylists(matchProfile, matchPlaylists), |
||||||
if (matchProfile?.live) { |
[matchProfile, matchPlaylists], |
||||||
start() |
) |
||||||
} else { |
|
||||||
stop() |
|
||||||
} |
|
||||||
}, [ |
|
||||||
matchProfile, |
|
||||||
start, |
|
||||||
stop, |
|
||||||
]) |
|
||||||
|
|
||||||
return matchProfile |
return { |
||||||
|
events, |
||||||
|
profile, |
||||||
|
} |
||||||
} |
} |
||||||
|
|||||||
Loading…
Reference in new issue