Skip to content

Commit f59531d

Browse files
committed
feat: add dispatchRef, respond ACTIONS.PLAYER.PLAY
1 parent 8f10e6b commit f59531d

File tree

7 files changed

+64
-31
lines changed

7 files changed

+64
-31
lines changed

example/src/MP4Page.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import React, {useState, useLayoutEffect, useContext} from 'react'
2-
import PlayerContainer, {MessageContext, EVENTS} from 'griffith'
1+
import React, {
2+
useRef,
3+
useState,
4+
useLayoutEffect,
5+
useContext,
6+
} from 'react'
7+
import PlayerContainer, {MessageContext, ACTIONS, EVENTS} from 'griffith'
38
import Logo from './Logo'
49
import {logEvent} from './utils'
510

@@ -36,10 +41,11 @@ const props = {
3641
autoplay: true,
3742
shouldObserveResize: true,
3843
src: 'https://zhstatic.zhihu.com/cfe/griffith/zhihu2018_sd.mp4',
39-
onEvent: logEvent,
4044
}
4145

46+
const shouldLoop = new URLSearchParams(location.search).has('loop')
4247
const canShowLogo = new URLSearchParams(location.search).has('logo')
48+
4349
/** 常规通讯方式,建议直接使用 `onEvent` 替代 */
4450
const LogoListener = () => {
4551
const [isLogoVisible, setIsLogoVisible] = useState(false)
@@ -52,10 +58,24 @@ const LogoListener = () => {
5258
return canShowLogo && isLogoVisible ? <Logo /> : null
5359
}
5460

55-
const App = () => (
56-
<PlayerContainer {...props}>
57-
<LogoListener />
58-
</PlayerContainer>
59-
)
61+
const App = () => {
62+
const dispatchRef = useRef()
63+
return (
64+
<PlayerContainer
65+
{...props}
66+
dispatchRef={dispatchRef}
67+
onEvent={(e, data) => {
68+
if (shouldLoop && e === EVENTS.DOM.ENDED) {
69+
dispatchRef.current?.(ACTIONS.PLAYER.PLAY)
70+
}
71+
logEvent(e, data)
72+
}}
73+
>
74+
<LogoListener />
75+
<button onClick={() => dispatchRef.current?.(ACTIONS.PLAYER.PLAY)}>Play</button>
76+
<button onClick={() => dispatchRef.current?.(ACTIONS.PLAYER.PAUSE)}>Pause</button>
77+
</PlayerContainer>
78+
)
79+
}
6080

6181
export default App

packages/griffith-message/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ declare const ACTIONS: {
1212
}
1313
}
1414

15+
// TODO:合并这两项,与 ACTIONS 不对称
1516
declare const EVENTS: {
1617
DOM: {
1718
PLAY: string

packages/griffith/index.d.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import {EVENTS} from 'griffith-message'
2+
import {EVENTS, ACTIONS} from 'griffith-message'
33

44
type RealQuality = 'ld' | 'sd' | 'hd' | 'fhd'
55

@@ -24,7 +24,8 @@ interface PlayerContainerProps {
2424
message: string
2525
}
2626
onBeforePlay?: (src: string) => Promise<void>
27-
onEvent?: (type: string) => void
27+
onEvent?: (type: string, data?: any) => void
28+
dispatchRef?: React.Ref<MessageContextValue['dispatchAction']>,
2829
shouldObserveResize?: boolean
2930
initialObjectFit?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
3031
useMSE?: boolean
@@ -41,7 +42,7 @@ interface MessageContextValue {
4142
eventName: string,
4243
eventHandler: (data: any) => void
4344
) => Subscription
44-
dispatchAction: (actionName: string, data: any) => void
45+
dispatchAction: (actionName: string, data?: any) => void
4546
}
4647

4748
type Quality = 'auto' | RealQuality
@@ -74,4 +75,4 @@ declare const Layer: React.ComponentType
7475

7576
export default PlayerContainer
7677

77-
export {VideoSourceContext, MessageContext, Layer, EVENTS}
78+
export {VideoSourceContext, MessageContext, Layer, EVENTS, ACTIONS}

packages/griffith/src/components/Player/Player.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,17 @@ class Player extends Component {
106106
this.setState({volume: historyVolume})
107107
}
108108

109-
this.pauseActionSubscription = this.props.subscribeAction(
110-
ACTIONS.PLAYER.PAUSE,
111-
this.handlePauseAction
112-
)
113-
114-
this.timeUpdateActionSubscription = this.props.subscribeAction(
115-
ACTIONS.PLAYER.TIME_UPDATE,
116-
({currentTime}) => this.handleSeek(currentTime)
117-
)
118-
119-
this.showControllerActionSubscription = this.props.subscribeAction(
120-
ACTIONS.PLAYER.SHOW_CONTROLLER,
121-
this.handleShowController
122-
)
109+
this.actionSubscriptions_ = [
110+
this.props.subscribeAction(ACTIONS.PLAYER.PLAY, this.handlePlay),
111+
this.props.subscribeAction(ACTIONS.PLAYER.PAUSE, this.handlePauseAction),
112+
this.props.subscribeAction(ACTIONS.PLAYER.TIME_UPDATE, ({currentTime}) =>
113+
this.handleSeek(currentTime)
114+
),
115+
this.props.subscribeAction(
116+
ACTIONS.PLAYER.SHOW_CONTROLLER,
117+
this.handleShowController
118+
),
119+
]
123120

124121
if (this.videoRef.current.root) {
125122
if (this.props.muted) {
@@ -191,9 +188,7 @@ class Player extends Component {
191188
}
192189

193190
componentWillUnmount() {
194-
this.pauseActionSubscription.unsubscribe()
195-
this.timeUpdateActionSubscription.unsubscribe()
196-
this.showControllerActionSubscription.unsubscribe()
191+
this.actionSubscriptions_.forEach(s => s.unsubscribe())
197192
}
198193

199194
handlePauseAction = ({dontApplyOnFullScreen} = {}) => {

packages/griffith/src/components/PlayerContainer/PlayerContainer.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const PlayerContainer = ({
2020
error,
2121
onBeforePlay = () => Promise.resolve(),
2222
onEvent,
23+
dispatchRef,
2324
shouldObserveResize,
2425
children,
2526
initialObjectFit = 'contain',
@@ -40,7 +41,12 @@ const PlayerContainer = ({
4041
}) => (
4142
<ObjectFitProvider initialObjectFit={initialObjectFit}>
4243
<PositionProvider shouldObserveResize={shouldObserveResize}>
43-
<MessageProvider id={id} enableCrossWindow={standalone} onEvent={onEvent}>
44+
<MessageProvider
45+
id={id}
46+
enableCrossWindow={standalone}
47+
onEvent={onEvent}
48+
dispatchRef={dispatchRef}
49+
>
4450
<InternalContext.Consumer>
4551
{({emitEvent, subscribeAction}) => (
4652
<VideoSourceProvider
@@ -109,6 +115,9 @@ PlayerContainer.propTypes = {
109115
}),
110116
onBeforePlay: PropTypes.func,
111117
onEvent: PropTypes.func,
118+
dispatchRef: PropTypes.shape({
119+
current: PropTypes.func,
120+
}),
112121
initialObjectFit: PropTypes.oneOf(VALID_FIT),
113122
useMSE: PropTypes.bool,
114123
defaultQuality: PropTypes.oneOf(['ld', 'sd', 'hd', 'fhd']),

packages/griffith/src/contexts/Message/MessageContext.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ export class MessageProvider extends React.PureComponent {
2323
id: PropTypes.string.isRequired,
2424
enableCrossWindow: PropTypes.bool,
2525
targetOrigin: PropTypes.string.isRequired,
26+
onEvent: PropTypes.func,
27+
dispatchRef: PropTypes.shape({
28+
current: PropTypes.func,
29+
}),
2630
}
2731

2832
static defaultProps = {
@@ -40,6 +44,9 @@ export class MessageProvider extends React.PureComponent {
4044

4145
this.subscribeCrossWindowMessage = subscribeMessage
4246
this.dispatchCrossWindowMessage = dispatchMessage
47+
if (this.props.dispatchRef) {
48+
this.props.dispatchRef.current = this.externalContextValue.dispatchAction
49+
}
4350
}
4451

4552
componentDidMount() {

packages/griffith/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ export {ExternalContext as MessageContext} from './contexts/Message'
33
export {VideoSourceContext} from './contexts/VideoSource'
44
export {default as Controller} from './components/Controller'
55
export {default as Layer} from './components/Layer'
6-
export {EVENTS} from 'griffith-message'
6+
export {EVENTS, ACTIONS} from 'griffith-message'

0 commit comments

Comments
 (0)