diff --git a/packages/edit-post/src/index.native.js b/packages/edit-post/src/index.native.js index 13cf9ce44efe3c..1f72de810287e8 100644 --- a/packages/edit-post/src/index.native.js +++ b/packages/edit-post/src/index.native.js @@ -3,23 +3,30 @@ */ 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( { + initialHtml, + initialTitle, + initialHtmlModeEnabled, + postType, +} ) { if ( blocksRegistered ) { return; } @@ -27,6 +34,13 @@ export function initializeEditor() { // register and setup blocks registerCoreBlocks(); blocksRegistered = true; -} -export { default as Editor } from './editor'; + return render( + + ); +} diff --git a/packages/element/src/react-platform.native.js b/packages/element/src/react-platform.native.js index e69de29bb2d1d6..6259ad7e610d12 100644 --- a/packages/element/src/react-platform.native.js +++ b/packages/element/src/react-platform.native.js @@ -0,0 +1,54 @@ +/** + * External dependencies + */ +import { isEmpty, omit } from 'lodash'; + +/** + * WordPress dependencies + */ +import { applyFilters, doAction } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import { cloneElement, useEffect } from './react'; + +const render = ( element ) => ( propsFromNative ) => { + useEffect( () => { + doAction( 'native.init', propsFromNative ); + }, [] ); + + useEffect( () => { + doAction( 'native.render', propsFromNative ); + } ); + + // if we have not received props from a parent native app + // just render the element as it is + if ( isEmpty( omit( propsFromNative, [ 'rootTag' ] ) ) ) { + return element; + } + + // Otherwise overwrite the existing props using a filter hook + let filteredProps = null; + + useEffect( () => { + filteredProps = applyFilters( + 'native.block_editor_props', + propsFromNative + ); + }, [] ); + + if ( ! filteredProps ) { + return null; + } + + return cloneElement( element, filteredProps ); +}; + +/** + * Renders a given element into the target DOM node. + * + * @param {WPElement} element Element to render. + * @param {HTMLElement} target DOM node into which element should be rendered. + */ +export { render }; diff --git a/packages/react-native-editor/index.js b/packages/react-native-editor/index.js index 7d33caa42e3718..efd78a15fe6ae1 100644 --- a/packages/react-native-editor/index.js +++ b/packages/react-native-editor/index.js @@ -4,6 +4,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 2528f6e492c5ce..23363d705f06a9 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 fe2bb686e7582a..7e6cfbdd2e19a9 100644 --- a/packages/react-native-editor/src/index.js +++ b/packages/react-native-editor/src/index.js @@ -1,19 +1,7 @@ /** * External dependencies - * - * @format */ - -/** - * External dependencies - */ -import { AppRegistry, I18nManager } from 'react-native'; -import { Component } from '@wordpress/element'; - -/** - * WordPress dependencies - */ -import { setLocaleData } from '@wordpress/i18n'; +import {AppRegistry, I18nManager} from 'react-native'; /** * Internal dependencies @@ -23,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' ); @@ -30,9 +26,49 @@ const gutenbergSetup = () => { const userId = 1; const storageKey = 'WP_DATA_USER_' + userId; wpData.use( wpData.plugins.persistence, { storageKey } ); + + setupInitHooks(); + + const initializeEditor = require( '@wordpress/edit-post' ).initializeEditor; + return initializeEditor( { + 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.init', 'core/react-native-editor', ( props ) => { + setupLocale( 'fr', props.translations ); + setupApiFetch(); + + const isHermes = () => global.HermesInternal !== null; + // eslint-disable-next-line no-console + console.log( 'Hermes is: ' + isHermes() ); + } ); + + // 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 ); @@ -50,51 +86,6 @@ 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(); +reactNativeSetup(); - AppRegistry.registerComponent( 'gutenberg', () => RootComponent ); -} +AppRegistry.registerComponent( 'gutenberg', gutenbergSetup );