Skip to content

Commit

Permalink
[RNMobile] Extract caption component (#16825)
Browse files Browse the repository at this point in the history
* Extract caption component

* Use caption component for video

* Move Caption to block-editor for mobile tests

This move avoids a dependency issue that was causing the mobile tests to
fail due to the Caption component's import of RichText from the
block-editor package.

* Pass onBlur to Caption component

* Connect Caption component to store
  • Loading branch information
mchowning authored Aug 16, 2019
1 parent fbf1938 commit 15f5ff4
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 66 deletions.
65 changes: 65 additions & 0 deletions packages/block-editor/src/components/caption/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* External dependencies
*/
import { View } from 'react-native';

/**
* WordPress dependencies
*/
import { RichText } from '@wordpress/block-editor';
import { compose } from '@wordpress/compose';
import { withDispatch, withSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

const Caption = ( { accessible, accessibilityLabel, onBlur, onChange, onFocus, isSelected, shouldDisplay, text } ) => (
<View style={ { padding: 12, flex: 1, display: shouldDisplay ? 'flex' : 'none' } }
accessible={ accessible }
accessibilityLabel={ accessibilityLabel }
accessibilityRole={ 'button' }
>
<RichText
rootTagsToEliminate={ [ 'p' ] }
placeholder={ __( 'Write caption…' ) }
value={ text }
onChange={ onChange }
unstableOnFocus={ onFocus }
onBlur={ onBlur } // always assign onBlur as props
isSelected={ isSelected }
__unstableMobileNoFocusOnMount
fontSize={ 14 }
underlineColorAndroid="transparent"
textAlign={ 'center' }
tagName={ '' }
/>
</View>
);

export default compose( [
withSelect( ( select, { accessibilityLabelCreator, clientId } ) => {
const {
getBlockAttributes,
getSelectedBlockClientId,
} = select( 'core/block-editor' );
const { caption } = getBlockAttributes( clientId );
const accessibilityLabel = accessibilityLabelCreator ? accessibilityLabelCreator( caption ) : undefined;
const isBlockSelected = getSelectedBlockClientId() === clientId;

// We'll render the caption so that the soft keyboard is not forced to close on Android
// but still hide it by setting its display style to none. See wordpress-mobile/gutenberg-mobile#1221
const shouldDisplay = ! RichText.isEmpty( caption ) > 0 || isBlockSelected;

return {
accessibilityLabel,
shouldDisplay,
text: caption,
};
} ),
withDispatch( ( dispatch, { clientId } ) => {
const { updateBlockAttributes } = dispatch( 'core/block-editor' );
return {
onChange: ( caption ) => {
updateBlockAttributes( clientId, { caption } );
},
};
} ),
] )( Caption );
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { default as MediaPlaceholder } from './media-placeholder';
export { default as MediaUpload, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO } from './media-upload';
export { default as URLInput } from './url-input';
export { default as BlockInvalidWarning } from './block-list/block-invalid-warning';
export { default as Caption } from './caption';

// Content Related Components
export { default as BlockList } from './block-list';
Expand Down
49 changes: 13 additions & 36 deletions packages/block-library/src/image/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import {
ToolbarButton,
} from '@wordpress/components';
import {
Caption,
MediaPlaceholder,
MediaUpload,
MEDIA_TYPE_IMAGE,
RichText,
BlockControls,
InspectorControls,
} from '@wordpress/block-editor';
Expand Down Expand Up @@ -115,7 +115,6 @@ class ImageEdit extends React.Component {
requestImageFailedRetryDialog( attributes.id );
}

this._caption.blur();
this.setState( {
isCaptionSelected: false,
} );
Expand Down Expand Up @@ -201,8 +200,8 @@ class ImageEdit extends React.Component {
}

render() {
const { attributes, isSelected, setAttributes } = this.props;
const { url, caption, height, width, alt, href, id } = attributes;
const { attributes, isSelected } = this.props;
const { url, height, width, alt, href, id } = attributes;

const onImageSettingsButtonPressed = () => {
this.setState( { showSettings: true } );
Expand Down Expand Up @@ -270,12 +269,6 @@ class ImageEdit extends React.Component {
);
}

// We still want to render the caption so that the soft keyboard is not forced to close on Android
const shouldCaptionDisplay = () => {
const isCaptionEmpty = RichText.isEmpty( caption ) > 0;
return ! isCaptionEmpty || isSelected;
};

const imageContainerHeight = Dimensions.get( 'window' ).width / IMAGE_ASPECT_RATIO;
const getImageComponent = ( openMediaOptions, getMediaOptions ) => (
<TouchableWithoutFeedback
Expand Down Expand Up @@ -344,38 +337,22 @@ class ImageEdit extends React.Component {
);
} }
/>
<View style={ { padding: 12, flex: 1, display: shouldCaptionDisplay() ? 'flex' : 'none' } }
<Caption
clientId={ this.props.clientId }
isSelected={ this.state.isCaptionSelected }
accessible={ true }
accessibilityLabel={
accessibilityLabelCreator={ ( caption ) =>
isEmpty( caption ) ?
/* translators: accessibility text. Empty image caption. */
__( 'Image caption. Empty' ) :
( 'Image caption. Empty' ) :
sprintf(
/* translators: accessibility text. %s: image caption. */
/* translators: accessibility text. %s: image caption. */
__( 'Image caption. %s' ),
caption
)
caption )
}
accessibilityRole={ 'button' }
>
<RichText
setRef={ ( ref ) => {
this._caption = ref;
} }
rootTagsToEliminate={ [ 'p' ] }
placeholder={ __( 'Write caption…' ) }
value={ caption }
onChange={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
unstableOnFocus={ this.onFocusCaption }
onBlur={ this.props.onBlur } // always assign onBlur as props
isSelected={ this.state.isCaptionSelected }
__unstableMobileNoFocusOnMount
fontSize={ 14 }
underlineColorAndroid="transparent"
textAlign={ 'center' }
tagName={ '' }
/>
</View>
onFocus={ this.onFocusCaption }
onBlur={ this.props.onBlur } // always assign onBlur as props
/>
</View>
</TouchableWithoutFeedback>
);
Expand Down
57 changes: 35 additions & 22 deletions packages/block-library/src/video/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import React from 'react';
import { View, TextInput, TouchableWithoutFeedback, Text } from 'react-native';
import { View, TouchableWithoutFeedback, Text } from 'react-native';
/**
* Internal dependencies
*/
Expand All @@ -22,10 +22,10 @@ import {
ToolbarButton,
} from '@wordpress/components';
import {
Caption,
MediaPlaceholder,
MediaUpload,
MEDIA_TYPE_VIDEO,
RichText,
BlockControls,
InspectorControls,
} from '@wordpress/block-editor';
Expand All @@ -48,6 +48,7 @@ class VideoEdit extends React.Component {
super( props );

this.state = {
isCaptionSelected: false,
showSettings: false,
videoContainerHeight: 0,
};
Expand All @@ -59,6 +60,7 @@ class VideoEdit extends React.Component {
this.updateMediaProgress = this.updateMediaProgress.bind( this );
this.onVideoPressed = this.onVideoPressed.bind( this );
this.onVideoContanerLayout = this.onVideoContanerLayout.bind( this );
this.onFocusCaption = this.onFocusCaption.bind( this );
}

componentDidMount() {
Expand All @@ -75,6 +77,14 @@ class VideoEdit extends React.Component {
}
}

static getDerivedStateFromProps( props, state ) {
// Avoid a UI flicker in the toolbar by insuring that isCaptionSelected
// is updated immediately any time the isSelected prop becomes false
return {
isCaptionSelected: props.isSelected && state.isCaptionSelected,
};
}

onVideoPressed() {
const { attributes } = this.props;

Expand All @@ -83,6 +93,16 @@ class VideoEdit extends React.Component {
} else if ( attributes.id && ! isURL( attributes.src ) ) {
requestImageFailedRetryDialog( attributes.id );
}

this.setState( {
isCaptionSelected: false,
} );
}

onFocusCaption() {
if ( ! this.state.isCaptionSelected ) {
this.setState( { isCaptionSelected: true } );
}
}

updateMediaProgress( payload ) {
Expand Down Expand Up @@ -135,8 +155,8 @@ class VideoEdit extends React.Component {
}

render() {
const { attributes, isSelected, setAttributes } = this.props;
const { caption, id, src } = attributes;
const { attributes, isSelected } = this.props;
const { id, src } = attributes;
const { videoContainerHeight } = this.state;

const toolbarEditButton = (
Expand Down Expand Up @@ -173,9 +193,10 @@ class VideoEdit extends React.Component {
return (
<TouchableWithoutFeedback onPress={ this.onVideoPressed } disabled={ ! isSelected }>
<View style={ { flex: 1 } }>
<BlockControls>
{ toolbarEditButton }
</BlockControls>
{ ! this.state.isCaptionSelected &&
<BlockControls>
{ toolbarEditButton }
</BlockControls> }
<InspectorControls>
{ false && <ToolbarButton //Not rendering settings button until it has an action
label={ __( 'Video Settings' ) }
Expand Down Expand Up @@ -212,7 +233,7 @@ class VideoEdit extends React.Component {
{ showVideo &&
<View style={ style.videoContainer }>
<Video
isSelected={ isSelected }
isSelected={ isSelected && ! this.state.isCaptionSelected }
style={ videoStyle }
source={ { uri: src } }
paused={ true }
Expand All @@ -229,20 +250,12 @@ class VideoEdit extends React.Component {
);
} }
/>
{ ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && (
<View style={ { paddingTop: 8, paddingBottom: 0, flex: 1 } }>
<TextInput
style={ { textAlign: 'center' } }
fontFamily={ this.props.fontFamily || ( style[ 'caption-text' ].fontFamily ) }
underlineColorAndroid="transparent"
value={ caption }
placeholder={ __( 'Write caption…' ) }
placeholderTextColor={ style.captionPlaceholder.color }
onChangeText={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
onFocus={ this.props.onFocus }
/>
</View>
) }
<Caption
clientId={ this.props.clientId }
isSelected={ this.state.isCaptionSelected }
onFocus={ this.onFocusCaption }
onBlur={ this.props.onBlur } // always assign onBlur as props
/>
</View>
</TouchableWithoutFeedback>
);
Expand Down
8 changes: 0 additions & 8 deletions packages/block-library/src/video/style.native.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@
border-style: solid;
}

.caption-text {
font-family: $default-regular-font;
}

.captionPlaceholder {
color: $gray;
}

.icon {
fill: $gray-dark;
width: 100%;
Expand Down

0 comments on commit 15f5ff4

Please sign in to comment.