Skip to content

Commit

Permalink
[RNMobile] Gallery block: Fix crash when adding images and selecting …
Browse files Browse the repository at this point in the history
…a gallery item (#38238)

* Add the native variant of MediaReplaceFlow

Since the MediaReplaceFlow component is not implemented yet in the native version of the editor, we return an empty component instead.

* Set MediaPlaceholder props by platform in gallery

* Update react-native-editor changelog

* Remove autoOpenMediaUpload from web props

`autoOpenMediaUpload` prop is only used in the native version of the `MediaPlaceholder` component hence, we don't need to define it in the props set for the web version.

* Add gallery block integration tests

* Unify shared props between web and native
  • Loading branch information
fluiddot authored Jan 27, 2022
1 parent 7163532 commit d9d473b
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export {
RichTextToolbarButton,
__unstableRichTextInputEvent,
} from './rich-text';
export { default as MediaReplaceFlow } from './media-replace-flow';
export { default as MediaPlaceholder } from './media-placeholder';
export {
default as MediaUpload,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// MediaReplaceFlow component is not yet implemented in the native version,
// so we return an empty component instead.
export default () => null;
28 changes: 23 additions & 5 deletions packages/block-library/src/gallery/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,11 +429,26 @@ function GalleryEdit( props ) {
( img ) => ! img.id && img.url?.indexOf( 'blob:' ) === 0
);

// MediaPlaceholder props are different between web and native hence, we provide a platform-specific set.
const mediaPlaceholderProps = Platform.select( {
web: {
addToGallery: false,
disableMediaButtons: imagesUploading,
value: {},
},
native: {
addToGallery: hasImageIds,
isAppender: hasImages,
disableMediaButtons:
( hasImages && ! isSelected ) || imagesUploading,
value: hasImageIds ? images : {},
autoOpenMediaUpload:
! hasImages && isSelected && wasBlockJustInserted,
},
} );
const mediaPlaceholder = (
<MediaPlaceholder
addToGallery={ false }
handleUpload={ false }
disableMediaButtons={ imagesUploading }
icon={ sharedIcon }
labels={ {
title: __( 'Gallery' ),
Expand All @@ -443,10 +458,9 @@ function GalleryEdit( props ) {
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
value={ {} }
onError={ onUploadError }
notices={ noticeUI }
autoOpenMediaUpload={ isSelected && wasBlockJustInserted }
{ ...mediaPlaceholderProps }
/>
);

Expand Down Expand Up @@ -537,7 +551,11 @@ function GalleryEdit( props ) {
<Gallery
{ ...props }
images={ images }
mediaPlaceholder={ ! hasImages ? mediaPlaceholder : undefined }
mediaPlaceholder={
! hasImages || Platform.isNative
? mediaPlaceholder
: undefined
}
blockProps={ blockProps }
insertBlocksAfter={ insertBlocksAfter }
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Gallery block inserts block 1`] = `
"<!-- wp:gallery {\\"linkTo\\":\\"none\\"} -->
<figure class=\\"wp-block-gallery has-nested-images columns-default is-cropped\\"></figure>
<!-- /wp:gallery -->"
`;
128 changes: 128 additions & 0 deletions packages/block-library/src/gallery/test/index.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**
* External dependencies
*/
import {
getEditorHtml,
initializeEditor,
fireEvent,
waitFor,
within,
} from 'test/helpers';

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

beforeAll( () => {
// Register all core blocks
registerCoreBlocks();
} );

afterAll( () => {
// Clean up registered blocks
getBlockTypes().forEach( ( block ) => {
unregisterBlockType( block.name );
} );
} );

const GALLERY_WITH_ONE_IMAGE = `<!-- wp:gallery {"linkTo":"none"} -->
<figure class="wp-block-gallery has-nested-images columns-default is-cropped"><!-- wp:image {"id":1} -->
<figure class="wp-block-image"><img src="https://cldup.com/cXyG__fTLN.jpg" alt="" class="wp-image-1"/></figure>
<!-- /wp:image --></figure>
<!-- /wp:gallery -->`;

const addGalleryBlock = async () => {
const screen = initializeEditor();
const { getByA11yLabel, getByTestId, getByText } = screen;

fireEvent.press( getByA11yLabel( 'Add block' ) );

const blockList = getByTestId( 'InserterUI-Blocks' );
// onScroll event used to force the FlatList to render all items
fireEvent.scroll( blockList, {
nativeEvent: {
contentOffset: { y: 0, x: 0 },
contentSize: { width: 100, height: 100 },
layoutMeasurement: { width: 100, height: 100 },
},
} );

fireEvent.press( await waitFor( () => getByText( 'Gallery' ) ) );

return screen;
};

describe( 'Gallery block', () => {
it( 'inserts block', async () => {
const { getByA11yLabel } = await addGalleryBlock();

const galleryBlock = await waitFor( () =>
getByA11yLabel( /Gallery Block\. Row 1/ )
);

expect( galleryBlock ).toHaveProperty( 'type', 'View' );
expect( getEditorHtml() ).toMatchSnapshot();
} );

it( 'selects a gallery item', async () => {
const { getByA11yLabel } = initializeEditor( {
initialHtml: GALLERY_WITH_ONE_IMAGE,
} );

const galleryBlock = await waitFor( () =>
getByA11yLabel( /Gallery Block\. Row 1/ )
);
fireEvent.press( galleryBlock );

const innerBlockListWrapper = await waitFor( () =>
within( galleryBlock ).getByTestId( 'block-list-wrapper' )
);
fireEvent( innerBlockListWrapper, 'layout', {
nativeEvent: {
layout: {
width: 100,
},
},
} );

const galleryItem = await waitFor( () =>
getByA11yLabel( /Image Block\. Row 1/ )
);
fireEvent.press( galleryItem );

expect( galleryItem ).toHaveProperty( 'type', 'View' );
} );

it( 'shows appender button when gallery has images', async () => {
const { getByA11yLabel, getByText } = initializeEditor( {
initialHtml: GALLERY_WITH_ONE_IMAGE,
} );

const galleryBlock = await waitFor( () =>
getByA11yLabel( /Gallery Block\. Row 1/ )
);
fireEvent.press( galleryBlock );

const innerBlockListWrapper = await waitFor( () =>
within( galleryBlock ).getByTestId( 'block-list-wrapper' )
);
fireEvent( innerBlockListWrapper, 'layout', {
nativeEvent: {
layout: {
width: 100,
},
},
} );

const appenderButton = await waitFor( () =>
within( galleryBlock ).getByA11yLabel( /Gallery block\. Empty/ )
);
fireEvent.press( appenderButton );

expect( getByText( 'Choose from device' ) ).toBeDefined();
expect( getByText( 'Take a Photo' ) ).toBeDefined();
expect( getByText( 'WordPress Media Library' ) ).toBeDefined();
} );
} );
2 changes: 2 additions & 0 deletions packages/react-native-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ For each user feature we should also add a importance categorization label to i

## Unreleased

- [**] [Gallery block] Fix crash when adding images and selecting a gallery item [#38238]

## 1.70.0

- [**] Fix content justification attribute in Buttons block [#37887]
Expand Down
3 changes: 3 additions & 0 deletions test/native/__mocks__/styleMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,7 @@ module.exports = {
'components-autocomplete': {
height: 100,
},
addMediaButton: {
color: 'white',
},
};

0 comments on commit d9d473b

Please sign in to comment.