react-native-theoplayer 2.6.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/android/build.gradle +1 -1
- package/android/local/com/theoplayer/android-connector/mediasession/5.2.0-local/mediasession-5.2.0-local.aar +0 -0
- package/android/local/com/theoplayer/android-connector/mediasession/{4.12.0-local/mediasession-4.12.0-local.pom → 5.2.0-local/mediasession-5.2.0-local.pom} +1 -1
- package/android/local/com/theoplayer/android-connector/mediasession/maven-metadata-local.xml +4 -4
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt +1 -1
- package/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt +36 -20
- package/android/src/main/java/com/theoplayer/media/CustomMediaButtonReceiver.kt +25 -0
- package/android/src/main/java/com/theoplayer/{audio → media}/MediaNotificationBuilder.kt +1 -1
- package/android/src/main/java/com/theoplayer/{audio → media}/MediaPlaybackService.kt +8 -3
- package/android/src/main/java/com/theoplayer/source/SourceAdapter.kt +12 -0
- package/android/src/main/java/com/theoplayer/track/TrackListAdapter.kt +17 -13
- package/android/src/main/java/com/theoplayer/util/ViewResolver.kt +9 -1
- package/ios/THEOplayerRCTDebug.swift +3 -3
- package/ios/THEOplayerRCTMainEventHandler.swift +59 -59
- package/ios/THEOplayerRCTMediaTrackEventHandler.swift +18 -18
- package/ios/THEOplayerRCTNetworkUtils.swift +1 -1
- package/ios/THEOplayerRCTPlayerAPI.swift +14 -14
- package/ios/THEOplayerRCTPrintUtils.swift +16 -0
- package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +6 -6
- package/ios/THEOplayerRCTTextTrackEventHandler.swift +21 -21
- package/ios/THEOplayerRCTView.swift +29 -29
- package/ios/ads/THEOplayerRCTAdsAPI+DAI.swift +6 -6
- package/ios/ads/THEOplayerRCTAdsAPI.swift +13 -13
- package/ios/ads/THEOplayerRCTAdsEventHandler.swift +27 -27
- package/ios/ads/THEOplayerRCTSourceDescriptionBuilder+Ads.swift +5 -5
- package/ios/backgroundAudio/THEOplayerRCTNowPlayingManager.swift +16 -15
- package/ios/backgroundAudio/THEOplayerRCTRemoteCommandsManager.swift +16 -16
- package/ios/casting/THEOplayerRCTCastAPI+Airplay.swift +6 -6
- package/ios/casting/THEOplayerRCTCastAPI+Chromecast.swift +10 -10
- package/ios/casting/THEOplayerRCTCastAPI.swift +1 -1
- package/ios/casting/THEOplayerRCTCastEventHandler.swift +11 -11
- package/ios/contentprotection/THEOplayerRCTContentProtectionAPI.swift +1 -1
- package/ios/pip/THEOplayerRCTPipControlsManager.swift +1 -1
- package/lib/commonjs/api/source/dash/DashPlaybackConfiguration.js.map +1 -1
- package/lib/commonjs/api/track/TextTrack.js.map +1 -1
- package/lib/commonjs/internal/adapter/THEOplayerAdapter.js +58 -10
- package/lib/commonjs/internal/adapter/THEOplayerAdapter.js.map +1 -1
- package/lib/commonjs/internal/adapter/web/FullscreenAPI.js +41 -0
- package/lib/commonjs/internal/adapter/web/FullscreenAPI.js.map +1 -0
- package/lib/commonjs/internal/adapter/web/WebPresentationModeManager.js +45 -39
- package/lib/commonjs/internal/adapter/web/WebPresentationModeManager.js.map +1 -1
- package/lib/commonjs/internal/utils/CommonUtils.js +10 -0
- package/lib/commonjs/internal/utils/CommonUtils.js.map +1 -0
- package/lib/commonjs/ui/components/seekbar/thumbnail/Urlpolyfill.web.js +4 -11
- package/lib/commonjs/ui/components/seekbar/thumbnail/Urlpolyfill.web.js.map +1 -1
- package/lib/module/api/source/dash/DashPlaybackConfiguration.js.map +1 -1
- package/lib/module/api/track/TextTrack.js.map +1 -1
- package/lib/module/internal/adapter/THEOplayerAdapter.js +59 -11
- package/lib/module/internal/adapter/THEOplayerAdapter.js.map +1 -1
- package/lib/module/internal/adapter/web/FullscreenAPI.js +34 -0
- package/lib/module/internal/adapter/web/FullscreenAPI.js.map +1 -0
- package/lib/module/internal/adapter/web/WebPresentationModeManager.js +45 -39
- package/lib/module/internal/adapter/web/WebPresentationModeManager.js.map +1 -1
- package/lib/module/internal/utils/CommonUtils.js +4 -0
- package/lib/module/internal/utils/CommonUtils.js.map +1 -0
- package/lib/module/ui/components/seekbar/thumbnail/Urlpolyfill.web.js +3 -2
- package/lib/module/ui/components/seekbar/thumbnail/Urlpolyfill.web.js.map +1 -1
- package/lib/typescript/api/source/dash/DashPlaybackConfiguration.d.ts +52 -0
- package/lib/typescript/api/track/TextTrack.d.ts +2 -2
- package/lib/typescript/internal/adapter/THEOplayerAdapter.d.ts +3 -0
- package/lib/typescript/internal/adapter/web/FullscreenAPI.d.ts +9 -0
- package/lib/typescript/internal/utils/CommonUtils.d.ts +1 -0
- package/lib/typescript/ui/components/seekbar/thumbnail/Urlpolyfill.web.d.ts +8 -1
- package/package.json +1 -1
- package/src/api/source/dash/DashPlaybackConfiguration.ts +56 -0
- package/src/api/track/TextTrack.ts +2 -2
- package/src/internal/adapter/THEOplayerAdapter.ts +63 -10
- package/src/internal/adapter/web/FullscreenAPI.ts +59 -0
- package/src/internal/adapter/web/WebPresentationModeManager.ts +29 -22
- package/src/internal/utils/CommonUtils.ts +3 -0
- package/src/ui/components/seekbar/thumbnail/Urlpolyfill.web.ts +3 -2
- package/android/local/com/theoplayer/android-connector/mediasession/4.12.0-local/mediasession-4.12.0-local.aar +0 -0
- package/lib/commonjs/web/platform/BrowserDetection.js +0 -34
- package/lib/commonjs/web/platform/BrowserDetection.js.map +0 -1
- package/lib/module/web/platform/BrowserDetection.js +0 -27
- package/lib/module/web/platform/BrowserDetection.js.map +0 -1
- package/lib/typescript/web/platform/BrowserDetection.d.ts +0 -23
- package/src/web/platform/BrowserDetection.ts +0 -38
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const fullscreenAPI = (() => {
|
|
2
|
+
if (!document) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// browser API methods
|
|
7
|
+
// map approach from Screenful.js - https://github.com/sindresorhus/screenfull.js
|
|
8
|
+
const apiMap = [
|
|
9
|
+
// Spec: https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
|
|
10
|
+
['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],
|
|
11
|
+
// WebKit
|
|
12
|
+
['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'],
|
|
13
|
+
// Old WebKit (Safari 5.1)
|
|
14
|
+
['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'],
|
|
15
|
+
// Mozilla
|
|
16
|
+
['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'],
|
|
17
|
+
// Microsoft
|
|
18
|
+
['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']];
|
|
19
|
+
for (const browserMap of apiMap) {
|
|
20
|
+
// check for exitFullscreen function
|
|
21
|
+
if (browserMap[1] in document) {
|
|
22
|
+
return {
|
|
23
|
+
requestFullscreen_: browserMap[0],
|
|
24
|
+
exitFullscreen_: browserMap[1],
|
|
25
|
+
fullscreenElement_: browserMap[2],
|
|
26
|
+
fullscreenEnabled_: browserMap[3],
|
|
27
|
+
fullscreenchange_: browserMap[4],
|
|
28
|
+
fullscreenerror_: browserMap[5]
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
})();
|
|
34
|
+
//# sourceMappingURL=FullscreenAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fullscreenAPI","document","apiMap","browserMap","requestFullscreen_","exitFullscreen_","fullscreenElement_","fullscreenEnabled_","fullscreenchange_","fullscreenerror_","undefined"],"sources":["FullscreenAPI.ts"],"sourcesContent":["export interface FullscreenAPIMap {\n requestFullscreen_: 'requestFullscreen';\n exitFullscreen_: 'exitFullscreen';\n fullscreenElement_: 'fullscreenElement';\n fullscreenEnabled_: 'fullscreenEnabled';\n fullscreenchange_: 'fullscreenchange';\n fullscreenerror_: 'fullscreenerror';\n}\n\nexport const fullscreenAPI: FullscreenAPIMap | undefined = (() => {\n if (!document) {\n return;\n }\n\n // browser API methods\n // map approach from Screenful.js - https://github.com/sindresorhus/screenfull.js\n const apiMap: string[][] = [\n // Spec: https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html\n ['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],\n // WebKit\n [\n 'webkitRequestFullscreen',\n 'webkitExitFullscreen',\n 'webkitFullscreenElement',\n 'webkitFullscreenEnabled',\n 'webkitfullscreenchange',\n 'webkitfullscreenerror'\n ],\n // Old WebKit (Safari 5.1)\n [\n 'webkitRequestFullScreen',\n 'webkitCancelFullScreen',\n 'webkitCurrentFullScreenElement',\n 'webkitCancelFullScreen',\n 'webkitfullscreenchange',\n 'webkitfullscreenerror'\n ],\n // Mozilla\n ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'],\n // Microsoft\n ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']\n ];\n\n for (const browserMap of apiMap) {\n // check for exitFullscreen function\n if (browserMap[1] in document) {\n return {\n requestFullscreen_: browserMap[0],\n exitFullscreen_: browserMap[1],\n fullscreenElement_: browserMap[2],\n fullscreenEnabled_: browserMap[3],\n fullscreenchange_: browserMap[4],\n fullscreenerror_: browserMap[5]\n } as FullscreenAPIMap;\n }\n }\n\n return undefined;\n})();\n"],"mappings":"AASA,OAAO,MAAMA,aAA2C,GAAG,CAAC,MAAM;EAChE,IAAI,CAACC,QAAQ,EAAE;IACb;EACF;;EAEA;EACA;EACA,MAAMC,MAAkB,GAAG;EACzB;EACA,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,CAAC;EACxH;EACA,CACE,yBAAyB,EACzB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,CACxB;EACD;EACA,CACE,yBAAyB,EACzB,wBAAwB,EACxB,gCAAgC,EAChC,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,CACxB;EACD;EACA,CAAC,sBAAsB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;EAC5I;EACA,CAAC,qBAAqB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,CACrI;EAED,KAAK,MAAMC,UAAU,IAAID,MAAM,EAAE;IAC/B;IACA,IAAIC,UAAU,CAAC,CAAC,CAAC,IAAIF,QAAQ,EAAE;MAC7B,OAAO;QACLG,kBAAkB,EAAED,UAAU,CAAC,CAAC,CAAC;QACjCE,eAAe,EAAEF,UAAU,CAAC,CAAC,CAAC;QAC9BG,kBAAkB,EAAEH,UAAU,CAAC,CAAC,CAAC;QACjCI,kBAAkB,EAAEJ,UAAU,CAAC,CAAC,CAAC;QACjCK,iBAAiB,EAAEL,UAAU,CAAC,CAAC,CAAC;QAChCM,gBAAgB,EAAEN,UAAU,CAAC,CAAC;MAChC,CAAC;IACH;EACF;EAEA,OAAOO,SAAS;AAClB,CAAC,GAAG"}
|
|
@@ -3,13 +3,30 @@ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typ
|
|
|
3
3
|
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
4
4
|
import { PresentationMode } from 'react-native-theoplayer';
|
|
5
5
|
import { DefaultPresentationModeChangeEvent } from '../event/PlayerEvents';
|
|
6
|
-
import {
|
|
6
|
+
import { fullscreenAPI } from './FullscreenAPI';
|
|
7
|
+
import { noOp } from '../../utils/CommonUtils';
|
|
7
8
|
export class WebPresentationModeManager {
|
|
8
9
|
constructor(player, eventForwarder) {
|
|
9
10
|
_defineProperty(this, "_player", void 0);
|
|
10
11
|
_defineProperty(this, "_presentationMode", PresentationMode.inline);
|
|
11
12
|
_defineProperty(this, "_element", undefined);
|
|
12
13
|
_defineProperty(this, "_eventForwarder", void 0);
|
|
14
|
+
_defineProperty(this, "updatePresentationMode", () => {
|
|
15
|
+
// detect new presentation mode
|
|
16
|
+
let newPresentationMode = PresentationMode.inline;
|
|
17
|
+
if (fullscreenAPI !== undefined && document[fullscreenAPI.fullscreenElement_] !== null) {
|
|
18
|
+
newPresentationMode = PresentationMode.fullscreen;
|
|
19
|
+
} else if (document.pictureInPictureElement !== null) {
|
|
20
|
+
newPresentationMode = PresentationMode.pip;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// when changed, notify by dispatching presentationModeChange event
|
|
24
|
+
const previousPresentationMode = this._presentationMode;
|
|
25
|
+
if (newPresentationMode !== previousPresentationMode) {
|
|
26
|
+
this._presentationMode = newPresentationMode;
|
|
27
|
+
this._eventForwarder.dispatchEvent(new DefaultPresentationModeChangeEvent(this._presentationMode, previousPresentationMode));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
13
30
|
this._player = player;
|
|
14
31
|
this._eventForwarder = eventForwarder;
|
|
15
32
|
}
|
|
@@ -21,36 +38,40 @@ export class WebPresentationModeManager {
|
|
|
21
38
|
return;
|
|
22
39
|
}
|
|
23
40
|
this.prepareForPresentationModeChanges();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if ( /*browserDetection.IS_IOS_ && */browserDetection.IS_SAFARI_) {
|
|
27
|
-
if (presentationMode === PresentationMode.fullscreen) {
|
|
28
|
-
var _this$_element, _this$_element$webkit;
|
|
29
|
-
(_this$_element = this._element) === null || _this$_element === void 0 ? void 0 : (_this$_element$webkit = _this$_element.webkitEnterFullscreen) === null || _this$_element$webkit === void 0 ? void 0 : _this$_element$webkit.call(_this$_element);
|
|
30
|
-
} else if (presentationMode === PresentationMode.pip) {
|
|
31
|
-
var _this$_element2, _this$_element2$webki;
|
|
32
|
-
(_this$_element2 = this._element) === null || _this$_element2 === void 0 ? void 0 : (_this$_element2$webki = _this$_element2.webkitSetPresentationMode) === null || _this$_element2$webki === void 0 ? void 0 : _this$_element2$webki.call(_this$_element2, PresentationMode.pip);
|
|
33
|
-
} else {
|
|
34
|
-
var _this$_element3, _this$_element3$webki;
|
|
35
|
-
(_this$_element3 = this._element) === null || _this$_element3 === void 0 ? void 0 : (_this$_element3$webki = _this$_element3.webkitSetPresentationMode) === null || _this$_element3$webki === void 0 ? void 0 : _this$_element3$webki.call(_this$_element3, PresentationMode.inline);
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
// other web-platformsyarn
|
|
39
|
-
|
|
41
|
+
if (fullscreenAPI !== undefined) {
|
|
42
|
+
// All other browsers
|
|
40
43
|
if (presentationMode === PresentationMode.fullscreen) {
|
|
41
44
|
const appElement = document.getElementById('app');
|
|
42
|
-
|
|
45
|
+
const promise = appElement[fullscreenAPI.requestFullscreen_]();
|
|
46
|
+
if (promise && promise.then) {
|
|
47
|
+
promise.then(noOp, noOp);
|
|
48
|
+
}
|
|
43
49
|
} else if (presentationMode === PresentationMode.pip) {
|
|
44
|
-
var _this$
|
|
45
|
-
void ((_this$
|
|
50
|
+
var _this$_element, _this$_element$reques;
|
|
51
|
+
void ((_this$_element = this._element) === null || _this$_element === void 0 ? void 0 : (_this$_element$reques = _this$_element.requestPictureInPicture) === null || _this$_element$reques === void 0 ? void 0 : _this$_element$reques.call(_this$_element));
|
|
46
52
|
} else {
|
|
47
53
|
if (this._presentationMode === PresentationMode.fullscreen) {
|
|
48
|
-
|
|
54
|
+
const promise = document[fullscreenAPI.exitFullscreen_]();
|
|
55
|
+
if (promise && promise.then) {
|
|
56
|
+
promise.then(noOp, noOp);
|
|
57
|
+
}
|
|
49
58
|
}
|
|
50
59
|
if (this._presentationMode === PresentationMode.pip) {
|
|
51
60
|
void document.exitPictureInPicture();
|
|
52
61
|
}
|
|
53
62
|
}
|
|
63
|
+
} else {
|
|
64
|
+
// iOS Safari doesn't properly support fullscreen, use native fullscreen instead
|
|
65
|
+
if (presentationMode === PresentationMode.fullscreen) {
|
|
66
|
+
var _this$_element2, _this$_element2$webki;
|
|
67
|
+
(_this$_element2 = this._element) === null || _this$_element2 === void 0 ? void 0 : (_this$_element2$webki = _this$_element2.webkitEnterFullscreen) === null || _this$_element2$webki === void 0 ? void 0 : _this$_element2$webki.call(_this$_element2);
|
|
68
|
+
} else if (presentationMode === PresentationMode.pip) {
|
|
69
|
+
var _this$_element3, _this$_element3$webki;
|
|
70
|
+
(_this$_element3 = this._element) === null || _this$_element3 === void 0 ? void 0 : (_this$_element3$webki = _this$_element3.webkitSetPresentationMode) === null || _this$_element3$webki === void 0 ? void 0 : _this$_element3$webki.call(_this$_element3, PresentationMode.pip);
|
|
71
|
+
} else {
|
|
72
|
+
var _this$_element4, _this$_element4$webki;
|
|
73
|
+
(_this$_element4 = this._element) === null || _this$_element4 === void 0 ? void 0 : (_this$_element4$webki = _this$_element4.webkitSetPresentationMode) === null || _this$_element4$webki === void 0 ? void 0 : _this$_element4$webki.call(_this$_element4, PresentationMode.inline);
|
|
74
|
+
}
|
|
54
75
|
}
|
|
55
76
|
}
|
|
56
77
|
prepareForPresentationModeChanges() {
|
|
@@ -70,24 +91,9 @@ export class WebPresentationModeManager {
|
|
|
70
91
|
};
|
|
71
92
|
}
|
|
72
93
|
// listen for fullscreen updates on document
|
|
73
|
-
|
|
74
|
-
this.updatePresentationMode
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
updatePresentationMode() {
|
|
78
|
-
// detect new presentation mode
|
|
79
|
-
let newPresentationMode = PresentationMode.inline;
|
|
80
|
-
if (document.fullscreenElement !== null) {
|
|
81
|
-
newPresentationMode = PresentationMode.fullscreen;
|
|
82
|
-
} else if (document.pictureInPictureElement !== null) {
|
|
83
|
-
newPresentationMode = PresentationMode.pip;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// when changed, notify by dispatching presentationModeChange event
|
|
87
|
-
const previousPresentationMode = this._presentationMode;
|
|
88
|
-
if (newPresentationMode !== previousPresentationMode) {
|
|
89
|
-
this._presentationMode = newPresentationMode;
|
|
90
|
-
this._eventForwarder.dispatchEvent(new DefaultPresentationModeChangeEvent(this._presentationMode, previousPresentationMode));
|
|
94
|
+
if (fullscreenAPI !== undefined) {
|
|
95
|
+
document.addEventListener(fullscreenAPI.fullscreenchange_, this.updatePresentationMode);
|
|
96
|
+
document.addEventListener(fullscreenAPI.fullscreenerror_, this.updatePresentationMode);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["PresentationMode","DefaultPresentationModeChangeEvent","
|
|
1
|
+
{"version":3,"names":["PresentationMode","DefaultPresentationModeChangeEvent","fullscreenAPI","noOp","WebPresentationModeManager","constructor","player","eventForwarder","_defineProperty","inline","undefined","newPresentationMode","document","fullscreenElement_","fullscreen","pictureInPictureElement","pip","previousPresentationMode","_presentationMode","_eventForwarder","dispatchEvent","_player","presentationMode","prepareForPresentationModeChanges","appElement","getElementById","promise","requestFullscreen_","then","_this$_element","_this$_element$reques","_element","requestPictureInPicture","call","exitFullscreen_","exitPictureInPicture","_this$_element2","_this$_element2$webki","webkitEnterFullscreen","_this$_element3","_this$_element3$webki","webkitSetPresentationMode","_this$_element4","_this$_element4$webki","elements","element","children","Array","from","tagName","attributes","getNamedItem","onenterpictureinpicture","updatePresentationMode","onleavepictureinpicture","addEventListener","fullscreenchange_","fullscreenerror_"],"sources":["WebPresentationModeManager.ts"],"sourcesContent":["import type { PlayerEventMap } from 'react-native-theoplayer';\nimport { PresentationMode } from 'react-native-theoplayer';\nimport type * as THEOplayerWeb from 'theoplayer';\nimport { DefaultPresentationModeChangeEvent } from '../event/PlayerEvents';\nimport type { DefaultEventDispatcher } from '../event/DefaultEventDispatcher';\nimport { fullscreenAPI } from './FullscreenAPI';\nimport { noOp } from '../../utils/CommonUtils';\n\nexport class WebPresentationModeManager {\n private readonly _player: THEOplayerWeb.ChromelessPlayer;\n private _presentationMode: PresentationMode = PresentationMode.inline;\n private _element: HTMLVideoElement | undefined = undefined;\n private _eventForwarder: DefaultEventDispatcher<PlayerEventMap>;\n\n constructor(player: THEOplayerWeb.ChromelessPlayer, eventForwarder: DefaultEventDispatcher<PlayerEventMap>) {\n this._player = player;\n this._eventForwarder = eventForwarder;\n }\n\n get presentationMode(): PresentationMode {\n return this._presentationMode;\n }\n\n set presentationMode(presentationMode: PresentationMode) {\n if (presentationMode === this._presentationMode) {\n return;\n }\n\n this.prepareForPresentationModeChanges();\n\n if (fullscreenAPI !== undefined) {\n // All other browsers\n if (presentationMode === PresentationMode.fullscreen) {\n const appElement = document.getElementById('app')!;\n const promise = appElement[fullscreenAPI.requestFullscreen_]();\n if (promise && promise.then) {\n promise.then(noOp, noOp);\n }\n } else if (presentationMode === PresentationMode.pip) {\n void this._element?.requestPictureInPicture?.();\n } else {\n if (this._presentationMode === PresentationMode.fullscreen) {\n const promise = document[fullscreenAPI.exitFullscreen_]();\n if (promise && promise.then) {\n promise.then(noOp, noOp);\n }\n }\n if (this._presentationMode === PresentationMode.pip) {\n void document.exitPictureInPicture();\n }\n }\n } else {\n // iOS Safari doesn't properly support fullscreen, use native fullscreen instead\n if (presentationMode === PresentationMode.fullscreen) {\n this._element?.webkitEnterFullscreen?.();\n } else if (presentationMode === PresentationMode.pip) {\n this._element?.webkitSetPresentationMode?.(PresentationMode.pip);\n } else {\n this._element?.webkitSetPresentationMode?.(PresentationMode.inline);\n }\n }\n }\n\n private prepareForPresentationModeChanges() {\n const elements = this._player.element.children;\n for (const element of Array.from(elements)) {\n if (element.tagName === 'VIDEO' && element.attributes.getNamedItem('src') !== null) {\n this._element = element as HTMLVideoElement;\n }\n }\n // listen for pip updates on element\n if (this._element !== undefined) {\n this._element.onenterpictureinpicture = () => {\n this.updatePresentationMode();\n };\n this._element.onleavepictureinpicture = () => {\n this.updatePresentationMode();\n };\n }\n // listen for fullscreen updates on document\n if (fullscreenAPI !== undefined) {\n document.addEventListener(fullscreenAPI.fullscreenchange_, this.updatePresentationMode);\n document.addEventListener(fullscreenAPI.fullscreenerror_, this.updatePresentationMode);\n }\n }\n\n private updatePresentationMode = () => {\n // detect new presentation mode\n let newPresentationMode: PresentationMode = PresentationMode.inline;\n if (fullscreenAPI !== undefined && document[fullscreenAPI.fullscreenElement_] !== null) {\n newPresentationMode = PresentationMode.fullscreen;\n } else if (document.pictureInPictureElement !== null) {\n newPresentationMode = PresentationMode.pip;\n }\n\n // when changed, notify by dispatching presentationModeChange event\n const previousPresentationMode = this._presentationMode;\n if (newPresentationMode !== previousPresentationMode) {\n this._presentationMode = newPresentationMode;\n this._eventForwarder.dispatchEvent(new DefaultPresentationModeChangeEvent(this._presentationMode, previousPresentationMode));\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["noOp"],"sources":["CommonUtils.ts"],"sourcesContent":["export function noOp(): void {\n return;\n}\n"],"mappings":"AAAA,OAAO,SAASA,IAAIA,CAAA,EAAS;EAC3B;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["Urlpolyfill.web.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"names":["URL","global"],"sources":["Urlpolyfill.web.ts"],"sourcesContent":["import 'url-polyfill';\nconst URL = global.URL;\nexport { URL };\n"],"mappings":"AAAA,OAAO,cAAc;AACrB,MAAMA,GAAG,GAAGC,MAAM,CAACD,GAAG;AACtB,SAASA,GAAG"}
|
|
@@ -24,6 +24,8 @@ export interface DashPlaybackConfiguration {
|
|
|
24
24
|
* Whether to seamlessly switch between DASH periods.
|
|
25
25
|
*
|
|
26
26
|
* @remarks
|
|
27
|
+
* <br/> - Available on Web only.
|
|
28
|
+
*
|
|
27
29
|
* The player supports two strategies for handling a switch between two periods in an MPEG-DASH stream:
|
|
28
30
|
* <br/> - <strong>Seamless</strong>: Once the player is done buffering the current period, it immediately starts buffering the next period.
|
|
29
31
|
* This requires that the current period and the next period have compatible codecs and content protection, or that the platform
|
|
@@ -41,4 +43,54 @@ export interface DashPlaybackConfiguration {
|
|
|
41
43
|
* @defaultValue `'auto'`
|
|
42
44
|
*/
|
|
43
45
|
useSeamlessPeriodSwitch?: SeamlessPeriodSwitchStrategy;
|
|
46
|
+
/**
|
|
47
|
+
* (Experimental) Whether the timescales of the media data need to be shifted,
|
|
48
|
+
* in order to work around platform-specific issues on certain smart TV platforms.
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* <br/> - Available since v4.1.0.
|
|
52
|
+
* <br/> - Available on Web only.
|
|
53
|
+
* <br/> - On certain smart TV platforms (such as Tizen 2), playback issues may arise when
|
|
54
|
+
* the timescale of the media data changes across periods or discontinuities.
|
|
55
|
+
* In that case, the player may need to shift all the timescales first,
|
|
56
|
+
* however this strategy may not work for all streams.
|
|
57
|
+
* <br/> - When not specified, the player will decide whether or not to shift timescales
|
|
58
|
+
* based on the platform.
|
|
59
|
+
* <br/> - This is an experimental option. It should only be used after consulting with
|
|
60
|
+
* THEOplayer support or engineering.
|
|
61
|
+
*/
|
|
62
|
+
needsTimescaleShifting?: boolean | null;
|
|
63
|
+
/**
|
|
64
|
+
* (Experimental) The desired timescale to which the media data should be shifted.
|
|
65
|
+
*
|
|
66
|
+
* @remarks
|
|
67
|
+
* <br/> - Available since v4.11.0.
|
|
68
|
+
* <br/> - Available on Web only.
|
|
69
|
+
* <br/> - When specified, if the player decides to shift the timescale (see {@link DashPlaybackConfiguration.needsTimescaleShifting}), the timescale will be set to the
|
|
70
|
+
* given desired timescale.
|
|
71
|
+
* <br/> - When not specified, if the player decides to shift timescale, the player will decide the timescale to which it should shift.
|
|
72
|
+
* <br/> - This is an experimental option. It should only be used after consulting with
|
|
73
|
+
* THEOplayer support or engineering.
|
|
74
|
+
*/
|
|
75
|
+
desiredTimescale?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Whether the player should try to force the seek on period switching to realign video and audio.
|
|
78
|
+
*
|
|
79
|
+
* @internal
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* <br/> - Available on Web only.
|
|
83
|
+
*/
|
|
84
|
+
forceSeekToSynchronize?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* (Experimental) Force the player to ignore the availability window of individual segments in the MPD,
|
|
87
|
+
* and instead consider every listed segment to be immediately available.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* <br/> - Available since v5.2.0.
|
|
91
|
+
* <br/> - Available on Web and Android.
|
|
92
|
+
* <br/> - This only applies to livestreams (with `<MPD type="dynamic">`).
|
|
93
|
+
* <br/> - This only applies to streams that use `<SegmentTimeline>`.
|
|
94
|
+
*/
|
|
95
|
+
ignoreAvailabilityWindow?: boolean;
|
|
44
96
|
}
|
|
@@ -95,6 +95,6 @@ export declare function filterThumbnailTracks(textTracks: TextTrack[] | undefine
|
|
|
95
95
|
*/
|
|
96
96
|
export declare function isThumbnailTrack(textTrack: TextTrack | undefined): boolean;
|
|
97
97
|
export declare function hasTextTrackCue(textTrack: TextTrack, cue: TextTrackCue): boolean;
|
|
98
|
-
export declare function removeTextTrackCue(textTrack
|
|
99
|
-
export declare function addTextTrackCue(textTrack
|
|
98
|
+
export declare function removeTextTrackCue(textTrack?: TextTrack, cue?: TextTrackCue): void;
|
|
99
|
+
export declare function addTextTrackCue(textTrack?: TextTrack, cue?: TextTrackCue): void;
|
|
100
100
|
export declare function findTextTrackByUid(textTracks: TextTrack[], uid: number): TextTrack | undefined;
|
|
@@ -12,6 +12,7 @@ export declare class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEven
|
|
|
12
12
|
private readonly _textTrackStyleAdapter;
|
|
13
13
|
constructor(view: THEOplayerView, initialState?: NativePlayerState);
|
|
14
14
|
private onSourceChange;
|
|
15
|
+
private hasValidSource;
|
|
15
16
|
private onPause;
|
|
16
17
|
private onPlaying;
|
|
17
18
|
private onPresentationModeChange;
|
|
@@ -22,11 +23,13 @@ export declare class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEven
|
|
|
22
23
|
private onSeeking;
|
|
23
24
|
private onSeeked;
|
|
24
25
|
private onProgress;
|
|
26
|
+
private onTextTrack;
|
|
25
27
|
private onTextTrackList;
|
|
26
28
|
private onMediaTrack;
|
|
27
29
|
private onMediaTrackList;
|
|
28
30
|
get abr(): ABRConfiguration | undefined;
|
|
29
31
|
get ads(): AdsAPI;
|
|
32
|
+
private applyAutoplay;
|
|
30
33
|
set autoplay(autoplay: boolean);
|
|
31
34
|
get autoplay(): boolean;
|
|
32
35
|
set preload(type: PreloadType);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface FullscreenAPIMap {
|
|
2
|
+
requestFullscreen_: 'requestFullscreen';
|
|
3
|
+
exitFullscreen_: 'exitFullscreen';
|
|
4
|
+
fullscreenElement_: 'fullscreenElement';
|
|
5
|
+
fullscreenEnabled_: 'fullscreenEnabled';
|
|
6
|
+
fullscreenchange_: 'fullscreenchange';
|
|
7
|
+
fullscreenerror_: 'fullscreenerror';
|
|
8
|
+
}
|
|
9
|
+
export declare const fullscreenAPI: FullscreenAPIMap | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function noOp(): void;
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import 'url-polyfill';
|
|
2
|
+
declare const URL: {
|
|
3
|
+
new (url: string | URL, base?: string | URL | undefined): URL;
|
|
4
|
+
prototype: URL;
|
|
5
|
+
createObjectURL(obj: Blob | MediaSource): string;
|
|
6
|
+
revokeObjectURL(url: string): void;
|
|
7
|
+
};
|
|
8
|
+
export { URL };
|
package/package.json
CHANGED
|
@@ -25,6 +25,8 @@ export interface DashPlaybackConfiguration {
|
|
|
25
25
|
* Whether to seamlessly switch between DASH periods.
|
|
26
26
|
*
|
|
27
27
|
* @remarks
|
|
28
|
+
* <br/> - Available on Web only.
|
|
29
|
+
*
|
|
28
30
|
* The player supports two strategies for handling a switch between two periods in an MPEG-DASH stream:
|
|
29
31
|
* <br/> - <strong>Seamless</strong>: Once the player is done buffering the current period, it immediately starts buffering the next period.
|
|
30
32
|
* This requires that the current period and the next period have compatible codecs and content protection, or that the platform
|
|
@@ -42,4 +44,58 @@ export interface DashPlaybackConfiguration {
|
|
|
42
44
|
* @defaultValue `'auto'`
|
|
43
45
|
*/
|
|
44
46
|
useSeamlessPeriodSwitch?: SeamlessPeriodSwitchStrategy;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* (Experimental) Whether the timescales of the media data need to be shifted,
|
|
50
|
+
* in order to work around platform-specific issues on certain smart TV platforms.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* <br/> - Available since v4.1.0.
|
|
54
|
+
* <br/> - Available on Web only.
|
|
55
|
+
* <br/> - On certain smart TV platforms (such as Tizen 2), playback issues may arise when
|
|
56
|
+
* the timescale of the media data changes across periods or discontinuities.
|
|
57
|
+
* In that case, the player may need to shift all the timescales first,
|
|
58
|
+
* however this strategy may not work for all streams.
|
|
59
|
+
* <br/> - When not specified, the player will decide whether or not to shift timescales
|
|
60
|
+
* based on the platform.
|
|
61
|
+
* <br/> - This is an experimental option. It should only be used after consulting with
|
|
62
|
+
* THEOplayer support or engineering.
|
|
63
|
+
*/
|
|
64
|
+
needsTimescaleShifting?: boolean | null;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* (Experimental) The desired timescale to which the media data should be shifted.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* <br/> - Available since v4.11.0.
|
|
71
|
+
* <br/> - Available on Web only.
|
|
72
|
+
* <br/> - When specified, if the player decides to shift the timescale (see {@link DashPlaybackConfiguration.needsTimescaleShifting}), the timescale will be set to the
|
|
73
|
+
* given desired timescale.
|
|
74
|
+
* <br/> - When not specified, if the player decides to shift timescale, the player will decide the timescale to which it should shift.
|
|
75
|
+
* <br/> - This is an experimental option. It should only be used after consulting with
|
|
76
|
+
* THEOplayer support or engineering.
|
|
77
|
+
*/
|
|
78
|
+
desiredTimescale?: number;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Whether the player should try to force the seek on period switching to realign video and audio.
|
|
82
|
+
*
|
|
83
|
+
* @internal
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* <br/> - Available on Web only.
|
|
87
|
+
*/
|
|
88
|
+
forceSeekToSynchronize?: boolean;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* (Experimental) Force the player to ignore the availability window of individual segments in the MPD,
|
|
92
|
+
* and instead consider every listed segment to be immediately available.
|
|
93
|
+
*
|
|
94
|
+
* @remarks
|
|
95
|
+
* <br/> - Available since v5.2.0.
|
|
96
|
+
* <br/> - Available on Web and Android.
|
|
97
|
+
* <br/> - This only applies to livestreams (with `<MPD type="dynamic">`).
|
|
98
|
+
* <br/> - This only applies to streams that use `<SegmentTimeline>`.
|
|
99
|
+
*/
|
|
100
|
+
ignoreAvailabilityWindow?: boolean;
|
|
45
101
|
}
|
|
@@ -121,13 +121,13 @@ export function hasTextTrackCue(textTrack: TextTrack, cue: TextTrackCue): boolea
|
|
|
121
121
|
return !!(textTrack.cues && cue && textTrack.cues.find((c) => cue.uid === c.uid));
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
export function removeTextTrackCue(textTrack
|
|
124
|
+
export function removeTextTrackCue(textTrack?: TextTrack, cue?: TextTrackCue) {
|
|
125
125
|
if (textTrack && textTrack.cues && cue && !hasTextTrackCue(textTrack, cue)) {
|
|
126
126
|
textTrack.cues = textTrack.cues.filter((c) => c.uid !== cue.uid);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
export function addTextTrackCue(textTrack
|
|
130
|
+
export function addTextTrackCue(textTrack?: TextTrack, cue?: TextTrackCue) {
|
|
131
131
|
if (textTrack && textTrack.cues && cue && !hasTextTrackCue(textTrack, cue)) {
|
|
132
132
|
textTrack.cues.push(cue);
|
|
133
133
|
}
|
|
@@ -16,21 +16,26 @@ import type {
|
|
|
16
16
|
RateChangeEvent,
|
|
17
17
|
SourceDescription,
|
|
18
18
|
TextTrack,
|
|
19
|
+
TextTrackEvent,
|
|
19
20
|
TextTrackListEvent,
|
|
20
21
|
THEOplayer,
|
|
21
22
|
THEOplayerView,
|
|
22
23
|
TimeUpdateEvent,
|
|
23
24
|
} from 'react-native-theoplayer';
|
|
24
25
|
import {
|
|
26
|
+
addTextTrackCue,
|
|
25
27
|
addTrack,
|
|
26
28
|
AspectRatio,
|
|
27
29
|
findMediaTrackByUid,
|
|
30
|
+
findTextTrackByUid,
|
|
28
31
|
MediaTrackEventType,
|
|
29
32
|
MediaTrackType,
|
|
30
33
|
PlayerEventType,
|
|
31
34
|
PreloadType,
|
|
32
35
|
PresentationMode,
|
|
36
|
+
removeTextTrackCue,
|
|
33
37
|
removeTrack,
|
|
38
|
+
TextTrackEventType,
|
|
34
39
|
TextTrackMode,
|
|
35
40
|
TextTrackStyle,
|
|
36
41
|
TrackListEventType,
|
|
@@ -97,19 +102,20 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
97
102
|
this.addEventListener(PlayerEventType.SEEKED, this.onSeeked);
|
|
98
103
|
this.addEventListener(PlayerEventType.PROGRESS, this.onProgress);
|
|
99
104
|
this.addEventListener(PlayerEventType.TEXT_TRACK_LIST, this.onTextTrackList);
|
|
105
|
+
this.addEventListener(PlayerEventType.TEXT_TRACK, this.onTextTrack);
|
|
100
106
|
this.addEventListener(PlayerEventType.MEDIA_TRACK, this.onMediaTrack);
|
|
101
107
|
this.addEventListener(PlayerEventType.MEDIA_TRACK_LIST, this.onMediaTrackList);
|
|
102
108
|
this.addEventListener(PlayerEventType.PRESENTATIONMODE_CHANGE, this.onPresentationModeChange);
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
private onSourceChange = () => {
|
|
106
|
-
|
|
107
|
-
this.play();
|
|
108
|
-
} else {
|
|
109
|
-
this.pause();
|
|
110
|
-
}
|
|
112
|
+
this.applyAutoplay();
|
|
111
113
|
};
|
|
112
114
|
|
|
115
|
+
private hasValidSource(): boolean {
|
|
116
|
+
return this._state.source !== undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
113
119
|
private onPause = () => {
|
|
114
120
|
this._state.paused = true;
|
|
115
121
|
};
|
|
@@ -157,6 +163,19 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
157
163
|
this._state.buffered = event.buffered?.sort((a, b) => a.end - b.end);
|
|
158
164
|
};
|
|
159
165
|
|
|
166
|
+
private onTextTrack = (event: TextTrackEvent) => {
|
|
167
|
+
const { subType, cue, trackUid } = event;
|
|
168
|
+
const track = findTextTrackByUid(this._state.textTracks, trackUid);
|
|
169
|
+
switch (subType) {
|
|
170
|
+
case TextTrackEventType.ADD_CUE:
|
|
171
|
+
addTextTrackCue(track, cue);
|
|
172
|
+
break;
|
|
173
|
+
case TextTrackEventType.REMOVE_CUE:
|
|
174
|
+
removeTextTrackCue(track, cue);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
160
179
|
private onTextTrackList = (event: TextTrackListEvent) => {
|
|
161
180
|
const { subType, track } = event;
|
|
162
181
|
switch (subType) {
|
|
@@ -225,9 +244,23 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
225
244
|
return this._adsAdapter;
|
|
226
245
|
}
|
|
227
246
|
|
|
247
|
+
private applyAutoplay() {
|
|
248
|
+
if (!this.hasValidSource()) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (this._state.autoplay) {
|
|
252
|
+
this.play();
|
|
253
|
+
} else {
|
|
254
|
+
this.pause();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
228
258
|
set autoplay(autoplay: boolean) {
|
|
229
259
|
this._state.autoplay = autoplay;
|
|
230
|
-
|
|
260
|
+
|
|
261
|
+
// Apply autoplay in case a source was already set.
|
|
262
|
+
// If autoplay is changed before setting a source, `onSourceChange` applies autoplay.
|
|
263
|
+
this.applyAutoplay();
|
|
231
264
|
}
|
|
232
265
|
|
|
233
266
|
get autoplay(): boolean {
|
|
@@ -265,6 +298,10 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
265
298
|
}
|
|
266
299
|
|
|
267
300
|
set currentTime(currentTime: number) {
|
|
301
|
+
if (!this.hasValidSource()) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
268
305
|
if (isNaN(currentTime)) {
|
|
269
306
|
return;
|
|
270
307
|
}
|
|
@@ -345,6 +382,9 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
345
382
|
}
|
|
346
383
|
|
|
347
384
|
set selectedAudioTrack(trackUid: number | undefined) {
|
|
385
|
+
if (!this.hasValidSource()) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
348
388
|
this._state.selectedAudioTrack = trackUid;
|
|
349
389
|
NativeModules.PlayerModule.setSelectedAudioTrack(this._view.nativeHandle, trackUid || -1);
|
|
350
390
|
}
|
|
@@ -358,6 +398,9 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
358
398
|
}
|
|
359
399
|
|
|
360
400
|
set selectedVideoTrack(trackUid: number | undefined) {
|
|
401
|
+
if (!this.hasValidSource()) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
361
404
|
this._state.selectedVideoTrack = trackUid;
|
|
362
405
|
this._state.targetVideoQuality = undefined;
|
|
363
406
|
NativeModules.PlayerModule.setSelectedVideoTrack(this._view.nativeHandle, trackUid || -1);
|
|
@@ -372,6 +415,9 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
372
415
|
}
|
|
373
416
|
|
|
374
417
|
set selectedTextTrack(trackUid: number | undefined) {
|
|
418
|
+
if (!this.hasValidSource()) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
375
421
|
this._state.selectedTextTrack = trackUid;
|
|
376
422
|
this.textTracks.forEach((track) => {
|
|
377
423
|
if (track.uid === trackUid) {
|
|
@@ -417,6 +463,9 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
417
463
|
}
|
|
418
464
|
|
|
419
465
|
set targetVideoQuality(target: number | number[] | undefined) {
|
|
466
|
+
if (!this.hasValidSource()) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
420
469
|
// Always pass an array for targetVideoQuality.
|
|
421
470
|
this._state.targetVideoQuality = !target ? [] : Array.isArray(target) ? target : [target];
|
|
422
471
|
|
|
@@ -447,13 +496,17 @@ export class THEOplayerAdapter extends DefaultEventDispatcher<PlayerEventMap> im
|
|
|
447
496
|
}
|
|
448
497
|
|
|
449
498
|
pause(): void {
|
|
450
|
-
this.
|
|
451
|
-
|
|
499
|
+
if (this.hasValidSource()) {
|
|
500
|
+
this._state.paused = true;
|
|
501
|
+
NativeModules.PlayerModule.setPaused(this._view.nativeHandle, true);
|
|
502
|
+
}
|
|
452
503
|
}
|
|
453
504
|
|
|
454
505
|
play(): void {
|
|
455
|
-
this.
|
|
456
|
-
|
|
506
|
+
if (this.hasValidSource()) {
|
|
507
|
+
this._state.paused = false;
|
|
508
|
+
NativeModules.PlayerModule.setPaused(this._view.nativeHandle, false);
|
|
509
|
+
}
|
|
457
510
|
}
|
|
458
511
|
|
|
459
512
|
get nativeHandle(): NativeHandleType {
|