diff --git a/packages/edit-post/src/index.native.js b/packages/edit-post/src/index.native.js index 13cf9ce44efe3c..8efafa0714d633 100644 --- a/packages/edit-post/src/index.native.js +++ b/packages/edit-post/src/index.native.js @@ -3,23 +3,31 @@ */ import '@wordpress/core-data'; import '@wordpress/block-editor'; -import '@wordpress/editor'; import '@wordpress/viewport'; import '@wordpress/notices'; import { registerCoreBlocks } from '@wordpress/block-library'; import '@wordpress/format-library'; +import { render } from '@wordpress/element'; /** * Internal dependencies */ import './store'; +import Editor from './editor'; let blocksRegistered = false; /** - * Initializes the Editor. + * Initializes the Editor and returns a componentProvider + * that can be registered with `AppRegistry.registerComponent` */ -export function initializeEditor() { +export function initializeEditor( { + id, + initialHtml, + initialTitle, + initialHtmlModeEnabled, + postType, +} ) { if ( blocksRegistered ) { return; } @@ -27,6 +35,14 @@ export function initializeEditor() { // register and setup blocks registerCoreBlocks(); blocksRegistered = true; -} -export { default as Editor } from './editor'; + render( + , + id + ); +} diff --git a/packages/element/src/react-platform.native.js b/packages/element/src/react-platform.native.js index e69de29bb2d1d6..ab2e8bd32fdc6f 100644 --- a/packages/element/src/react-platform.native.js +++ b/packages/element/src/react-platform.native.js @@ -0,0 +1,44 @@ +/** + * External dependencies + */ +import { AppRegistry } from 'react-native'; +import { isEmpty, omit } from 'lodash'; + +/** + * WordPress dependencies + */ +import { applyFilters, doAction } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import { cloneElement } from './react'; + +const render = ( element, id ) => + AppRegistry.registerComponent( id, () => ( propsFromNative ) => { + const nativeProps = omit( propsFromNative || {}, [ 'rootTag' ] ); + + doAction( 'native.render', nativeProps ); + + // if we have not received props from a parent native app + // just render the element as it is + if ( isEmpty( nativeProps ) ) { + return element; + } + + // Otherwise overwrite the existing props using a filter hook + const filteredProps = applyFilters( + 'native.block_editor_props', + nativeProps + ); + + return cloneElement( element, filteredProps ); + } ); + +/** + * Render a given element on Native. + * This actually returns a componentProvider that can be registered with `AppRegistry.registerComponent` + * + * @param {WPElement} element Element to render. + */ +export { render }; diff --git a/packages/react-native-editor/index.js b/packages/react-native-editor/index.js index a3c56418ddeb4c..1417cc0322975d 100644 --- a/packages/react-native-editor/index.js +++ b/packages/react-native-editor/index.js @@ -1,6 +1,4 @@ /** * Internal dependencies */ -import { registerApp } from './src'; - -registerApp(); +import './src'; diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index 5429f1da2c61db..ce574de4d5d987 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -26,6 +26,8 @@ "node": ">=10", "npm": ">=6.9" }, + "main": "src/index.js", + "react-native": "src/index", "dependencies": { "@babel/runtime": "^7.7.7", "@react-native-community/slider": "git+https://github.com/wordpress-mobile/react-native-slider.git#5ad284d92b8d886e366445bf215be741ed53ddc6", diff --git a/packages/react-native-editor/src/index.js b/packages/react-native-editor/src/index.js index 19a144395396b5..919ed86a727d0e 100644 --- a/packages/react-native-editor/src/index.js +++ b/packages/react-native-editor/src/index.js @@ -1,16 +1,7 @@ /** * External dependencies */ -import { AppRegistry, I18nManager } from 'react-native'; -/** - * WordPress dependencies - */ -import { Component } from '@wordpress/element'; - -/** - * WordPress dependencies - */ -import { setLocaleData } from '@wordpress/i18n'; +import { I18nManager } from 'react-native'; /** * Internal dependencies @@ -20,6 +11,14 @@ import { getTranslation } from '../i18n-cache'; import initialHtml from './initial-html'; import setupApiFetch from './api-fetch-setup'; +const reactNativeSetup = () => { + // Disable warnings as they disrupt the user experience in dev mode + // eslint-disable-next-line no-console + console.disableYellowBox = true; + + I18nManager.forceRTL( false ); // Change to `true` to debug RTL layout easily. +}; + const gutenbergSetup = () => { const wpData = require( '@wordpress/data' ); @@ -27,9 +26,51 @@ const gutenbergSetup = () => { const userId = 1; const storageKey = 'WP_DATA_USER_' + userId; wpData.use( wpData.plugins.persistence, { storageKey } ); + + setupApiFetch(); + + const isHermes = () => global.HermesInternal !== null; + // eslint-disable-next-line no-console + console.log( 'Hermes is: ' + isHermes() ); + + setupInitHooks(); + + const initializeEditor = require( '@wordpress/edit-post' ).initializeEditor; + initializeEditor( { + id: 'gutenberg', + initialHtml, + initialHtmlModeEnabled: false, + initialTitle: 'Welcome to Gutenberg!', + postType: 'post' + } ); +}; + +const setupInitHooks = () => { + const wpHooks = require( '@wordpress/hooks' ); + + wpHooks.doAction( 'native.setup-init-hooks' ); + + wpHooks.addAction( 'native.render', 'core/react-native-editor', ( props ) => { + setupLocale( props.locale, props.translations ); + } ); + + // Map native props to Editor props + wpHooks.addFilter( 'native.block_editor_props', 'core/react-native-editor', ( { + initialData, + initialTitle, + initialHtmlModeEnabled, + postType, + } ) => ( { + initialHtml: initialData, + initialHtmlModeEnabled, + initialTitle, + postType, + } ) ); }; const setupLocale = ( locale, extraTranslations ) => { + const setLocaleData = require( '@wordpress/i18n' ).setLocaleData; + I18nManager.forceRTL( false ); // Change to `true` to debug RTL layout easily. let gutenbergTranslations = getTranslation( locale ); @@ -51,51 +92,5 @@ const setupLocale = ( locale, extraTranslations ) => { } }; -export class RootComponent extends Component { - constructor( props ) { - super( props ); - setupLocale( props.locale, props.translations ); - setupApiFetch(); - require( '@wordpress/edit-post' ).initializeEditor(); - - const isHermes = () => global.HermesInternal !== null; - // eslint-disable-next-line no-console - console.log( 'Hermes is: ' + isHermes() ); - } - - render() { - const { initialHtmlModeEnabled } = this.props; - let initialData = this.props.initialData; - let initialTitle = this.props.initialTitle; - let postType = this.props.postType; - - if ( initialData === undefined && __DEV__ ) { - initialData = initialHtml; - } - if ( initialTitle === undefined ) { - initialTitle = 'Welcome to Gutenberg!'; - } - if ( postType === undefined ) { - postType = 'post'; - } - const Editor = require( '@wordpress/edit-post' ).Editor; - return ( - - ); - } -} - -export function registerApp() { - // Disable warnings as they disrupt the user experience in dev mode - // eslint-disable-next-line no-console - console.disableYellowBox = true; - - gutenbergSetup(); - - AppRegistry.registerComponent( 'gutenberg', () => RootComponent ); -} +reactNativeSetup(); +gutenbergSetup();