develop #194

Merged
andrey.dekterev merged 5 commits from develop into master 3 years ago
  1. 46440
      package-lock.json
  2. 1
      package.json
  3. 4
      src/config/procedures.tsx
  4. 1
      src/features/AuthStore/helpers.tsx
  5. 47
      src/features/AuthStore/hooks/useAuth.tsx
  6. 3
      src/features/MatchPage/components/FinishedMatch/index.tsx
  7. 3
      src/features/MatchPage/components/LiveMatch/index.tsx
  8. 6
      src/features/MatchPage/components/MatchDescription/styled.tsx
  9. 32
      src/features/MatchPage/store/hooks/useMatchData.tsx
  10. 1
      src/features/MatchPage/store/hooks/useMatchPlaylists.tsx
  11. 7
      src/features/MatchPage/styled.tsx
  12. 1
      src/features/MatchPopup/store/hooks/index.tsx
  13. 2
      src/features/MatchSidePlaylists/index.tsx
  14. 6
      src/features/MatchSidePlaylists/styled.tsx
  15. 42
      src/features/UserFavorites/hooks/index.tsx
  16. 25
      src/features/UserFavorites/index.tsx
  17. 2
      src/hooks/useInterval.tsx
  18. 4
      src/requests/checkDevice.tsx
  19. 15
      src/requests/getMatchEvents.tsx
  20. 22
      src/requests/getMatchPlaylists.tsx

46440
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -27,6 +27,7 @@
"@stripe/stripe-js": "^1.13.2",
"babel-polyfill": "^6.26.0",
"date-fns": "^2.14.0",
"dueljs": "^1.2.7",
"eslint-plugin-typescript-sort-keys": "^2.3.0",
"history": "^4.10.1",
"hls.js": "^1.1.1",

@ -3,7 +3,9 @@ export const PROCEDURES = {
get_cities: 'get_cities',
get_languages: 'get_languages',
get_match_info: 'get_match_info',
get_match_plays: 'get_match_plays',
get_match_subscriptions: 'get_match_subscriptions',
get_match_watch: 'get_match_watch',
get_matches: 'get_matches',
get_objects: 'get_objects',
get_player_info: 'get_player_info',
@ -28,8 +30,6 @@ export const PROCEDURES = {
get_view_user_match: 'get_view_user_match',
landing_get_match_info: 'landing_get_match_info',
lst_c_country: 'lst_c_country',
ott_match_events: 'ott_match_events',
ott_match_popup: 'ott_match_popup',
ott_match_popup_actions: 'ott_match_popup_actions',
ott_match_popup_player_playlist: 'ott_match_popup_player_playlist',
param_lexical: 'param_lexical',

@ -61,7 +61,6 @@ const redirectUrl = () => {
export const getClientSettings = (): Settings => ({
authority: AUTH_SERVICE,
automaticSilentRenew: true,
client_id: client.auth.clientId,
filterProtocolClaims: false,
loadUserInfo: false,

@ -7,6 +7,8 @@ import {
import { useHistory } from 'react-router'
import type { User } from 'oidc-client'
// @ts-expect-error
import duel from 'dueljs'
import isString from 'lodash/isString'
import isBoolean from 'lodash/isBoolean'
@ -21,14 +23,12 @@ import {
readToken,
setCookie,
removeCookie,
TOKEN_KEY,
} from 'helpers'
import {
useLocalStore,
useSessionStore,
useToggle,
useEventListener,
} from 'hooks'
import { useLexicsStore } from 'features/LexicsStore'
@ -172,27 +172,6 @@ export const useAuth = () => {
markUserLoaded,
])
useEventListener({
callback: useCallback(async (e: StorageEvent) => {
const loadedUser = await userManager.getUser()
if (
e.storageArea !== localStorage
|| e.key !== TOKEN_KEY
|| !e.newValue
|| !loadedUser
|| loadedUser.access_token === e.newValue
) return
userManager.storeUser({
...loadedUser,
access_token: e.newValue,
toStorageString: loadedUser.toStorageString,
})
}, []),
event: 'storage',
})
useEffect(() => {
const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect'
isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser()
@ -238,28 +217,24 @@ export const useAuth = () => {
setIsNewDeviceLogin,
])
duel.channel('active_page') // поле в LS, определяющее активность вкладки
useEffect(() => {
// попытаемся обновить токен используя refresh_token
const tryRenewToken = () => {
const tokenLastUpdated = Number(localStorage.getItem('token_updated'))
// предотвращаем одновременное обновление токена в разных окнах/вкладках
const needRenewToken = Date.now() - tokenLastUpdated >= 2 * 1e3
if (!needRenewToken) return
localStorage.setItem('token_updated', String(Date.now()))
userManager.signinSilent()
.catch(logout)
// библиотека oidc-client не поддерживает обновление токена только на 1 вкладке
// @ts-ignore
if (window.isMaster()) {
userManager.signinSilent().catch(logout)
}
}
// если запросы вернули 401 | 403
window.addEventListener('FORBIDDEN_REQUEST', tryRenewToken)
// и если токен истек
userManager.events.addAccessTokenExpired(tryRenewToken)
// и если токен истекает (по дефолту за 60 секунд)
userManager.events.addAccessTokenExpiring(tryRenewToken)
return () => {
window.removeEventListener('FORBIDDEN_REQUEST', tryRenewToken)
userManager.events.removeAccessTokenExpired(tryRenewToken)
userManager.events.removeAccessTokenExpiring(tryRenewToken)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [logout])

@ -18,6 +18,7 @@ export const FinishedMatch = () => {
access,
isOpenFiltersPopup,
profile,
profileCardShown,
} = useMatchPageStore()
const {
chapters,
@ -46,7 +47,7 @@ export const FinishedMatch = () => {
/>
</Modal>
<Container>
<Container isHidden={!profileCardShown}>
{!isEmpty(chapters) && (
<Fragment>
<MultiSourcePlayer

@ -15,6 +15,7 @@ import { MatchDescription } from '../MatchDescription'
export const LiveMatch = () => {
const {
profile,
profileCardShown,
selectedPlaylist,
} = useMatchPageStore()
@ -29,7 +30,7 @@ export const LiveMatch = () => {
} = useLiveMatch()
return (
<Fragment>
<Container>
<Container isHidden={!profileCardShown}>
{profile?.youtube_link ? (
<YoutubePlayer
chapters={chapters}

@ -17,10 +17,8 @@ export const Description = styled.div<{isHidden?: boolean}>`
: ''};
${({ isHidden }) => (isHidden && isMobileDevice ? css`
height: 0;
opacity: 0;
margin-bottom: 0;
` : '')}
display: none;
` : '')}
`
export const DescriptionInnerBlock = styled.div`

@ -1,11 +1,9 @@
import {
useEffect,
useMemo,
useState,
useCallback,
} from 'react'
import debounce from 'lodash/debounce'
import type { MatchInfo } from 'requests/getMatchInfo'
import { usePageParams, useInterval } from 'hooks'
@ -19,8 +17,7 @@ import { useMatchPlaylists } from './useMatchPlaylists'
import { useEvents } from './useEvents'
import { initialPlaylist } from './useSelectedPlaylist'
const MATCH_DATA_POLL_INTERVAL = 60000
const MATCH_PLAYLISTS_DELAY = 5000
const MATCH_DATA_POLL_INTERVAL = 5000
type UseMatchDataArgs = {
matchProfile: MatchInfo,
@ -42,37 +39,38 @@ export const useMatchData = ({ matchProfile: profile, selectedTab }: UseMatchDat
const { events, fetchMatchEvents } = useEvents()
const fetchPlaylistsDebounced = useMemo(
() => debounce(fetchMatchPlaylists, MATCH_PLAYLISTS_DELAY),
[fetchMatchPlaylists],
)
const chaptersDuration = useDuration(chapters) / 1000
const fullMatchDuration = matchDuration
useEffect(() => {
if (!profile || (profile.live && Number(profile.c_match_calc_status) <= 1)) return
if (!profile || profile.live) return
fetchMatchPlaylists({
fullMatchDuration,
id: matchId,
sportType,
})
fetchMatchEvents()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
profile,
profile?.live,
fullMatchDuration,
matchId,
sportType,
fetchMatchPlaylists,
fetchMatchEvents,
])
const intervalCallback = () => {
fetchPlaylistsDebounced({
const intervalCallback = useCallback(() => {
fetchMatchPlaylists({
fullMatchDuration,
id: matchId,
sportType,
})
fetchMatchEvents()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
fullMatchDuration,
matchId,
sportType,
])
const { start, stop } = useInterval({
callback: intervalCallback,
@ -86,7 +84,7 @@ export const useMatchData = ({ matchProfile: profile, selectedTab }: UseMatchDat
} else {
stop()
}
}, [profile?.live, profile?.c_match_calc_status, start, stop])
}, [profile?.live, profile?.c_match_calc_status, start, stop, matchId])
useEffect(() => {
selectedPlaylist?.id === FULL_GAME_KEY && setMatchDuration(chaptersDuration)

@ -67,7 +67,6 @@ export const useMatchPlaylists = ({
getMatchPlaylists({
fullMatchDuration,
matchId: id,
selectedActions: [],
sportType,
}).then(fetchLexics)
.then(buildPlaylists)

@ -35,7 +35,7 @@ export const Wrapper = styled.div<WrapperProps>`
: '')};
`
export const Container = styled.div`
export const Container = styled.div<{isHidden?: boolean}>`
width: 100%;
max-height: 896px;
display: flex;
@ -63,4 +63,9 @@ export const Container = styled.div`
}
`
: ''};
${({ isHidden }) => (isHidden && isMobileDevice
? css`
margin-bottom: 0;`
: '')}
`

@ -95,7 +95,6 @@ export const useMatchPopup = () => {
getMatchPlaylists({
fullMatchDuration,
matchId: id,
selectedActions: [],
sportType,
withFullMatchDuration,
}).then(fetchLexics)

@ -60,6 +60,7 @@ export const MatchSidePlaylists = ({
hideProfileCard,
matchPlaylists: playlists,
profile,
profileCardShown,
selectedTab,
showProfileCard,
tournamentData,
@ -137,6 +138,7 @@ export const MatchSidePlaylists = ({
data-step={Steps.Welcome}
highlighted={Boolean(isOpen) && currentStep === Steps.Welcome}
isTourOpen={Boolean(isOpen)}
isHidden={!profileCardShown}
>
<TabsWrapper>
<TabsGroup hasLessThanFourTabs={hasLessThanFourTabs}>

@ -11,6 +11,7 @@ import { T9n } from 'features/T9n'
type WrapperProps = {
highlighted?: boolean,
isHidden?: boolean,
isTourOpen?: boolean,
}
@ -38,6 +39,11 @@ export const Wrapper = styled.div<WrapperProps>`
`
: ''};
${({ isHidden }) => (isHidden && isMobileDevice
? css`
padding-top: 50px;`
: '')}
${({ isTourOpen }) => (isTourOpen
? css`
overflow-y: initial;

@ -1,18 +1,14 @@
import {
useCallback,
useEffect,
useMemo,
useState,
} from 'react'
import find from 'lodash/find'
import forEach from 'lodash/forEach'
import { reduce } from 'lodash'
import type { ObjectWithName } from 'features/Name'
import {
FavoritesActions,
UserFavorites,
modifyUserFavorites,
getUserFavorites,
@ -53,29 +49,6 @@ export const useUserFavorites = () => {
open,
} = useToggle()
const superTournaments = useMemo(() => {
const uniqueTournamnetIds: Record<number, number> = {}
return reduce(
userFavorites,
(acc, item) => {
if (
item?.info?.super_tournament
&& !uniqueTournamnetIds[item.info.super_tournament.id]
) {
uniqueTournamnetIds[item.info.super_tournament.id] = item.info.super_tournament.id
acc.push({
...item.info.super_tournament,
sport: item.sport,
type: ProfileTypes.SUPERTOURNAMENTS,
})
}
return acc
},
[] as Array<SuperTournament>,
)
}, [userFavorites])
const fetchFavorites = useCallback(() => {
getUserFavorites().then((value) => {
if (Array.isArray(value)) {
@ -85,19 +58,6 @@ export const useUserFavorites = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [userInfo?.email])
const removeSuperTournament = (id: number) => {
forEach(userFavorites, (item) => {
if (item.info.super_tournament?.id === id) {
addRemoveFavorite({
action: FavoritesActions.REMOVE,
id: item.id,
sport: item.sport,
type: item.type,
})
}
})
}
useEffect(() => {
if (!user) return
@ -122,9 +82,7 @@ export const useUserFavorites = () => {
isOpen,
open,
playerHighlight,
removeSuperTournament,
setPlayerHighlight,
superTournaments,
userFavorites,
}
}

@ -37,8 +37,6 @@ export const UserFavorites = ({ marginTop }: Props) => {
addRemoveFavorite,
close,
isOpen,
removeSuperTournament,
superTournaments,
userFavorites,
} = useUserFavoritesStore()
@ -54,29 +52,6 @@ export const UserFavorites = ({ marginTop }: Props) => {
<UserSportFavWrapper>
<UserSportFavStar marginTop={marginTop} />
<ScrollWrapper>
{
map(superTournaments, (item) => (
<UserSportFavItemLogoWrapper
onFocus={getPosition}
onMouseOver={getPosition}
key={`${item.type}_${item.sport}_${item.id}`}
>
<UserSportFavXWrapper onClick={() => removeSuperTournament(item.id)}>
<Close size={9} />
<FavoritesToolip
topPosition={position}
superTournament={item}
/>
</UserSportFavXWrapper>
<UserSportFavImgWrapper
id={item.id}
altNameObj={item}
sportType={item.sport}
profileType={item.type}
/>
</UserSportFavItemLogoWrapper>
))
}
{
map(userFavorites, (item) => (
<UserSportFavItemLogoWrapper

@ -31,7 +31,7 @@ export const useInterval = ({
const id = setInterval(savedCallback.current, intervalDuration)
return () => clearInterval(id)
}, [isRunning, intervalDuration])
}, [isRunning, intervalDuration, callback])
return { start, stop }
}

@ -1,4 +1,4 @@
import { AUTH_SERVICE } from '../config/routes'
import { API_ROOT } from 'features/AuthServiceApp/config/routes'
export type FailedResponse = {
error?: string,
@ -10,7 +10,7 @@ export type SuccessResponse = {
}
export const checkDevice = async (token: string) => {
const url = `${AUTH_SERVICE}/authorize/check-device?access_token=${token}`
const url = `${API_ROOT}/authorize/check-device?access_token=${token}`
const config = {
method: 'GET',

@ -1,14 +1,10 @@
import {
DATA_URL,
PROCEDURES,
} from 'config'
import { STATS_API_URL, PROCEDURES } from 'config'
import { Episode, Episodes } from 'requests'
import { callApi, getSportLexic } from 'helpers'
import { callApi } from 'helpers'
const proc = PROCEDURES.ott_match_events
const proc = PROCEDURES.get_match_plays
type Args = {
matchId: number,
@ -66,7 +62,8 @@ export const getMatchEvents = async ({
const config = {
body: {
params: {
_p_match_id: matchId,
match_id: matchId,
sport_id: sportType,
},
proc,
},
@ -74,7 +71,7 @@ export const getMatchEvents = async ({
const response: Response = await callApi({
config,
url: `${DATA_URL}/${getSportLexic(sportType)}`,
url: `${STATS_API_URL}/data/stats`,
})
if (!response?.data) return Promise.reject(response)

@ -1,18 +1,11 @@
import isEmpty from 'lodash/isEmpty'
import { PROCEDURES, STATS_API_URL } from 'config'
import { callApi } from 'helpers'
import {
DATA_URL,
PROCEDURES,
} from 'config'
import { callApi, getSportLexic } from 'helpers'
const proc = PROCEDURES.ott_match_popup
const proc = PROCEDURES.get_match_watch
type Args = {
fullMatchDuration?: number,
matchId: number,
selectedActions: Array<number>,
sportType: number,
withFullMatchDuration?: boolean,
}
@ -79,16 +72,13 @@ type Response = {
export const getMatchPlaylists = async ({
fullMatchDuration,
matchId,
selectedActions,
sportType,
}: Args): Promise<MatchPlaylists> => {
const actions = isEmpty(selectedActions) ? null : selectedActions
const config = {
body: {
params: {
_p_actions: actions,
_p_match_id: matchId,
match_id: matchId,
sport_id: sportType,
},
proc,
},
@ -102,7 +92,7 @@ export const getMatchPlaylists = async ({
try {
const playlist: Response = await callApi({
config,
url: `${DATA_URL}/${getSportLexic(sportType)}`,
url: `${STATS_API_URL}/data/stats`,
})
if (playlist.data) {
return { ...playlist.data, full_game }

Loading…
Cancel
Save