Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(h5): 修复 video methods #7891

Merged
merged 10 commits into from
Dec 12, 2020
8 changes: 8 additions & 0 deletions packages/taro-components/__tests__/test-tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export async function mount (node, wrapper) {
async componentDidMount () {
const ref = this.ref.current
const dom = ref instanceof HTMLElement ? ref : ReactDOM.findDOMNode(ref)
const { ref: forwardRef } = node
if (typeof forwardRef === 'function') {
forwardRef(ref)
} else if (forwardRef && typeof forwardRef === 'object' && forwardRef.hasOwnProperty('current')) {
forwardRef.current = ref
} else if (typeof forwardRef === 'string') {
console.warn('内置组件不支持字符串 ref')
}

await waitForChange(dom)

Expand Down
87 changes: 76 additions & 11 deletions packages/taro-components/__tests__/video.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,40 +106,98 @@ describe('Video', () => {
)
const wrapper = await mount(app, scratch)
const { node } = wrapper
const box = document.querySelector('.taro-video')
const video = wrapper.find('video.taro-video-video')
const fullscreenBtn = wrapper.find('.taro-video-fullscreen')
video.requestFullscreen = sinon.fake()

assert(box.children.length === 1)
assert(node.parentElement === box)
assert(fullscreenBtn.classList.contains('taro-nodevideo-type-fullscreen') === false)

fullscreenBtn.click()
await waitForChange(node)

assert(box.children.length === 0)
assert(node.parentElement === document.body)
assert(fullscreenBtn.classList.contains('taro-video-type-fullscreen') === true)
assert(onFullScreenChange.calledOnceWith({
fullScreen: true,
direction: 'vertical'
}))
assert(video.requestFullscreen.calledOnceWith({
navigationUI: 'show'
}))

fullscreenBtn.click()
await waitForChange(node)

assert(box.children.length === 1)
assert(node.parentElement === box)
assert(fullscreenBtn.classList.contains('taro-video-type-fullscreen') === false)
assert(onFullScreenChange.callCount === 2)
assert(onFullScreenChange.calledWith({
fullScreen: false,
direction: 'vertical'
}))
assert(video.requestFullscreen.callCount === 1)
})

it('should play', async () => {
const ref = React.createRef()
const app = (
<Video
ref={ref}
src='http://storage.jd.com/cjj-pub-images/bear.mp4'
onError={ev => ev.stopPropagation()}
/>
)
const wrapper = await mount(app, scratch)
const video = wrapper.find('video.taro-video-video')
video.play = sinon.fake()
ref.current.play()
const { node } = wrapper
await waitForChange(node)

assert(video.play.callCount === 1)
})

it('controls bar', async () => {
it('should pause', async () => {
const ref = React.createRef()
const app = (
<Video
ref={ref}
src='http://storage.jd.com/cjj-pub-images/bear.mp4'
onError={ev => ev.stopPropagation()}
/>
)
const wrapper = await mount(app, scratch)
const video = wrapper.find('video.taro-video-video')
video.pause = sinon.fake()
ref.current.pause()
const { node } = wrapper
await waitForChange(node)

assert(video.pause.callCount === 1)
})

it('should seek and stop', async () => {
const ref = React.createRef()
const app = (
<Video
ref={ref}
src='http://storage.jd.com/cjj-pub-images/bear.mp4'
onError={ev => ev.stopPropagation()}
/>
)
const wrapper = await mount(app, scratch)
const video = wrapper.find('video.taro-video-video')
ref.current.seek(233)
const { node } = wrapper
await waitForChange(node)

assert(video.currentTime === 233)
video.pause = sinon.fake()
ref.current.stop()
await waitForChange(node)

assert(video.currentTime === 0)
assert(video.pause.callCount === 1)
})

it('should be controlled by bar', async () => {
const app = (
<Video
src='http://storage.jd.com/cjj-pub-images/bear.mp4'
Expand All @@ -151,7 +209,7 @@ describe('Video', () => {
let currentTime = wrapper.find('.taro-video-current-time')
let progress = wrapper.find('.taro-video-progress-container')
let duration = wrapper.find('.taro-video-duration')
let playBtn = wrapper.find('.taro-video-control-button')
let playBtn = wrapper.find('.taro-video-control-button-play')
let muteBtn = wrapper.find('.taro-video-mute')
let danmuBtn = wrapper.find('.taro-video-danmu-button')
let fullscreenBtn = wrapper.find('.taro-video-fullscreen')
Expand All @@ -164,6 +222,13 @@ describe('Video', () => {
assert(muteBtn === null)
assert(danmuBtn === null)

const video = wrapper.find('video.taro-video-video')
video.play = sinon.fake()
const { node } = wrapper
playBtn.click()
await waitForChange(node)
assert(video.play.callCount === 1)

await wrapper.setProps({
showProgress: false,
showFullscreenBtn: false,
Expand All @@ -176,7 +241,7 @@ describe('Video', () => {
currentTime = wrapper.find('.taro-video-current-time')
progress = wrapper.find('.taro-video-progress-container')
duration = wrapper.find('.taro-video-duration')
playBtn = wrapper.find('.taro-video-control-button')
playBtn = wrapper.find('.taro-video-control-button-play')
muteBtn = wrapper.find('.taro-video-mute')
danmuBtn = wrapper.find('.taro-video-danmu-button')
fullscreenBtn = wrapper.find('.taro-video-fullscreen')
Expand Down
3 changes: 1 addition & 2 deletions packages/taro-components/src/components/video/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const screenFn = (function () {
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'

],
// Old WebKit
[
Expand Down Expand Up @@ -88,7 +87,7 @@ export const screenFn = (function () {
return ret
}
}
// If it doesn't find any of them, this whole function returns false
// If it doesn't find any of them, this whole function returns {}
// and the fn variable is set to this returned value.
return ret
})()
59 changes: 29 additions & 30 deletions packages/taro-components/src/components/video/video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class Video implements ComponentInterface {
private lastPercentage
private nextPercentage
private gestureType = 'none'
private wrapperElement: HTMLElement

@Element() el: HTMLTaroVideoCoreElement

Expand Down Expand Up @@ -189,30 +188,18 @@ export class Video implements ComponentInterface {
}
// 目前只支持 danmuList 初始化弹幕列表,还未支持更新弹幕列表
this.danmuRef.sendDanmu(this.danmuList)

if (document.addEventListener) {
document.addEventListener(screenFn.fullscreenchange, this.handleFullScreenChange)
}
}

componentDidRender () {
const parentElement = this.el.parentElement as HTMLElement
const parentTagName = parentElement.tagName
if (this.isFullScreen) {
if (parentTagName !== 'BODY') {
parentElement.removeChild(this.el)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这一段我没理解原来想做什么,对于全屏以及退出全屏我没测出有影响,反而导致了 Safari 上全屏后自动退出。我先全删了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document.body.appendChild(this.el)
}
} else {
if (parentTagName !== 'DIV' || !parentElement.className.includes('taro-video')) {
if (!this.wrapperElement) {
const container = document.createElement('div')
container.className = 'taro-video'
parentElement.removeChild(this.el)
container.appendChild(this.el)
parentElement.appendChild(container)
this.wrapperElement = container
} else {
parentElement.removeChild(this.el)
this.wrapperElement.appendChild(this.el)
}
}
}

disconnectedCallback () {
if (document.removeEventListener) {
document.removeEventListener(screenFn.fullscreenchange, this.handleFullScreenChange)
}
}

Expand Down Expand Up @@ -387,22 +374,34 @@ export class Video implements ComponentInterface {

/** 播放视频 */
@Method() async play () {
this.videoRef.play()
this._play()
}

_play = () => this.videoRef.play()

/** 暂停视频 */
@Method() async pause () {
this.videoRef.pause()
this._pause()
}

_pause = () => this.videoRef.pause()

/** 停止视频 */
@Method() async stop () {
this._stop()
}

_stop = () => {
this.videoRef.pause()
this.seek(0)
this._seek(0)
}

/** 跳转到指定位置 */
@Method() async seek (position: number) {
this._seek(position)
}

_seek = (position: number) => {
this.videoRef.currentTime = position
}

Expand Down Expand Up @@ -438,8 +437,8 @@ export class Video implements ComponentInterface {
this.toggleFullScreen()
}

// 全屏后,"点击按钮退出"走的是浏览器事件,在此同步状态
@Listen('fullscreenchange') onNativeFullScreenExit (e) {
handleFullScreenChange = e => {
// 全屏后,"退出"走的是浏览器事件,在此同步状态
const timestamp = new Date().getTime()
if (!e.detail && this.isFullScreen && !document[screenFn.fullscreenElement] && timestamp - this.fullScreenTimestamp > 100) {
this.toggleFullScreen(false)
Expand Down Expand Up @@ -556,9 +555,9 @@ export class Video implements ComponentInterface {
currentTime={this.currentTime}
duration={this.duration || this._duration || undefined}
isPlaying={this.isPlaying}
pauseFunc={this.pause}
playFunc={this.play}
seekFunc={this.seek}
pauseFunc={this._pause}
playFunc={this._play}
seekFunc={this._seek}
showPlayBtn={this.showPlayBtn}
showProgress={this.showProgress}
>
Expand Down