Skip to content

Commit

Permalink
[RNMobile] [Embed block] Detect when an embeddable URL is pasted into…
Browse files Browse the repository at this point in the history
… an empty paragraph (#35204)

* added unstableEmbedURLOnPaste prop to activate embed detection.

* reintegrated Embed transformation that was disabled - testing required.

* Added functionality that would convert the URL to a link.

* integrated the bottom sheet component that displays Create embed/link.

* The EmbedHandlerPicker was extracted to a standalone component.

* Updated changelog.

* added onChange to the embed logic so that the url is visible.

* only process URLs on empty paragraphs.

* utilized useCallback to lessen re-renders.

* added pickerOptions to the dependencies array.

* if there is content within a paragraph then insert the link.

* utilized isEmpty to check the text property of value.

* memoized the EmbedHandlerPicker

* Added a comment to clarify changes.

* Fixed issue with release notes that doesn't follow format.

* refactored embed paste logic.

* disables onReplace on non embed rich-text instances.

* Fixed CHANGELOG formatting issue.

* Fixed formatting issue in CHANGELOG.

* refactored the Embed pasting logic so that it is centralized

* Changed the variable to something more meaningful.

* Removed unnecessary content length check since this is already checked.

* if block is not derived then we check if content is a string url.

* Refactor embed paste logic

* Removed the __unstableEmbedURLOnPaste flag from mode logic for Heading

* Resolved isPastedURL logic issues to fix HEADING bug.

* Fixed typo in CHANGELOG.

Co-authored-by: Carlos Garcia <fluiddot@gmail.com>
  • Loading branch information
jd-alexander and fluiddot committed Oct 13, 2021
1 parent ae12d94 commit 5430baf
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 3 deletions.
@@ -0,0 +1,67 @@
/**
* External dependencies
*/
import { noop } from 'lodash';

/**
* WordPress dependencies
*/
import {
forwardRef,
useRef,
useImperativeHandle,
memo,
useCallback,
} from '@wordpress/element';
import { Picker } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

const DEFAULT_PICKER_OPTIONS = [
{
id: 'createEmbed',
label: __( 'Create embed' ),
value: 'createEmbed',
onSelect: noop,
},
{
id: 'createLink',
label: __( 'Create link' ),
value: 'createLink',
onSelect: noop,
},
];

const EmbedHandlerPicker = forwardRef( ( {}, ref ) => {
const pickerRef = useRef();
const pickerOptions = useRef( DEFAULT_PICKER_OPTIONS ).current;

const onPickerSelect = useCallback(
( value ) => {
const selectedItem = pickerOptions.find(
( item ) => item.value === value
);
selectedItem.onSelect();
},
[ pickerOptions ]
);

useImperativeHandle( ref, () => ( {
presentPicker: ( { createEmbed, createLink } ) => {
pickerOptions[ 0 ].onSelect = createEmbed;
pickerOptions[ 1 ].onSelect = createLink;
pickerRef.current?.presentPicker();
},
} ) );

return (
<Picker
ref={ pickerRef }
options={ pickerOptions }
onChange={ onPickerSelect }
hideCancelButton
leftAlign
/>
);
} );

export default memo( EmbedHandlerPicker );
36 changes: 35 additions & 1 deletion packages/block-editor/src/components/rich-text/index.native.js
Expand Up @@ -55,7 +55,9 @@ import {
getMultilineTag,
getAllowedFormats,
isShortcode,
createLinkInParagraph,
} from './utils';
import EmbedHandlerPicker from './embed-handler-picker';

const wrapperClasses = 'block-editor-rich-text';
const classes = 'block-editor-rich-text__editable';
Expand Down Expand Up @@ -118,6 +120,7 @@ function RichTextWrapper(
const fallbackRef = useRef();
const { clientId, isSelected: blockIsSelected } = useBlockEditContext();
const nativeProps = useNativeProps();
const embedHandlerPickerRef = useRef();
const selector = ( select ) => {
const {
isCaretWithinFormattedText,
Expand Down Expand Up @@ -439,10 +442,19 @@ function RichTextWrapper(
mode = 'BLOCKS';
}

const isPastedURL = isURL( plainText.trim() );
const presentEmbedHandlerPicker = () =>
embedHandlerPickerRef.current?.presentPicker( {
createEmbed: () =>
onReplace( content, content.length - 1, -1 ),
createLink: () =>
createLinkInParagraph( plainText.trim(), onReplace ),
} );

if (
__unstableEmbedURLOnPaste &&
isEmpty( value ) &&
isURL( plainText.trim() )
isPastedURL
) {
mode = 'BLOCKS';
}
Expand Down Expand Up @@ -472,9 +484,30 @@ function RichTextWrapper(

onChange( insert( value, valueToInsert ) );
} else if ( content.length > 0 ) {
// When an URL is pasted in an empty paragraph then the EmbedHandlerPicker should showcase options allowing the transformation of that URL
// into either an Embed block or a link within the target paragraph. If the paragraph is non-empty, the URL is pasted as text.
const canPasteEmbed =
isPastedURL &&
content.length === 1 &&
content[ 0 ].name === 'core/embed';
if ( onReplace && isEmpty( value ) ) {
if ( canPasteEmbed ) {
onChange(
insert( value, create( { text: plainText } ) )
);
if ( __unstableEmbedURLOnPaste ) {
presentEmbedHandlerPicker();
}
return;
}
onReplace( content, content.length - 1, -1 );
} else {
if ( canPasteEmbed ) {
onChange(
insert( value, create( { text: plainText } ) )
);
return;
}
splitValue( value, content );
}
}
Expand Down Expand Up @@ -650,6 +683,7 @@ function RichTextWrapper(
/>
) }
</Autocomplete>
<EmbedHandlerPicker ref={ embedHandlerPickerRef } />
</>
) }
</RichText>
Expand Down
16 changes: 16 additions & 0 deletions packages/block-editor/src/components/rich-text/utils.js
Expand Up @@ -3,6 +3,8 @@
*/
import { regexp } from '@wordpress/shortcode';
import deprecated from '@wordpress/deprecated';
import { renderToString } from '@wordpress/element';
import { createBlock } from '@wordpress/blocks';

export function addActiveFormats( value, activeFormats ) {
if ( activeFormats?.length ) {
Expand Down Expand Up @@ -60,3 +62,17 @@ export function getAllowedFormats( {
getAllowedFormats.EMPTY_ARRAY = [];

export const isShortcode = ( text ) => regexp( '.*' ).test( text );

/**
* Creates a link from pasted URL.
* Creates a paragraph block containing a link to the URL, and calls `onReplace`.
*
* @param {string} url The URL that could not be embedded.
* @param {Function} onReplace Function to call with the created fallback block.
*/
export function createLinkInParagraph( url, onReplace ) {
const link = <a href={ url }>{ url }</a>;
onReplace(
createBlock( 'core/paragraph', { content: renderToString( link ) } )
);
}
2 changes: 2 additions & 0 deletions packages/block-library/src/embed/transforms.native.js
@@ -1,9 +1,11 @@
/**
* Internal dependencies
*/
import webTransforms from './transforms.js';
import transformationCategories from '../transformationCategories';

const transforms = {
...webTransforms,
supportedMobileTransforms: transformationCategories.media,
};

Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/paragraph/edit.native.js
Expand Up @@ -83,6 +83,7 @@ function ParagraphBlock( {
onRemove={ onReplace ? () => onReplace( [] ) : undefined }
placeholder={ placeholder || __( 'Start writing…' ) }
textAlign={ align }
__unstableEmbedURLOnPaste
/>
</>
);
Expand Down
5 changes: 3 additions & 2 deletions packages/react-native-editor/CHANGELOG.md
Expand Up @@ -11,6 +11,7 @@ For each user feature we should also add a importance categorization label to i

## Unreleased
- [*] [Embed block] Fix inline preview cut-off when editing URL [#35321]
- [**] [Embed block] Detect when an embeddable URL is pasted into an empty paragraph. [#35204]
- [*] [Unsupported Block Editor] Fix text selection bug for Android [#34668]
- [*] [Embed block] Fix URL not editable after dismissing the edit URL bottom sheet with empty value [#35460]
- [**] Pullquote block - Added support for text and background color customization [#34451]
Expand All @@ -28,8 +29,8 @@ For each user feature we should also add a importance categorization label to i
- Same as 1.62.1 but with the changelog.

## 1.62.1
- [**] Image block: fix height and border regression. [https://github.com/WordPress/gutenberg/pull/34957]
- [**] Column block: fix width float attribute cut off. [#35061]
- [**] Image block: fix height and border regression. [#34957]
- [**] Column block: fix width attribute float cut off. [#34604]

## 1.62.0
- [**] [Embed block] Implement WP embed preview component [#34004]
Expand Down

0 comments on commit 5430baf

Please sign in to comment.