Skip to content

Commit

Permalink
[Mobile] Image height (#13096)
Browse files Browse the repository at this point in the history
* [rnmobile]: Convert image-block into class

* [rnmobile]: Creating mobile version of `image-size`.

* [rnmobile]: Adding util to image-block to share math between image-size components.

* [rnmobile]: Adding newline at the end of image-size.native.js file

* [rnmobile]: Replace wrong tabs characters

* [rnmobile]: Clear image size when url changes.

* [rnmobile]: Fixed lint issues

* [rnmobile]: Removing unnecessary binding calls

* [rnmobile]: Added necessary this.onLayout.bind( this )

* [rnmobile]: Adding missing bind to `onMediaLibraryPress`.
  • Loading branch information
etoledom authored and youknowriad committed Mar 6, 2019
1 parent 6adc907 commit 277cb8c
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 51 deletions.
129 changes: 83 additions & 46 deletions packages/block-library/src/image/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,104 @@ import RNReactNativeGutenbergBridge from 'react-native-gutenberg-bridge';
*/
import { MediaPlaceholder, RichText, BlockControls } from '@wordpress/editor';
import { Toolbar, ToolbarButton } from '@wordpress/components';
import { Component } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import ImageSize from './image-size';

export default function ImageEdit( props ) {
const { attributes, isSelected, setAttributes } = props;
const { url, caption } = attributes;
class ImageEdit extends Component {
constructor() {
super( ...arguments );
this.onMediaLibraryPress = this.onMediaLibraryPress.bind( this );
}

const onUploadPress = () => {
onUploadPress() {
// This method should present an image picker from
// the device.
//TODO: Implement upload image method.
};
}

const onMediaLibraryPress = () => {
onMediaLibraryPress() {
RNReactNativeGutenbergBridge.onMediaLibraryPress( ( mediaUrl ) => {
if ( mediaUrl ) {
setAttributes( { url: mediaUrl } );
this.props.setAttributes( { url: mediaUrl } );
}
} );
};
}

if ( ! url ) {
toolbarEditButton() {
return (
<MediaPlaceholder
onUploadPress={ onUploadPress }
onMediaLibraryPress={ onMediaLibraryPress }
/>
<Toolbar>
<ToolbarButton
className="components-toolbar__control"
label={ __( 'Edit image' ) }
icon="edit"
onClick={ this.onMediaLibraryPress }
/>
</Toolbar>
);
}

const toolbarEditButton = (
<Toolbar>
<ToolbarButton
className="components-toolbar__control"
label={ __( 'Edit image' ) }
icon="edit"
onClick={ onMediaLibraryPress }
/>
</Toolbar>
);
render() {
const { attributes, isSelected, setAttributes } = this.props;
const { url, caption, height, width } = attributes;

if ( ! url ) {
return (
<MediaPlaceholder
onUploadPress={ this.onUploadPress }
onMediaLibraryPress={ this.onMediaLibraryPress }
/>
);
}

return (
<View style={ { flex: 1 } }>
<BlockControls>
{ this.toolbarEditButton() }
</BlockControls>
<ImageSize src={ url } >
{ ( sizes ) => {
const {
imageWidthWithinContainer,
imageHeightWithinContainer,
} = sizes;

return (
<View style={ { flex: 1 } }>
<BlockControls>
{ toolbarEditButton }
</BlockControls>
<Image
style={ { width: '100%', height: 200 } }
resizeMethod="scale"
source={ { uri: url } }
/>
{ ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && (
<View style={ { padding: 12, flex: 1 } }>
<TextInput
style={ { textAlign: 'center' } }
underlineColorAndroid="transparent"
value={ caption }
placeholder={ 'Write caption…' }
onChangeText={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
/>
</View>
) }
</View>
);
let finalHeight = imageHeightWithinContainer;
if ( height > 0 && height < imageHeightWithinContainer ) {
finalHeight = height;
}

let finalWidth = imageWidthWithinContainer;
if ( width > 0 && width < imageWidthWithinContainer ) {
finalWidth = width;
}

return (
<View style={ { flex: 1 } } >
<Image
style={ { width: finalWidth, height: finalHeight } }
resizeMethod="scale"
source={ { uri: url } }
key={ url }
/>
</View>
);
} }
</ImageSize>
{ ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && (
<View style={ { padding: 12, flex: 1 } }>
<TextInput
style={ { textAlign: 'center' } }
underlineColorAndroid="transparent"
value={ caption }
placeholder={ 'Write caption…' }
onChangeText={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
/>
</View>
) }
</View>
);
}
}

export default ImageEdit;
11 changes: 6 additions & 5 deletions packages/block-library/src/image/image-size.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import { noop } from 'lodash';
import { withGlobalEvents } from '@wordpress/compose';
import { Component } from '@wordpress/element';

/**
* Internal dependencies
*/
import { calculatePreferedImageSize } from './utils';

class ImageSize extends Component {
constructor() {
super( ...arguments );
Expand Down Expand Up @@ -55,11 +60,7 @@ class ImageSize extends Component {
}

calculateSize() {
const maxWidth = this.container.clientWidth;
const exceedMaxWidth = this.image.width > maxWidth;
const ratio = this.image.height / this.image.width;
const width = exceedMaxWidth ? maxWidth : this.image.width;
const height = exceedMaxWidth ? maxWidth * ratio : this.image.height;
const { width, height } = calculatePreferedImageSize( this.image, this.container );
this.setState( { width, height } );
}

Expand Down
87 changes: 87 additions & 0 deletions packages/block-library/src/image/image-size.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';

/**
* External dependencies
*/
import { View, Image } from 'react-native';

/**
* Internal dependencies
*/
import { calculatePreferedImageSize } from './utils';

class ImageSize extends Component {
constructor() {
super( ...arguments );
this.state = {
width: undefined,
height: undefined,
};
this.onLayout = this.onLayout.bind( this );
}

componentDidUpdate( prevProps ) {
if ( this.props.src !== prevProps.src ) {
this.image = {};

this.setState( {
width: undefined,
height: undefined,
} );
this.fetchImageSize();
}

if ( this.props.dirtynessTrigger !== prevProps.dirtynessTrigger ) {
this.calculateSize();
}
}

componentDidMount() {
this.fetchImageSize();
}

fetchImageSize() {
Image.getSize( this.props.src, ( width, height ) => {
this.image = { width, height };
this.calculateSize();
} );
}

calculateSize() {
if ( this.image === undefined || this.container === undefined ) {
return;
}
const { width, height } = calculatePreferedImageSize( this.image, this.container );
this.setState( { width, height } );
}

onLayout( event ) {
const { width, height } = event.nativeEvent.layout;
this.container = {
clientWidth: width,
clientHeight: height,
};
this.calculateSize();
}

render() {
const sizes = {
imageWidth: this.image && this.image.width,
imageHeight: this.image && this.image.height,
containerWidth: this.container && this.container.width,
containerHeight: this.container && this.container.height,
imageWidthWithinContainer: this.state.width,
imageHeightWithinContainer: this.state.height,
};
return (
<View onLayout={ this.onLayout }>
{ this.props.children( sizes ) }
</View>
);
}
}

export default ImageSize;
9 changes: 9 additions & 0 deletions packages/block-library/src/image/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

export function calculatePreferedImageSize( image, container ) {
const maxWidth = container.clientWidth;
const exceedMaxWidth = image.width > maxWidth;
const ratio = image.height / image.width;
const width = exceedMaxWidth ? maxWidth : image.width;
const height = exceedMaxWidth ? maxWidth * ratio : image.height;
return { width, height };
}

0 comments on commit 277cb8c

Please sign in to comment.