-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MediaUpload and MediaPlaceholder unify props #17145
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ This property is similar to the `allowedTypes` property. The difference is the f | |
|
||
- Type: `String` | ||
- Required: No | ||
- Platform: Web | ||
|
||
### addToGallery | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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 | ||
|
||
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the description above, the argument is an array containing those kinds of objects There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An array with those kinds of objects is an argument in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I thought it always returned an array on the web, but it seems the argument can be either an array or an object depending on the |
||
- 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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally I've updated EDIT: I've just noticed PR which is adding that functionality For Picker (bottom sheet) I had to add a default label for that case Except this I think we're ready to merge it. Please, let me know if everything is correct. cc: @koke There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think admin-media is the more generic option, but I'd ask @iamthomasbishop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are supporting only My preference would be to either use the existing icon (image icon as shown above by @pinarol ) or substitute in another icon, perhaps something that indicates There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that place, we are using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So right now there is a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, that makes sense. My suggestion would be to stay with |
||
|
||
getMediaOptionsItems() { | ||
|
@@ -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'; | ||
} | ||
} | ||
|
@@ -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 } ); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@youknowriad 👋 Could you also be able to review README.md changes here? I believe Platform attribute is being added the first time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this seems like a good idea to include in the README to raise awareness of the mobile side of things. I don't know if this is going to be clear enough that it's about native mobile apps. We should first provide some guidelines in the official Gutenberg docs about that and ensure that those components can work out of the box when imported as npm packages.
Can we discuss it first at the upcoming weekly Core JS meeting so people could share their opinions? See https://make.wordpress.org/meetings/.
There should also a way to include the same information in JSDoc comments as we are moving towards automated public API generation from such JSDoc comments. @nosolosw - do you think it would be easy to extend
@wordpress/docgen
to support it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The biggest problem as of now is to have the components' props documented automatically. Most of them don't contain any JSDoc and, AFAIK, we haven't looked into infer anything from the internal structure (such as inferring existing props from React components).
Another thing is that there is no JSDoc mechanism to declare that a particular param is only avaliable for web or mobile. I guess we can add that to the param's description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this topic during Core JS chat this week:
https://wordpress.slack.com/archives/C5UNMSU4R/p1566914617419700
(link requires registration at https://make.wordpress.org/chat/).
We should proceed with the platform related notes as proposed in this PR. Let's open PR which documents the process so we could replicate it for other components. It usually helps to enforce some standards when they are well documented.
@nosolosw, thanks for chiming in. We definitely will have to find a way to mark with JSDoc whether a given function or components as an entity is available on the given platform. We can start at the general level and leave props for future iterations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @gziolo ! We'll be starting such a document to describe
Platform
usage inREADME.md
files, we can then iterate on it on a separate PR.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gziolo @koke I've created #17230 to track the discussion about documentation taking into account the core-js conversation. Please, feel free to expand on what did you like about some of the examples provided (ionic, apple docs) or anything else that you find missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet, thanks @nosolosw 👍