Skip to content

Commit

Permalink
[RNMobile] Fix drag mode not being enabled when long-pressing over Sh…
Browse files Browse the repository at this point in the history
…ortcode block (#41155)

* Add prop for disabling suggestions button

* Use allowed formats in format types calculation

* Add RichText version to PlainText component

* Use experimental version of PlainText in Shortcode block

* Add disableAutocorrection prop to RichText

* Disable autocorrection in Shortcode block

* Update PlainText props in Shortcode block

* Use pre as tagName in PlainText

* Rename replaceLineBreaks function

* Update shortcode block unit tests

* Prevent text input focus when selecting Shortcode block

* Force text color in Shortcode block

* Remove tagName prop from PlainText component
  • Loading branch information
fluiddot authored and Gerardo committed May 20, 2022
1 parent 5c6fe0d commit 09d4368
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 75 deletions.
72 changes: 64 additions & 8 deletions packages/block-editor/src/components/plain-text/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { TextInput, Platform, Dimensions } from 'react-native';
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { getPxFromCssUnit } from '@wordpress/block-editor';
import { RichText, getPxFromCssUnit } from '@wordpress/block-editor';

/**
* Internal dependencies
Expand All @@ -18,6 +18,9 @@ export default class PlainText extends Component {
constructor() {
super( ...arguments );
this.isAndroid = Platform.OS === 'android';

this.onChangeTextInput = this.onChangeTextInput.bind( this );
this.onChangeRichText = this.onChangeRichText.bind( this );
}

componentDidMount() {
Expand All @@ -44,7 +47,7 @@ export default class PlainText extends Component {

componentDidUpdate( prevProps ) {
if ( ! this.props.isSelected && prevProps.isSelected ) {
this._input.blur();
this._input?.blur();
}
}

Expand All @@ -55,11 +58,11 @@ export default class PlainText extends Component {
}

focus() {
this._input.focus();
this._input?.focus();
}

blur() {
this._input.blur();
this._input?.blur();
}

getFontSize() {
Expand All @@ -79,20 +82,73 @@ export default class PlainText extends Component {
};
}

replaceLineBreakTags( value ) {
return value?.replace( RegExp( '<br>', 'gim' ), '\n' );
}

onChangeTextInput( event ) {
const { onChange } = this.props;
onChange( event.nativeEvent.text );
}

onChangeRichText( value ) {
const { onChange } = this.props;
// The <br> tags have to be replaced with new line characters
// as the content of plain text shouldn't contain HTML tags.
onChange( this.replaceLineBreakTags( value ) );
}

render() {
const { style } = this.props;
const {
style,
__experimentalVersion,
onFocus,
...otherProps
} = this.props;
const textStyles = [
style || styles[ 'block-editor-plain-text' ],
this.getFontSize(),
];

if ( __experimentalVersion === 2 ) {
const disableFormattingProps = {
withoutInteractiveFormatting: true,
disableEditingMenu: true,
__unstableDisableFormats: true,
disableSuggestions: true,
};

const forcePlainTextProps = {
preserveWhiteSpace: true,
__unstablePastePlainText: true,
multiline: false,
};

const fontProps = {
fontFamily: style?.fontFamily,
fontSize: style?.fontSize,
fontWeight: style?.fontWeight,
};

return (
<RichText
{ ...otherProps }
{ ...disableFormattingProps }
{ ...forcePlainTextProps }
{ ...fontProps }
identifier="content"
style={ style }
onChange={ this.onChangeRichText }
unstableOnFocus={ onFocus }
/>
);
}

return (
<TextInput
{ ...this.props }
ref={ ( x ) => ( this._input = x ) }
onChange={ ( event ) => {
this.props.onChange( event.nativeEvent.text );
} }
onChange={ this.onChangeTextInput }
onFocus={ this.props.onFocus } // Always assign onFocus as a props.
onBlur={ this.props.onBlur } // Always assign onBlur as a props.
fontFamily={
Expand Down
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ function removeNativeProps( props ) {
'minWidth',
'maxWidth',
'setRef',
'disableSuggestions',
'disableAutocorrection',
] );
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ function RichTextWrapper(
maxWidth,
onBlur,
setRef,
disableSuggestions,
disableAutocorrection,
...props
},
forwardedRef
Expand Down Expand Up @@ -635,6 +637,8 @@ function RichTextWrapper(
maxWidth={ maxWidth }
onBlur={ onBlur }
setRef={ setRef }
disableSuggestions={ disableSuggestions }
disableAutocorrection={ disableAutocorrection }
// Props to be set on the editable container are destructured on the
// element itself for web (see below), but passed through rich text
// for native.
Expand Down
44 changes: 29 additions & 15 deletions packages/block-library/src/shortcode/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { View, Text } from 'react-native';
import { __ } from '@wordpress/i18n';
import { PlainText } from '@wordpress/block-editor';
import { withPreferredColorScheme } from '@wordpress/compose';
import { useCallback } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -23,11 +24,16 @@ export function ShortcodeEdit( props ) {
onFocus,
onBlur,
getStylesFromColorScheme,
blockWidth,
} = props;
const titleStyle = getStylesFromColorScheme(
styles.blockTitle,
styles.blockTitleDark
);
const shortcodeContainerStyle = getStylesFromColorScheme(
styles.blockShortcodeContainer,
styles.blockShortcodeContainerDark
);
const shortcodeStyle = getStylesFromColorScheme(
styles.blockShortcode,
styles.blockShortcodeDark
Expand All @@ -37,24 +43,32 @@ export function ShortcodeEdit( props ) {
styles.placeholderDark
);

const maxWidth =
blockWidth -
shortcodeContainerStyle.paddingLeft +
shortcodeContainerStyle.paddingRight;

const onChange = useCallback( ( text ) => setAttributes( { text } ), [
setAttributes,
] );

return (
<View>
<Text style={ titleStyle }>{ __( 'Shortcode' ) }</Text>
<PlainText
value={ attributes.text }
style={ shortcodeStyle }
multiline={ true }
underlineColorAndroid="transparent"
onChange={ ( text ) => setAttributes( { text } ) }
placeholder={ __( 'Add a shortcode…' ) }
aria-label={ __( 'Shortcode' ) }
isSelected={ props.isSelected }
onFocus={ onFocus }
onBlur={ onBlur }
autoCorrect={ false }
autoComplete="off"
placeholderTextColor={ placeholderStyle.color }
/>
<View style={ shortcodeContainerStyle }>
<PlainText
__experimentalVersion={ 2 }
value={ attributes.text }
style={ shortcodeStyle }
onChange={ onChange }
placeholder={ __( 'Add a shortcode…' ) }
onFocus={ onFocus }
onBlur={ onBlur }
placeholderTextColor={ placeholderStyle.color }
maxWidth={ maxWidth }
disableAutocorrection
/>
</View>
</View>
);
}
Expand Down
15 changes: 11 additions & 4 deletions packages/block-library/src/shortcode/style.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,25 @@
color: $gray-50;
}

.blockShortcodeContainer {
padding: 12px;
border-radius: 4px;
background-color: $gray-light;
}

.blockShortcodeContainerDark {
background-color: $gray-100;
}

.blockShortcode {
font-family: $default-monospace-font;
font-weight: 400;
font-size: 14px;
padding: 12px;
border-radius: 4px;
background-color: $gray-light;
color: $gray-900;
}

.blockShortcodeDark {
color: $white;
background-color: $gray-100;
}

.placeholder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Shortcode block edits content 1`] = `
"<!-- wp:shortcode -->
[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]
<!-- /wp:shortcode -->"
`;

exports[`Shortcode block inserts block 1`] = `"<!-- wp:shortcode /-->"`;
98 changes: 58 additions & 40 deletions packages/block-library/src/shortcode/test/edit.native.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,76 @@
/**
* External dependencies
*/
import renderer from 'react-test-renderer';
import { TextInput } from 'react-native';
import {
getEditorHtml,
initializeEditor,
fireEvent,
waitFor,
} from 'test/helpers';

/**
* WordPress dependencies
*/
import { BlockEdit } from '@wordpress/block-editor';
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
import { registerCoreBlocks } from '@wordpress/block-library';

/**
* Internal dependencies
*/
import { metadata, settings, name } from '../index';
beforeAll( () => {
// Register all core blocks
registerCoreBlocks();
} );

afterAll( () => {
// Clean up registered blocks
getBlockTypes().forEach( ( block ) => {
unregisterBlockType( block.name );
} );
} );

describe( 'Shortcode block', () => {
it( 'inserts block', async () => {
const {
getByA11yLabel,
getByTestId,
getByText,
} = await initializeEditor();

const Shortcode = ( { clientId, ...props } ) => (
<BlockEdit name={ name } clientId={ clientId || 0 } { ...props } />
);
fireEvent.press( getByA11yLabel( 'Add block' ) );

describe( 'Shortcode', () => {
beforeAll( () => {
registerBlockType( name, {
...metadata,
...settings,
const blockList = getByTestId( 'InserterUI-Blocks' );
// onScroll event used to force the FlatList to render all items
fireEvent.scroll( blockList, {
nativeEvent: {
contentOffset: { y: 0, x: 0 },
contentSize: { width: 100, height: 100 },
layoutMeasurement: { width: 100, height: 100 },
},
} );
} );

afterAll( () => {
unregisterBlockType( name );
} );
fireEvent.press( await waitFor( () => getByText( 'Shortcode' ) ) );

it( 'renders without crashing', () => {
const component = renderer.create(
<Shortcode attributes={ { text: '' } } />
);
const rendered = component.toJSON();
expect( rendered ).toBeTruthy();
expect( getByA11yLabel( /Shortcode Block\. Row 1/ ) ).toBeVisible();
expect( getEditorHtml() ).toMatchSnapshot();
} );

it( 'renders given text without crashing', () => {
const component = renderer.create(
<Shortcode
attributes={ {
text:
'[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]',
} }
/>
);
const testInstance = component.root;
const textInput = testInstance.findByType( TextInput );
expect( textInput ).toBeTruthy();
expect( textInput.props.value ).toBe(
'[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]'
it( 'edits content', async () => {
const { getByA11yLabel, getByPlaceholderText } = await initializeEditor(
{
initialHtml: '<!-- wp:shortcode /-->',
}
);
const shortcodeBlock = getByA11yLabel( /Shortcode Block\. Row 1/ );
fireEvent.press( shortcodeBlock );

const textField = getByPlaceholderText( 'Add a shortcode…' );
fireEvent( textField, 'focus' );
fireEvent( textField, 'onChange', {
nativeEvent: {
eventCount: 1,
target: undefined,
text: '[youtube https://www.youtube.com/watch?v=ssfHW5lwFZg]',
},
} );

expect( getEditorHtml() ).toMatchSnapshot();
} );
} );
Loading

0 comments on commit 09d4368

Please sign in to comment.