Last active
September 17, 2021 13:17
-
-
Save nleush/19ff66a1deadfa74003f41ebae7946ac to your computer and use it in GitHub Desktop.
Rich media embeds for React Native - https://iframely.com/docs/react-native
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use as | |
// <EmbedWebView | |
// html = ".. html codes you get from Iframely .." | |
// /> | |
import React, { Component } from 'react'; | |
import { WebView, View } from 'react-native'; | |
// will receive height data from WebView | |
function parseMessage(data) { | |
try { | |
data = JSON.parse(data); | |
} catch(ex) { | |
data = null; | |
} | |
return data; | |
} | |
// script to inject into WebView | |
const script = ` | |
function getHeight(el) { | |
var elHeight = el.scrollHeight; | |
var docHeight = document.body.scrollHeight; | |
var height; | |
if (elHeight < docHeight && elHeight > 0) { | |
height = elHeight; | |
} else { | |
height = docHeight; | |
} | |
return height; | |
} | |
var height = 0; | |
var wrapper = document.body.firstChild; | |
function updateSize() { | |
var h = getHeight(wrapper); | |
if (h !== height) { | |
height = h; | |
window.ReactNativeWebView.postMessage(JSON.stringify({"height": height})); | |
} | |
} | |
window.addEventListener("message", function() { | |
// Listen to all messages to trigger additional size checks. | |
// Includes Iframely resize message, native pings from Twitter & et al | |
// You can also try checking sizes periodically if you have issues | |
// see https://github.com/react-native-community/react-native-webview/issues/154 | |
updateSize(); | |
}); | |
updateSize(); | |
`; | |
// prevent webview scaling & add Iframely default styles and embed.js script as necessary | |
const head = ` | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | |
<style> | |
.iframely-responsive { | |
top: 0; left: 0; width: 100%; height: 0; | |
position: relative; padding-bottom: 56.25%; | |
} | |
.iframely-responsive>* { | |
top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0; | |
} | |
</style> | |
`; | |
// please load embed.js script off your custom CDN, if you use it | |
const embedJsScript = '<script src="https://cdn.iframe.ly/embed.js"></script>'; | |
export default class EmbedWebView extends Component { | |
constructor(props) { | |
super(props); | |
const paddingBottomMatch = this.props.html.match(/padding-bottom:\s* ([\d\.]+)%/); | |
const paddingBottom = paddingBottomMatch && parseFloat(paddingBottomMatch[1]); | |
const needScript = this.props.html.match(/app=1/) || this.props.html.match(/data-iframely-url=/); | |
this.html = '<head>' + head + (needScript ? embedJsScript : '') + '</head><body>' + this.props.html + '</body>'; | |
this.state = { | |
height: 0, | |
aspectRatio: paddingBottom && (100 / paddingBottom) || 16/9 | |
}; | |
this.onWebViewMessage = this.onWebViewMessage.bind(this); | |
} | |
onWebViewMessage(e) { | |
var message = parseMessage(e.nativeEvent.data); | |
if (message && message.height) { | |
this.setState({ | |
height: message.height, | |
aspectRatio: null | |
}); | |
} | |
} | |
render() { | |
return ( | |
<View aspectRatio={this.state.aspectRatio}> | |
<WebView | |
// 'useWebKit' adds support of postMessage for iOS WebView, available from the 0.57 release | |
useWebKit={true} | |
scrollEnabled={false} | |
onMessage={this.onWebViewMessage} | |
source={{html: this.html}} | |
style={{height: this.state.height}} | |
javaScriptEnabled={true} | |
injectedJavaScript={script} | |
// add more props as you deem necessary, e.g. allowsInlineMediaPlayback, mediaPlaybackRequiresUserAction | |
/> | |
</View> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment