diff --git a/packages/block-library/src/audio/edit.js b/packages/block-library/src/audio/edit.js index 68e9cc88117afe..47b2f36b2fb342 100644 --- a/packages/block-library/src/audio/edit.js +++ b/packages/block-library/src/audio/edit.js @@ -13,6 +13,7 @@ import { SelectControl, Spinner, ToggleControl, + ToolbarButton, } from '@wordpress/components'; import { BlockControls, @@ -25,12 +26,13 @@ import { store as blockEditorStore, __experimentalGetElementClassName, } from '@wordpress/block-editor'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useState, useCallback } from '@wordpress/element'; import { __, _x } from '@wordpress/i18n'; import { useDispatch, useSelect } from '@wordpress/data'; -import { audio as icon } from '@wordpress/icons'; +import { audio as icon, caption as captionIcon } from '@wordpress/icons'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; import { store as noticesStore } from '@wordpress/notices'; +import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies @@ -48,6 +50,8 @@ function AudioEdit( { insertBlocksAfter, } ) { const { id, autoplay, caption, loop, preload, src } = attributes; + const prevCaption = usePrevious( caption ); + const [ showCaption, setShowCaption ] = useState( !! caption ); const isTemporaryAudio = ! id && isBlobURL( src ); const mediaUpload = useSelect( ( select ) => { const { getSettings } = select( blockEditorStore ); @@ -69,6 +73,30 @@ function AudioEdit( { } }, [] ); + // We need to show the caption when changes come from + // history navigation(undo/redo). + useEffect( () => { + if ( caption && ! prevCaption ) { + setShowCaption( true ); + } + }, [ caption, prevCaption ] ); + + // Focus the caption when we click to add one. + const captionRef = useCallback( + ( node ) => { + if ( node && ! caption ) { + node.focus(); + } + }, + [ caption ] + ); + + useEffect( () => { + if ( ! isSelected && ! caption ) { + setShowCaption( false ); + } + }, [ isSelected, caption ] ); + function toggleAttribute( attribute ) { return ( newValue ) => { setAttributes( { [ attribute ]: newValue } ); @@ -106,12 +134,20 @@ function AudioEdit( { if ( ! media || ! media.url ) { // In this case there was an error and we should continue in the editing state // previous attributes should be removed because they may be temporary blob urls. - setAttributes( { src: undefined, id: undefined } ); + setAttributes( { + src: undefined, + id: undefined, + caption: undefined, + } ); return; } // Sets the block's attribute and updates the edit component from the // selected media, then switches off the editing UI. - setAttributes( { src: media.url, id: media.id } ); + setAttributes( { + src: media.url, + id: media.id, + caption: media.caption, + } ); } const classes = classnames( className, { @@ -140,6 +176,23 @@ function AudioEdit( { return ( <> + + { + setShowCaption( ! showCaption ); + if ( showCaption && caption ) { + setAttributes( { caption: undefined } ); + } + } } + icon={ captionIcon } + isPressed={ showCaption } + label={ + showCaption + ? __( 'Remove caption' ) + : __( 'Add caption' ) + } + /> + { isTemporaryAudio && } - { ( ! RichText.isEmpty( caption ) || isSelected ) && ( - - setAttributes( { caption: value } ) - } - inlineToolbar - __unstableOnSplitAtEnd={ () => - insertBlocksAfter( - createBlock( getDefaultBlockName() ) - ) - } - /> - ) } + { showCaption && + ( ! RichText.isEmpty( caption ) || isSelected ) && ( + + setAttributes( { caption: value } ) + } + inlineToolbar + __unstableOnSplitAtEnd={ () => + insertBlocksAfter( + createBlock( getDefaultBlockName() ) + ) + } + /> + ) } ); diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 12e7f6dd96d2f1..244b26cbf3e7ce 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -32,7 +32,13 @@ import { __experimentalGetElementClassName, __experimentalUseBorderProps as useBorderProps, } from '@wordpress/block-editor'; -import { useEffect, useMemo, useState, useRef } from '@wordpress/element'; +import { + useEffect, + useMemo, + useState, + useRef, + useCallback, +} from '@wordpress/element'; import { __, sprintf, isRTL } from '@wordpress/i18n'; import { getFilename } from '@wordpress/url'; import { @@ -93,7 +99,6 @@ export default function Image( { sizeSlug, } = attributes; const imageRef = useRef(); - const captionRef = useRef(); const prevCaption = usePrevious( caption ); const [ showCaption, setShowCaption ] = useState( !! caption ); const { allowResize = true } = context; @@ -195,11 +200,14 @@ export default function Image( { }, [ caption, prevCaption ] ); // Focus the caption when we click to add one. - useEffect( () => { - if ( showCaption && ! caption ) { - captionRef.current?.focus(); - } - }, [ caption, showCaption ] ); + const captionRef = useCallback( + ( node ) => { + if ( node && ! caption ) { + node.focus(); + } + }, + [ caption ] + ); // 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 @@ -343,7 +351,11 @@ export default function Image( { } } icon={ captionIcon } isPressed={ showCaption } - label={ __( 'Caption' ) } + label={ + showCaption + ? __( 'Remove caption' ) + : __( 'Add caption' ) + } /> ) } { ! multiImageSelection && ! isEditingImage && ( diff --git a/packages/block-library/src/video/edit.js b/packages/block-library/src/video/edit.js index f3c1e620955729..ac7970a20d2704 100644 --- a/packages/block-library/src/video/edit.js +++ b/packages/block-library/src/video/edit.js @@ -224,7 +224,11 @@ function VideoEdit( { } } icon={ captionIcon } isPressed={ showCaption } - label={ __( 'Caption' ) } + label={ + showCaption + ? __( 'Remove caption' ) + : __( 'Add caption' ) + } /> { const imageListLink = ( await getListViewBlocks( 'Image' ) )[ 0 ]; await imageListLink.click(); - await clickBlockToolbarButton( 'Caption' ); + await clickBlockToolbarButton( 'Add caption' ); const captionElement = await figureElement.$( '.block-editor-rich-text__editable' ); diff --git a/test/e2e/specs/editor/blocks/image.spec.js b/test/e2e/specs/editor/blocks/image.spec.js index 0413aa3e33e012..209511d2d1cfa5 100644 --- a/test/e2e/specs/editor/blocks/image.spec.js +++ b/test/e2e/specs/editor/blocks/image.spec.js @@ -157,7 +157,7 @@ test.describe( 'Image', () => { imageBlock.locator( 'data-testid=form-file-upload-input' ) ); await expect( image ).toHaveAttribute( 'src', new RegExp( filename ) ); - await editor.clickBlockToolbarButton( 'Caption' ); + await editor.clickBlockToolbarButton( 'Add caption' ); await page.keyboard.type( '1' ); await page.keyboard.press( 'Enter' ); await page.keyboard.press( 'Backspace' ); @@ -186,7 +186,7 @@ test.describe( 'Image', () => { await expect( image ).toBeVisible(); await expect( image ).toHaveAttribute( 'src', new RegExp( fileName ) ); - await editor.clickBlockToolbarButton( 'Caption' ); + await editor.clickBlockToolbarButton( 'Add caption' ); await page.keyboard.type( '12' ); await page.keyboard.press( 'ArrowLeft' ); await page.keyboard.press( 'Enter' ); @@ -217,7 +217,7 @@ test.describe( 'Image', () => { await expect( image ).toHaveAttribute( 'src', new RegExp( fileName ) ); // Add caption and navigate to inline toolbar. - await editor.clickBlockToolbarButton( 'Caption' ); + await editor.clickBlockToolbarButton( 'Add caption' ); await pageUtils.pressKeyWithModifier( 'shift', 'Tab' ); await expect( await page.evaluate( () =>