diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index 881b011c8a08a..5965c13e26eae 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -21,7 +21,8 @@ export { default as withSpokenMessages } from './higher-order/with-spoken-messag // Mobile Components export { default as BottomSheet } from './mobile/bottom-sheet'; -export { default as Picker } from './mobile/picker'; +export { default as HTMLTextInput } from './mobile/html-text-input'; export { default as KeyboardAvoidingView } from './mobile/keyboard-avoiding-view'; export { default as KeyboardAwareFlatList } from './mobile/keyboard-aware-flat-list'; +export { default as Picker } from './mobile/picker'; export { default as ReadableContentView } from './mobile/readable-content-view'; diff --git a/packages/components/src/mobile/html-text-input/container.android.js b/packages/components/src/mobile/html-text-input/container.android.js new file mode 100644 index 0000000000000..ef62fc0178a3d --- /dev/null +++ b/packages/components/src/mobile/html-text-input/container.android.js @@ -0,0 +1,22 @@ +/** + * External dependencies + */ +import { ScrollView } from 'react-native'; + +/** + * Internal dependencies + */ +import KeyboardAvoidingView from '../keyboard-avoiding-view'; +import styles from './style.android.scss'; + +const HTMLInputContainer = ( { children, parentHeight } ) => ( + + + { children } + + +); + +HTMLInputContainer.scrollEnabled = false; + +export default HTMLInputContainer; diff --git a/packages/components/src/mobile/html-text-input/container.ios.js b/packages/components/src/mobile/html-text-input/container.ios.js new file mode 100644 index 0000000000000..a9074311f473b --- /dev/null +++ b/packages/components/src/mobile/html-text-input/container.ios.js @@ -0,0 +1,50 @@ +/** + * External dependencies + */ +import { UIManager, PanResponder } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import KeyboardAvoidingView from '../keyboard-avoiding-view'; +import styles from './style.ios.scss'; + +class HTMLInputContainer extends Component { + constructor() { + super( ...arguments ); + + this.panResponder = PanResponder.create( { + onStartShouldSetPanResponderCapture: () => true, + + onPanResponderMove: ( e, gestureState ) => { + if ( gestureState.dy > 100 && gestureState.dy < 110 ) { + //Keyboard.dismiss() and this.textInput.blur() are not working here + //They require to know the currentlyFocusedID under the hood but + //during this gesture there's no currentlyFocusedID + UIManager.blur( e.target ); + } + }, + } ); + } + + render() { + return ( + + { this.props.children } + + ); + } +} + +HTMLInputContainer.scrollEnabled = true; + +export default HTMLInputContainer; diff --git a/packages/components/src/mobile/html-text-input/index.native.js b/packages/components/src/mobile/html-text-input/index.native.js new file mode 100644 index 0000000000000..3811085213dd1 --- /dev/null +++ b/packages/components/src/mobile/html-text-input/index.native.js @@ -0,0 +1,115 @@ +/** + * External dependencies + */ +import { TextInput } from 'react-native'; + +/** + * WordPress dependencies + */ +import { Component } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { parse } from '@wordpress/blocks'; +import { withDispatch, withSelect } from '@wordpress/data'; +import { withInstanceId, compose } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import HTMLInputContainer from './container'; +import styles from './style.scss'; + +export class HTMLTextInput extends Component { + constructor() { + super( ...arguments ); + + this.edit = this.edit.bind( this ); + this.stopEditing = this.stopEditing.bind( this ); + + this.state = { + isDirty: false, + value: '', + }; + } + + static getDerivedStateFromProps( props, state ) { + if ( state.isDirty ) { + return null; + } + + return { + value: props.value, + isDirty: false, + }; + } + + componentWillUnmount() { + //TODO: Blocking main thread + this.stopEditing(); + } + + edit( html ) { + this.props.onChange( html ); + this.setState( { value: html, isDirty: true } ); + } + + stopEditing() { + if ( this.state.isDirty ) { + this.props.onPersist( this.state.value ); + this.setState( { isDirty: false } ); + } + } + + render() { + return ( + + + + + ); + } +} + +export default compose( [ + withSelect( ( select ) => { + const { + getEditedPostContent, + } = select( 'core/editor' ); + + return { + value: getEditedPostContent(), + }; + } ), + withDispatch( ( dispatch ) => { + const { resetBlocks } = dispatch( 'core/block-editor' ); + const { editPost } = dispatch( 'core/editor' ); + return { + onChange( content ) { + editPost( { content } ); + }, + onPersist( content ) { + resetBlocks( parse( content ) ); + }, + }; + } ), + withInstanceId, +] )( HTMLTextInput ); diff --git a/packages/components/src/mobile/html-text-input/style-common.native.scss b/packages/components/src/mobile/html-text-input/style-common.native.scss new file mode 100644 index 0000000000000..4db5b98516140 --- /dev/null +++ b/packages/components/src/mobile/html-text-input/style-common.native.scss @@ -0,0 +1,15 @@ +$padding: 8; +$backgroundColor: $white; +$htmlFont: $default-monospace-font; + +.keyboardAvoidingView { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; +} + +.container { + flex: 1; +} diff --git a/packages/components/src/mobile/html-text-input/style.android.scss b/packages/components/src/mobile/html-text-input/style.android.scss new file mode 100644 index 0000000000000..10594358722c3 --- /dev/null +++ b/packages/components/src/mobile/html-text-input/style.android.scss @@ -0,0 +1,23 @@ +@import "./style-common.scss"; + +.htmlView { + font-family: $htmlFont; + background-color: $backgroundColor; + padding-left: $padding; + padding-right: $padding; + padding-top: $padding; + padding-bottom: $padding + 16; +} + +.htmlViewTitle { + font-family: $htmlFont; + background-color: $backgroundColor; + padding-left: $padding; + padding-right: $padding; + padding-top: $padding; + padding-bottom: $padding; +} + +.scrollView { + flex: 1; +} diff --git a/packages/components/src/mobile/html-text-input/style.ios.scss b/packages/components/src/mobile/html-text-input/style.ios.scss new file mode 100644 index 0000000000000..8b13392b95a9a --- /dev/null +++ b/packages/components/src/mobile/html-text-input/style.ios.scss @@ -0,0 +1,21 @@ +@import "./style-common.scss"; + +$title-height: 32; + +.htmlView { + font-family: $htmlFont; + background-color: $backgroundColor; + padding-left: $padding; + padding-right: $padding; + padding-bottom: $title-height + $padding; +} + +.htmlViewTitle { + font-family: $htmlFont; + background-color: $backgroundColor; + padding-left: $padding; + padding-right: $padding; + padding-top: $padding; + padding-bottom: $padding; + height: $title-height; +}