Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image: Reflect media deletion in the editor #35973

Merged
merged 11 commits into from Dec 14, 2021
Expand Up @@ -75,6 +75,7 @@ export function MediaPlaceholder( {
onDoubleClick,
onFilesPreUpload = noop,
onHTMLDrop = noop,
onClose = noop,
children,
mediaLibraryButton,
placeholder,
Expand Down Expand Up @@ -328,6 +329,7 @@ export function MediaPlaceholder( {
gallery={ multiple && onlyAllowsImages() }
multiple={ multiple }
onSelect={ onSelect }
onClose={ onClose }
allowedTypes={ allowedTypes }
value={
Array.isArray( value )
Expand Down
Expand Up @@ -39,6 +39,7 @@ const MediaReplaceFlow = ( {
onSelect,
onSelectURL,
onFilesUpload = noop,
onCloseModal = noop,
name = __( 'Replace' ),
createNotice,
removeNotice,
Expand Down Expand Up @@ -136,6 +137,7 @@ const MediaReplaceFlow = ( {
value={ mediaId }
onSelect={ ( media ) => selectMedia( media ) }
allowedTypes={ allowedTypes }
onClose={ onCloseModal }
render={ ( { open } ) => (
<MenuItem icon={ mediaIcon } onClick={ open }>
{ __( 'Open Media Library' ) }
Expand Down
44 changes: 44 additions & 0 deletions packages/block-library/src/image/edit.js
Expand Up @@ -87,6 +87,20 @@ function hasDefaultSize( image, defaultSize ) {
);
}

/**
* Checks if a media attachment object has been "destroyed",
* that is, removed from the media library. The core Media Library
* adds a `destroyed` property to a deleted attachment object in the media collection.
*
* @param {number} id The attachment id.
*
* @return {boolean} Whether the image has been destroyed.
*/
export function isMediaDestroyed( id ) {
const attachment = wp?.media?.attachment( id ) || {};
ramonjd marked this conversation as resolved.
Show resolved Hide resolved
return attachment.destroyed;
}

export function ImageEdit( {
attributes,
setAttributes,
Expand Down Expand Up @@ -127,6 +141,33 @@ export function ImageEdit( {
return pick( getSettings(), [ 'imageDefaultSize', 'mediaUpload' ] );
}, [] );

// A callback passed to MediaUpload,
// fired when the media modal closes.
function onCloseModal() {
if ( isMediaDestroyed( attributes?.id ) ) {
setAttributes( {
url: undefined,
id: undefined,
} );
}
}

/*
Runs an error callback if the image does not load.
If the error callback is triggered, we infer that that image
has been deleted.
*/
function onImageError( isReplaced = false ) {
// If the image block was not replaced with an embed,
// clear the attributes and trigger the placeholder.
if ( ! isReplaced ) {
setAttributes( {
url: undefined,
id: undefined,
} );
}
}

function onUploadError( message ) {
noticeOperations.removeAllNotices();
noticeOperations.createErrorNotice( message );
Expand Down Expand Up @@ -324,6 +365,8 @@ export function ImageEdit( {
containerRef={ ref }
context={ context }
clientId={ clientId }
onCloseModal={ onCloseModal }
onImageLoadError={ onImageError }
/>
) }
{ ! url && (
Expand All @@ -340,6 +383,7 @@ export function ImageEdit( {
onSelectURL={ onSelectURL }
notices={ noticeUI }
onError={ onUploadError }
onClose={ onCloseModal }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ { id, src } }
Expand Down
17 changes: 14 additions & 3 deletions packages/block-library/src/image/image.js
Expand Up @@ -43,7 +43,7 @@ import { store as coreStore } from '@wordpress/core-data';
*/
import { createUpgradedEmbedBlock } from '../embed/util';
import useClientWidth from './use-client-width';
import { isExternalImage } from './edit';
import { isExternalImage, isMediaDestroyed } from './edit';

/**
* Module constants
Expand Down Expand Up @@ -72,12 +72,14 @@ export default function Image( {
isSelected,
insertBlocksAfter,
onReplace,
onCloseModal,
onSelectImage,
onSelectURL,
onUploadError,
containerRef,
context,
clientId,
onImageLoadError,
} ) {
const imageRef = useRef();
const captionRef = useRef();
Expand Down Expand Up @@ -213,11 +215,16 @@ export default function Image( {
}

function onImageError() {
// Check if there's an embed block that handles this URL.
// Check if there's an embed block that handles this URL, e.g., instagram URL.
// See: https://github.com/WordPress/gutenberg/pull/11472
const embedBlock = createUpgradedEmbedBlock( { attributes: { url } } );
if ( undefined !== embedBlock ) {
const shouldReplace = undefined !== embedBlock;

if ( shouldReplace ) {
onReplace( embedBlock );
}

onImageLoadError( shouldReplace );
}

function onSetHref( props ) {
Expand Down Expand Up @@ -289,6 +296,9 @@ export default function Image( {
if ( ! isSelected ) {
setIsEditingImage( false );
}
if ( isSelected && isMediaDestroyed( id ) ) {
onImageLoadError();
}
}, [ isSelected ] );

const canEditImage = id && naturalWidth && naturalHeight && imageEditing;
Expand Down Expand Up @@ -352,6 +362,7 @@ export default function Image( {
onSelect={ onSelectImage }
onSelectURL={ onSelectURL }
onError={ onUploadError }
onCloseModal={ onCloseModal }
/>
</BlockControls>
) }
Expand Down