Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RNMobile] Update Sandbox component #49663

Merged
merged 5 commits into from
Apr 10, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 70 additions & 36 deletions packages/components/src/sandbox/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
useRef,
useState,
useEffect,
forwardRef,
useCallback,
} from '@wordpress/element';
import { usePreferredColorScheme } from '@wordpress/compose';

Expand Down Expand Up @@ -98,7 +100,6 @@ const observeAndResizeJS = `
// get an DOM mutations for that, so do the resize when the window is resized, too.
window.addEventListener( 'resize', sendResize, true );
window.addEventListener( 'orientationchange', sendResize, true );
widow.addEventListener( 'click', sendResize, true );
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
})();
`;

Expand Down Expand Up @@ -171,20 +172,23 @@ const style = `

const EMPTY_ARRAY = [];

function Sandbox( {
containerStyle,
customJS,
html = '',
lang = 'en',
providerUrl = '',
scripts = EMPTY_ARRAY,
styles = EMPTY_ARRAY,
title = '',
type,
url,
} ) {
const Sandbox = forwardRef( function Sandbox(
{
containerStyle,
customJS,
html = '',
lang = 'en',
providerUrl = '',
scripts = EMPTY_ARRAY,
styles = EMPTY_ARRAY,
title = '',
type,
url,
onWindowEvents = {},
},
ref
) {
const colorScheme = usePreferredColorScheme();
const ref = useRef();
const [ height, setHeight ] = useState( 0 );
const [ contentHtml, setContentHtml ] = useState( getHtmlDoc() );

Expand Down Expand Up @@ -239,6 +243,21 @@ function Sandbox( {
return '<!DOCTYPE html>' + renderToString( htmlDoc );
}

const getInjectedJavaScript = useCallback( () => {
// Allow parent to override the resize observers with prop.customJS (legacy support)
let injectedJS = customJS || observeAndResizeJS;

// Add any event listeners that were passed in.
Object.keys( onWindowEvents ).forEach( ( eventType ) => {
injectedJS += `
window.addEventListener( '${ eventType }', function( event ) {
window.ReactNativeWebView.postMessage( JSON.stringify( { type: '${ eventType }', ...event.data } ) );
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
});`;
} );

return injectedJS;
}, [ customJS, onWindowEvents ] );

function updateContentHtml( forceRerender = false ) {
const newContentHtml = getHtmlDoc();

Expand All @@ -253,25 +272,6 @@ function Sandbox( {
}
}

function checkMessageForResize( event ) {
// Attempt to parse the message data as JSON if passed as string.
let data = event.nativeEvent.data || {};

if ( 'string' === typeof data ) {
try {
data = JSON.parse( data );
} catch ( e ) {}
}

// Update the state only if the message is formatted as we expect,
// i.e. as an object with a 'resize' action.
if ( 'resize' !== data.action ) {
return;
}

setHeight( data.height );
}

function getSizeStyle() {
const contentHeight = Math.ceil( height );

Expand All @@ -282,6 +282,39 @@ function Sandbox( {
setIsLandscape( dimensions.window.width >= dimensions.window.height );
}

const onMessage = useCallback(
( message ) => {
let data = message?.nativeEvent?.data;

try {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I omitted the existing string check. The try is robust enough to handle non strings.

data = JSON.parse( data );
} catch ( e ) {
return;
}

// check for resize event
if ( 'resize' === data?.action ) {
setHeight( data.height );
}

// Forward the event to parent event listeners
Object.keys( onWindowEvents ).forEach( ( eventType ) => {
if ( data?.type === eventType ) {
try {
onWindowEvents[ eventType ]( data );
} catch ( e ) {
// eslint-disable-next-line no-console
console.warn(
`Error handling event ${ eventType }`,
e
);
}
}
} );
},
[ onWindowEvents ]
);

useEffect( () => {
const dimensionsChangeSubscription = Dimensions.addEventListener(
'change',
Expand Down Expand Up @@ -314,7 +347,7 @@ function Sandbox( {
sandboxStyles[ 'sandbox-webview__container' ],
containerStyle,
] }
injectedJavaScript={ customJS || observeAndResizeJS }
injectedJavaScript={ getInjectedJavaScript() }
key={ key }
ref={ ref }
source={ { baseUrl: providerUrl, html: contentHtml } }
Expand All @@ -326,14 +359,15 @@ function Sandbox( {
getSizeStyle(),
Platform.isAndroid && workaroundStyles.webView,
] }
onMessage={ checkMessageForResize }
onMessage={ onMessage }
scrollEnabled={ false }
setBuiltInZoomControls={ false }
showsHorizontalScrollIndicator={ false }
showsVerticalScrollIndicator={ false }
mediaPlaybackRequiresUserAction={ false }
/>
);
}
} );

const workaroundStyles = StyleSheet.create( {
webView: {
Expand Down