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

Reuse players (to circumvent Chrome autoplay issues) #12

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ import React, { Component } from 'react'

import ReactPlayer from './ReactPlayer'

const DELAY = 5000;

export default class App extends Component {
state = {
url: null,
playing: false,
volume: 0.8,
played: 0,
loaded: 0
loaded: 0,
delayLoad: false
}
load = url => {
this.setState({ url, playing: true })
const delay = this.state.delayLoad ? DELAY : 0;
setTimeout(() => {
this.setState({ url, playing: true })
}, delay)
}
playPause = () => {
this.setState({ playing: !this.state.playing })
Expand Down Expand Up @@ -51,7 +57,7 @@ export default class App extends Component {
render () {
return (
<div>
<h1>rmp</h1>
<h1>React Player Test App</h1>
<ReactPlayer
ref='player'
url={this.state.url}
Expand All @@ -68,15 +74,6 @@ export default class App extends Component {
/>
<button onClick={this.stop}>Stop</button>
<button onClick={this.playPause}>{this.state.playing ? 'Pause' : 'Play'}</button>
<button onClick={this.load.bind(this, 'https://www.youtube.com/watch?v=oUFJJNQGwhk')}>Youtube video</button>
<button onClick={this.load.bind(this, 'https://soundcloud.com/miami-nights-1984/accelerated')}>Soundcloud song</button>
<button onClick={this.load.bind(this, 'https://vimeo.com/90509568')}>Vimeo video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')}>MP4 video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv')}>OGV video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm')}>WEBM video</button>
<input ref='url' placeholder='url' />
<button onClick={() => { this.load(this.refs.url.value) }}>Load URL</button>
<hr />
seek: <input
type='range' min={0} max={1} step='any'
value={this.state.played}
Expand All @@ -92,6 +89,22 @@ export default class App extends Component {
onChange={this.setVolume}
/>
<hr />
<button onClick={this.load.bind(this, 'https://www.youtube.com/watch?v=oUFJJNQGwhk')}>Youtube video</button>
<button onClick={this.load.bind(this, 'https://soundcloud.com/miami-nights-1984/accelerated')}>Soundcloud song</button>
<button onClick={this.load.bind(this, 'https://vimeo.com/90509568')}>Vimeo video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')}>MP4 video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.ogv')}>OGV video</button>
<button onClick={this.load.bind(this, 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.webm')}>WEBM video</button>
<input ref='url' placeholder='url' />
<button onClick={() => { this.load(this.refs.url.value) }}>Load URL</button>
<label>
<input
type="checkbox"
value={this.state.delayLoad}
onClick={()=>{this.setState({ delayLoad: !this.state.delayLoad })}}/>
<span> delay {DELAY / 1000} seconds</span>
</label>
<hr />
<textarea ref='config' placeholder='Config JSON' style={{width: '200px', height: '200px'}}></textarea>
<button onClick={this.onConfigSubmit}>Update Config</button>
</div>
Expand Down
28 changes: 22 additions & 6 deletions src/ReactPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import 'array.prototype.find'
import propTypes from './propTypes'
import players from './players'

const NO_OP = function () {}

export default class ReactPlayer extends Component {
static propTypes = propTypes
static defaultProps = {
volume: 0.8,
width: 640,
height: 360,
onPlay: function () {}, // TODO: Empty func var in react?
onPause: function () {},
onBuffer: function () {},
onEnded: function () {}
onPlay: NO_OP,
onPause: NO_OP,
onBuffer: NO_OP,
onEnded: NO_OP
}
static canPlay (url) {
return players.some(player => player.canPlay(url))
Expand All @@ -37,15 +39,29 @@ export default class ReactPlayer extends Component {
player.seekTo(fraction)
}
}
renderPlayers () {
return players.map(Player => {
const canPlay = Player.canPlay(this.props.url);
const style = {
display: canPlay ? 'block' : 'none'
}
return (
<div style={style} key={Player.name}>
<Player ref={canPlay ? "player" : null} {...this.props} />
</div>
)
})
}
render () {
const Player = this.state.Player
const style = {
width: this.props.width,
height: this.props.height
height: this.props.height,
background: 'black'
}
return (
<div style={style}>
{ Player && <Player ref='player' {...this.props} /> }
{this.renderPlayers()}
</div>
)
}
Expand Down
16 changes: 10 additions & 6 deletions src/players/Base.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default class Base extends Component {
onProgress: function () {}
}
componentDidMount () {
this.play(this.props.url)
this.update()
}
componentWillUnmount () {
Expand All @@ -19,12 +18,17 @@ export default class Base extends Component {
}
componentWillReceiveProps (nextProps) {
// Invoke player methods based on incoming props
if (this.props.url !== nextProps.url) {
const canPlay = this.constructor.canPlay(nextProps.url);
if ((this.props.url !== nextProps.url)) {
if (canPlay) {
this.play(nextProps.url)
this.props.onProgress({ played: 0, loaded: 0 })
} else {
this.stop()
}
} else if ((!this.props.playing && nextProps.playing) && canPlay) {
this.play(nextProps.url)
this.props.onProgress({ played: 0, loaded: 0 })
} else if (!this.props.playing && nextProps.playing) {
this.play()
} else if (this.props.playing && !nextProps.playing) {
} else if ((this.props.playing && !nextProps.playing) && canPlay) {
this.pause()
} else if (this.props.volume !== nextProps.volume) {
this.setVolume(nextProps.volume)
Expand Down
10 changes: 6 additions & 4 deletions src/players/FilePlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default class FilePlayer extends Base {
static canPlay (url) {
return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url)
}
state = {}
componentDidMount () {
this.player = this.refs.player
this.player.oncanplay = this.onReady
Expand Down Expand Up @@ -47,13 +48,14 @@ export default class FilePlayer extends Base {
return this.player.buffered.end(0) / this.player.duration
}
render () {
const Media = AUDIO_EXTENSIONS.test(this.props.url) ? 'audio' : 'video'
const { url, width, height } = this.props
const Media = AUDIO_EXTENSIONS.test(url) ? 'audio' : 'video'
return (
<Media
ref='player'
src={this.props.url}
width={this.props.width}
height={this.props.height}
src={url}
width={width}
height={height}
/>
)
}
Expand Down
6 changes: 4 additions & 2 deletions src/players/Vimeo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default class Vimeo extends Base {
static canPlay (url) {
return MATCH_URL.test(url)
}
state = {}
componentDidMount () {
window.addEventListener('message', this.onMessage, false)
this.iframe = this.refs.iframe
Expand Down Expand Up @@ -81,12 +82,13 @@ export default class Vimeo extends Base {
return this.iframe.contentWindow && this.iframe.contentWindow.postMessage(data, this.origin)
}
render () {
const id = this.props.url.match(MATCH_URL)[3]
const { url, vimeoConfig } = this.props
const id = ((url || '').match(MATCH_URL) || [])[3]
const style = {
width: '100%',
height: '100%'
}
const iframeParams = { ...DEFAULT_IFRAME_PARAMS, ...this.props.vimeoConfig.iframeParams }
const iframeParams = { ...DEFAULT_IFRAME_PARAMS, ...vimeoConfig.iframeParams }
return (
<iframe
ref='iframe'
Expand Down
1 change: 1 addition & 0 deletions src/players/YouTube.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class YouTube extends Base {
static canPlay (url) {
return MATCH_URL.test(url)
}
state = {}
shouldComponentUpdate () {
return false
}
Expand Down
12 changes: 8 additions & 4 deletions test/ReactPlayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,28 @@ describe('ReactPlayer', () => {
it('renders YouTube player', () => {
shallowRenderer.render(<ReactPlayer url={YOUTUBE_URL} />)
const result = shallowRenderer.getRenderOutput()
expect(result.props.children.type).to.equal(YouTube)
const activePlayer = result.props.children.find(child => child.props.children.ref === 'player')
expect(activePlayer.props.children.type).to.equal(YouTube)
})

it('renders SoundCloud player', () => {
shallowRenderer.render(<ReactPlayer url={SOUNDCLOUD_URL} />)
const result = shallowRenderer.getRenderOutput()
expect(result.props.children.type).to.equal(SoundCloud)
const activePlayer = result.props.children.find(child => child.props.children.ref === 'player')
expect(activePlayer.props.children.type).to.equal(SoundCloud)
})

it('renders Vimeo player', () => {
shallowRenderer.render(<ReactPlayer url={VIMEO_URL} />)
const result = shallowRenderer.getRenderOutput()
expect(result.props.children.type).to.equal(Vimeo)
const activePlayer = result.props.children.find(child => child.props.children.ref === 'player')
expect(activePlayer.props.children.type).to.equal(Vimeo)
})

it('renders FilePlayer', () => {
shallowRenderer.render(<ReactPlayer url={FILE_URL} />)
const result = shallowRenderer.getRenderOutput()
expect(result.props.children.type).to.equal(FilePlayer)
const activePlayer = result.props.children.find(child => child.props.children.ref === 'player')
expect(activePlayer.props.children.type).to.equal(FilePlayer)
})
})