Remove DOM support. Closes #2647

This commit is contained in:
Eran Hammer 2022-06-22 07:51:02 +00:00
parent 691a11dc4e
commit 879572edd3
8 changed files with 2 additions and 489 deletions

44
API.md
View File

@ -5,7 +5,6 @@
* [tvOS](#tvos-installation) * [tvOS](#tvos-installation)
* [Android](#android-installation) * [Android](#android-installation)
* [Windows](#windows-installation) * [Windows](#windows-installation)
* [react-native-dom](#react-native-dom-installation)
* [Examples](#examples) * [Examples](#examples)
* [iOS](#ios-example) * [iOS](#ios-example)
* [Android](#android-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_. 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 ## Examples
Run `yarn xbasic install` before running any of the examples. Run `yarn xbasic install` before running any of the examples.
@ -298,7 +269,7 @@ var styles = StyleSheet.create({
|[backBufferDurationMs](#backBufferDurationMs)| Android | |[backBufferDurationMs](#backBufferDurationMs)| Android |
|[bufferConfig](#bufferconfig)|Android| |[bufferConfig](#bufferconfig)|Android|
|[contentStartTime](#contentStartTime)| Android | |[contentStartTime](#contentStartTime)| Android |
|[controls](#controls)|Android, iOS, react-native-dom| |[controls](#controls)|Android, iOS|
|[currentPlaybackTime](#currentPlaybackTime)|Android| |[currentPlaybackTime](#currentPlaybackTime)|Android|
|[disableFocus](#disableFocus)|Android, iOS| |[disableFocus](#disableFocus)|Android, iOS|
|[disableDisconnectError](#disableDisconnectError)|Android| |[disableDisconnectError](#disableDisconnectError)|Android|
@ -309,7 +280,6 @@ var styles = StyleSheet.create({
|[fullscreenOrientation](#fullscreenorientation)|iOS| |[fullscreenOrientation](#fullscreenorientation)|iOS|
|[headers](#headers)|Android| |[headers](#headers)|Android|
|[hideShutterView](#hideshutterview)|Android| |[hideShutterView](#hideshutterview)|Android|
|[id](#id)|react-native-dom|
|[ignoreSilentSwitch](#ignoresilentswitch)|iOS| |[ignoreSilentSwitch](#ignoresilentswitch)|iOS|
|[maxBitRate](#maxbitrate)|Android, iOS| |[maxBitRate](#maxbitrate)|Android, iOS|
|[minLoadRetryCount](#minLoadRetryCount)|Android| |[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]. 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 #### disableFocus
Determines whether video audio should override background music/audio in Android devices. 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 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 #### ignoreSilentSwitch
Controls the iOS silent switch behavior Controls the iOS silent switch behavior
* **"inherit" (default)** - Use the default AVPlayer behavior * **"inherit" (default)** - Use the default AVPlayer behavior

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -1,3 +0,0 @@
// @flow
module.exports = require('./RCTVideoManager');

View File

@ -1,8 +0,0 @@
// @flow
export default {
ScaleNone: 0,
ScaleToFill: 1,
ScaleAspectFit: 2,
ScaleAspectFill: 3,
};

View File

@ -1,10 +0,0 @@
// @flow
export type VideoSource = {
uri: string,
type: string,
mainVer: number,
patchVer: number,
isNetwork: boolean,
isAsset: boolean,
};

View File

@ -13,10 +13,8 @@
"@react-native-community/eslint-config": "^0.0.5", "@react-native-community/eslint-config": "^0.0.5",
"eslint": "^6.5.1", "eslint": "^6.5.1",
"react": "16.9.0", "react": "16.9.0",
"react-dom": "16.9.0",
"react-hot-loader": "^4.12.19", "react-hot-loader": "^4.12.19",
"react-native": "0.61.5", "react-native": "0.61.5",
"react-native-dom": "^0.5.0",
"react-native-windows": "^0.61.0-0" "react-native-windows": "^0.61.0-0"
}, },
"dependencies": { "dependencies": {
@ -31,7 +29,6 @@
}, },
"files": [ "files": [
"android", "android",
"dom",
"ios", "ios",
"windows", "windows",
"FilterType.js", "FilterType.js",