Ott 700 play next prev episodes (#271)

* fix(700): fixed useObjectState hook types

* feat(700): added play prev/next episode buttons
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 5 years ago committed by GitHub
parent 53fe8601c4
commit 7c0a75d950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      src/features/MultiSourcePlayer/hooks/index.tsx
  2. 32
      src/features/MultiSourcePlayer/hooks/usePlayingHandlers.tsx
  3. 18
      src/features/MultiSourcePlayer/index.tsx
  4. 12
      src/features/StreamPlayer/styled.tsx
  5. 14
      src/hooks/useObjectState.tsx

@ -55,6 +55,7 @@ export const useMultiSourcePlayer = ({
onProgressChange: onProgressChangeCallback,
resumeFrom,
}: Props) => {
const numberOfChapters = size(chapters)
const [
{
activeChapterIndex,
@ -69,10 +70,12 @@ export const useMultiSourcePlayer = ({
const videoRef = useRef<HTMLVideoElement>(null)
const {
onReady,
playNextChapter,
playPrevChapter,
startPlaying,
stopPlaying,
togglePlaying,
} = usePlayingHandlers(setPlayerState)
} = usePlayingHandlers(setPlayerState, numberOfChapters)
const {
selectedQuality,
@ -105,16 +108,6 @@ export const useMultiSourcePlayer = ({
setSelectedQuality(quality)
}
const playNextChapter = useCallback(() => {
const nextIndex = (activeChapterIndex + 1) % size(chapters)
setPlayerState({
activeChapterIndex: nextIndex,
loadedProgress: 0,
playedProgress: 0,
playing: nextIndex !== 0,
})
}, [activeChapterIndex, chapters, setPlayerState])
const onPlayerClick = (e: MouseEvent<HTMLDivElement>) => {
if (e.target === videoRef.current) {
togglePlaying()
@ -168,6 +161,8 @@ export const useMultiSourcePlayer = ({
activeSrc: getActiveChapterUrl(),
chapters,
duration,
isFirstChapterPlaying: activeChapterIndex === 0,
isLastChapterPlaying: activeChapterIndex === numberOfChapters - 1,
loadedProgress,
onError: handleError,
onLoadedProgress,
@ -177,6 +172,7 @@ export const useMultiSourcePlayer = ({
onQualitySelect,
onReady,
playNextChapter,
playPrevChapter,
playedProgress,
playing,
seek,

@ -4,7 +4,10 @@ import { SetPartialState } from 'hooks'
import { PlayerState } from '.'
export const usePlayingHandlers = (setPlayerState: SetPartialState<PlayerState>) => {
export const usePlayingHandlers = (
setPlayerState: SetPartialState<PlayerState>,
numberOfChapters: number,
) => {
const onReady = useCallback(() => {
setPlayerState((state) => (
state.ready
@ -33,8 +36,35 @@ export const usePlayingHandlers = (setPlayerState: SetPartialState<PlayerState>)
))
}, [setPlayerState])
const playNextChapter = useCallback(() => {
setPlayerState((state) => {
if (!state.ready) return state
const isLastChapter = state.activeChapterIndex + 1 === numberOfChapters
return {
activeChapterIndex: isLastChapter ? 0 : state.activeChapterIndex + 1,
loadedProgress: 0,
playedProgress: 0,
playing: isLastChapter ? false : state.playing,
}
})
}, [numberOfChapters, setPlayerState])
const playPrevChapter = useCallback(() => {
setPlayerState((state) => {
if (!state.ready || state.activeChapterIndex === 0) return state
return {
activeChapterIndex: state.activeChapterIndex - 1,
loadedProgress: 0,
playedProgress: 0,
}
})
}, [setPlayerState])
return {
onReady,
playNextChapter,
playPrevChapter,
startPlaying,
stopPlaying,
togglePlaying,

@ -4,6 +4,8 @@ import {
Controls,
PlayStop,
Fullscreen,
Next,
Prev,
} from 'features/StreamPlayer/styled'
import { VideoPlayer } from 'features/VideoPlayer'
@ -18,7 +20,9 @@ export const MultiSourcePlayer = (props: Props) => {
activeSrc,
chapters,
duration,
isFirstChapterPlaying,
isFullscreen,
isLastChapterPlaying,
loadedProgress,
muted,
onError,
@ -34,6 +38,7 @@ export const MultiSourcePlayer = (props: Props) => {
playedProgress,
playing,
playNextChapter,
playPrevChapter,
seek,
selectedQuality,
togglePlaying,
@ -64,7 +69,18 @@ export const MultiSourcePlayer = (props: Props) => {
onReady={onReady}
/>
<Controls>
<PlayStop onClick={togglePlaying} playing={playing} />
<Prev
disabled={isFirstChapterPlaying}
onClick={playPrevChapter}
/>
<PlayStop
playing={playing}
onClick={togglePlaying}
/>
<Next
disabled={isLastChapterPlaying}
onClick={playNextChapter}
/>
<VolumeBar
value={volumeInPercent}
muted={muted}

@ -69,11 +69,21 @@ export const PlayStop = styled(ButtonBase)<PlayStopProps>`
)};
`
export const Prev = styled(ButtonBase)`
type PrevProps = {
disabled?: boolean,
}
export const Prev = styled(ButtonBase)<PrevProps>`
width: 29px;
height: 28px;
margin-right: 19px;
background-image: url(/images/player-prev.svg);
${({ disabled }) => (
disabled
? 'opacity: 0.5;'
: ''
)}
`
export const Next = styled(Prev)`

@ -1,25 +1,25 @@
import type { Dispatch, SetStateAction } from 'react'
import type { Dispatch } from 'react'
import { useCallback, useState } from 'react'
import isFunction from 'lodash/isFunction'
type Updater<T> = (prevState: T) => T
const isUpdater = <T extends object>(value: any): value is Updater<T> => (
type Updater<S> = (prevState: S) => Partial<S>
const isUpdater = <S extends object>(value: any): value is Updater<S> => (
isFunction(value)
)
/**
* Дженерик для создания типа сеттера, получает тип стейта как параметр
*/
export type SetPartialState<T> = Dispatch<SetStateAction<Partial<T>>>
export type SetPartialState<S> = Dispatch<Partial<S> | Updater<S>>
/**
* Хук на основе useState с возможносьтю мержа стейта как в классовых компонентах
*/
export const useObjectState = <T extends object>(initialState: T) => {
export const useObjectState = <S extends object>(initialState: S) => {
const [state, setState] = useState(initialState)
const setPlayerState: SetPartialState<T> = useCallback((newStateOrUpdater) => {
const setPartialState: SetPartialState<S> = useCallback((newStateOrUpdater) => {
setState((oldState) => {
const newState = isUpdater(newStateOrUpdater)
? newStateOrUpdater(oldState)
@ -32,5 +32,5 @@ export const useObjectState = <T extends object>(initialState: T) => {
})
}, [])
return [state, setPlayerState] as const
return [state, setPartialState] as const
}

Loading…
Cancel
Save