Skip to content

Commit

Permalink
feat: overload subscribeMessage, add action params type
Browse files Browse the repository at this point in the history
  • Loading branch information
ambar committed Sep 16, 2021
1 parent aba53a7 commit e814282
Show file tree
Hide file tree
Showing 12 changed files with 357 additions and 182 deletions.
165 changes: 100 additions & 65 deletions example/src/IframePage.tsx
Original file line number Diff line number Diff line change
@@ -1,85 +1,120 @@
import React, {useEffect} from 'react'
import React, {useCallback, useEffect, useRef, useState} from 'react'
import {EVENTS, ACTIONS, createMessageHelper} from 'griffith-message'

export default function IframePage() {
export default function IframePage(): JSX.Element {
const [iframeRefs] = useState(() =>
[...Array(4).keys()].map(() => React.createRef<HTMLIFrameElement>())
)
const timeInputRef = useRef<HTMLInputElement>(null)
const helperRef = useRef<ReturnType<typeof createMessageHelper>>()

useEffect(() => {
const {subscribeMessage, dispatchMessage} = createMessageHelper()
helperRef.current = createMessageHelper()

function pauseAllOtherVideos(thisWindow) {
Array.from(document.querySelectorAll('iframe'))
.map(node => node.contentWindow)
.filter(w => w !== thisWindow)
.forEach(w => dispatchMessage(w, ACTIONS.PLAYER.PAUSE))
function pauseAllOtherVideos(thisWindow: MessageEventSource) {
iframeRefs
.map((ref) => ref.current!.contentWindow!)
.filter((w) => w !== thisWindow)
.forEach((w) =>
helperRef.current!.dispatchMessage(w, ACTIONS.PLAYER.PAUSE)
)
}

const disposer = subscribeMessage((messageName, data, sourceWindow) => {
if (messageName === EVENTS.DOM.PLAY) {
pauseAllOtherVideos(sourceWindow)
const disposer = helperRef.current.subscribeMessage(
(messageName, data, sourceWindow) => {
if (messageName === EVENTS.DOM.PLAY) {
pauseAllOtherVideos(sourceWindow!)
}
}
})

const firstVideoWindow = document.querySelector('iframe').contentWindow

document.getElementById('jsPauseFirst').addEventListener('click', () => {
dispatchMessage(firstVideoWindow, ACTIONS.PLAYER.PAUSE)
})

document.getElementById('jsPlayFirst').addEventListener('click', () => {
dispatchMessage(firstVideoWindow, ACTIONS.PLAYER.PLAY)
})

document.getElementById('jsSeekFirst').addEventListener('click', () => {
const currentTime = Number(document.getElementById('time').value)
dispatchMessage(firstVideoWindow, ACTIONS.PLAYER.TIME_UPDATE, {
currentTime,
})
})

document
.getElementById('jsShowControllerFirst')
.addEventListener('click', () => {
dispatchMessage(firstVideoWindow, ACTIONS.PLAYER.SHOW_CONTROLLER)
})

document
.getElementById('jsSetVolumeFirst')
.addEventListener('click', () => {
dispatchMessage(firstVideoWindow, ACTIONS.PLAYER.SET_VOLUME, {
volume: 0,
})
})
)

return () => {
disposer.unsubscribe()
}
}, [])
}, [iframeRefs])

const getFirstWindow = useCallback(
() => iframeRefs[0].current!.contentWindow!,
[iframeRefs]
)

return (
<>
<p>本页面可以测试播放器在 iframe 中的效果,还可以测试跨窗口消息接口</p>
<p>场景 1:向一个视频发出暂停 / 播放指令</p>
<p>场景 2:一个视频开始播放时,暂停其他视频</p>
<p>场景 3:手动 seek</p>
<p>场景 4:显示进度条</p>
<p>场景 5:设置视频的音量</p>
<div>
<iframe src="/mp4?nonav" allowFullScreen frameBorder="0" />
<iframe src="/mp4?nonav" allowFullScreen frameBorder="0" />
<iframe src="/mp4?nonav" allowFullScreen frameBorder="0" />
<iframe src="/mp4?nonav" allowFullScreen frameBorder="0" />
</div>
<br />
<button id="jsPauseFirst">暂停第一个视频</button>
<br />
<button id="jsPlayFirst">播放第一个视频</button>
<br />
<div>
<input id="time" />
<button id="jsSeekFirst">手动 seek 第一个视频</button>
{iframeRefs.map((ref, i) => (
<iframe
ref={ref}
key={i}
src="/mp4?nonav"
allowFullScreen
frameBorder="0"
/>
))}
</div>
<button id="jsShowControllerFirst">让第一个视频显示进度条</button>
<br />
<button id="jsSetVolumeFirst">让第一个视频静音</button>
<section>
<h2>场景演示</h2>
<button
onClick={() => {
helperRef.current!.dispatchMessage(
getFirstWindow(),
ACTIONS.PLAYER.PAUSE
)
}}
>
暂停第一个视频
</button>
<button
onClick={() => {
helperRef.current!.dispatchMessage(
getFirstWindow(),
ACTIONS.PLAYER.PLAY
)
}}
>
播放第一个视频(暂停其他视频)
</button>
<div>
<input ref={timeInputRef} />
<button
onClick={() => {
const currentTime = Number(timeInputRef.current!.value)
helperRef.current!.dispatchMessage(
getFirstWindow(),
ACTIONS.PLAYER.TIME_UPDATE,
{
currentTime,
}
)
}}
>
手动 seek 第一个视频
</button>
</div>
<button
onClick={() => {
helperRef.current!.dispatchMessage(
getFirstWindow(),
ACTIONS.PLAYER.SHOW_CONTROLLER
)
}}
>
让第一个视频显示进度条
</button>
<button
onClick={() => {
helperRef.current!.dispatchMessage(
getFirstWindow(),
ACTIONS.PLAYER.SET_VOLUME,
{
volume: 0,
}
)
}}
>
让第一个视频静音
</button>
</section>
</>
)
}
10 changes: 8 additions & 2 deletions example/src/MP4Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import React, {
useContext,
useEffect,
} from 'react'
import Player, {MessageContext, ACTIONS, EVENTS} from 'griffith'
import Player, {
MessageContext,
MessageContextValue,
ACTIONS,
EVENTS,
} from 'griffith'
import {useLocation} from 'react-router-dom'
import Logo from './Logo'
import {logEvent} from './utils'
Expand Down Expand Up @@ -74,8 +79,9 @@ const LogoListener: React.FC<{shouldShowLogo: boolean}> = ({
}

const App = () => {
const dispatchRef = useRef(null)
const dispatchRef = useRef<MessageContextValue['dispatchAction']>()
const query = useQuery()

return (
<>
<Player
Expand Down
18 changes: 9 additions & 9 deletions packages/griffith-message/README-zh-Hans.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ dispatchMessage(targetWindow, messageName, data)

往播放器发送的事件

| `messageName` | 说明 | `data` | 状态 |
| --------------------------------- | -------------------- | ------------------------------------------------- | ------ |
| `ACTIONS.PLAYER.PLAY` | 播放 | `{applyOnFullScreen: boolean}` 是否应用于全屏视频 | 已支持 |
| `ACTIONS.PLAYER.PAUSE` | 暂停 | 同上 | 已支持 |
| `ACTIONS.PLAYER.SET_VOLUME` | 设置音量 | `{volume: number}` 音量值,0 到 1 | 已支持 |
| `ACTIONS.PLAYER.ENTER_FULLSCREEN` | 进入全屏 | | 已支持 |
| `ACTIONS.PLAYER.EXIT_FULLSCREEN` | 退出全屏 | | 已支持 |
| `ACTIONS.PLAYER.TIME_UPDATE` | 设置视频播放进度 | `{currentTime: number} 设置视频当前的进度` | 已支持 |
| `ACTIONS.PLAYER.SHOW_CONTROLLER` | 显示播放器进度条控件 | | 已支持 |
| `messageName` | 说明 | `data` |
| --------------------------------- | -------------------- | ----------------------------------------------------- |
| `ACTIONS.PLAYER.PLAY` | 播放 | `void` |
| `ACTIONS.PLAYER.PAUSE` | 暂停 | `{dontApplyOnFullScreen: boolean}` 是否应用于全屏视频 |
| `ACTIONS.PLAYER.SET_VOLUME` | 设置音量 | `{volume: number}` 音量值,0 到 1 |
| `ACTIONS.PLAYER.ENTER_FULLSCREEN` | 进入全屏 | `void` |
| `ACTIONS.PLAYER.EXIT_FULLSCREEN` | 退出全屏 | `void` |
| `ACTIONS.PLAYER.TIME_UPDATE` | 设置视频播放进度 | `{currentTime: number}` 设置视频当前的进度 |
| `ACTIONS.PLAYER.SHOW_CONTROLLER` | 显示播放器进度条控件 | `void` |
24 changes: 12 additions & 12 deletions packages/griffith-message/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,15 @@ Events received from the player

### ACTIONS

Event sent to the player

| `messageName` | Description | `data` | Status |
| ---------------------------------- | ------------------------- | ----------------------------------------------------------- | --------- |
| `ACTIONS.PLAYER.PLAY` | Play | `{applyOnFullScreen: boolean}` Applied to full screen video | SUPPORTED |
| `ACTIONS.PLAYER.PAUSE` | Pause | Applied to full screen video | SUPPORTED |
| `ACTIONS.PLAYER.SET_VOLUME` | Set the volume | `{volume: number}` Volume value from 0 to 1 | SUPPORTED |
| `ACTIONS.PLAYER.ENTER_FULLSCREEN` | Enter fullScreen | null | SUPPORTED |
| `ACTIONS.PLAYER.EXIT_FULLSCREEN` | Exit fullscreen | null | SUPPORTED |
| `ACTIONS.PLAYER.TIME_UPDATE` | Set current time | `{currentTime: number} Set the currentTime` | SUPPORTED |
| `ACTIONS.PLAYER.SHOW_CONTROLLER` | Show Controller | null | SUPPORTED |
| `EVENTS.PLAYER.SUBSCRIPTION_READY` | Action subscription ready | null |
Actions sent to the player

| `messageName` | Description | `data` |
| ---------------------------------- | ------------------------- | ------------------------------------------------------------------------ |
| `ACTIONS.PLAYER.PLAY` | Play | `void` |
| `ACTIONS.PLAYER.PAUSE` | Pause | `{dontApplyOnFullScreen: boolean}` Whether to apply to full screen video |
| `ACTIONS.PLAYER.SET_VOLUME` | Set the volume | `{volume: number}` Volume value from 0 to 1 |
| `ACTIONS.PLAYER.ENTER_FULLSCREEN` | Enter fullScreen | `void` |
| `ACTIONS.PLAYER.EXIT_FULLSCREEN` | Exit fullscreen | `void` |
| `ACTIONS.PLAYER.TIME_UPDATE` | Set current time | `{currentTime: number}` Set the current playback time |
| `ACTIONS.PLAYER.SHOW_CONTROLLER` | Show Controller | `void` |
| `EVENTS.PLAYER.SUBSCRIPTION_READY` | Action subscription ready | `void` |
51 changes: 39 additions & 12 deletions packages/griffith-message/src/constants/actions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
export const PLAYER = {
PLAY: 'action/player/play',
PAUSE: 'action/player/pause',
SET_VOLUME: 'action/player/set-volume',
ENTER_FULLSCREEN: 'action/player/enter-fullscreen',
EXIT_FULLSCREEN: 'action/player/exit-fullscreen',
ENTER_PAGE_FULLSCREEN: 'event/player/enter-page-fullscreen',
EXIT_PAGE_FULLSCREEN: 'event/player/exit-page-fullscreen',
ENTER_PIP: 'action/player/enter-pip',
EXIT_PIP: 'action/player/exit-pip',
TIME_UPDATE: 'action/player/time-update',
SHOW_CONTROLLER: 'action/player/show-controller',
// NOTE: 补充新类型时,应当在 `ActionParamsMap` 中定义参数类型
enum PLAYER {
PLAY = 'action/player/play',
PAUSE = 'action/player/pause',
SET_VOLUME = 'action/player/set-volume',
ENTER_FULLSCREEN = 'action/player/enter-fullscreen',
EXIT_FULLSCREEN = 'action/player/exit-fullscreen',
ENTER_PAGE_FULLSCREEN = 'event/player/enter-page-fullscreen',
EXIT_PAGE_FULLSCREEN = 'event/player/exit-page-fullscreen',
ENTER_PIP = 'action/player/enter-pip',
EXIT_PIP = 'action/player/exit-pip',
TIME_UPDATE = 'action/player/time-update',
SHOW_CONTROLLER = 'action/player/show-controller',
}

// TODO:临时兼容,下一版本删除,直接在定义上合并,否则造成引用上的麻烦
export const ACTIONS = {
...PLAYER,
/** @deprecated */
PLAYER,
}

export type ACTIONS = PLAYER | never

// 泛型确保了 void 定义有效应用于 spread 提取
type Dispatch<P> = (params: P) => void

export type ActionParamsMap = {
[ACTIONS.PLAY]: Dispatch<void>
[ACTIONS.PAUSE]: Dispatch<void | {dontApplyOnFullScreen: boolean}>
[ACTIONS.SET_VOLUME]: Dispatch<{volume: number}>
[ACTIONS.ENTER_FULLSCREEN]: Dispatch<void>
[ACTIONS.EXIT_FULLSCREEN]: Dispatch<void>
[ACTIONS.ENTER_PAGE_FULLSCREEN]: Dispatch<void>
[ACTIONS.EXIT_PAGE_FULLSCREEN]: Dispatch<void>
[ACTIONS.ENTER_PIP]: Dispatch<void>
[ACTIONS.EXIT_PIP]: Dispatch<void>
[ACTIONS.TIME_UPDATE]: Dispatch<{currentTime: number}>
[ACTIONS.SHOW_CONTROLLER]: Dispatch<void>
}
Loading

0 comments on commit e814282

Please sign in to comment.