Skip to content

Commit

Permalink
[RNMobile] Embed Block Bottom Sheet to set a link (#31343)
Browse files Browse the repository at this point in the history
* Add separatorType option to LinkSettings footer

* Create native EmbedBottomSheet component

* Use EmbedBottomSheet in native EmbedPlaceholder

* Add onSetAttributes callback to embed bottom sheet

When the attributes are modified in the LinkSettingsNavigation component the setAttributes callback is triggered. This callback is called once unlike the onClose callback, which is called multiple times and doesn't guarantee that the attributes are up-to-date at the time is triggered.

* Correct isEmbedSheetVisible typo

* Use onDismiss callback to notify embed URL value update

* Add comment to onChangeURL embed placeholder

* Only display the embed sheet on block insertion

* Add native version of onSubmit in embed

* Prevent onDismiss prop overwriting in bottom sheet

I noticed that if a onDismiss prop is passed to the bottom sheet component, the internal function onDismiss is not executed. This behavior looks wrong because this function is intended to actually call the onDismiss prop.

* Show only the embed sheet automatically if empty

* Fix clipboard case for embed sheet

* Omit onDismiss prop from rest object

Co-authored-by: Carlos Garcia <[email protected]>
  • Loading branch information
ceyhun and fluiddot authored Jul 1, 2021
1 parent d527b54 commit 8567be7
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 26 deletions.
33 changes: 25 additions & 8 deletions packages/block-library/src/embed/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,26 @@ const EmbedEdit = ( props ) => {
web: sprintf( __( '%s URL' ), title ),
native: title,
} );

const onSubmit = ( event ) => {
if ( event ) {
event.preventDefault();
}

setIsEditingURL( false );
setAttributes( { url } );
};

const onSubmitNative = ( value ) => {
// On native, the URL change is only notified when submitting
// so we have to explicitly set the URL.
setURL( value );

// Replicate the same behavior as onSubmit
setIsEditingURL( false );
setAttributes( { url: value } );
};

// No preview, or we can't embed the current URL, or we've clicked the edit button.
const showEmbedPlaceholder = ! preview || cannotEmbed || isEditingURL;
if ( showEmbedPlaceholder ) {
Expand All @@ -201,21 +221,18 @@ const EmbedEdit = ( props ) => {
icon={ icon }
label={ label }
onFocus={ onFocus }
onSubmit={ ( event ) => {
if ( event ) {
event.preventDefault();
}

setIsEditingURL( false );
setAttributes( { url } );
} }
onSubmit={ Platform.select( {
web: onSubmit,
native: onSubmitNative,
} ) }
value={ url }
cannotEmbed={ cannotEmbed }
onChange={ ( event ) => setURL( event.target.value ) }
fallback={ () => fallback( url, onReplace ) }
tryAgain={ () => {
invalidateResolution( 'getEmbedPreview', [ url ] );
} }
isSelected={ isSelected }
/>
</View>
);
Expand Down
66 changes: 66 additions & 0 deletions packages/block-library/src/embed/embed-bottom-sheet.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import {
LinkSettingsNavigation,
FooterMessageLink,
} from '@wordpress/components';
import { isURL } from '@wordpress/url';
import { useDispatch } from '@wordpress/data';
import { store as noticesStore } from '@wordpress/notices';
import { useCallback, useState } from '@wordpress/element';

const linkSettingsOptions = {
url: {
label: __( 'Embed link' ),
placeholder: __( 'Add link' ),
autoFocus: true,
autoFill: true,
},
footer: {
label: (
<FooterMessageLink
href={ __( 'https://wordpress.org/support/article/embeds/' ) }
value={ __( 'Learn more about embeds' ) }
/>
),
separatorType: 'topFullWidth',
},
};

const EmbedBottomSheet = ( { value, isVisible, onClose, onSubmit } ) => {
const [ url, setURL ] = useState( value );
const { createErrorNotice } = useDispatch( noticesStore );

const onDismiss = useCallback( () => {
if ( url !== '' && url !== value ) {
if ( isURL( url ) ) {
onSubmit( url );
} else {
createErrorNotice(
__( 'Invalid URL. Please enter a valid URL.' )
);
}
}
}, [ url, onSubmit ] );

function setAttributes( attributes ) {
setURL( attributes.url );
}

return (
<LinkSettingsNavigation
isVisible={ isVisible }
url={ url }
onClose={ onClose }
onDismiss={ onDismiss }
setAttributes={ setAttributes }
options={ linkSettingsOptions }
withBottomSheet
showIcon
/>
);
};

export default EmbedBottomSheet;
72 changes: 56 additions & 16 deletions packages/block-library/src/embed/embed-placeholder.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,40 @@ import { View, Text, TouchableWithoutFeedback } from 'react-native';
*/
import { __ } from '@wordpress/i18n';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
import { useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import {
useBlockEditContext,
store as blockEditorStore,
} from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import EmbedBottomSheet from './embed-bottom-sheet';
import styles from './styles.scss';

const EmbedPlaceholder = ( { icon, label, onFocus } ) => {
const EmbedPlaceholder = ( {
icon,
isSelected,
label,
onFocus,
value,
onSubmit,
} ) => {
const { clientId } = useBlockEditContext();
const { wasBlockJustInserted } = useSelect(
( select ) => ( {
wasBlockJustInserted: select(
blockEditorStore
).wasBlockJustInserted( clientId, 'inserter_menu' ),
} ),
[ clientId ]
);
const [ isEmbedSheetVisible, setIsEmbedSheetVisible ] = useState(
isSelected && wasBlockJustInserted && ! value
);

const emptyStateContainerStyle = usePreferredColorSchemeStyle(
styles.emptyStateContainer,
styles.emptyStateContainerDark
Expand All @@ -26,21 +53,34 @@ const EmbedPlaceholder = ( { icon, label, onFocus } ) => {
);

return (
<TouchableWithoutFeedback
accessibilityRole={ 'button' }
accessibilityHint={ __( 'Double tap to add a link.' ) }
onPress={ ( event ) => {
onFocus( event );
} }
>
<View style={ emptyStateContainerStyle }>
<View style={ styles.modalIcon }>{ icon }</View>
<Text style={ emptyStateTitleStyle }>{ label }</Text>
<Text style={ styles.emptyStateDescription }>
{ __( 'ADD LINK' ) }
</Text>
</View>
</TouchableWithoutFeedback>
<>
{ value ? (
<Text>{ value }</Text>
) : (
<TouchableWithoutFeedback
accessibilityRole={ 'button' }
accessibilityHint={ __( 'Double tap to add a link.' ) }
onPress={ ( event ) => {
onFocus( event );
setIsEmbedSheetVisible( true );
} }
>
<View style={ emptyStateContainerStyle }>
<View style={ styles.modalIcon }>{ icon }</View>
<Text style={ emptyStateTitleStyle }>{ label }</Text>
<Text style={ styles.emptyStateDescription }>
{ __( 'ADD LINK' ) }
</Text>
</View>
</TouchableWithoutFeedback>
) }
<EmbedBottomSheet
value={ value }
isVisible={ isEmbedSheetVisible }
onClose={ () => setIsEmbedSheetVisible( false ) }
onSubmit={ onSubmit }
/>
</>
);
};

Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/mobile/bottom-sheet/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from 'react-native';
import Modal from 'react-native-modal';
import SafeArea from 'react-native-safe-area';
import { omit } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -510,7 +511,9 @@ class BottomSheet extends Component {
panResponder.panHandlers.onMoveShouldSetResponderCapture
}
onAccessibilityEscape={ this.onCloseBottomSheet }
{ ...rest }
// We need to prevent overwriting the onDismiss prop,
// for this reason it is excluded from the rest object.
{ ...omit( rest, 'onDismiss' ) }
>
<KeyboardAvoidingView
behavior={ Platform.OS === 'ios' && 'padding' }
Expand Down
5 changes: 4 additions & 1 deletion packages/components/src/mobile/link-settings/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,10 @@ function LinkSettings( {
</PanelBody>
{ options.footer && (
<PanelBody style={ styles.linkSettingsPanel }>
<FooterMessageControl label={ options.footer.label } />
<FooterMessageControl
label={ options.footer.label }
separatorType={ options.footer.separatorType }
/>
</PanelBody>
) }
{ actions && <PanelActions actions={ actions } /> }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function LinkSettingsNavigation( props ) {
<BottomSheet
isVisible={ props.isVisible }
onClose={ props.onClose }
onDismiss={ props.onDismiss }
hideHeader
hasNavigation
>
Expand Down

0 comments on commit 8567be7

Please sign in to comment.