Skip to content

Commit

Permalink
[RNMobile] Update Sandbox component (#49663)
Browse files Browse the repository at this point in the history
* Add ref forwarding

* Fix typo

* Enable non touch play events

* Allow parent to register window event listeners

* Catch calling non-functions

---------

Co-authored-by: jhnstn <jhnstn@pm.me>
  • Loading branch information
jhnstn and jhnstn committed Apr 10, 2023
1 parent e5dc1bb commit acfff0e
Showing 1 changed file with 70 additions and 36 deletions.
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 );
})();
`;

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 } ) );
});`;
} );

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 {
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

1 comment on commit acfff0e

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in acfff0e.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4661098376
📝 Reported issues:

Please sign in to comment.