diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 5b4132e19a2b2..476dea2981b15 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -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 ( - + + + ); } - const toolbarEditButton = ( - - - - ); + render() { + const { attributes, isSelected, setAttributes } = this.props; + const { url, caption, height, width } = attributes; + + if ( ! url ) { + return ( + + ); + } + + return ( + + + { this.toolbarEditButton() } + + + { ( sizes ) => { + const { + imageWidthWithinContainer, + imageHeightWithinContainer, + } = sizes; - return ( - - - { toolbarEditButton } - - - { ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && ( - - setAttributes( { caption: newCaption } ) } - /> - - ) } - - ); + let finalHeight = imageHeightWithinContainer; + if ( height > 0 && height < imageHeightWithinContainer ) { + finalHeight = height; + } + + let finalWidth = imageWidthWithinContainer; + if ( width > 0 && width < imageWidthWithinContainer ) { + finalWidth = width; + } + + return ( + + + + ); + } } + + { ( ! RichText.isEmpty( caption ) > 0 || isSelected ) && ( + + setAttributes( { caption: newCaption } ) } + /> + + ) } + + ); + } } + +export default ImageEdit; diff --git a/packages/block-library/src/image/image-size.js b/packages/block-library/src/image/image-size.js index 0a1b88aed12d7..bc7ebaeaa59b4 100644 --- a/packages/block-library/src/image/image-size.js +++ b/packages/block-library/src/image/image-size.js @@ -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 ); @@ -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 } ); } diff --git a/packages/block-library/src/image/image-size.native.js b/packages/block-library/src/image/image-size.native.js new file mode 100644 index 0000000000000..8b29b9607e81e --- /dev/null +++ b/packages/block-library/src/image/image-size.native.js @@ -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 ( + + { this.props.children( sizes ) } + + ); + } +} + +export default ImageSize; diff --git a/packages/block-library/src/image/utils.js b/packages/block-library/src/image/utils.js new file mode 100644 index 0000000000000..32bdb9d71564c --- /dev/null +++ b/packages/block-library/src/image/utils.js @@ -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 }; +}