diff --git a/README.md b/README.md index 104b0c14..94bf02b7 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,7 @@ var styles = StyleSheet.create({ * [bufferConfig](#bufferconfig) * [controls](#controls) * [headers](#headers) +* [id](#id) * [ignoreSilentSwitch](#ignoresilentswitch) * [muted](#muted) * [paused](#paused) @@ -349,7 +350,7 @@ To enable this on iOS, you will need to manually edit RCTVideo.m and uncomment t Example: ``` -headers = {{ +headers={{ Authorization: 'bearer some-token-value', 'X-Custom-Header': 'some value' }} @@ -357,6 +358,16 @@ headers = {{ Platforms: Android ExoPlayer +#### id +Set the DOM id element so you can use document.getElementById on web platforms. Accepts string values. + +Example: +``` +id="video" +``` + +Platforms: DOM + #### ignoreSilentSwitch Controls the iOS silent switch behavior * **"inherit" (default)** - Use the default AVPlayer behavior diff --git a/dom/RCTVideo.js b/dom/RCTVideo.js index b249721f..9831b61d 100644 --- a/dom/RCTVideo.js +++ b/dom/RCTVideo.js @@ -1,6 +1,7 @@ // @flow import { RCTEvent, RCTView, type RCTBridge } from "react-native-dom"; +import shaka from "shaka-player"; import resizeModes from "./resizeModes"; import type { VideoSource } from "./types"; @@ -25,6 +26,8 @@ class RCTVideo extends RCTView { this.eventDispatcher = bridge.getModuleByName("EventDispatcher"); + shaka.polyfill.installAll(); + this.onEnd = this.onEnd.bind(this); this.onLoad = this.onLoad.bind(this); this.onLoadStart = this.onLoadStart.bind(this); @@ -37,11 +40,11 @@ class RCTVideo extends RCTView { this.videoElement.addEventListener("loadstart", this.onLoadStart); this.videoElement.addEventListener("pause", this.onPause); this.videoElement.addEventListener("play", this.onPlay); + this.player = new shaka.Player(this.videoElement); this.muted = false; this.rate = 1.0; this.volume = 1.0; - this.videoElement.autoplay = true; this.childContainer.appendChild(this.videoElement); } @@ -71,36 +74,28 @@ class RCTVideo extends RCTView { } presentFullscreenPlayer() { - console.log("V PF"); this.videoElement.webkitRequestFullScreen(); } set controls(value: boolean) { - if (value) { - this.videoElement.controls = true; - this.videoElement.style.pointerEvents = "auto"; - } else { - this.videoElement.controls = false; - this.videoElement.style.pointerEvents = ""; - } + this.videoElement.controls = value; + this.videoElement.style.pointerEvents = value ? "auto" : ""; + } + + set id(value: string) { + this.videoElement.id = value; } set muted(value: boolean) { - if (value) { - this.videoElement.muted = true; - } else { - this.videoElement.muted = false; - } + this.videoElement.muted = true; } set paused(value: boolean) { - this.playPromise.then(() => { - if (value) { - this.videoElement.pause(); - } else { - this.playPromise = this.videoElement.play(); - } - }); + if (value) { + this.videoElement.pause(); + } else { + this.requestPlay(); + } this._paused = value; } @@ -118,11 +113,7 @@ class RCTVideo extends RCTView { } set repeat(value: boolean) { - if (value) { - this.videoElement.setAttribute("loop", "true"); - } else { - this.videoElement.removeAttribute("loop"); - } + this.videoElement.loop = value; } set resizeMode(value: number) { @@ -161,9 +152,19 @@ class RCTVideo extends RCTView { uri = URL.createObjectURL(blob); } - this.videoElement.setAttribute("src", uri); - if (!this._paused) { - this.playPromise = this.videoElement.play(); + if (!shaka.Player.isBrowserSupported()) { // primarily iOS WebKit + this.videoElement.setAttribute("src", uri); + if (!this._paused) { + this.requestPlay(); + } + } else { + this.player.load(uri) + .then(() => { + if (!this._paused) { + this.requestPlay(); + } + }) + .catch(this.onError); } } @@ -182,6 +183,10 @@ class RCTVideo extends RCTView { this.stopProgressTimer(); } + onError = error => { + console.warn("topVideoError", error); + } + onLoad = () => { // height & width are safe with audio, will be 0 const height = this.videoElement.videoHeight; @@ -223,6 +228,25 @@ class RCTVideo extends RCTView { this.sendEvent("topVideoProgress", payload); } + onRejectedAutoplay = () => { + this.sendEvent("topVideoRejectedAutoplay", null); + } + + requestPlay() { + const playPromise = this.videoElement.play(); + if (playPromise) { + playPromise + .then(() => {}) + .catch(e => { + /* This is likely one of: + * name: NotAllowedError - autoplay is not supported + * name: NotSupportedError - format is not supported + */ + this.onError({ code: e.name, message: e.message }); + }); + } + } + sendEvent(eventName, payload) { const event = new RCTVideoEvent(eventName, this.reactTag, 0, payload); this.eventDispatcher.sendEvent(event); diff --git a/dom/RCTVideoManager.js b/dom/RCTVideoManager.js index b5b3f3f3..2eb5309b 100644 --- a/dom/RCTVideoManager.js +++ b/dom/RCTVideoManager.js @@ -18,6 +18,7 @@ class RCTVideoManager extends RCTViewManager { return super .describeProps() .addBooleanProp("controls", this.setControls) + .addStringProp("id", this.setId) .addBooleanProp("muted", this.setMuted) .addBooleanProp("paused", this.setPaused) .addNumberProp("progressUpdateInterval", this.setProgressUpdateInterval) @@ -28,11 +29,16 @@ class RCTVideoManager extends RCTViewManager { .addObjectProp("src", this.setSource) .addNumberProp("volume", this.setVolume) .addDirectEvent("onVideoEnd") + .addDirectEvent("onVideoError") .addDirectEvent("onVideoLoad") .addDirectEvent("onVideoLoadStart") .addDirectEvent("onVideoProgress"); } + dismissFullscreenPlayer() { + // not currently working + } + presentFullscreenPlayer() { // not currently working } @@ -41,6 +47,10 @@ class RCTVideoManager extends RCTViewManager { view.controls = value; } + setId(view: RCTVideo, value: string) { + view.id = value; + } + setMuted(view: RCTVideo, value: boolean) { view.muted = value; } diff --git a/package.json b/package.json index 5fc9a51c..92366be3 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,8 @@ }, "dependencies": { "keymirror": "0.1.1", - "prop-types": "^15.5.10" + "prop-types": "^15.5.10", + "shaka-player": "2.4.4" }, "scripts": { "test": "node_modules/.bin/eslint *.js" @@ -54,4 +55,4 @@ "react-native-video.podspec", "VideoResizeMode.js" ] -} \ No newline at end of file +}