Skip to content

Commit

Permalink
Add loading state on image upload in featured image, Site logo and Co…
Browse files Browse the repository at this point in the history
…ver blocks (WordPress#59519)


Co-authored-by: sunil25393 <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: annezazu <[email protected]>
  • Loading branch information
5 people authored Apr 15, 2024
1 parent cca1f55 commit d9a6429
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 62 deletions.
15 changes: 12 additions & 3 deletions packages/block-library/src/cover/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,18 @@
}

// Applied while media is being uploaded
&.is-transient::before {
background-color: #fff;
opacity: 0.3;
&.is-transient {
position: relative;

&::before {
background-color: #fff;
content: "";
height: 100%;
opacity: 0.3;
position: absolute;
width: 100%;
z-index: 1;
}
}

// Shown while media is being uploaded
Expand Down
66 changes: 44 additions & 22 deletions packages/block-library/src/post-featured-image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { isBlobURL } from '@wordpress/blob';
import { useEntityProp, store as coreStore } from '@wordpress/core-data';
import { useSelect, useDispatch } from '@wordpress/data';
import {
Expand All @@ -14,6 +15,7 @@ import {
PanelBody,
Placeholder,
Button,
Spinner,
TextControl,
} from '@wordpress/components';
import {
Expand All @@ -27,7 +29,7 @@ import {
__experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
useBlockEditingMode,
} from '@wordpress/block-editor';
import { useMemo } from '@wordpress/element';
import { useMemo, useEffect, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { upload } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
Expand Down Expand Up @@ -70,6 +72,7 @@ export default function PostFeaturedImageEdit( {
linkTarget,
useFirstImageFromPost,
} = attributes;
const [ temporaryURL, setTemporaryURL ] = useState();

const [ storedFeaturedImage, setFeaturedImage ] = useEntityProp(
'postType',
Expand Down Expand Up @@ -144,6 +147,9 @@ export default function PostFeaturedImageEdit( {

const blockProps = useBlockProps( {
style: { width, height, aspectRatio },
className: classnames( {
'is-transient': temporaryURL,
} ),
} );
const borderProps = useBorderProps( attributes );
const shadowProps = getShadowClassesAndStyles( attributes );
Expand Down Expand Up @@ -173,11 +179,23 @@ export default function PostFeaturedImageEdit( {
if ( value?.id ) {
setFeaturedImage( value.id );
}

if ( value?.url && isBlobURL( value.url ) ) {
setTemporaryURL( value.url );
}
};

// Reset temporary url when media is available.
useEffect( () => {
if ( mediaUrl && temporaryURL ) {
setTemporaryURL();
}
}, [ mediaUrl, temporaryURL ] );

const { createErrorNotice } = useDispatch( noticesStore );
const onUploadError = ( message ) => {
createErrorNotice( message, { type: 'snackbar' } );
setTemporaryURL();
};

const controls = blockEditingMode === 'default' && (
Expand Down Expand Up @@ -241,7 +259,7 @@ export default function PostFeaturedImageEdit( {
/**
* A Post Featured Image block should not have image replacement
* or upload options in the following cases:
* - Is placed in a Query Loop. This is a consious decision to
* - Is placed in a Query Loop. This is a conscious decision to
* prevent content editing of different posts in Query Loop, and
* this could change in the future.
* - Is in a context where it does not have a postId (for example
Expand Down Expand Up @@ -289,7 +307,7 @@ export default function PostFeaturedImageEdit( {
* - It has no image assigned yet
* Then display the placeholder with the image upload option.
*/
if ( ! featuredImage ) {
if ( ! featuredImage && ! temporaryURL ) {
image = (
<MediaPlaceholder
onSelect={ onSelectImage }
Expand All @@ -315,24 +333,28 @@ export default function PostFeaturedImageEdit( {
);
} else {
// We have a Featured image so show a Placeholder if is loading.
image = ! media ? (
placeholder()
) : (
<img
className={ borderProps.className }
src={ mediaUrl }
alt={
media.alt_text
? sprintf(
// translators: %s: The image's alt text.
__( 'Featured image: %s' ),
media.alt_text
)
: __( 'Featured image' )
}
style={ imageStyles }
/>
);
image =
! media && ! temporaryURL ? (
placeholder()
) : (
<>
<img
className={ borderProps.className }
src={ temporaryURL || mediaUrl }
alt={
media && media?.alt_text
? sprintf(
// translators: %s: The image's alt text.
__( 'Featured image: %s' ),
media.alt_text
)
: __( 'Featured image' )
}
style={ imageStyles }
/>
{ temporaryURL && <Spinner /> }
</>
);
}

/**
Expand All @@ -343,7 +365,7 @@ export default function PostFeaturedImageEdit( {
*/
return (
<>
{ controls }
{ ! temporaryURL && controls }
{ !! media && ! isDescendentOfQueryLoop && (
<BlockControls group="other">
<MediaReplaceFlow
Expand Down
17 changes: 17 additions & 0 deletions packages/block-library/src/post-featured-image/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@
pointer-events: auto;
}
}

// When image being uploaded.
&.is-transient {
position: relative;

img {
opacity: 0.3;
}

// Show spinner while image is being uploaded.
.components-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}

div[data-type="core/post-featured-image"] {
Expand Down
82 changes: 49 additions & 33 deletions packages/block-library/src/site-logo/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,7 @@ const SiteLogo = ( {
const [ { naturalWidth, naturalHeight }, setNaturalSize ] = useState( {} );
const [ isEditingImage, setIsEditingImage ] = useState( false );
const { toggleSelection } = useDispatch( blockEditorStore );
const classes = classnames( 'custom-logo-link', {
'is-transient': isBlobURL( logoUrl ),
} );
const classes = classnames( 'custom-logo-link' );
const { imageEditing, maxWidth, title } = useSelect( ( select ) => {
const settings = select( blockEditorStore ).getSettings();
const siteEntities = select( coreStore ).getEntityRecord(
Expand Down Expand Up @@ -113,17 +111,20 @@ const SiteLogo = ( {
}

const img = (
<img
className="custom-logo"
src={ logoUrl }
alt={ alt }
onLoad={ ( event ) => {
setNaturalSize( {
naturalWidth: event.target.naturalWidth,
naturalHeight: event.target.naturalHeight,
} );
} }
/>
<>
<img
className="custom-logo"
src={ logoUrl }
alt={ alt }
onLoad={ ( event ) => {
setNaturalSize( {
naturalWidth: event.target.naturalWidth,
naturalHeight: event.target.naturalHeight,
} );
} }
/>
{ isBlobURL( logoUrl ) && <Spinner /> }
</>
);

let imgWrapper = img;
Expand Down Expand Up @@ -434,6 +435,7 @@ export default function LogoEdit( {
};
}, [] );
const { getSettings } = useSelect( blockEditorStore );
const [ temporaryURL, setTemporaryURL ] = useState();

const { editEntityRecord } = useDispatch( coreStore );

Expand Down Expand Up @@ -480,6 +482,7 @@ export default function LogoEdit( {

if ( ! media.id && media.url ) {
// This is a temporary blob image.
setTemporaryURL( media.url );
setLogo( undefined );
return;
}
Expand All @@ -495,6 +498,7 @@ export default function LogoEdit( {
const { createErrorNotice } = useDispatch( noticesStore );
const onUploadError = ( message ) => {
createErrorNotice( message, { type: 'snackbar' } );
setTemporaryURL();
};

const onFilesDrop = ( filesList ) => {
Expand All @@ -503,6 +507,7 @@ export default function LogoEdit( {
filesList,
onFileChange( [ image ] ) {
if ( isBlobURL( image?.url ) ) {
setTemporaryURL( image.url );
return;
}
onInitialSelectLogo( image );
Expand All @@ -517,7 +522,7 @@ export default function LogoEdit( {
onError: onUploadError,
onRemoveLogo,
};
const controls = canUserEdit && logoUrl && (
const controls = canUserEdit && logoUrl && ! temporaryURL && (
<BlockControls group="other">
<SiteLogoReplaceFlow { ...mediaReplaceFlowProps } />
</BlockControls>
Expand All @@ -528,22 +533,32 @@ export default function LogoEdit( {
if ( isLoading ) {
logoImage = <Spinner />;
}
if ( !! logoUrl ) {

// Reset temporary url when logoUrl is available.
useEffect( () => {
if ( logoUrl && temporaryURL ) {
setTemporaryURL();
}
}, [ logoUrl, temporaryURL ] );

if ( !! logoUrl || !! temporaryURL ) {
logoImage = (
<SiteLogo
alt={ alt }
attributes={ attributes }
className={ className }
isSelected={ isSelected }
setAttributes={ setAttributes }
logoUrl={ logoUrl }
setLogo={ setLogo }
logoId={ mediaItemData?.id || siteLogoId }
siteUrl={ url }
setIcon={ setIcon }
iconId={ siteIconId }
canUserEdit={ canUserEdit }
/>
<>
<SiteLogo
alt={ alt }
attributes={ attributes }
className={ className }
isSelected={ isSelected }
setAttributes={ setAttributes }
logoUrl={ temporaryURL || logoUrl }
setLogo={ setLogo }
logoId={ mediaItemData?.id || siteLogoId }
siteUrl={ url }
setIcon={ setIcon }
iconId={ siteIconId }
canUserEdit={ canUserEdit }
/>
</>
);
}
const placeholder = ( content ) => {
Expand All @@ -568,6 +583,7 @@ export default function LogoEdit( {

const classes = classnames( className, {
'is-default-size': ! width,
'is-transient': temporaryURL,
} );

const blockProps = useBlockProps( { className: classes } );
Expand Down Expand Up @@ -631,8 +647,8 @@ export default function LogoEdit( {
<div { ...blockProps }>
{ controls }
{ mediaInspectorPanel }
{ !! logoUrl && logoImage }
{ ! logoUrl && ! canUserEdit && (
{ ( !! logoUrl || !! temporaryURL ) && logoImage }
{ ! temporaryURL && ! logoUrl && ! canUserEdit && (
<Placeholder className="site-logo_placeholder">
{ !! isLoading && (
<span className="components-placeholder__preview">
Expand All @@ -641,7 +657,7 @@ export default function LogoEdit( {
) }
</Placeholder>
) }
{ ! logoUrl && canUserEdit && (
{ ! temporaryURL && ! logoUrl && canUserEdit && (
<MediaPlaceholder
onSelect={ onInitialSelectLogo }
accept={ ACCEPT_MEDIA_STRING }
Expand Down
21 changes: 17 additions & 4 deletions packages/block-library/src/site-logo/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,30 @@
&:focus {
box-shadow: none;
}

&.is-transient img {
opacity: 0.3;
}
}

img {
display: block;
height: auto;
max-width: 100%;
}

&.is-transient {
position: relative;

img {
opacity: 0.3;
}

// Shown while image is being uploaded.
.components-spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: 0;
}
}
}

// Provide special styling for the placeholder.
Expand Down

0 comments on commit d9a6429

Please sign in to comment.