diff --git a/public/images/rewind-left.svg b/public/images/rewind-left.svg
new file mode 100644
index 00000000..37f6a190
--- /dev/null
+++ b/public/images/rewind-left.svg
@@ -0,0 +1,28 @@
+
diff --git a/public/images/rewind-right.svg b/public/images/rewind-right.svg
new file mode 100644
index 00000000..f786c740
--- /dev/null
+++ b/public/images/rewind-right.svg
@@ -0,0 +1,28 @@
+
diff --git a/src/features/HeaderFilters/components/DateFilter/styled.tsx b/src/features/HeaderFilters/components/DateFilter/styled.tsx
index 7d0f7fef..3857d476 100644
--- a/src/features/HeaderFilters/components/DateFilter/styled.tsx
+++ b/src/features/HeaderFilters/components/DateFilter/styled.tsx
@@ -84,6 +84,7 @@ export const DateButton = styled(BaseButton) `
position: static;
width: 9px;
height: 9px;
+ margin-left: 10px;
`
: ''};
@@ -96,17 +97,6 @@ export const DateButton = styled(BaseButton) `
? 'opacity: 1;'
: ''
)}
-
- ${isMobileDevice
- ? css`
- /* right: 14px;
- width: 16px;
- height: 16px; */
- @media screen and (orientation: landscape){
- /* right: 20px; */
- }
- `
- : ''};
`
export const WeekDaysWrapper = styled.div`
diff --git a/src/features/MatchCard/helpers/index.tsx b/src/features/MatchCard/helpers/index.tsx
index bca3139d..3d65a5b5 100644
--- a/src/features/MatchCard/helpers/index.tsx
+++ b/src/features/MatchCard/helpers/index.tsx
@@ -12,6 +12,6 @@ export const getPrepareTimeFormat = ({
time,
}: prepareTimeFormat) => (
isNeedFormatTimeChanged
- ? format(date, 'h:mm aaa')
+ ? format(date, 'h:mm a')
: time
)
diff --git a/src/features/MatchPage/components/FinishedMatch/hooks/index.tsx b/src/features/MatchPage/components/FinishedMatch/hooks/index.tsx
index 1ff17d42..5a33de95 100644
--- a/src/features/MatchPage/components/FinishedMatch/hooks/index.tsx
+++ b/src/features/MatchPage/components/FinishedMatch/hooks/index.tsx
@@ -4,19 +4,19 @@ import { useToggle } from 'hooks/useToggle'
import type { Settings } from 'features/MatchPopup'
import { useMatchPopupStore } from 'features/MatchPopup'
+import { useMatchPageStore } from 'features/MatchPage/store'
import { usePlayerLogger } from './usePlayerLogger'
import { useEpisodes } from './useEpisodes'
import { useChapters } from './useChapters'
export const useFinishedMatch = () => {
+ const { setChapters, setSettings } = useMatchPopupStore()
const {
handlePlaylistClick,
matchPlaylists,
selectedPlaylist,
- setChapters,
- setSettings,
- } = useMatchPopupStore()
+ } = useMatchPageStore()
const {
close: closeSettingsPopup,
isOpen: isSettingsPopupOpen,
diff --git a/src/features/MatchPage/components/FinishedMatch/hooks/useEpisodes.tsx b/src/features/MatchPage/components/FinishedMatch/hooks/useEpisodes.tsx
index 152638cf..93b7dc40 100644
--- a/src/features/MatchPage/components/FinishedMatch/hooks/useEpisodes.tsx
+++ b/src/features/MatchPage/components/FinishedMatch/hooks/useEpisodes.tsx
@@ -12,6 +12,8 @@ import { getPlayerPlaylists } from 'requests'
import { usePageParams } from 'hooks/usePageParams'
import { PlaylistOption, PlaylistTypes } from 'features/MatchPage/types'
+import { useMatchPageStore } from 'features/MatchPage/store'
+
import {
defaultSettings,
Settings,
@@ -19,12 +21,12 @@ import {
} from 'features/MatchPopup'
export const useEpisodes = () => {
+ const { settings } = useMatchPopupStore()
const {
handlePlaylistClick,
matchPlaylists: playlists,
selectedPlaylist,
- settings,
- } = useMatchPopupStore()
+ } = useMatchPageStore()
const [episodes, setEpisodes] = useState([])
const { profileId: matchId, sportType } = usePageParams()
diff --git a/src/features/MatchPage/components/FinishedMatch/index.tsx b/src/features/MatchPage/components/FinishedMatch/index.tsx
index f8190c7f..4d588a3c 100644
--- a/src/features/MatchPage/components/FinishedMatch/index.tsx
+++ b/src/features/MatchPage/components/FinishedMatch/index.tsx
@@ -2,11 +2,6 @@ import { Fragment } from 'react'
import isEmpty from 'lodash/isEmpty'
-import { isMobileDevice } from 'config/userAgent'
-
-import type { Events } from 'requests/getMatchEvents'
-import type { MatchInfo } from 'requests/getMatchInfo'
-
import { MatchSidePlaylists } from 'features/MatchSidePlaylists'
import { MultiSourcePlayer } from 'features/MultiSourcePlayer'
@@ -15,28 +10,17 @@ import { SettingsPopup } from '../SettingsPopup'
import { useFinishedMatch } from './hooks'
import { Container } from '../../styled'
import { Modal } from './styled'
-import { TournamentData } from '../../types'
import { MatchDescription } from '../MatchDescription'
-import { MatchProfileCardMobile } from '../MatchProfileCardMobile'
-
-type Props = {
- events: Events,
- profile: MatchInfo,
- tournamentData: TournamentData,
-}
+import { useMatchPageStore } from '../../store'
-export const FinishedMatch = ({
- events,
- profile,
- tournamentData,
-}: Props) => {
+export const FinishedMatch = () => {
+ const { profile } = useMatchPageStore()
const {
chapters,
closeSettingsPopup,
isSettingsPopupOpen,
onPlayingChange,
onPlaylistSelect,
- playlists,
selectedPlaylist,
setEpisodesSettings,
} = useFinishedMatch()
@@ -64,20 +48,14 @@ export const FinishedMatch = ({
onPlayingChange={onPlayingChange}
profile={profile}
/>
- {isMobileDevice
- ? : (
- )}
+
)}
)
diff --git a/src/features/MatchPage/components/LiveMatch/index.tsx b/src/features/MatchPage/components/LiveMatch/index.tsx
index 79abf0cb..b6a405f1 100644
--- a/src/features/MatchPage/components/LiveMatch/index.tsx
+++ b/src/features/MatchPage/components/LiveMatch/index.tsx
@@ -7,25 +7,13 @@ import { StreamPlayer } from 'features/StreamPlayer'
import { YoutubePlayer } from 'features/StreamPlayer/components/YoutubePlayer'
import { MatchSidePlaylists } from 'features/MatchSidePlaylists'
-import { isMobileDevice } from 'config/userAgent'
-
import { Container } from '../../styled'
import { useLiveMatch } from './hooks'
-import { TournamentData } from '../../types'
import { MatchDescription } from '../MatchDescription'
-import { MatchProfileCardMobile } from '../MatchProfileCardMobile'
-
-type Props = {
- tournamentData: TournamentData,
-}
-export const LiveMatch = ({
- tournamentData,
-}: Props) => {
+export const LiveMatch = () => {
const {
- events,
- matchPlaylists,
profile,
selectedPlaylist,
} = useMatchPageStore()
@@ -47,8 +35,8 @@ export const LiveMatch = ({
@@ -58,24 +46,18 @@ export const LiveMatch = ({
onDurationChange={onDurationChange}
onPlayingChange={onPlayingChange}
onProgressChange={onPlayerProgressChange}
- isLive={profile?.live}
+ isLive={profile?.live ?? false}
resumeFrom={resume}
chapters={chapters}
profile={profile}
/>
)
)}
- {isMobileDevice
- ? : (
- )}
+
diff --git a/src/features/MatchPage/components/MatchDescription/index.tsx b/src/features/MatchPage/components/MatchDescription/index.tsx
index 239d3fbb..3a3a3377 100644
--- a/src/features/MatchPage/components/MatchDescription/index.tsx
+++ b/src/features/MatchPage/components/MatchDescription/index.tsx
@@ -1,43 +1,54 @@
+import { useCallback } from 'react'
+
import { format } from 'date-fns'
import includes from 'lodash/includes'
-import type { MatchInfo } from 'requests/getMatchInfo'
+import type { Team } from 'requests/getMatchInfo'
-import { Name } from 'features/Name'
-import { SportIcon } from 'components/SportIcon/SportIcon'
+import { getName, Name } from 'features/Name'
import { useAuthStore } from 'features/AuthStore'
import { useMatchSwitchesStore } from 'features/MatchSwitches'
+import { TournamentSubtitle } from 'features/TournamentSubtitle'
+import { useLexicsStore } from 'features/LexicsStore'
+import { useMatchPageStore } from 'features/MatchPage/store'
import { parseDate } from 'helpers/parseDate'
import { ProfileTypes } from 'config'
+import { isMobileDevice } from 'config/userAgent'
import { usePageParams } from 'hooks/usePageParams'
import {
- CountryFlag,
Description,
DescriptionInnerBlock,
MatchDate,
StyledLink,
Score,
Title,
- Tournament,
Views,
Time,
} from './styled'
-type Props = {
- profile: MatchInfo,
-}
-
-export const MatchDescription = ({
- profile,
-}: Props) => {
+export const MatchDescription = () => {
const { sportType } = usePageParams()
const { user } = useAuthStore()
const { isScoreHidden } = useMatchSwitchesStore()
+ const { suffix } = useLexicsStore()
+ const { profile, profileCardShown } = useMatchPageStore()
+
+ const getTeamName = useCallback((team: Team) => {
+ if (isMobileDevice) {
+ const teamNameLimit = 14
+ let name = getName({ nameObj: team, suffix })
+ if (name.length > teamNameLimit) {
+ name = `${name.substring(0, teamNameLimit)}...`
+ }
+ return name
+ }
+ return
+ }, [suffix])
if (!profile) return
@@ -50,12 +61,12 @@ export const MatchDescription = ({
} = profile
const isChangedTimeFormat = includes(['US', 'CA'], user?.profile.country_code)
- const localDate = format(parseDate(date), 'MMMM d, y')
+ const localDate = format(parseDate(date), 'MMM d, y')
const changedTimeFormat = format(parseDate(date),
- isChangedTimeFormat ? 'h:mm aaa' : 'HH:mm')
+ isChangedTimeFormat ? 'h:mm a' : 'HH:mm')
return (
-
+
-
+ {getTeamName(team1)}
{
@@ -77,22 +88,13 @@ export const MatchDescription = ({
profileType={ProfileTypes.TEAMS}
sportType={sportType}
>
-
+ {getTeamName(team2)}
-
-
-
-
-
-
-
+
diff --git a/src/features/MatchPage/components/MatchDescription/styled.tsx b/src/features/MatchPage/components/MatchDescription/styled.tsx
index 3045b861..c3369aab 100644
--- a/src/features/MatchPage/components/MatchDescription/styled.tsx
+++ b/src/features/MatchPage/components/MatchDescription/styled.tsx
@@ -3,7 +3,7 @@ import { isMobileDevice } from 'config/userAgent'
import { ProfileLink } from 'features/ProfileLink'
-export const Description = styled.div`
+export const Description = styled.div<{isHidden?: boolean}>`
padding: 22px 0 24px;
display: flex;
justify-content: space-between;
@@ -11,24 +11,37 @@ export const Description = styled.div`
${isMobileDevice
? css`
- @media (orientation: portrait) {
- padding-left: 14px;
- }
+ padding: 0 5px;
`
: ''};
+
+ ${({ isHidden }) => (isHidden && isMobileDevice ? css`
+ height: 0;
+ opacity: 0;
+ margin-bottom: 0;
+ ` : '')}
`
-export const DescriptionInnerBlock = styled.div``
+export const DescriptionInnerBlock = styled.div`
+ margin-right: 10px;
+`
export const Score = styled.span`
margin: 0 10px;
color: inherit;
+
+ ${isMobileDevice
+ ? css`
+ margin: 0 5px;
+ `
+ : ''};
`
export const StyledLink = styled(ProfileLink)`
display: flex;
align-items: center;
color: #fff;
+ white-space: nowrap;
&:hover {
text-decoration: underline;
@@ -37,11 +50,8 @@ export const StyledLink = styled(ProfileLink)`
export const Title = styled.div`
display: flex;
- flex-direction: row;
font-weight: 500;
font-size: 20px;
- line-height: 24px;
- margin-bottom: 1px;
&:hover > ${StyledLink}:not(:hover) {
opacity: 0.7;
@@ -51,34 +61,28 @@ export const Title = styled.div`
opacity: 0.7;
pointer-events: none;
}
-`
-
-export const Tournament = styled.span`
- display: flex;
- flex-direction: row;
- align-items: center;
- font-size: 14px;
- line-height: 16px;
- margin-bottom: 1px;
- opacity: 0.7;
-
- &:hover {
- opacity: 1;
- text-decoration: underline;
- }
-`
-export const CountryFlag = styled.img`
- height: 12px;
- margin: 0 6px;
+ ${isMobileDevice
+ ? css`
+ font-size: 14px;
+ margin-bottom: 5px;
+ `
+ : ''};
`
export const Views = styled.div`
color: #fff;
opacity: 0.7;
font-size: 20px;
- line-height: 24px;
- align-self: flex-start;
+
+ ${isMobileDevice
+ ? css`
+ font-size: 10px;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ `
+ : ''};
`
export const MatchDate = styled.span`
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/index.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/index.tsx
deleted file mode 100644
index c8c7964c..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/index.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { useMemo } from 'react'
-
-import { format, parseISO } from 'date-fns'
-
-import { MatchInfo } from 'requests'
-
-import { ScDate, ScDateMonth } from './styled'
-
-type Props = {
- profile: MatchInfo,
-}
-
-export const MatchDate = ({ profile }: Props) => {
- const {
- date,
- } = { ...profile! }
-
- const month = useMemo(() => (
- format(parseISO(date), 'MMM dd,')
- ), [date])
-
- const hour = useMemo(() => (
- format(parseISO(date), ' HH:mm')
- ), [date])
-
- return (
-
-
- {month}
-
- {hour}
-
- )
-}
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/styled.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/styled.tsx
deleted file mode 100644
index 694bb0da..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/components/MatchDate/styled.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import styled from 'styled-components'
-
-export const ScDate = styled.div`
- font-size: 10px;
- color: rgba(255, 255, 255, 0.7);
-`
-
-export const ScDateMonth = styled.span`
- font-weight: 600;
-`
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/index.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/index.tsx
deleted file mode 100644
index c99e3507..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/index.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useCallback } from 'react'
-
-import { ProfileTypes } from 'config'
-
-import { getName } from 'features/Name'
-import { useMatchSwitchesStore } from 'features/MatchSwitches'
-import { useLexicsStore } from 'features/LexicsStore'
-
-import { usePageParams } from 'hooks/usePageParams'
-
-import { MatchInfo, Team } from 'requests'
-
-import {
- Score,
- ScoreWrapper,
- StyledLink,
- ScTeam,
- Wrapper,
-} from './styled'
-
-type Props = {
- profile: MatchInfo,
- teamNameLimit?: number,
-}
-
-export const TeamsDetails = ({ profile, teamNameLimit }: Props) => {
- const { sportType } = usePageParams()
- const { isScoreHidden } = useMatchSwitchesStore()
- const { suffix } = useLexicsStore()
-
- const {
- team1,
- team2,
- } = { ...profile! }
-
- const getTeamName = useCallback((team: Team) => {
- let name = getName({ nameObj: team, suffix })
- if (!!teamNameLimit && name.length > teamNameLimit) name = name.substring(0, teamNameLimit).concat('...')
- return name
- }, [suffix, teamNameLimit])
-
- return (
-
-
-
- {getTeamName(team1)}
-
-
-
-
- {
- isScoreHidden
- ? '-'
- : `${team1.score} - ${team2.score}`
- }
-
-
-
-
- {getTeamName(team2)}
-
-
-
- )
-}
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/styled.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/styled.tsx
deleted file mode 100644
index 90b95f01..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/components/TeamsDetails/styled.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import styled, { css } from 'styled-components'
-
-import { isMobileDevice } from 'config/userAgent'
-
-import { ProfileLink } from 'features/ProfileLink'
-import { ProfileLogo } from 'features/ProfileLogo'
-
-export const Wrapper = styled.div`
- display: flex;
- font-weight: 600;
- margin-bottom: 5px;
-`
-
-export const ScTeam = styled.div`
- font-size: 21px;
-
- ${isMobileDevice
- ? css`
- font-size: 16px;
- `
- : ''};
-`
-
-export const StyledLink = styled(ProfileLink)`
- display: flex;
- align-items: center;
- color: white;
- font-size: 14px;
-
- &:hover {
- text-decoration: underline;
- }
-`
-
-export const ScoreWrapper = styled.div`
- margin: 0 10px;
- display: flex;
- flex-direction: column;
- align-items: center;
-`
-
-export const Score = styled.span`
- font-size: 14px;
- white-space: nowrap;
-`
-
-export const MatchStatus = styled.span`
- text-align: center;
- background-color: #CC0000;
- border-radius: 1.3px;
- font-weight: 600;
- font-size: 13px;
- line-height: 16px;
- letter-spacing: 0.05em;
- text-transform: uppercase;
- padding: 2.5px 14px;
- margin-top: 6px;
-`
-
-export const Logo = styled(ProfileLogo)`
- width: 41px;
- height: 41px;
- margin: 0 9px;
- ${isMobileDevice
- ? css`
- width: 30px;
- height: 30px;
- `
- : ''};
-`
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/index.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/index.tsx
deleted file mode 100644
index 824f7696..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { MatchInfo } from 'requests'
-import { TournamentSubtitle } from 'features/TournamentSubtitle'
-
-import { Wrapper, WrapperTop } from './styled'
-
-import { TeamsDetails } from './components/TeamsDetails'
-import { MatchDate } from './components/MatchDate'
-import { useMatchPageStore } from '../../store'
-
-type Props = {
- profile: MatchInfo,
-}
-
-export const MatchProfileCardMobile = ({ profile }: Props) => {
- const { profileCardShown } = useMatchPageStore()
-
- if (!profile) return null
-
- return (
-
-
-
-
-
-
-
- )
-}
diff --git a/src/features/MatchPage/components/MatchProfileCardMobile/styled.tsx b/src/features/MatchPage/components/MatchProfileCardMobile/styled.tsx
deleted file mode 100644
index a6c0e552..00000000
--- a/src/features/MatchPage/components/MatchProfileCardMobile/styled.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import styled, { css } from 'styled-components/macro'
-
-export const Wrapper = styled.div<{isHidden?: boolean}>`
- transition: 0.3s linear;
- padding: 0 5px;
- color: white;
- margin-bottom: 15px;
-
- ${({ isHidden }) => (isHidden ? css`
- height: 0;
- opacity: 0;
- margin-bottom: 0;
- ` : '')}
-`
-
-export const WrapperTop = styled.div`
- display: flex;
- justify-content: space-between;
-`
diff --git a/src/features/MatchPage/hooks/index.tsx b/src/features/MatchPage/hooks/index.tsx
deleted file mode 100644
index 64d0936b..00000000
--- a/src/features/MatchPage/hooks/index.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useToggle } from 'hooks'
-
-export const useMatchPage = () => {
- const {
- close: hideProfileCard,
- isOpen: profileCardShown,
- open: showProfileCard,
- } = useToggle(true)
-
- return {
- hideProfileCard,
- profileCardShown,
- showProfileCard,
- }
-}
diff --git a/src/features/MatchPage/hooks/useEvents.tsx b/src/features/MatchPage/hooks/useEvents.tsx
deleted file mode 100644
index 14f7095c..00000000
--- a/src/features/MatchPage/hooks/useEvents.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { useCallback, useState } from 'react'
-
-import type { Events } from 'requests'
-import { getMatchEvents } from 'requests'
-
-import { usePageParams } from 'hooks/usePageParams'
-
-import { useEventsLexics } from './useEventsLexics'
-
-export const useEvents = () => {
- const [events, setEvents] = useState([])
- const { fetchLexics } = useEventsLexics()
- const { profileId: matchId, sportType } = usePageParams()
-
- const fetchMatchEvents = useCallback(() => {
- getMatchEvents({
- matchId,
- sportType,
- }).then(fetchLexics)
- .then(setEvents)
- }, [
- fetchLexics,
- matchId,
- sportType,
- ])
-
- return { events, fetchMatchEvents }
-}
diff --git a/src/features/MatchPage/hooks/useEventsLexics.tsx b/src/features/MatchPage/hooks/useEventsLexics.tsx
deleted file mode 100644
index cc886d0f..00000000
--- a/src/features/MatchPage/hooks/useEventsLexics.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useCallback } from 'react'
-
-import isEmpty from 'lodash/isEmpty'
-import map from 'lodash/map'
-import uniq from 'lodash/uniq'
-
-import type { Events } from 'requests'
-
-import { useLexicsStore } from 'features/LexicsStore'
-
-export const useEventsLexics = () => {
- const { addLexicsConfig } = useLexicsStore()
-
- const fetchLexics = useCallback((events: Events) => {
- const lexics = uniq(map(events, ({ l }) => l))
-
- if (!isEmpty(lexics)) {
- addLexicsConfig(lexics)
- }
-
- return events
- }, [addLexicsConfig])
-
- return { fetchLexics }
-}
diff --git a/src/features/MatchPage/hooks/useMatchData.tsx b/src/features/MatchPage/hooks/useMatchData.tsx
deleted file mode 100644
index 3918361a..00000000
--- a/src/features/MatchPage/hooks/useMatchData.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-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 }
-}
diff --git a/src/features/MatchPage/hooks/useMatchProfile.tsx b/src/features/MatchPage/hooks/useMatchProfile.tsx
deleted file mode 100644
index 1f3b3580..00000000
--- a/src/features/MatchPage/hooks/useMatchProfile.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import {
- useEffect,
- useState,
- useMemo,
-} from 'react'
-
-import type { MatchInfo } from 'requests'
-import { getMatchInfo } from 'requests'
-
-import { usePageParams } from 'hooks/usePageParams'
-
-import { parseDate } from 'helpers/parseDate'
-
-import type { Playlists } from '../types'
-import { useMatchData } from './useMatchData'
-import { useTournamentData } from './useTournamentData'
-
-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 = () => {
- const [matchProfile, setMatchProfile] = useState(null)
- const { profileId: matchId, sportType } = usePageParams()
-
- useEffect(() => {
- getMatchInfo(sportType, matchId).then(setMatchProfile)
- }, [sportType, matchId])
-
- useEffect(() => {
- let getIntervalMatch: ReturnType
- if (matchProfile?.live && !matchProfile.youtube_link) {
- getIntervalMatch = setInterval(
- () => getMatchInfo(sportType, matchId).then(setMatchProfile), 1000 * 60 * 3,
- )
- }
- return () => clearInterval(getIntervalMatch)
- }, [matchProfile, sportType, matchId])
-
- const { events, matchPlaylists } = useMatchData(matchProfile?.live)
-
- const profile = useMemo(
- () => addScoresFromPlaylists(matchProfile, matchPlaylists),
- [matchProfile, matchPlaylists],
- )
-
- const { tournamentData } = useTournamentData(matchProfile?.tournament.id ?? null)
-
- const isStarted = useMemo(() => (
- profile?.date
- ? parseDate(profile.date) < new Date()
- : true
- ), [profile?.date])
-
- return {
- events,
- isStarted,
- profile,
- tournamentData,
- }
-}
diff --git a/src/features/MatchPage/index.tsx b/src/features/MatchPage/index.tsx
index 58f8bdeb..aa86b625 100644
--- a/src/features/MatchPage/index.tsx
+++ b/src/features/MatchPage/index.tsx
@@ -15,11 +15,10 @@ import { ProfileTypes } from 'config'
import { usePageLogger } from 'hooks/usePageLogger'
import { usePageParams } from 'hooks/usePageParams'
-import { MatchPageStore } from './store'
+import { MatchPageStore, useMatchPageStore } from './store'
import { SubscriptionGuard } from './components/SubscriptionGuard'
import { LiveMatch } from './components/LiveMatch'
-import { useMatchProfile } from './hooks/useMatchProfile'
import { Wrapper } from './styled'
import { FinishedMatch } from './components/FinishedMatch'
@@ -28,12 +27,7 @@ const MatchPageComponent = () => {
const history = useHistory()
const { addRemoveFavorite, userFavorites } = useUserFavoritesStore()
- const {
- events,
- isStarted,
- profile,
- tournamentData,
- } = useMatchProfile()
+ const { isStarted, profile } = useMatchPageStore()
const {
profileType,
@@ -77,16 +71,10 @@ const MatchPageComponent = () => {
{playFromOTT && (
-
+
)}
{playFromScout && (
-
+
)}
diff --git a/src/features/MatchPage/store/hooks/index.tsx b/src/features/MatchPage/store/hooks/index.tsx
index 5e17b1a0..3f09735b 100644
--- a/src/features/MatchPage/store/hooks/index.tsx
+++ b/src/features/MatchPage/store/hooks/index.tsx
@@ -12,6 +12,7 @@ import { usePageParams } from 'hooks/usePageParams'
import { parseDate } from 'helpers/parseDate'
+import { useTournamentData } from './useTournamentData'
import { useMatchData } from './useMatchData'
import type { Playlists } from '../../types'
@@ -70,13 +71,14 @@ export const useMatchPage = () => {
() => addScoresFromPlaylists(matchProfile, matchPlaylists),
[matchProfile, matchPlaylists],
)
-
const isStarted = useMemo(() => (
profile?.date
? parseDate(profile.date) < new Date()
: true
), [profile?.date])
+ const { tournamentData } = useTournamentData(matchProfile?.tournament.id ?? null)
+
return {
events,
handlePlaylistClick,
@@ -88,5 +90,6 @@ export const useMatchPage = () => {
selectedPlaylist,
setFullMatchPlaylistDuration,
showProfileCard,
+ tournamentData,
}
}
diff --git a/src/features/MatchPage/store/hooks/useMatchPlaylists.tsx b/src/features/MatchPage/store/hooks/useMatchPlaylists.tsx
index 5667b8e2..5af4789c 100644
--- a/src/features/MatchPage/store/hooks/useMatchPlaylists.tsx
+++ b/src/features/MatchPage/store/hooks/useMatchPlaylists.tsx
@@ -3,8 +3,6 @@ import {
useCallback,
} from 'react'
-import isEmpty from 'lodash/isEmpty'
-
import type { SportTypes } from 'config/sportTypes'
import { getMatchPlaylists } from 'requests/getMatchPlaylists'
@@ -34,12 +32,7 @@ export const useMatchPlaylists = () => {
} = useSelectedPlaylist()
const setInitialSeletedPlaylist = useCallback((playlists: Playlists) => {
- setSelectedPlaylist((playlist) => {
- if (!playlist && !isEmpty(playlists.match)) {
- return playlists.match[0]
- }
- return playlist
- })
+ setSelectedPlaylist(playlists.match[0])
return playlists
}, [setSelectedPlaylist])
diff --git a/src/features/MatchPage/hooks/useTournamentData.tsx b/src/features/MatchPage/store/hooks/useTournamentData.tsx
similarity index 97%
rename from src/features/MatchPage/hooks/useTournamentData.tsx
rename to src/features/MatchPage/store/hooks/useTournamentData.tsx
index 2d1c9c0c..d3a55aa5 100644
--- a/src/features/MatchPage/hooks/useTournamentData.tsx
+++ b/src/features/MatchPage/store/hooks/useTournamentData.tsx
@@ -18,7 +18,7 @@ import { parseDate } from 'helpers/parseDate'
import { usePageParams } from 'hooks/usePageParams'
-import { TournamentData } from '../types'
+import { TournamentData } from '../../types'
export const useTournamentData = (tournamentId: number | null) => {
const { sportType } = usePageParams()
diff --git a/src/features/MatchPage/styled.tsx b/src/features/MatchPage/styled.tsx
index 6661053d..3d4cef56 100644
--- a/src/features/MatchPage/styled.tsx
+++ b/src/features/MatchPage/styled.tsx
@@ -17,12 +17,10 @@ export const Wrapper = styled.div`
${isMobileDevice
? css`
+ height: calc(100vh - 40px);
+
@media screen and (orientation: landscape) {
- padding-top: 20px;
flex-direction: row;
- justify-content: space-between;
- margin-left: 10px;
- width: 100vw;
}
`
: ''};
diff --git a/src/features/MatchSidePlaylists/components/TabVideo/components/VideoDate/styled.tsx b/src/features/MatchSidePlaylists/components/TabVideo/components/VideoDate/styled.tsx
index 9b75ab2b..1a07d61d 100644
--- a/src/features/MatchSidePlaylists/components/TabVideo/components/VideoDate/styled.tsx
+++ b/src/features/MatchSidePlaylists/components/TabVideo/components/VideoDate/styled.tsx
@@ -1,5 +1,7 @@
import styled, { css } from 'styled-components/macro'
+import { isMobileDevice } from 'config/userAgent'
+
export const Wrapper = styled.div`
color: #FFFFFF;
display: flex;
@@ -10,6 +12,14 @@ export const Wrapper = styled.div`
> :not(:last-child) {
margin-right: 20px;
}
+
+ ${isMobileDevice ? css`
+ @media screen and (orientation: landscape){
+ > :not(:last-child) {
+ margin-right: 3px;
+ }
+ }
+ ` : ''}
`
export const WeekDay = styled.div.attrs(() => ({
diff --git a/src/features/MatchSidePlaylists/components/TabVideo/styled.tsx b/src/features/MatchSidePlaylists/components/TabVideo/styled.tsx
index d10607e1..e9b0b502 100644
--- a/src/features/MatchSidePlaylists/components/TabVideo/styled.tsx
+++ b/src/features/MatchSidePlaylists/components/TabVideo/styled.tsx
@@ -1,14 +1,20 @@
-import styled from 'styled-components/macro'
+import styled, { css } from 'styled-components/macro'
import { customScrollbar } from 'features/Common'
+import { isMobileDevice } from '../../../../config/userAgent'
export const MatchesWrapper = styled.div`
- overflow-y: scroll;
+ overflow-y: auto;
max-height: calc(100vh - 170px);
-
+ padding-right: 5px;
+
> * {
margin-bottom: 15px;
}
-
${customScrollbar}
+
+ ${isMobileDevice ? css`
+ overflow: hidden;
+ max-height: initial;
+ ` : ''}
`
diff --git a/src/features/MatchSidePlaylists/hooks.tsx b/src/features/MatchSidePlaylists/hooks.tsx
index df3dc7c3..158e5d18 100644
--- a/src/features/MatchSidePlaylists/hooks.tsx
+++ b/src/features/MatchSidePlaylists/hooks.tsx
@@ -6,25 +6,16 @@ import {
import reduce from 'lodash/reduce'
-import { Playlists, TournamentData } from 'features/MatchPage/types'
-
-import type { Events } from 'requests'
+import { useMatchPageStore } from 'features/MatchPage/store'
import { Tabs } from './config'
-export type Props = {
- events: Events,
- playlists: Playlists,
- tournamentData: TournamentData,
-}
-
-export const useMatchSidePlaylists = (props: Props) => {
+export const useMatchSidePlaylists = () => {
const {
events,
- playlists,
+ matchPlaylists: playlists,
tournamentData,
- } = props
-
+ } = useMatchPageStore()
const [selectedTab, setSelectedTab] = useState(Tabs.WATCH)
const isWatchTabVisible = useMemo(() => {
diff --git a/src/features/MatchSidePlaylists/index.tsx b/src/features/MatchSidePlaylists/index.tsx
index f16e49bc..0722f795 100644
--- a/src/features/MatchSidePlaylists/index.tsx
+++ b/src/features/MatchSidePlaylists/index.tsx
@@ -1,19 +1,12 @@
import { useRef } from 'react'
-import type { Events, MatchInfo } from 'requests'
-
-import type {
- PlaylistOption,
- Playlists,
- TournamentData,
-} from 'features/MatchPage/types'
+import type { PlaylistOption } from 'features/MatchPage/types'
import { Tab, TabsGroup } from 'features/Common'
import { T9n } from 'features/T9n'
+import { useMatchPageStore } from 'features/MatchPage/store'
import { useEventListener } from 'hooks'
-import { useMatchPageStore } from 'features/MatchPage/store'
-
import { isIOS } from 'config/userAgent'
import { Tabs } from './config'
@@ -22,7 +15,6 @@ import { TabWatch } from './components/TabWatch'
import { TabVideo } from './components/TabVideo'
import { useMatchSidePlaylists } from './hooks'
import {
- BackToTopBtn,
Wrapper,
TabsWrapper,
Container,
@@ -35,39 +27,30 @@ const tabPanes = {
}
type Props = {
- events: Events,
onSelect: (option: PlaylistOption) => void,
- playlists: Playlists,
- profile: MatchInfo,
selectedPlaylist?: PlaylistOption,
- tournamentData: TournamentData,
}
export const MatchSidePlaylists = ({
- events,
onSelect,
- playlists,
- profile,
selectedPlaylist,
- tournamentData,
}: Props) => {
+ const {
+ events,
+ hideProfileCard,
+ matchPlaylists: playlists,
+ profile,
+ showProfileCard,
+ tournamentData,
+ } = useMatchPageStore()
+
const {
isEventTabVisible,
isVideoTabVisible,
isWatchTabVisible,
onTabClick,
selectedTab,
- } = useMatchSidePlaylists({
- events,
- playlists,
- tournamentData,
- })
-
- const {
- hideProfileCard,
- profileCardShown,
- showProfileCard,
- } = useMatchPageStore()
+ } = useMatchSidePlaylists()
const TabPane = tabPanes[selectedTab]
@@ -76,9 +59,7 @@ export const MatchSidePlaylists = ({
useEventListener({
callback: () => {
const screenLandscape = isIOS ? window.orientation : window.screen.orientation.type
- const yOffset = isIOS
- ? containerRef.current?.offsetTop
- : containerRef.current?.scrollTop
+ const yOffset = containerRef.current?.scrollTop
const isScreenLandscape = isIOS
? (screenLandscape === 90 || screenLandscape === -90)
: (screenLandscape === 'landscape-primary' || screenLandscape === 'landscape-secondary')
@@ -86,12 +67,12 @@ export const MatchSidePlaylists = ({
if (yOffset && yOffset > 10 && !isScreenLandscape) hideProfileCard()
if (yOffset && yOffset < 10) showProfileCard()
},
- event: isIOS ? 'touchmove' : 'scroll',
+ event: 'scroll',
target: containerRef,
})
return (
-
+
{isWatchTabVisible ? (
@@ -119,15 +100,9 @@ export const MatchSidePlaylists = ({
) : null}
- {
- containerRef.current?.scrollTo(0, 0)
- showProfileCard()
- }}
- />
+
-
+
`
margin-top: 14px;
padding: 0 10px 0 14px;
max-height: calc(100vh - 170px);
- overflow-y: ${({ forVideoTab }) => (forVideoTab ? 'none' : 'scroll')};
+ overflow-y: ${({ forVideoTab }) => (forVideoTab ? 'hidden' : 'auto')};
${customScrollbar}
@media ${devices.tablet} {
- max-height: calc(100vh - 40px);
margin-top: 15px;
}
${isMobileDevice
? css`
padding: 0 5px;
- overflow-y: auto;
-
+ overflow-y: hidden;
+ max-height: initial;
+
@media (max-width: 750px){
width: 100%;
}
@@ -138,27 +135,3 @@ export const BlockTitle = styled.span`
color: rgba(255, 255, 255, 0.5);
text-transform: uppercase;
`
-export const BackToTopBtn = styled.div`
- position: absolute;
- left: 50%;
- bottom: -100%;
- background: rgba(0, 0, 0, 0.5);
- border-radius: 0px 0 20px 20px;
- width: 37px;
- height: 34px;
- z-index: 1;
- cursor: pointer;
- transform: translate(-50%, 6%);
-
- :after {
- content: '';
- width: 10px;
- height: 10px;
- position: absolute;
- border-left: 2px solid rgb(255, 255, 255);
- border-top: 2px solid rgb(255, 255, 255);
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%) rotate(45deg);
- }
-`
diff --git a/src/features/MultiSourcePlayer/components/ProgressBar/index.tsx b/src/features/MultiSourcePlayer/components/ProgressBar/index.tsx
index 2882700b..17be301b 100644
--- a/src/features/MultiSourcePlayer/components/ProgressBar/index.tsx
+++ b/src/features/MultiSourcePlayer/components/ProgressBar/index.tsx
@@ -1,6 +1,6 @@
import { useSlider } from 'features/StreamPlayer/hooks/useSlider'
import { TimeTooltip } from 'features/StreamPlayer/components/TimeTooltip'
-import { Scrubber } from 'features/StreamPlayer/components/ProgressBar/styled'
+import { Scrubber, ScrubberContainer } from 'features/StreamPlayer/components/ProgressBar/styled'
import { Chapters } from 'features/StreamPlayer/components/Chapters'
import type { Props } from './hooks'
@@ -35,9 +35,11 @@ export const ProgressBar = (props: ProgressBarProps) => {
{isScrubberVisible === false ? null : (
-
-
-
+
+
+
+
+
)}
)
diff --git a/src/features/MultiSourcePlayer/config.tsx b/src/features/MultiSourcePlayer/config.tsx
index 4602985b..02537a31 100644
--- a/src/features/MultiSourcePlayer/config.tsx
+++ b/src/features/MultiSourcePlayer/config.tsx
@@ -1,3 +1,5 @@
-export const REWIND_SECONDS = 5
+import { isMobileDevice } from 'config/userAgent'
+
+export const REWIND_SECONDS = isMobileDevice ? 10 : 5
export const HOUR_IN_MILLISECONDS = 60 * 60 * 1000
diff --git a/src/features/MultiSourcePlayer/hooks/index.tsx b/src/features/MultiSourcePlayer/hooks/index.tsx
index fb9cfa2d..244b8df5 100644
--- a/src/features/MultiSourcePlayer/hooks/index.tsx
+++ b/src/features/MultiSourcePlayer/hooks/index.tsx
@@ -274,7 +274,7 @@ export const useMultiSourcePlayer = ({
video2Ref,
videoQualities,
wrapperRef,
- ...useControlsVisibility(isFullscreen),
+ ...useControlsVisibility(isFullscreen, playing),
...useVolume(),
}
}
diff --git a/src/features/MultiSourcePlayer/index.tsx b/src/features/MultiSourcePlayer/index.tsx
index e0e03a81..b41cf85f 100644
--- a/src/features/MultiSourcePlayer/index.tsx
+++ b/src/features/MultiSourcePlayer/index.tsx
@@ -12,6 +12,7 @@ import {
import { VideoPlayer } from 'features/VideoPlayer'
import { Controls } from 'features/StreamPlayer/components/Controls'
import { Name } from 'features/Name'
+import RewindMobile from 'features/StreamPlayer/components/RewindMobile'
import { isMobileDevice } from 'config/userAgent'
@@ -27,13 +28,15 @@ export const MultiSourcePlayer = (props: Props) => {
activePlayer,
activeSrc,
allPlayedProgress,
+ centerControlsVisible,
chapters,
- controlsVisible,
duration,
+ hideCenterControls,
isFirstChapterPlaying,
isFullscreen,
isLastChapterPlaying,
loadedProgress,
+ mainControlsVisible,
muted,
nextSrc,
numberOfChapters,
@@ -63,6 +66,7 @@ export const MultiSourcePlayer = (props: Props) => {
rewindForward,
seek,
selectedQuality,
+ showCenterControls,
togglePlaying,
video1Ref,
video2Ref,
@@ -76,7 +80,7 @@ export const MultiSourcePlayer = (props: Props) => {
{
onReady={onReady}
/>
- {isMobileDevice && isFullscreen && controlsVisible && profile && (
+ {isMobileDevice && isFullscreen && mainControlsVisible && profile && (
{` ${profile.team1.score}-${profile.team2.score} `}
@@ -132,22 +136,29 @@ export const MultiSourcePlayer = (props: Props) => {
)}
{ready && (
-
- {REWIND_SECONDS}
+
+ {isMobileDevice
+ ?
+ : {REWIND_SECONDS}}
{
+ togglePlaying()
+ hideCenterControls()
+ }}
/>
- {REWIND_SECONDS}
+ {isMobileDevice
+ ?
+ : {REWIND_SECONDS}}
)}
{
volume={volume}
volumeInPercent={volumeInPercent}
/>
-
+
)
}
diff --git a/src/features/SportsFilter/components/SelectSport/styled.tsx b/src/features/SportsFilter/components/SelectSport/styled.tsx
index 9cb43fba..6dcb599e 100644
--- a/src/features/SportsFilter/components/SelectSport/styled.tsx
+++ b/src/features/SportsFilter/components/SelectSport/styled.tsx
@@ -22,6 +22,7 @@ export const ScSportsFilter = styled.div`
width: 30%;
letter-spacing: 0.15rem;
font-size: 10px;
+ white-space: nowrap;
`
: ''};
`
diff --git a/src/features/SportsFilter/components/SelectSportPopup/styled.tsx b/src/features/SportsFilter/components/SelectSportPopup/styled.tsx
index bccc6693..b086d542 100644
--- a/src/features/SportsFilter/components/SelectSportPopup/styled.tsx
+++ b/src/features/SportsFilter/components/SelectSportPopup/styled.tsx
@@ -179,7 +179,7 @@ export const ScModal = styled(BaseModal)`
height: auto;
${ModalCloseButton} {
- padding: 16px 14px 15px 15px;
+ padding: 0;
}
`
: ''};
diff --git a/src/features/StreamPlayer/components/Chapters/styled.tsx b/src/features/StreamPlayer/components/Chapters/styled.tsx
index 7a20409c..729b8132 100644
--- a/src/features/StreamPlayer/components/Chapters/styled.tsx
+++ b/src/features/StreamPlayer/components/Chapters/styled.tsx
@@ -1,4 +1,6 @@
-import styled from 'styled-components/macro'
+import styled, { css } from 'styled-components/macro'
+
+import { isMobileDevice } from 'config/userAgent'
export const ChapterList = styled.div`
width: 100%;
@@ -23,6 +25,12 @@ export const LoadedProgress = styled.div`
background-color: rgba(255, 255, 255, 0.6);
height: 100%;
max-width: 100%;
+
+ ${isMobileDevice
+ ? css`
+ background-color: rgba(255, 255, 255, 0.3);
+ `
+ : ''}
`
export const PlayedProgress = styled.div`
@@ -31,4 +39,10 @@ export const PlayedProgress = styled.div`
background-color: #CC0000;
height: 100%;
max-width: 100%;
+
+ ${isMobileDevice
+ ? css`
+ background-color: rgba(255, 255, 255, 1);
+ `
+ : ''}
`
diff --git a/src/features/StreamPlayer/components/Controls/Components/ControlsMobile/styled.tsx b/src/features/StreamPlayer/components/Controls/Components/ControlsMobile/styled.tsx
index 2b98d9b1..d61b5757 100644
--- a/src/features/StreamPlayer/components/Controls/Components/ControlsMobile/styled.tsx
+++ b/src/features/StreamPlayer/components/Controls/Components/ControlsMobile/styled.tsx
@@ -15,10 +15,9 @@ export const Controls = styled.div`
flex-direction: column;
align-items: center;
filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));
- bottom: 0;
+ bottom: ${({ isFullscreen }) => (isFullscreen ? '20px' : 0)};
@media (orientation: landscape){
- bottom: ${({ isFullscreen }) => (isFullscreen ? '20px' : 0)};
width: 100%;
left: 50%;
transform: translateX(-50%);
diff --git a/src/features/StreamPlayer/components/Controls/index.tsx b/src/features/StreamPlayer/components/Controls/index.tsx
index 9542d828..1f14e9b5 100644
--- a/src/features/StreamPlayer/components/Controls/index.tsx
+++ b/src/features/StreamPlayer/components/Controls/index.tsx
@@ -7,17 +7,17 @@ import { isMobileDevice } from 'config/userAgent'
import { secondsToHms } from 'helpers/secondsToHms'
import { ProgressBar as ProgressBarMultiSource } from 'features/MultiSourcePlayer/components/ProgressBar'
-import { Chapters } from 'features/MultiSourcePlayer/types'
+import { Chapters as MultiSourceChapters } from 'features/MultiSourcePlayer/types'
+import { Chapters as LiveChapters } from 'features/StreamPlayer/types'
import { ControlsMobile } from './Components/ControlsMobile'
import { ControlsWeb } from './Components/ControlsWeb'
-// import { ProgressBar } from '../ProgressBar'
+import { ProgressBar } from '../ProgressBar'
export type ControlsProps = {
- activeChapterIndex?: number,
- allPlayedProgress?: number,
+ activeChapterIndex: number,
+ allPlayedProgress: number,
backToLive?: () => void,
- chapters?: Chapters,
controlsVisible: boolean,
duration: number,
isFirstChapterPlaying?: boolean,
@@ -25,12 +25,13 @@ export type ControlsProps = {
isLastChapterPlaying?: boolean,
isLive?: boolean,
isStorage?: boolean,
+ liveChapters?: LiveChapters,
loadedProgress: number,
+ multiSourceChapters?: MultiSourceChapters,
muted: boolean,
numberOfChapters?: number,
onFullscreenClick: () => void,
- onProgressChange?: (progress: number, seeking: boolean) => void,
- onProgressChangeLive?: (progress: number) => void,
+ onProgressChange: (progress: number, seeking: boolean) => void,
onQualitySelect: (quality: string) => void,
onTouchEnd: DebouncedFunc<() => void>,
onTouchStart: () => void,
@@ -58,14 +59,14 @@ export const Controls = (props: ControlsProps) => {
const {
activeChapterIndex = 0,
allPlayedProgress = 0,
- chapters,
controlsVisible,
duration,
isLive,
isStorage,
+ liveChapters,
loadedProgress,
+ multiSourceChapters,
onProgressChange,
- // onProgressChangeLive,
onTouchEnd,
onTouchStart,
playedProgress,
@@ -86,21 +87,24 @@ export const Controls = (props: ControlsProps) => {
])
const progressBarElement = useMemo(() => {
if (isLive || isStorage) {
- // return (
- //
- // )
+ return (
+
+ )
}
return (
{
}, [
activeChapterIndex,
allPlayedProgress,
- chapters,
+ liveChapters,
+ multiSourceChapters,
controlsVisible,
duration,
isLive,
isStorage,
loadedProgress,
onProgressChange,
- // onProgressChangeLive,
onTouchEnd,
onTouchStart,
playedProgress,
diff --git a/src/features/StreamPlayer/components/ProgressBar/index.tsx b/src/features/StreamPlayer/components/ProgressBar/index.tsx
index 0475d15d..47845144 100644
--- a/src/features/StreamPlayer/components/ProgressBar/index.tsx
+++ b/src/features/StreamPlayer/components/ProgressBar/index.tsx
@@ -1,6 +1,6 @@
import { useSlider } from 'features/StreamPlayer/hooks/useSlider'
import { TimeTooltip } from 'features/StreamPlayer/components/TimeTooltip'
-import { Scrubber } from 'features/StreamPlayer/components/ProgressBar/styled'
+import { Scrubber, ScrubberContainer } from 'features/StreamPlayer/components/ProgressBar/styled'
import { Chapters } from '../Chapters'
import type { Props } from './hooks'
@@ -8,7 +8,7 @@ import { useProgressBar } from './hooks'
import { ProgressBarList } from './styled'
export const ProgressBar = (props: Props) => {
- const { onPlayedProgressChange } = props
+ const { isScrubberVisible, onPlayedProgressChange } = props
const progressBarRef = useSlider({ onChange: onPlayedProgressChange })
const {
calculatedChapters,
@@ -18,9 +18,13 @@ export const ProgressBar = (props: Props) => {
return (
-
-
-
+ {isScrubberVisible === false ? null : (
+
+
+
+
+
+ )}
)
}
diff --git a/src/features/StreamPlayer/components/ProgressBar/styled.tsx b/src/features/StreamPlayer/components/ProgressBar/styled.tsx
index bce8da4c..e3fa149c 100644
--- a/src/features/StreamPlayer/components/ProgressBar/styled.tsx
+++ b/src/features/StreamPlayer/components/ProgressBar/styled.tsx
@@ -8,6 +8,23 @@ export const ProgressBarList = styled.div`
flex-grow: 1;
height: 4px;
position: relative;
+ background-color: rgba(255, 255, 255, 0.3);
+ cursor: pointer;
+
+ ${isMobileDevice
+ ? css`
+ height: 1px;
+ `
+ : ''}
+`
+export const ScrubberContainer = styled.div`
+ ${isMobileDevice
+ ? css`
+ position: relative;
+ margin: 0 7px;
+ `
+ : ''}
+
`
export const Scrubber = styled.div`
@@ -15,24 +32,24 @@ export const Scrubber = styled.div`
outline: none;
position: absolute;
top: 0;
- transform: translate(-50%, -43%);
+ transform: translate(-50%, -38%);
z-index: 3;
width: 18px;
height: 18px;
background-color: #CC0000;
border-radius: 50%;
cursor: pointer;
-
+
:hover ${Wrapper} {
visibility: visible;
}
${isMobileDevice
? css`
- width: 30px;
- height: 30px;
- background-clip: padding-box;
- border: 10px solid transparent;
+ width: 14px;
+ height: 14px;
+ background-color: #FFFFFF;
+ transform: translate(-50%, -48%);
`
: ''}
`
diff --git a/src/features/StreamPlayer/components/RewindMobile/index.tsx b/src/features/StreamPlayer/components/RewindMobile/index.tsx
new file mode 100644
index 00000000..e489e16a
--- /dev/null
+++ b/src/features/StreamPlayer/components/RewindMobile/index.tsx
@@ -0,0 +1,67 @@
+import {
+ useCallback,
+ useMemo,
+ useState,
+} from 'react'
+
+import debounce from 'lodash/debounce'
+
+import {
+ Background,
+ RewindIcon,
+ Time,
+} from './styled'
+
+export type RewindProps = {
+ isBackward?: boolean,
+ isForward?: boolean,
+ rewindCallback: () => void,
+}
+
+const RewindMobile = ({
+ isBackward,
+ isForward,
+ rewindCallback,
+}: RewindProps) => {
+ const [isActive, setIsActive] = useState(false)
+ const [time, setTime] = useState(0)
+
+ const resetData = useCallback(() => {
+ setIsActive(false)
+ setTime(0)
+ }, [])
+
+ const resetDataDebounced = useMemo(() => (
+ debounce(resetData, 1500)
+ ), [resetData])
+
+ const handleDoubleClick = useCallback(() => {
+ setIsActive(true)
+ rewindCallback()
+ setTime(time + 10)
+ resetDataDebounced()
+ }, [resetDataDebounced, rewindCallback, time])
+
+ const TimeContent = useMemo(() => (
+
+ ), [isBackward, isForward, time])
+
+ return (
+
+ {isActive && TimeContent}
+
+ )
+}
+
+export default RewindMobile
diff --git a/src/features/StreamPlayer/components/RewindMobile/styled.tsx b/src/features/StreamPlayer/components/RewindMobile/styled.tsx
new file mode 100644
index 00000000..c66681ac
--- /dev/null
+++ b/src/features/StreamPlayer/components/RewindMobile/styled.tsx
@@ -0,0 +1,41 @@
+import styled, { css } from 'styled-components/macro'
+
+type RewindProps = {
+ isActive?: boolean,
+ isBackward?: boolean,
+ isForward?: boolean,
+}
+
+export const Background = styled.div`
+ width: 920px;
+ height: 920px;
+ border-radius: 50%;
+ background-color: ${({ isActive }) => (isActive ? 'rgba(0, 0, 0, 0.4)' : 'rgba(0, 0, 0, 0)')};
+ position: absolute;
+ ${({ isBackward }) => isBackward && css`right: 60%;`}
+ ${({ isForward }) => isForward && css`left: 60%;`}
+ transition: all 0.3s ease-in-out;
+`
+
+export const Time = styled.div`
+ position: absolute;
+ color: #FFFFFF;
+ top: 50%;
+ font-size: 20px;
+ transform: translate(0, -50%);
+ display: flex;
+ align-items: center;
+ user-select: none;
+
+ ${({ isBackward }) => isBackward && css`right: 2%;`}
+ ${({ isForward }) => isForward && css`left: 2%;`}
+
+ > :first-child {
+ margin-right: 10px;
+ }
+`
+
+export const RewindIcon = styled.img`
+ width: 43px;
+ height: 28px;
+`
diff --git a/src/features/StreamPlayer/components/YoutubePlayer/index.tsx b/src/features/StreamPlayer/components/YoutubePlayer/index.tsx
index daf63fd2..214ffccb 100644
--- a/src/features/StreamPlayer/components/YoutubePlayer/index.tsx
+++ b/src/features/StreamPlayer/components/YoutubePlayer/index.tsx
@@ -1,10 +1,12 @@
import YouTube from 'react-youtube'
+import { useMatchPageStore } from 'features/MatchPage/store'
+
import { PlayerWrapper } from '../../styled'
import { useVideoPlayer, Props } from '../../hooks'
export const YoutubePlayer = (props: Props) => {
- const { profile } = props
+ const { profile } = useMatchPageStore()
const {
onMouseMove,
diff --git a/src/features/StreamPlayer/config.tsx b/src/features/StreamPlayer/config.tsx
index 77418095..eb585004 100644
--- a/src/features/StreamPlayer/config.tsx
+++ b/src/features/StreamPlayer/config.tsx
@@ -2,6 +2,8 @@ import type { HlsConfig } from 'hls.js'
import { readToken } from 'helpers/token'
+import { isMobileDevice } from 'config/userAgent'
+
export const streamConfig: Partial = {
liveSyncDuration: 30,
maxBufferLength: 30,
@@ -12,6 +14,6 @@ export const streamConfig: Partial = {
},
}
-export const REWIND_SECONDS = 5
+export const REWIND_SECONDS = isMobileDevice ? 10 : 5
export const HOUR_IN_MILLISECONDS = 60 * 60 * 1000
diff --git a/src/features/StreamPlayer/hooks/index.tsx b/src/features/StreamPlayer/hooks/index.tsx
index 6eb9f291..e65615e3 100644
--- a/src/features/StreamPlayer/hooks/index.tsx
+++ b/src/features/StreamPlayer/hooks/index.tsx
@@ -20,8 +20,6 @@ import { useLiveMatch } from 'features/MatchPage/components/LiveMatch/hooks'
import type { Chapters } from 'features/StreamPlayer/types'
-import { MatchInfo } from 'requests/getMatchInfo'
-
import { REWIND_SECONDS } from '../config'
import { useHlsPlayer } from './useHlsPlayer'
import { useFullscreen } from './useFullscreen'
@@ -50,11 +48,10 @@ const initialState = {
export type Props = {
chapters: Chapters,
- isLive?: boolean,
+ isLive: boolean,
onDurationChange?: (duration: number) => void,
onPlayingChange: (playing: boolean) => void,
onProgressChange: (seconds: number) => void,
- profile?: MatchInfo,
resumeFrom?: number,
url?: string,
}
@@ -414,7 +411,7 @@ export const useVideoPlayer = ({
url,
videoRef,
wrapperRef,
- ...useControlsVisibility(isFullscreen),
+ ...useControlsVisibility(isFullscreen, playing),
...useVolume(),
...useVideoQuality(hls),
}
diff --git a/src/features/StreamPlayer/hooks/useControlsVisibility.tsx b/src/features/StreamPlayer/hooks/useControlsVisibility.tsx
index efead7dd..ca7c8134 100644
--- a/src/features/StreamPlayer/hooks/useControlsVisibility.tsx
+++ b/src/features/StreamPlayer/hooks/useControlsVisibility.tsx
@@ -1,40 +1,56 @@
-import {
- useMemo,
- useState,
- useCallback,
-} from 'react'
+import { useCallback, useMemo } from 'react'
import debounce from 'lodash/debounce'
-export const useControlsVisibility = (isFullscreen: boolean) => {
- const [controlsVisible, setControlsVisibility] = useState(true)
+import { useToggle } from 'hooks'
- const show = useCallback(() => {
- setControlsVisibility(true)
- }, [])
+export const useControlsVisibility = (isFullscreen: boolean, playing: boolean) => {
+ const {
+ close: hideCenterControls,
+ isOpen: centerControlsVisible,
+ open: showCenterControls,
+ } = useToggle(playing)
- const hide = useCallback(() => {
- setControlsVisibility(false)
- }, [])
+ const hideCenterDebounced = useMemo(() => (
+ debounce(hideCenterControls, 2000)
+ ), [hideCenterControls])
+
+ const showCenter = useCallback(() => {
+ if (playing) {
+ showCenterControls()
+ hideCenterDebounced()
+ } else {
+ showCenterControls()
+ }
+ }, [hideCenterDebounced, playing, showCenterControls])
+
+ const {
+ close: hideMainControls,
+ isOpen: mainControlsVisible,
+ open: showMainControls,
+ } = useToggle(true)
const hideDebounced = useMemo(
- () => debounce(hide, 3000),
- [hide],
+ () => debounce(hideMainControls, 3000),
+ [hideMainControls],
)
const onMouseMove = () => {
- show()
+ showMainControls()
if (isFullscreen) {
hideDebounced()
}
}
return {
- controlsVisible,
- onMouseEnter: show,
- onMouseLeave: hide,
+ centerControlsVisible,
+ hideCenterControls,
+ mainControlsVisible,
+ onMouseEnter: showMainControls,
+ onMouseLeave: hideMainControls,
onMouseMove,
onTouchEnd: hideDebounced,
- onTouchStart: show,
+ onTouchStart: showMainControls,
+ showCenterControls: showCenter,
}
}
diff --git a/src/features/StreamPlayer/index.tsx b/src/features/StreamPlayer/index.tsx
index 95ef3e48..2d8318e7 100644
--- a/src/features/StreamPlayer/index.tsx
+++ b/src/features/StreamPlayer/index.tsx
@@ -1,62 +1,49 @@
-import { Fragment } from 'react'
-
-import { T9n } from 'features/T9n'
import { Loader } from 'features/Loader'
import { VideoPlayer } from 'features/VideoPlayer'
+import { useMatchPageStore } from 'features/MatchPage/store'
+import { Name } from 'features/Name'
import { WaterMark } from 'components/WaterMark'
-import { secondsToHms } from 'helpers'
+import { isMobileDevice } from 'config/userAgent'
-import { HOUR_IN_MILLISECONDS, REWIND_SECONDS } from './config'
-import { VolumeBar } from './components/VolumeBar'
-import { Settings } from './components/Settings'
-import { ProgressBar } from './components/ProgressBar'
+import { REWIND_SECONDS } from './config'
import {
PlayerWrapper,
- Controls,
- ControlsRow,
- ControlsGroup,
CenterControls,
PlayStop,
- Fullscreen,
LoaderWrapper,
Backward,
Forward,
- PlaybackTime,
ControlsGradient,
- LiveBtn,
- ChaptersText,
- Next,
- Prev,
- // WaterMark,
+ TeamsDetailsWrapper,
} from './styled'
import type { Props } from './hooks'
import { useVideoPlayer } from './hooks'
import { useAuthStore } from '../AuthStore'
+import { Controls } from './components/Controls'
+import RewindMobile from './components/RewindMobile'
/**
* HLS плеер, применяется на лайв и завершенных матчах
*/
export const StreamPlayer = (props: Props) => {
- const { isLive, profile } = props
+ const { profile } = useMatchPageStore()
const { user } = useAuthStore()
const {
activeChapterIndex,
- allPlayedProgress,
backToLive,
buffering,
+ centerControlsVisible,
chapters,
- controlsVisible,
duration,
- isFirstChapterPlaying,
+ hideCenterControls,
isFullscreen,
- isLastChapterPlaying,
loadedProgress,
+ mainControlsVisible,
muted,
- numberOfChapters,
onDuration,
onError,
onFullscreenClick,
@@ -79,13 +66,12 @@ export const StreamPlayer = (props: Props) => {
onWaiting,
playedProgress,
playing,
- playNextChapter,
- playPrevChapter,
ready,
rewindBackward,
rewindForward,
seek,
selectedQuality,
+ showCenterControls,
togglePlaying,
url,
videoQualities,
@@ -98,7 +84,7 @@ export const StreamPlayer = (props: Props) => {
{
onError={onError}
crossOrigin='use-credentials'
/>
+
+ {isMobileDevice && isFullscreen && mainControlsVisible && profile && (
+
+
+ {` ${profile.team1.score}-${profile.team2.score} `}
+
+
+ )}
+
{ready && (
-
-
- {REWIND_SECONDS}
-
+
+ {isMobileDevice
+ ?
+ : {REWIND_SECONDS}}
{
+ togglePlaying()
+ hideCenterControls()
+ }}
/>
-
- {REWIND_SECONDS}
-
+ {isMobileDevice
+ ?
+ : {REWIND_SECONDS}}
)}
-
-
-
-
-
-
-
- {
- numberOfChapters > 1 && (
-
- playPrevChapter()}
- />
-
- {activeChapterIndex + 1} / {numberOfChapters}
-
- playNextChapter()}
- />
-
- )
- }
-
- {
- isLive
- ? (
-
- {secondsToHms(allPlayedProgress / 1000)}
-
- )
- : (
- HOUR_IN_MILLISECONDS ? 150 : 130}>
- {secondsToHms(allPlayedProgress / 1000)}
- {' / '}
- {secondsToHms(duration / 1000)}
-
- )
- }
- {REWIND_SECONDS}
- {REWIND_SECONDS}
-
-
- {
- isLive && (
-
-
-
- )
- }
-
-
-
-
-
-
+
+
)
}
diff --git a/src/features/StreamPlayer/styled.tsx b/src/features/StreamPlayer/styled.tsx
index d99334aa..8ee6ff80 100644
--- a/src/features/StreamPlayer/styled.tsx
+++ b/src/features/StreamPlayer/styled.tsx
@@ -170,11 +170,14 @@ export const PlayStop = styled(ButtonBase)`
)};
${isMobileDevice
? css`
- width: 20%;
- height: 60%;
- margin-right: 0;
- padding: 0;
- `
+ width: ${sizes.sm}px;
+ height: ${sizes.sm}px;
+ margin-right: 0;
+ padding: 0;
+ position: absolute;
+ left: 50%;
+ transform: translate(-50%, 0);
+ `
: ''};
`
@@ -271,6 +274,7 @@ export const PlaybackTime = styled.span`
`
type CenterControlsProps = {
+ controlsVisible: boolean,
playing: boolean,
}
@@ -287,11 +291,14 @@ export const CenterControls = styled.div`
transition: opacity 0.3s ease-in-out;
opacity: ${({ playing }) => (playing ? 0 : 1)};
pointer-events: ${({ playing }) => (playing ? 'none' : 'auto')};
- ${isMobileDevice
- ? css`
- width: 70%;
- `
- : ''};
+
+ ${({ controlsVisible, playing }) => isMobileDevice && css`
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ opacity: ${controlsVisible || !playing ? 1 : 0};
+ pointer-events: ${controlsVisible || !playing ? 'auto' : 'none'};
+ `}
`
export const LiveBtn = styled(ButtonBase)`
diff --git a/src/features/TournamentList/components/TournamentMobile/styled.tsx b/src/features/TournamentList/components/TournamentMobile/styled.tsx
index 1dfdacaa..e38eda59 100644
--- a/src/features/TournamentList/components/TournamentMobile/styled.tsx
+++ b/src/features/TournamentList/components/TournamentMobile/styled.tsx
@@ -35,6 +35,7 @@ export const CardWrapper = styled.div<{
padding: 10px;
width: 100%;
height: 50px;
+ justify-content: space-between;
`
: ''};
`
@@ -61,7 +62,7 @@ export const CountMatches = styled.span<{ color?: string }>`
color: ${({ color }) => color};
width: 20px;
text-align: end;
- margin: 0 9px 0 20px;
+ margin: 0 9px 0 10px;
`
export const ScFirstInfo = styled.div`
@@ -69,7 +70,8 @@ export const ScFirstInfo = styled.div`
flex-direction: row;
align-items: center;
justify-content: flex-start;
- width: 80%;
+ margin-right: 10px;
+ overflow: hidden;
`
export const ScSecondInfo = styled.div`
@@ -77,7 +79,6 @@ export const ScSecondInfo = styled.div`
flex-direction: row;
align-items: center;
justify-content: flex-end;
- width: 100%;
`
export const ScMatchesWrapper = styled.ul`
diff --git a/src/features/TournamentSubtitle/index.tsx b/src/features/TournamentSubtitle/index.tsx
index 408d0b2d..1191ef24 100644
--- a/src/features/TournamentSubtitle/index.tsx
+++ b/src/features/TournamentSubtitle/index.tsx
@@ -2,7 +2,7 @@ import { Fragment } from 'react'
import { SportIcon } from 'components/SportIcon/SportIcon'
-import { useName } from 'features/Name'
+import { Name } from 'features/Name'
import { useUserFavoritesStore } from 'features/UserFavorites/store'
import { ProfileTypes, SportTypes } from 'config'
@@ -12,12 +12,13 @@ import { usePageParams } from 'hooks/usePageParams'
import { TournamentType } from 'requests'
+import { isMatchPage } from 'helpers/isMatchPage'
+
import {
CountryFlag,
FavoriteSign,
- NameSignWrapper,
Wrapper,
- TournamentName,
+ StyledLink,
} from './styled'
type Props = {
@@ -33,7 +34,6 @@ export const TournamentSubtitle = ({
}: Props) => {
const { isInFavorites } = useUserFavoritesStore()
const { sportType: sportTypeFromUrl } = usePageParams()
- const tournamentName = useName(tournament)
const tournamentInFavorites = isInFavorites(ProfileTypes.TOURNAMENTS, tournament.id)
return (
@@ -44,14 +44,16 @@ export const TournamentSubtitle = ({
)}
- {tournament && (
-
-
- {tournamentName}
-
- {tournamentInFavorites && }
-
- )}
+
+
+
+ {tournamentInFavorites && }
)
}
diff --git a/src/features/TournamentSubtitle/styled.tsx b/src/features/TournamentSubtitle/styled.tsx
index 7d35a962..95e2e352 100644
--- a/src/features/TournamentSubtitle/styled.tsx
+++ b/src/features/TournamentSubtitle/styled.tsx
@@ -2,6 +2,8 @@ import styled, { css } from 'styled-components'
import { isMobileDevice } from 'config/userAgent'
+import { ProfileLink } from 'features/ProfileLink'
+
export const Wrapper = styled.div`
display: flex;
align-items: center;
@@ -13,6 +15,7 @@ export const CountryFlag = styled.img`
margin-left: 0.567rem;
object-fit: contain;
object-position: bottom;
+
${isMobileDevice
? css`
width: 12px;
@@ -27,31 +30,32 @@ export const NameSignWrapper = styled.div`
max-width: 90%;
align-items: center;
`
-
-const nameStyles = css`
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
-`
-
-type TTournamentName = {
+type StyledLinkProps = {
+ isMatchPage?: boolean,
isLeftSide?: boolean,
}
-export const TournamentName = styled.span`
+export const StyledLink = styled(ProfileLink)`
color: rgba(255, 255, 255, 0.7);
font-size: 0.567rem;
line-height: 0.95rem;
margin-left: ${({ isLeftSide }) => (isLeftSide ? '0px' : '0.567rem')};
- ${isMobileDevice
+
+ &:hover {
+ text-decoration: underline;
+ color: rgba(255, 255, 255, 1);
+ }
+
+ ${({ isMatchPage }) => (isMatchPage
? css`
- font-size: 10px;
- line-height: 100%;
- max-width: 100%;
- `
- : ''};
+ font-size: 14px;
- ${nameStyles}
+ ${isMobileDevice
+ ? css`
+ font-size: 10px;
+ `
+ : ''};
+ ` : null)}
`
type FavoriteSignProps = {