Skip to content

Commit

Permalink
[RNMobile] Add media inserter blocks to toolbar (#51827)
Browse files Browse the repository at this point in the history
* Add media button to native header toolbar

* Add other media button types

* Display media inserter buttons when no block is selected

* Add insertBlocks function to Header Toolbar

* Use const instead of function for renderMediaButtons

* Remove inline function for onInsertBlock

* Update header toolbar media block insertion method

* Update media toolbar insertion tests

* Update media toolbar insertion tests

* Update visual-editor test with Media Toolbar insertion tests

* Fix typo in Gallery block test

* Update visual editor tests to use toBeVisible when selecting Media Toolbar buttons

* Update Visual Editor gallery block selector

* Wrap Media Inserter toolbar buttons in ToolbarGroup

* Remove iOS ActionSheet conditional from Visual Editor test

* Update CHANGELOG

---------

Co-authored-by: Gerardo <gerardo.pacheco@automattic.com>
  • Loading branch information
derekblank and Gerardo authored Jul 6, 2023
1 parent 1ade4ec commit 1b82cbf
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 4 deletions.
4 changes: 2 additions & 2 deletions packages/block-library/src/gallery/test/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ describe( 'Gallery block', () => {

// This case is disabled until the issue (https://github.com/WordPress/gutenberg/issues/38444)
// is addressed.
it.skip( 'block remains selected after dimissing the media options picker', async () => {
it.skip( 'block remains selected after dismissing the media options picker', async () => {
// Initialize with an empty gallery
const { getByLabelText, getByText, getByTestId } =
await initializeEditor( {
Expand All @@ -175,7 +175,7 @@ describe( 'Gallery block', () => {
expect( getByText( 'Choose images' ) ).toBeVisible();
expect( getByText( 'WordPress Media Library' ) ).toBeVisible();

// Dimiss the picker
// Dismiss the picker
if ( Platform.isIOS ) {
fireEvent.press( getByText( 'Cancel' ) );
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ import {
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
import {
keyboardClose,
audio as audioIcon,
media as imageIcon,
video as videoIcon,
gallery as galleryIcon,
undo as undoIcon,
redo as redoIcon,
} from '@wordpress/icons';
import { store as editorStore } from '@wordpress/editor';
import { createBlock } from '@wordpress/blocks';

/**
* Internal dependencies
Expand All @@ -38,6 +43,7 @@ function HeaderToolbar( {
showInserter,
showKeyboardHideButton,
getStylesFromColorScheme,
insertBlock,
onHideKeyboard,
isRTL,
noContentSelected,
Expand All @@ -55,6 +61,7 @@ function HeaderToolbar( {
scrollViewRef.current.scrollTo( { x: 0 } );
}
};

const renderHistoryButtons = () => {
const buttons = [
/* TODO: replace with EditorHistoryRedo and EditorHistoryUndo. */
Expand Down Expand Up @@ -83,6 +90,60 @@ function HeaderToolbar( {
return isRTL ? buttons.reverse() : buttons;
};

const onInsertBlock = useCallback(
( blockType ) => () => {
insertBlock( createBlock( blockType ), undefined, undefined, true, {
source: 'inserter_menu',
} );
},
[ insertBlock ]
);

const renderMediaButtons = (
<ToolbarGroup>
<ToolbarButton
key="imageButton"
title={ __( 'Image' ) }
icon={ imageIcon }
onClick={ onInsertBlock( 'core/image' ) }
testID="insert-image-button"
extraProps={ {
hint: __( 'Insert Image Block' ),
} }
/>
<ToolbarButton
key="videoButton"
title={ __( 'Video' ) }
icon={ videoIcon }
onClick={ onInsertBlock( 'core/video' ) }
testID="insert-video-button"
extraProps={ {
hint: __( 'Insert Video Block' ),
} }
/>
<ToolbarButton
key="galleryButton"
title={ __( 'Gallery' ) }
icon={ galleryIcon }
onClick={ onInsertBlock( 'core/gallery' ) }
testID="insert-gallery-button"
extraProps={ {
hint: __( 'Insert Gallery Block' ),
} }
/>
<ToolbarButton
key="audioButton"
title={ __( 'Audio' ) }
icon={ audioIcon }
onClick={ onInsertBlock( 'core/audio' ) }
testID="insert-audio-button"
extraProps={ {
hint: __( 'Insert Audio Block' ),
} }
/>
</ToolbarGroup>
);

const onToggleInserter = useCallback(
( isOpen ) => {
if ( isOpen ) {
Expand Down Expand Up @@ -131,6 +192,7 @@ function HeaderToolbar( {
useExpandedMode={ useExpandedMode }
onToggle={ onToggleInserter }
/>
{ noContentSelected && renderMediaButtons }
{ renderHistoryButtons() }
<BlockToolbar />
</ScrollView>
Expand Down Expand Up @@ -181,7 +243,8 @@ export default compose( [
};
} ),
withDispatch( ( dispatch ) => {
const { clearSelectedBlock } = dispatch( blockEditorStore );
const { clearSelectedBlock, insertBlock } =
dispatch( blockEditorStore );
const { togglePostTitleSelection } = dispatch( editorStore );

return {
Expand All @@ -191,6 +254,7 @@ export default compose( [
clearSelectedBlock();
togglePostTitleSelection( false );
},
insertBlock,
};
} ),
withViewportMatch( { isLargeViewport: 'medium' } ),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`when nothing is selected media buttons and picker display correctly 1`] = `
"<!-- wp:paragraph -->
<p>First example paragraph.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Second example paragraph.</p>
<!-- /wp:paragraph -->
<!-- wp:gallery {"linkTo":"none"} -->
<figure class="wp-block-gallery has-nested-images columns-default is-cropped"></figure>
<!-- /wp:gallery -->"
`;
119 changes: 118 additions & 1 deletion packages/edit-post/src/components/visual-editor/test/index.native.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/**
* External dependencies
*/
import { initializeEditor, fireEvent } from 'test/helpers';
import { initializeEditor, getEditorHtml, fireEvent } from 'test/helpers';

/**
* WordPress dependencies
*/
import { Platform } from '@wordpress/element';
import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
import { registerCoreBlocks } from '@wordpress/block-library';

Expand All @@ -21,6 +22,12 @@ afterAll( () => {
} );
} );

const MEDIA_OPTIONS = [
'Choose from device',
'Take a Photo',
'WordPress Media Library',
];

const initialHtml = `
<!-- wp:paragraph -->
<p>First example paragraph.</p>
Expand Down Expand Up @@ -63,6 +70,38 @@ describe( 'when title is focused', () => {
screen.getAllByLabelText( /Paragraph Block. Row 3/ )[ 0 ]
).toBeDefined();
} );

it( 'media blocks should be displayed', async () => {
const screen = await initializeEditor( {
initialHtml,
} );

// Focus first block
fireEvent.press(
screen.getAllByLabelText( /Paragraph Block. Row 1/ )[ 0 ]
);

// Focus title
fireEvent(
screen.getAllByLabelText( 'Post title. test' )[ 0 ],
'select'
);

// Assert that the media buttons are visible
const imageButton = await screen.findByTestId( 'insert-image-button' );
expect( imageButton ).toBeVisible();

const videoButton = await screen.findByTestId( 'insert-video-button' );
expect( videoButton ).toBeVisible();

const galleryButton = await screen.findByTestId(
'insert-gallery-button'
);
expect( galleryButton ).toBeVisible();

const audioButton = await screen.findByTestId( 'insert-audio-button' );
expect( audioButton ).toBeVisible();
} );
} );

describe( 'when title is no longer focused', () => {
Expand Down Expand Up @@ -101,4 +140,82 @@ describe( 'when title is no longer focused', () => {
screen.getAllByLabelText( /Heading Block. Row 3/ )[ 0 ]
).toBeDefined();
} );

it( 'media blocks should not be displayed', async () => {
const screen = await initializeEditor( {
initialHtml,
} );

// Focus first block
fireEvent.press(
screen.getAllByLabelText( /Paragraph Block. Row 1/ )[ 0 ]
);

// Focus title
fireEvent(
screen.getAllByLabelText( 'Post title. test' )[ 0 ],
'select'
);

// Focus last block
fireEvent.press(
screen.getAllByLabelText( /Paragraph Block. Row 2/ )[ 0 ]
);

// Assert that the media buttons are not visible
const imageButton = screen.queryByTestId( 'insert-image-button' );
expect( imageButton ).toBeNull();

const videoButton = screen.queryByTestId( 'insert-video-button' );
expect( videoButton ).toBeNull();

const galleryButton = screen.queryByTestId( 'insert-gallery-button' );
expect( galleryButton ).toBeNull();

const audioButton = screen.queryByTestId( 'insert-audio-button' );
expect( audioButton ).toBeNull();
} );
} );

describe( 'when nothing is selected', () => {
it( 'media buttons and picker display correctly', async () => {
const screen = await initializeEditor( {
initialHtml,
} );

const { getByText, getByTestId } = screen;

// Check that the gallery button is visible within the toolbar
const galleryButton = await screen.queryByTestId(
'insert-gallery-button'
);
expect( galleryButton ).toBeVisible();

// Press the toolbar Gallery button
fireEvent.press( galleryButton );

// Expect the block to be created
expect(
screen.getAllByLabelText( /Gallery Block. Row 3/ )[ 0 ]
).toBeDefined();

expect( getByText( 'Choose images' ) ).toBeVisible();
MEDIA_OPTIONS.forEach( ( option ) =>
expect( getByText( option ) ).toBeVisible()
);

// Dismiss the picker
if ( Platform.isIOS ) {
fireEvent.press( getByText( 'Cancel' ) );
} else {
fireEvent( getByTestId( 'media-options-picker' ), 'backdropPress' );
}

// Expect the Gallery block to remain
expect(
screen.getAllByLabelText( /Gallery Block. Row 3/ )[ 0 ]
).toBeDefined();

expect( getEditorHtml() ).toMatchSnapshot();
} );
} );
1 change: 1 addition & 0 deletions packages/react-native-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ For each user feature we should also add a importance categorization label to i
## Unreleased
- [*] Rename "Reusable blocks" to "Synced patterns", aligning with the web editor. [#51704]
- [**] Fix a crash related to Reanimated when closing the editor [#52320]
- [**] Add media inserter buttons to editor toolbar [#51827]

## 1.98.1
- [*] fix: Display heading level dropdown icons and labels [#52004]
Expand Down

1 comment on commit 1b82cbf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 1b82cbf.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/5476109382
📝 Reported issues:

Please sign in to comment.