From 027a3dbd70d9fe969232d89a20f4da28cec3047d Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Mon, 13 Dec 2021 11:35:21 +1100 Subject: [PATCH] Image: Fix resizer controls being hidden in Safari when switching between alignments (#37210) * Image: Update naturalWidth and naturalHeight to pull from image ref instead of local component state * Re-introduce onLoad setState behaviour to allow fallback while cropping images * Remove useMemo * Re-instate useMemo as removing it caused the resizer to disappear intermittently --- packages/block-library/src/image/image.js | 40 ++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 43c5cc6dc37738..8c49687685d87b 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -30,7 +30,7 @@ import { __experimentalImageEditor as ImageEditor, __experimentalImageEditingProvider as ImageEditingProvider, } from '@wordpress/block-editor'; -import { useEffect, useState, useRef } from '@wordpress/element'; +import { useEffect, useMemo, useState, useRef } from '@wordpress/element'; import { __, sprintf, isRTL } from '@wordpress/i18n'; import { getFilename } from '@wordpress/url'; import { createBlock, switchToBlockType } from '@wordpress/blocks'; @@ -79,6 +79,7 @@ export default function Image( { context, clientId, } ) { + const imageRef = useRef(); const captionRef = useRef(); const prevUrl = usePrevious( url ); const { allowResize = true } = context; @@ -141,7 +142,10 @@ export default function Image( { ); const isLargeViewport = useViewportMatch( 'medium' ); const isWideAligned = includes( [ 'wide', 'full' ], align ); - const [ { naturalWidth, naturalHeight }, setNaturalSize ] = useState( {} ); + const [ + { loadedNaturalWidth, loadedNaturalHeight }, + setLoadedNaturalSize, + ] = useState( {} ); const [ isEditingImage, setIsEditingImage ] = useState( false ); const [ externalBlob, setExternalBlob ] = useState(); const clientWidth = useClientWidth( containerRef, [ align ] ); @@ -179,6 +183,27 @@ export default function Image( { } }, [ url, prevUrl ] ); + // Get naturalWidth and naturalHeight from image ref, and fall back to loaded natural + // width and height. This resolves an issue in Safari where the loaded natural + // witdth and height is otherwise lost when switching between alignments. + // See: https://github.com/WordPress/gutenberg/pull/37210. + const { naturalWidth, naturalHeight } = useMemo( () => { + return { + naturalWidth: + imageRef.current?.naturalWidth || + loadedNaturalWidth || + undefined, + naturalHeight: + imageRef.current?.naturalHeight || + loadedNaturalHeight || + undefined, + }; + }, [ + loadedNaturalWidth, + loadedNaturalHeight, + imageRef.current?.complete, + ] ); + function onResizeStart() { toggleSelection( false ); } @@ -411,13 +436,12 @@ export default function Image( { alt={ defaultedAlt } onError={ () => onImageError() } onLoad={ ( event ) => { - setNaturalSize( - pick( event.target, [ - 'naturalWidth', - 'naturalHeight', - ] ) - ); + setLoadedNaturalSize( { + loadedNaturalWidth: event.target?.naturalWidth, + loadedNaturalHeight: event.target?.naturalHeight, + } ); } } + ref={ imageRef } /> { temporaryURL && }