Remove DOM support. Closes #2647
This commit is contained in:
parent
691a11dc4e
commit
879572edd3
44
API.md
44
API.md
@ -5,7 +5,6 @@
|
||||
* [tvOS](#tvos-installation)
|
||||
* [Android](#android-installation)
|
||||
* [Windows](#windows-installation)
|
||||
* [react-native-dom](#react-native-dom-installation)
|
||||
* [Examples](#examples)
|
||||
* [iOS](#ios-example)
|
||||
* [Android](#android-example)
|
||||
@ -211,34 +210,6 @@ Add `PackageProviders().Append(winrt::ReactNativeVideoCPP::ReactPackageProvider(
|
||||
|
||||
Follow the manual linking instuctions for React Native Windows 0.62 above, but substitute _ReactNativeVideoCPP61_ for _ReactNativeVideoCPP_.
|
||||
|
||||
</details>
|
||||
|
||||
### react-native-dom installation
|
||||
<details>
|
||||
<summary>react-native-dom details</summary>
|
||||
|
||||
Make the following additions to the given files manually:
|
||||
|
||||
#### **dom/bootstrap.js**
|
||||
|
||||
Import RCTVideoManager and add it to the list of nativeModules:
|
||||
|
||||
```javascript
|
||||
import { RNDomInstance } from "react-native-dom";
|
||||
import { name as appName } from "../app.json";
|
||||
import RCTVideoManager from 'react-native-video/dom/RCTVideoManager'; // Add this
|
||||
|
||||
// Path to RN Bundle Entrypoint ================================================
|
||||
const rnBundlePath = "./entry.bundle?platform=dom&dev=true";
|
||||
|
||||
// React Native DOM Runtime Options =============================================
|
||||
const ReactNativeDomOptions = {
|
||||
enableHotReload: false,
|
||||
nativeModules: [RCTVideoManager] // Add this
|
||||
};
|
||||
```
|
||||
</details>
|
||||
|
||||
## Examples
|
||||
|
||||
Run `yarn xbasic install` before running any of the examples.
|
||||
@ -298,7 +269,7 @@ var styles = StyleSheet.create({
|
||||
|[backBufferDurationMs](#backBufferDurationMs)| Android |
|
||||
|[bufferConfig](#bufferconfig)|Android|
|
||||
|[contentStartTime](#contentStartTime)| Android |
|
||||
|[controls](#controls)|Android, iOS, react-native-dom|
|
||||
|[controls](#controls)|Android, iOS|
|
||||
|[currentPlaybackTime](#currentPlaybackTime)|Android|
|
||||
|[disableFocus](#disableFocus)|Android, iOS|
|
||||
|[disableDisconnectError](#disableDisconnectError)|Android|
|
||||
@ -309,7 +280,6 @@ var styles = StyleSheet.create({
|
||||
|[fullscreenOrientation](#fullscreenorientation)|iOS|
|
||||
|[headers](#headers)|Android|
|
||||
|[hideShutterView](#hideshutterview)|Android|
|
||||
|[id](#id)|react-native-dom|
|
||||
|[ignoreSilentSwitch](#ignoresilentswitch)|iOS|
|
||||
|[maxBitRate](#maxbitrate)|Android, iOS|
|
||||
|[minLoadRetryCount](#minLoadRetryCount)|Android|
|
||||
@ -447,7 +417,7 @@ The start time in ms for SSAI content. This determines at what time to load the
|
||||
|
||||
Note on Android, native controls are available by default. If needed, you can also add your controls or use a package like [react-native-video-controls].
|
||||
|
||||
Platforms: Android, iOS, react-native-dom
|
||||
Platforms: Android, iOS
|
||||
|
||||
#### disableFocus
|
||||
Determines whether video audio should override background music/audio in Android devices.
|
||||
@ -548,16 +518,6 @@ Controls whether the ExoPlayer shutter view (black screen while loading) is enab
|
||||
|
||||
Platforms: Android
|
||||
|
||||
#### id
|
||||
Set the DOM id element so you can use document.getElementById on web platforms. Accepts string values.
|
||||
|
||||
Example:
|
||||
```
|
||||
id="video"
|
||||
```
|
||||
|
||||
Platforms: react-native-dom
|
||||
|
||||
#### ignoreSilentSwitch
|
||||
Controls the iOS silent switch behavior
|
||||
* **"inherit" (default)** - Use the default AVPlayer behavior
|
||||
|
280
dom/RCTVideo.js
280
dom/RCTVideo.js
@ -1,280 +0,0 @@
|
||||
// @flow
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import { RCTView, type RCTBridge } from 'react-native-dom';
|
||||
import shaka from 'shaka-player';
|
||||
|
||||
import resizeModes from './resizeModes';
|
||||
import type { VideoSource } from './types';
|
||||
import RCTVideoEvent from './RCTVideoEvent';
|
||||
|
||||
class RCTVideo extends RCTView {
|
||||
playPromise: Promise<void> = Promise.resolve();
|
||||
progressTimer: number;
|
||||
videoElement: HTMLVideoElement;
|
||||
|
||||
onEnd: boolean = false;
|
||||
onLoad: boolean = false;
|
||||
onLoadStart: boolean = false;
|
||||
onProgress: boolean = false;
|
||||
|
||||
_paused: boolean = false;
|
||||
_progressUpdateInterval: number = 250.0;
|
||||
_savedVolume: number = 1.0;
|
||||
|
||||
constructor(bridge: RCTBridge) {
|
||||
super(bridge);
|
||||
|
||||
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);
|
||||
this.onPlay = this.onPlay.bind(this);
|
||||
this.onProgress = this.onProgress.bind(this);
|
||||
|
||||
this.videoElement = this.initializeVideoElement();
|
||||
this.videoElement.addEventListener('ended', this.onEnd);
|
||||
this.videoElement.addEventListener('loadeddata', this.onLoad);
|
||||
this.videoElement.addEventListener('canplay', this.onReadyForDisplay);
|
||||
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.childContainer.appendChild(this.videoElement);
|
||||
}
|
||||
|
||||
detachFromView(view: UIView) {
|
||||
this.videoElement.removeEventListener('ended', this.onEnd);
|
||||
this.videoElement.removeEventListener('loadeddata', this.onLoad);
|
||||
this.videoElement.removeEventListener('canplay', this.onReadyForDisplay);
|
||||
this.videoElement.removeEventListener('loadstart', this.onLoadStart);
|
||||
this.videoElement.removeEventListener('pause', this.onPause);
|
||||
this.videoElement.removeEventListener('play', this.onPlay);
|
||||
|
||||
this.stopProgressTimer();
|
||||
}
|
||||
|
||||
initializeVideoElement() {
|
||||
const elem = document.createElement('video');
|
||||
|
||||
Object.assign(elem.style, {
|
||||
display: 'block',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
});
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
presentFullscreenPlayer() {
|
||||
this.videoElement.webkitRequestFullScreen();
|
||||
}
|
||||
|
||||
set controls(value: boolean) {
|
||||
this.videoElement.controls = value;
|
||||
this.videoElement.style.pointerEvents = value ? 'auto' : '';
|
||||
}
|
||||
|
||||
set id(value: string) {
|
||||
this.videoElement.id = value;
|
||||
}
|
||||
|
||||
set muted(value: boolean) {
|
||||
this.videoElement.muted = true;
|
||||
}
|
||||
|
||||
set paused(value: boolean) {
|
||||
if (value) {
|
||||
this.videoElement.pause();
|
||||
} else {
|
||||
this.requestPlay();
|
||||
}
|
||||
this._paused = value;
|
||||
}
|
||||
|
||||
set progressUpdateInterval(value: number) {
|
||||
this._progressUpdateInterval = value;
|
||||
this.stopProgressTimer();
|
||||
if (!this._paused) {
|
||||
this.startProgressTimer();
|
||||
}
|
||||
}
|
||||
|
||||
set rate(value: number) {
|
||||
this.videoElement.defaultPlaybackRate = value; // playbackRate doesn't work on Chrome
|
||||
this.videoElement.playbackRate = value;
|
||||
}
|
||||
|
||||
set repeat(value: boolean) {
|
||||
this.videoElement.loop = value;
|
||||
}
|
||||
|
||||
set resizeMode(value: number) {
|
||||
switch (value) {
|
||||
case resizeModes.ScaleNone: {
|
||||
this.videoElement.style.objectFit = 'none';
|
||||
break;
|
||||
}
|
||||
case resizeModes.ScaleToFill: {
|
||||
this.videoElement.style.objectFit = 'fill';
|
||||
break;
|
||||
}
|
||||
case resizeModes.ScaleAspectFit: {
|
||||
this.videoElement.style.objectFit = 'contain';
|
||||
break;
|
||||
}
|
||||
case resizeModes.ScaleAspectFill: {
|
||||
this.videoElement.style.objectFit = 'cover';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set seek(value: number) {
|
||||
this.videoElement.currentTime = value;
|
||||
}
|
||||
|
||||
set source(value: VideoSource) {
|
||||
let uri = value.uri;
|
||||
|
||||
if (uri.startsWith('blob:')) {
|
||||
let blob = this.bridge.blobManager.resolveURL(uri);
|
||||
if (blob.type === 'text/xml') {
|
||||
blob = new Blob([blob], { type: 'video/mp4' });
|
||||
}
|
||||
uri = URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
set volume(value: number) {
|
||||
if (value === 0) {
|
||||
this.muted = true;
|
||||
} else {
|
||||
this.videoElement.volume = value;
|
||||
this.muted = false;
|
||||
}
|
||||
}
|
||||
|
||||
onEnd = () => {
|
||||
this.onProgress();
|
||||
this.sendEvent('topVideoEnd', null);
|
||||
this.stopProgressTimer();
|
||||
}
|
||||
|
||||
onError = error => {
|
||||
console.warn('topVideoError', error);
|
||||
}
|
||||
|
||||
onLoad = () => {
|
||||
// height & width are safe with audio, will be 0
|
||||
const height = this.videoElement.videoHeight;
|
||||
const width = this.videoElement.videoWidth;
|
||||
const payload = {
|
||||
currentPosition: this.videoElement.currentTime,
|
||||
duration: this.videoElement.duration,
|
||||
naturalSize: {
|
||||
width,
|
||||
height,
|
||||
orientation: width >= height ? 'landscape' : 'portrait',
|
||||
},
|
||||
};
|
||||
this.sendEvent('topVideoLoad', payload);
|
||||
}
|
||||
|
||||
onReadyForDisplay = () => {
|
||||
this.sendEvent('onReadyForDisplay');
|
||||
}
|
||||
|
||||
onLoadStart = () => {
|
||||
const src = this.videoElement.currentSrc;
|
||||
const payload = {
|
||||
isNetwork: !src.match(/^https?:\/\/localhost/), // require is served from localhost
|
||||
uri: this.videoElement.currentSrc,
|
||||
};
|
||||
this.sendEvent('topVideoLoadStart', payload);
|
||||
}
|
||||
|
||||
onPause = () => {
|
||||
this.stopProgressTimer();
|
||||
}
|
||||
|
||||
onPlay = () => {
|
||||
this.startProgressTimer();
|
||||
}
|
||||
|
||||
onProgress = () => {
|
||||
const payload = {
|
||||
currentTime: this.videoElement.currentTime,
|
||||
seekableDuration: this.videoElement.duration,
|
||||
};
|
||||
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);
|
||||
}
|
||||
|
||||
startProgressTimer() {
|
||||
if (!this.progressTimer && this._progressUpdateInterval) {
|
||||
this.onProgress();
|
||||
this.progressTimer = setInterval(this.onProgress, this._progressUpdateInterval);
|
||||
}
|
||||
}
|
||||
|
||||
stopProgressTimer() {
|
||||
if (this.progressTimer) {
|
||||
clearInterval(this.progressTimer);
|
||||
this.progressTimer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('rct-video', RCTVideo);
|
||||
|
||||
export default RCTVideo;
|
@ -1,56 +0,0 @@
|
||||
// import { RCTEvent } from "react-native-dom";
|
||||
|
||||
interface RCTEvent {
|
||||
viewTag: number;
|
||||
eventName: string;
|
||||
coalescingKey: number;
|
||||
|
||||
canCoalesce(): boolean;
|
||||
coalesceWithEvent(event: RCTEvent): RCTEvent;
|
||||
|
||||
moduleDotMethod(): string;
|
||||
arguments(): Array<any>;
|
||||
}
|
||||
|
||||
export default class RCTVideoEvent implements RCTEvent {
|
||||
viewTag: number;
|
||||
eventName: string;
|
||||
coalescingKey: number;
|
||||
|
||||
constructor(
|
||||
eventName: string,
|
||||
reactTag: number,
|
||||
coalescingKey: number,
|
||||
data: ?Object
|
||||
) {
|
||||
this.viewTag = reactTag;
|
||||
this.eventName = eventName;
|
||||
this.coalescingKey = coalescingKey;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
canCoalesce(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
coalesceWithEvent(event: RCTEvent): RCTEvent {
|
||||
return;
|
||||
}
|
||||
|
||||
moduleDotMethod(): string {
|
||||
return 'RCTEventEmitter.receiveEvent';
|
||||
}
|
||||
|
||||
arguments(): Array<any> {
|
||||
const args = [
|
||||
this.viewTag,
|
||||
this.eventName,
|
||||
this.data,
|
||||
];
|
||||
return args;
|
||||
}
|
||||
|
||||
coalescingKey(): number {
|
||||
return this.coalescingKey;
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
// @flow
|
||||
|
||||
import { RCTViewManager } from 'react-native-dom';
|
||||
|
||||
import RCTVideo from './RCTVideo';
|
||||
import resizeModes from './resizeModes';
|
||||
|
||||
import type { VideoSource } from './types';
|
||||
|
||||
class RCTVideoManager extends RCTViewManager {
|
||||
static moduleName = 'RCTVideoManager';
|
||||
|
||||
view() {
|
||||
return new RCTVideo(this.bridge);
|
||||
}
|
||||
|
||||
describeProps() {
|
||||
return super
|
||||
.describeProps()
|
||||
.addBooleanProp('controls', this.setControls)
|
||||
.addStringProp('id', this.setId)
|
||||
.addBooleanProp('muted', this.setMuted)
|
||||
.addBooleanProp('paused', this.setPaused)
|
||||
.addNumberProp('progressUpdateInterval', this.setProgressUpdateInterval)
|
||||
.addBooleanProp('rate', this.setRate)
|
||||
.addBooleanProp('repeat', this.setRepeat)
|
||||
.addNumberProp('resizeMode', this.setResizeMode)
|
||||
.addNumberProp('seek', this.setSeek)
|
||||
.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
|
||||
}
|
||||
|
||||
setControls(view: RCTVideo, value: boolean) {
|
||||
view.controls = value;
|
||||
}
|
||||
|
||||
setId(view: RCTVideo, value: string) {
|
||||
view.id = value;
|
||||
}
|
||||
|
||||
setMuted(view: RCTVideo, value: boolean) {
|
||||
view.muted = value;
|
||||
}
|
||||
|
||||
setPaused(view: RCTVideo, value: boolean) {
|
||||
view.paused = value;
|
||||
}
|
||||
|
||||
setRate(view: RCTVideo, value: number) {
|
||||
view.rate = value;
|
||||
}
|
||||
|
||||
setRepeat(view: RCTVideo, value: boolean) {
|
||||
view.repeat = value;
|
||||
}
|
||||
|
||||
setResizeMode(view: RCTVideo, value: number) {
|
||||
view.resizeMode = value;
|
||||
}
|
||||
|
||||
setSeek(view: RCTVideo, value: number) {
|
||||
view.seek = value;
|
||||
}
|
||||
|
||||
setSource(view: RCTVideo, value: VideoSource) {
|
||||
view.source = value;
|
||||
}
|
||||
|
||||
constantsToExport() {
|
||||
return { ...resizeModes };
|
||||
}
|
||||
}
|
||||
|
||||
export default RCTVideoManager;
|
@ -1,3 +0,0 @@
|
||||
// @flow
|
||||
|
||||
module.exports = require('./RCTVideoManager');
|
@ -1,8 +0,0 @@
|
||||
// @flow
|
||||
|
||||
export default {
|
||||
ScaleNone: 0,
|
||||
ScaleToFill: 1,
|
||||
ScaleAspectFit: 2,
|
||||
ScaleAspectFill: 3,
|
||||
};
|
10
dom/types.js
10
dom/types.js
@ -1,10 +0,0 @@
|
||||
// @flow
|
||||
|
||||
export type VideoSource = {
|
||||
uri: string,
|
||||
type: string,
|
||||
mainVer: number,
|
||||
patchVer: number,
|
||||
isNetwork: boolean,
|
||||
isAsset: boolean,
|
||||
};
|
@ -13,10 +13,8 @@
|
||||
"@react-native-community/eslint-config": "^0.0.5",
|
||||
"eslint": "^6.5.1",
|
||||
"react": "16.9.0",
|
||||
"react-dom": "16.9.0",
|
||||
"react-hot-loader": "^4.12.19",
|
||||
"react-native": "0.61.5",
|
||||
"react-native-dom": "^0.5.0",
|
||||
"react-native-windows": "^0.61.0-0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -31,7 +29,6 @@
|
||||
},
|
||||
"files": [
|
||||
"android",
|
||||
"dom",
|
||||
"ios",
|
||||
"windows",
|
||||
"FilterType.js",
|
||||
|
Loading…
Reference in New Issue
Block a user