Skip to content

Commit

Permalink
MediaUpload and MediaPlaceholder unify props (#17145)
Browse files Browse the repository at this point in the history
  • Loading branch information
dratwas authored and koke committed Aug 30, 2019
1 parent a78f204 commit 3db95b7
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 79 deletions.
16 changes: 15 additions & 1 deletion packages/block-editor/src/components/media-placeholder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ This property is similar to the `allowedTypes` property. The difference is the f

- Type: `String`
- Required: No
- Platform: Web

### addToGallery

Expand All @@ -46,6 +47,7 @@ If false the gallery media modal opens in the edit mode where the user can edit
- Type: `Boolean`
- Required: No
- Default: `false`
- Platform: Web

### allowedTypes

Expand All @@ -57,20 +59,23 @@ This property is similar to the `accept` property. The difference is the format

- Type: `Array`
- Required: No
- Platform: Web | Mobile

### className

Class name added to the placeholder.

- Type: `String`
- Required: No
- Platform: Web

### icon

Icon to display left of the title. When passed as a `String`, the icon will be resolved as a [Dashicon](https://developer.wordpress.org/resource/dashicons/). Alternatively, you can pass in a `WPComponent` such as `BlockIcon`to render instead.

- Type: `String|WPComponent`
- Required: No
- Platform: Web | Mobile

### isAppender

Expand All @@ -80,14 +85,15 @@ If false the default placeholder style is used.
- Type: `Boolean`
- Required: No
- Default: `false`
- Platform: Web

### labels

An object that can contain a `title` and `instructions` properties. These properties are passed to the placeholder component as `label` and `instructions` respectively.

- Type: `Object`
- Required: No

- Platform: Web | Mobile

### multiple

Expand All @@ -96,13 +102,15 @@ Whether to allow multiple selection of files or not.
- Type: `Boolean`
- Required: No
- Default: `false`
- Platform: Web

### onError

Callback called when an upload error happens.

- Type: `Function`
- Required: No
- Platform: Web

### onSelect

Expand All @@ -111,13 +119,19 @@ The call back receives an array with the new files. Each element of the collecti

- Type: `Function`
- Required: Yes
- Platform: Web | Mobile

The argument of the callback is an object containing the following properties:
- Web: `{ url, alt, id, link, caption, sizes, media_details }`
- Mobile: `{ id, url }`

### value

Media ID (or media IDs if multiple is true) to be selected by default when opening the media library.

- Type: `Number|Array`
- Required: No
- Platform: Web


## Extend
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { withTheme, useStyle } from '@wordpress/components';
import styles from './styles.scss';

function MediaPlaceholder( props ) {
const { mediaType, labels = {}, icon, onSelectURL, theme } = props;
const { allowedTypes = [], labels = {}, icon, onSelect, theme } = props;

const isImage = MEDIA_TYPE_IMAGE === mediaType;
const isVideo = MEDIA_TYPE_VIDEO === mediaType;
const isOneType = allowedTypes.length === 1;
const isImage = isOneType && allowedTypes.includes( MEDIA_TYPE_IMAGE );
const isVideo = isOneType && allowedTypes.includes( MEDIA_TYPE_VIDEO );

let placeholderTitle = labels.title;
if ( placeholderTitle === undefined ) {
Expand Down Expand Up @@ -52,8 +53,8 @@ function MediaPlaceholder( props ) {

return (
<MediaUpload
mediaType={ mediaType }
onSelectURL={ onSelectURL }
allowedTypes={ allowedTypes }
onSelect={ onSelect }
render={ ( { open, getMediaOptions } ) => {
return (
<TouchableWithoutFeedback
Expand Down
10 changes: 9 additions & 1 deletion packages/block-editor/src/components/media-upload/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ If allowedTypes is unset all mime types should be allowed.

- Type: `Array`
- Required: No
- Platform: Web | Mobile

### multiple

Expand All @@ -71,20 +72,23 @@ Whether to allow multiple selections or not.
- Type: `Boolean`
- Required: No
- Default: false
- Platform: Web

### value

Media ID (or media IDs if multiple is true) to be selected by default when opening the media library.

- Type: `Number|Array`
- Required: No
- Platform: Web

### onSelect

Callback called when the media modal is closed, the selected media are passed as an argument.

- Type: `Function`
- Required: Yes
- Platform: Web | Mobile

### title

Expand All @@ -93,14 +97,15 @@ Title displayed in the media modal.
- Type: `String`
- Required: No
- Default: `Select or Upload Media`
- Platform: Web

### modalClass

CSS class added to the media modal frame.

- Type: `String`
- Required: No

- Platform: Web

### addToGallery

Expand All @@ -111,6 +116,7 @@ Only applies if `gallery === true`.
- Type: `Boolean`
- Required: No
- Default: `false`
- Platform: Web

### gallery

Expand All @@ -119,13 +125,15 @@ If true, the component will initiate all the states required to represent a gall
- Type: `Boolean`
- Required: No
- Default: `false`
- Platform: Web

## render

A callback invoked to render the Button opening the media library.

- Type: `Function`
- Required: Yes
- Platform: Web | Mobile

The first argument of the callback is an object containing the following properties:

Expand Down
99 changes: 50 additions & 49 deletions packages/block-editor/src/components/media-upload/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,27 @@ export const MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_WORD_PRESS_LIBRARY = 'wordpress_med

export const OPTION_TAKE_VIDEO = __( 'Take a Video' );
export const OPTION_TAKE_PHOTO = __( 'Take a Photo' );
export const OPTION_TAKE_PHOTO_OR_VIDEO = __( 'Take a Photo or Video' );

export class MediaUpload extends React.Component {
constructor( props ) {
super( props );
this.onPickerPresent = this.onPickerPresent.bind( this );
this.onPickerChange = this.onPickerChange.bind( this );
this.onPickerSelect = this.onPickerSelect.bind( this );
}
getTakeMediaLabel() {
const { mediaType } = this.props;
const { allowedTypes = [] } = this.props;

const isOneType = allowedTypes.length === 1;
const isImage = isOneType && allowedTypes.includes( MEDIA_TYPE_IMAGE );
const isVideo = isOneType && allowedTypes.includes( MEDIA_TYPE_VIDEO );

if ( mediaType === MEDIA_TYPE_IMAGE ) {
if ( isImage ) {
return OPTION_TAKE_PHOTO;
} else if ( mediaType === MEDIA_TYPE_VIDEO ) {
} else if ( isVideo ) {
return OPTION_TAKE_VIDEO;
}
} return OPTION_TAKE_PHOTO_OR_VIDEO;
}

getMediaOptionsItems() {
Expand All @@ -44,11 +55,15 @@ export class MediaUpload extends React.Component {
}

getChooseFromDeviceIcon() {
const { mediaType } = this.props;
const { allowedTypes = [] } = this.props;

const isOneType = allowedTypes.length === 1;
const isImage = isOneType && allowedTypes.includes( MEDIA_TYPE_IMAGE );
const isVideo = isOneType && allowedTypes.includes( MEDIA_TYPE_VIDEO );

if ( mediaType === MEDIA_TYPE_IMAGE ) {
if ( isImage || ! isOneType ) {
return 'format-image';
} else if ( mediaType === MEDIA_TYPE_VIDEO ) {
} else if ( isVideo ) {
return 'format-video';
}
}
Expand All @@ -61,58 +76,44 @@ export class MediaUpload extends React.Component {
return 'wordpress-alt';
}

render() {
const { mediaType } = this.props;

const onMediaLibraryButtonPressed = () => {
requestMediaPickFromMediaLibrary( [ mediaType ], ( mediaId, mediaUrl ) => {
if ( mediaId ) {
this.props.onSelectURL( mediaId, mediaUrl );
}
} );
};

const onMediaUploadButtonPressed = () => {
requestMediaPickFromDeviceLibrary( [ mediaType ], ( mediaId, mediaUrl ) => {
if ( mediaId ) {
this.props.onSelectURL( mediaId, mediaUrl );
}
} );
};

const onMediaCaptureButtonPressed = () => {
requestMediaPickFromDeviceCamera( [ mediaType ], ( mediaId, mediaUrl ) => {
if ( mediaId ) {
this.props.onSelectURL( mediaId, mediaUrl );
}
} );
};
onPickerPresent() {
if ( this.picker ) {
this.picker.presentPicker();
}
}

const mediaOptions = this.getMediaOptionsItems();
onPickerSelect( requestFunction ) {
const { allowedTypes = [], onSelect } = this.props;
requestFunction( allowedTypes, ( id, url ) => {
if ( id ) {
onSelect( { id, url } );
}
} );
}

let picker;
onPickerChange( value ) {
if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_CHOOSE_FROM_DEVICE ) {
this.onPickerSelect( requestMediaPickFromDeviceLibrary );
} else if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_TAKE_MEDIA ) {
this.onPickerSelect( requestMediaPickFromDeviceCamera );
} else if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_WORD_PRESS_LIBRARY ) {
this.onPickerSelect( requestMediaPickFromMediaLibrary );
}
}

const onPickerPresent = () => {
picker.presentPicker();
};
render() {
const mediaOptions = this.getMediaOptionsItems();

const getMediaOptions = () => (
<Picker
hideCancelButton={ true }
ref={ ( instance ) => picker = instance }
ref={ ( instance ) => this.picker = instance }
options={ mediaOptions }
onChange={ ( value ) => {
if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_CHOOSE_FROM_DEVICE ) {
onMediaUploadButtonPressed();
} else if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_TAKE_MEDIA ) {
onMediaCaptureButtonPressed();
} else if ( value === MEDIA_UPLOAD_BOTTOM_SHEET_VALUE_WORD_PRESS_LIBRARY ) {
onMediaLibraryButtonPressed();
}
} }
onChange={ this.onPickerChange }
/>
);
return this.props.render( { open: onPickerPresent, getMediaOptions } );

return this.props.render( { open: this.onPickerPresent, getMediaOptions } );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ const MEDIA_ID = 123;
describe( 'MediaUpload component', () => {
it( 'renders without crashing', () => {
const wrapper = shallow(
<MediaUpload render={ () => {} } />
<MediaUpload allowedTypes={ [] } render={ () => {} } />
);
expect( wrapper ).toBeTruthy();
} );

it( 'opens media options picker', () => {
const wrapper = shallow(
<MediaUpload render={ ( { open, getMediaOptions } ) => {
<MediaUpload allowedTypes={ [] } render={ ( { open, getMediaOptions } ) => {
return (
<TouchableWithoutFeedback onPress={ open }>
{ getMediaOptions() }
Expand All @@ -51,7 +51,7 @@ describe( 'MediaUpload component', () => {
const expectOptionForMediaType = ( mediaType, expectedOption ) => {
const wrapper = shallow(
<MediaUpload
mediaType={ mediaType }
allowedTypes={ [ mediaType ] }
render={ ( { open, getMediaOptions } ) => {
return (
<TouchableWithoutFeedback onPress={ open }>
Expand All @@ -72,12 +72,12 @@ describe( 'MediaUpload component', () => {
callback( MEDIA_ID, MEDIA_URL );
} );

const onSelectURL = jest.fn();
const onSelect = jest.fn();

const wrapper = shallow(
<MediaUpload
mediaType={ MEDIA_TYPE_VIDEO }
onSelectURL={ onSelectURL }
allowedTypes={ [ MEDIA_TYPE_VIDEO ] }
onSelect={ onSelect }
render={ ( { open, getMediaOptions } ) => {
return (
<TouchableWithoutFeedback onPress={ open }>
Expand All @@ -87,10 +87,12 @@ describe( 'MediaUpload component', () => {
} } />
);
wrapper.find( 'Picker' ).simulate( 'change', option );
const media = { id: MEDIA_ID, url: MEDIA_URL };

expect( requestFunction ).toHaveBeenCalledTimes( 1 );

expect( onSelectURL ).toHaveBeenCalledTimes( 1 );
expect( onSelectURL ).toHaveBeenCalledWith( MEDIA_ID, MEDIA_URL );
expect( onSelect ).toHaveBeenCalledTimes( 1 );
expect( onSelect ).toHaveBeenCalledWith( media );
};

it( 'can select media from device library', () => {
Expand Down
Loading

0 comments on commit 3db95b7

Please sign in to comment.