Skip to content

Commit 64591eb

Browse files
authored
fix "embed not allowed" errors (#108)
* add remote html source * update url * t * test * update HTML * add flag for local html string * remove use of "yarn" in prepare script * read and minify iframe HTML
1 parent 0564f65 commit 64591eb

File tree

8 files changed

+2861
-2170
lines changed

8 files changed

+2861
-2170
lines changed

iframe.html

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />
5+
<style>
6+
body {
7+
margin: 0;
8+
}
9+
.container {
10+
position: relative;
11+
width: 100%;
12+
height: 0;
13+
padding-bottom: 56.25%;
14+
}
15+
.video {
16+
position: absolute;
17+
top: 0;
18+
left: 0;
19+
width: 100%;
20+
height: 100%;
21+
}
22+
</style>
23+
</head>
24+
<body>
25+
<div class="container">
26+
<div class="video" id="player"></div>
27+
</div>
28+
29+
<script>
30+
const parsedUrl = new URL(window.location.href);
31+
const UrlQueryData = parsedUrl.searchParams.get('data');
32+
const {
33+
end,
34+
list,
35+
color,
36+
start,
37+
rel_s,
38+
loop_s,
39+
listType,
40+
playerLang,
41+
playlist,
42+
videoId_s,
43+
controls_s,
44+
cc_lang_pref_s,
45+
contentScale_s,
46+
modestbranding_s,
47+
iv_load_policy,
48+
preventFullScreen_s,
49+
showClosedCaptions_s,
50+
} = JSON.parse(UrlQueryData);
51+
52+
function sendMessageToRN(msg) {
53+
window.ReactNativeWebView.postMessage(JSON.stringify(msg));
54+
}
55+
56+
var tag = document.createElement('script');
57+
tag.src = 'https://www.youtube.com/iframe_api';
58+
var firstScriptTag = document.getElementsByTagName('script')[0];
59+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
60+
61+
var player;
62+
function onYouTubeIframeAPIReady() {
63+
player = new YT.Player('player', {
64+
width: '1000',
65+
height: '1000',
66+
videoId: videoId_s,
67+
playerVars: {
68+
end: end,
69+
rel: rel_s,
70+
list: list,
71+
color: color,
72+
loop: loop_s,
73+
start: start,
74+
playsinline: 1,
75+
hl: playerLang,
76+
playlist: playlist,
77+
listType: listType,
78+
controls: controls_s,
79+
fs: preventFullScreen_s,
80+
cc_lang_pref: cc_lang_pref_s,
81+
iv_load_policy: iv_load_policy,
82+
modestbranding: modestbranding_s,
83+
cc_load_policy: showClosedCaptions_s,
84+
},
85+
events: {
86+
onReady: onPlayerReady,
87+
onError: onPlayerError,
88+
onStateChange: onPlayerStateChange,
89+
onPlaybackRateChange: onPlaybackRateChange,
90+
onPlaybackQualityChange: onPlaybackQualityChange,
91+
},
92+
});
93+
}
94+
95+
function onPlayerError(event) {
96+
sendMessageToRN({eventType: 'playerError', data: event.data});
97+
}
98+
99+
function onPlaybackRateChange(event) {
100+
sendMessageToRN({eventType: 'playbackRateChange', data: event.data});
101+
}
102+
103+
function onPlaybackQualityChange(event) {
104+
sendMessageToRN({eventType: 'playerQualityChange', data: event.data});
105+
}
106+
107+
function onPlayerReady(event) {
108+
sendMessageToRN({eventType: 'playerReady'});
109+
}
110+
111+
function onPlayerStateChange(event) {
112+
sendMessageToRN({eventType: 'playerStateChange', data: event.data});
113+
}
114+
115+
var isFullScreen = false;
116+
function onFullScreenChange() {
117+
isFullScreen =
118+
document.fullscreenElement ||
119+
document.msFullscreenElement ||
120+
document.mozFullScreenElement ||
121+
document.webkitFullscreenElement;
122+
123+
sendMessageToRN({
124+
eventType: 'fullScreenChange',
125+
data: Boolean(isFullScreen),
126+
});
127+
}
128+
129+
document.addEventListener('fullscreenchange', onFullScreenChange);
130+
document.addEventListener('msfullscreenchange', onFullScreenChange);
131+
document.addEventListener('mozfullscreenchange', onFullScreenChange);
132+
document.addEventListener('webkitfullscreenchange', onFullScreenChange);
133+
</script>
134+
</body>
135+
</html>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"lint": "eslint src",
99
"test": "echo \"Error: no test specified\" && exit 1",
1010
"build": "rimraf ./dist && babel src --out-dir dist",
11-
"prepare": "yarn build"
11+
"prepare": "rimraf ./dist && babel src --out-dir dist"
1212
},
1313
"repository": {
1414
"type": "git",

src/PlayerScripts.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,29 @@ export const MAIN_SCRIPT = (
110110
scale += `, maximum-scale=${contentScale_s}`;
111111
}
112112

113-
return `
113+
const safeData = {
114+
end,
115+
list,
116+
start,
117+
color,
118+
rel_s,
119+
loop_s,
120+
listType,
121+
playlist,
122+
videoId_s,
123+
controls_s,
124+
playerLang,
125+
iv_load_policy,
126+
contentScale_s,
127+
cc_lang_pref_s,
128+
modestbranding_s,
129+
preventFullScreen_s,
130+
showClosedCaptions_s,
131+
};
132+
133+
const urlEncodedJSON = encodeURI(JSON.stringify(safeData));
134+
135+
const htmlString = `
114136
<!DOCTYPE html>
115137
<html>
116138
<head>
@@ -218,4 +240,6 @@ export const MAIN_SCRIPT = (
218240
</body>
219241
</html>
220242
`;
243+
244+
return {htmlString, urlEncodedJSON};
221245
};

src/YoutubeIframe.js

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import React, {
55
forwardRef,
66
useCallback,
77
useImperativeHandle,
8+
useMemo,
89
} from 'react';
910
import {View, StyleSheet, Platform} from 'react-native';
1011
import {WebView} from './WebView';
@@ -17,6 +18,8 @@ import {
1718
PLAYER_FUNCTIONS,
1819
} from './PlayerScripts';
1920

21+
const defaultBaseUrl = 'https://lonelycpp.github.io/test/index.html';
22+
2023
const YoutubeIframe = (props, ref) => {
2124
const {
2225
height,
@@ -28,6 +31,8 @@ const YoutubeIframe = (props, ref) => {
2831
volume = 100,
2932
webViewStyle,
3033
webViewProps,
34+
useLocalHTML,
35+
baseUrlOverride,
3136
playbackRate = 1,
3237
contentScale = 1.0,
3338
onError = _err => {},
@@ -171,6 +176,39 @@ const YoutubeIframe = (props, ref) => {
171176
],
172177
);
173178

179+
const source = useMemo(() => {
180+
if (useLocalHTML) {
181+
return {
182+
html: MAIN_SCRIPT(
183+
videoId,
184+
playList,
185+
initialPlayerParams,
186+
allowWebViewZoom,
187+
contentScale,
188+
).htmlString,
189+
};
190+
}
191+
192+
const base = baseUrlOverride || defaultBaseUrl;
193+
const data = MAIN_SCRIPT(
194+
videoId,
195+
playList,
196+
initialPlayerParams,
197+
allowWebViewZoom,
198+
contentScale,
199+
).urlEncodedJSON;
200+
201+
return {uri: base + '?data=' + data};
202+
}, [
203+
videoId,
204+
playList,
205+
useLocalHTML,
206+
contentScale,
207+
baseUrlOverride,
208+
allowWebViewZoom,
209+
initialPlayerParams,
210+
]);
211+
174212
return (
175213
<View style={{height, width}}>
176214
<WebView
@@ -185,7 +223,11 @@ const YoutubeIframe = (props, ref) => {
185223
: ''
186224
}
187225
onShouldStartLoadWithRequest={request => {
188-
return request.mainDocumentURL === 'about:blank';
226+
console.log({request});
227+
return request.mainDocumentURL.startsWith(
228+
baseUrlOverride || defaultBaseUrl,
229+
);
230+
// return request.mainDocumentURL === 'about:blank';
189231
}}
190232
bounces={false}
191233
// props above this are override-able
@@ -195,20 +237,9 @@ const YoutubeIframe = (props, ref) => {
195237
// --
196238

197239
//add props that should not be allowed to be overridden below
240+
source={source}
198241
ref={webViewRef}
199242
onMessage={onWebMessage}
200-
source={{
201-
// partially allow source to be overridden
202-
...webViewProps?.source,
203-
method: 'GET',
204-
html: MAIN_SCRIPT(
205-
videoId,
206-
playList,
207-
initialPlayerParams,
208-
allowWebViewZoom,
209-
contentScale,
210-
),
211-
}}
212243
/>
213244
</View>
214245
);

website/generateIframe.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const fs = require('fs');
2+
const minify = require('html-minifier').minify;
3+
4+
const iframeContent = fs.readFileSync('../iframe.html').toString();
5+
6+
const minified = minify(iframeContent, {
7+
minifyJS: true,
8+
minifyCSS: true,
9+
removeComments: true,
10+
useShortDoctype: true,
11+
removeOptionalTags: true,
12+
collapseWhitespace: true,
13+
removeTagWhitespace: true,
14+
});
15+
16+
fs.writeFileSync('./static/iframe.html', minified);

website/package.json

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
"private": true,
55
"scripts": {
66
"docusaurus": "docusaurus",
7-
"start": "docusaurus start",
8-
"build": "docusaurus build",
9-
"swizzle": "docusaurus swizzle",
7+
"serve": "docusaurus serve",
108
"deploy": "docusaurus deploy",
11-
"serve": "docusaurus serve"
9+
"swizzle": "docusaurus swizzle",
10+
"genIframe": "node generateIframe.js",
11+
"start": "node generateIframe.js;docusaurus start",
12+
"build": "node generateIframe.js;docusaurus build"
1213
},
1314
"dependencies": {
14-
"@docusaurus/core": "^2.0.0-alpha.61",
15-
"@docusaurus/preset-classic": "^2.0.0-alpha.61",
16-
"@mdx-js/react": "^1.5.8",
15+
"@docusaurus/core": "^2.0.0-alpha.71",
16+
"@docusaurus/preset-classic": "^2.0.0-alpha.71",
17+
"@mdx-js/react": "^1.6.22",
1718
"clsx": "^1.1.1",
18-
"react": "^16.8.4",
19-
"react-dom": "^16.8.4"
19+
"html-minifier": "^4.0.0",
20+
"react": "^17.0.1",
21+
"react-dom": "^17.0.1"
2022
},
2123
"browserslist": {
2224
"production": [

website/static/iframe.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!doctypehtml><meta name="viewport"content="width=device-width,maximum-scale=1"><style>body{margin:0}.container{position:relative;width:100%;height:0;padding-bottom:56.25%}.video{position:absolute;top:0;left:0;width:100%;height:100%}</style><div class="container"><div class="video"id="player"></div></div><script>const parsedUrl=new URL(window.location.href),UrlQueryData=parsedUrl.searchParams.get("data"),{end:end,list:list,color:color,start:start,rel_s:rel_s,loop_s:loop_s,listType:listType,playerLang:playerLang,playlist:playlist,videoId_s:videoId_s,controls_s:controls_s,cc_lang_pref_s:cc_lang_pref_s,contentScale_s:contentScale_s,modestbranding_s:modestbranding_s,iv_load_policy:iv_load_policy,preventFullScreen_s:preventFullScreen_s,showClosedCaptions_s:showClosedCaptions_s}=JSON.parse(UrlQueryData);function sendMessageToRN(e){window.ReactNativeWebView.postMessage(JSON.stringify(e))}var tag=document.createElement("script");tag.src="https://www.youtube.com/iframe_api";var player,firstScriptTag=document.getElementsByTagName("script")[0];function onYouTubeIframeAPIReady(){player=new YT.Player("player",{width:"1000",height:"1000",videoId:videoId_s,playerVars:{end:end,rel:rel_s,list:list,color:color,loop:loop_s,start:start,playsinline:1,hl:playerLang,playlist:playlist,listType:listType,controls:controls_s,fs:preventFullScreen_s,cc_lang_pref:cc_lang_pref_s,iv_load_policy:iv_load_policy,modestbranding:modestbranding_s,cc_load_policy:showClosedCaptions_s},events:{onReady:onPlayerReady,onError:onPlayerError,onStateChange:onPlayerStateChange,onPlaybackRateChange:onPlaybackRateChange,onPlaybackQualityChange:onPlaybackQualityChange}})}function onPlayerError(e){sendMessageToRN({eventType:"playerError",data:e.data})}function onPlaybackRateChange(e){sendMessageToRN({eventType:"playbackRateChange",data:e.data})}function onPlaybackQualityChange(e){sendMessageToRN({eventType:"playerQualityChange",data:e.data})}function onPlayerReady(e){sendMessageToRN({eventType:"playerReady"})}function onPlayerStateChange(e){sendMessageToRN({eventType:"playerStateChange",data:e.data})}firstScriptTag.parentNode.insertBefore(tag,firstScriptTag);var isFullScreen=!1;function onFullScreenChange(){isFullScreen=document.fullscreenElement||document.msFullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement,sendMessageToRN({eventType:"fullScreenChange",data:Boolean(isFullScreen)})}document.addEventListener("fullscreenchange",onFullScreenChange),document.addEventListener("msfullscreenchange",onFullScreenChange),document.addEventListener("mozfullscreenchange",onFullScreenChange),document.addEventListener("webkitfullscreenchange",onFullScreenChange)</script>

0 commit comments

Comments
 (0)