Skip to content
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

Fix withMediaLibraryNotice issue with latest Gutenberg releases #7711

Merged
merged 5 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 139 additions & 142 deletions assets/src/block-editor/components/with-media-library-notice.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
/**
* External dependencies
*/
import { isFunction } from 'lodash';

/**
* WordPress dependencies
*/
import { dispatch } from '@wordpress/data';
import { isFunction, get } from 'lodash';

/**
* Internal dependencies
*/
import {
FeaturedImageToolbarSelect,
getSelectMediaFrame,
} from '../../common/components/select-media-frame';
import { setImageFromURL } from '../../common/helpers';

const { wp } = window;
import { FeaturedImageToolbarSelect } from '../../common/components/select-media-frame';

/**
* Gets a wrapped version of MediaUpload to display a notice for small images.
Expand All @@ -37,146 +26,154 @@ export default (InitialMediaUpload, minImageDimensions) => {
minImageDimensions;

/**
* Mostly copied from customize-controls.js, with slight changes.
* Prepares the Featured Image toolbars and frames.
*
* @see https://github.com/WordPress/wordpress-develop/blob/c80325658f85d24ff82295dd2d55bfdf789f4163/src/js/_enqueues/wp/customize/controls.js#L4695
* @see wp.media.HeaderControl
* @return {window.wp.media.view.MediaFrame.Select} The default media workflow.
*/
return class FeaturedImageMediaUpload extends InitialMediaUpload {
/**
* Constructs the class.
*
* @param {*} args Constructor arguments.
*/
constructor(...args) {
super(...args);

// @todo This should be a different event.
// This class should only be present in the MediaUpload for the Featured Image.
if (
'editor-post-featured-image__media-modal' ===
this.props.modalClass
) {
this.initFeaturedImage = this.initFeaturedImage.bind(this);
this.initFeaturedImage();
} else {
// Restore the original`onOpen` callback as it will be overridden by the parent class.
this.frame.off('open', this.onOpen);
this.frame.on('open', super.onOpen.bind(this));
}
}

/**
* Initialize.
*
* Mainly copied from customize-controls.js, like most of this class.
*
* Overwrites the Media Library frame, this.frame.
* Adds a suggested width and height.
*/
initFeaturedImage() {
const FeaturedImageSelectMediaFrame = getSelectMediaFrame(
FeaturedImageToolbarSelect
);

const FeaturedImageLibrary =
wp.media.controller.FeaturedImage.extend({
defaults: {
...wp.media.controller.FeaturedImage.prototype.defaults,
date: false,
filterable: false,
// Note: These suggestions are shown in the media library image browser.
suggestedWidth: EXPECTED_WIDTH,
suggestedHeight: EXPECTED_HEIGHT,
},
const getFeaturedImageMediaFrame = () => {
const { wp } = window;

return wp.media.view.MediaFrame.Select.extend({
/**
* Create select toolbar.
*
* The only reason for this method is to override the select toolbar view class.
*
Copy link
Member

Choose a reason for hiding this comment

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

* Modified from {@link https://github.com/WordPress/wordpress-develop/blob/71cb3f861573f065c6d7d7ef1975bf98532239b4/src/js/media/views/frame/select.js#L167-L179}
*
* @override
*
* @param {Object} toolbar
* @param {Object} [options={}]
* @this {wp.media.controller.Region}
*/
createSelectToolbar(toolbar, options) {
options = options || this.options.button || {};
options.controller = this;
options = {
...options,
allowedTypes: get(this, ['options', 'allowedTypes'], null),
};

toolbar.view = new FeaturedImageToolbarSelect(options);
},

/**
* Enables the Set Featured Image Button.
*
* @param {Object} toolbar toolbar for featured image state
* @return {void}
*/
featuredImageToolbar(toolbar) {
this.createSelectToolbar(toolbar, {
text: wp.media.view.l10n.setFeaturedImage,
state: this.options.state,
});

this.frame = new FeaturedImageSelectMediaFrame({
allowedTypes: this.props.allowedTypes,
state: 'featured-image',
states: [
new FeaturedImageLibrary(),
new wp.media.controller.EditImage(),
],
});

this.frame.on(
'toolbar:create:featured-image',
function (toolbar) {
/**
* @this {wp.media.view.MediaFrame.Select}
*/
this.createSelectToolbar(toolbar, {
text: wp.media.view.l10n.setFeaturedImage,
state: this.options.state,
},

/**
* Handle the edit state requirements of selected media item.
*
* @return {void}
*/
editState() {
const selection = this.state('featured-image').get('selection');
const view = new wp.media.view.EditImage({
model: selection.single(),
controller: this,
}).render();

// Set the view to the EditImage frame using the selected image.
this.content.set(view);

// After bringing in the frame, load the actual editor via an ajax call.
view.loadEditor();
},

/**
* Create the default states.
*
* @return {void}
*/
createStates: function createStates() {
this.on(
'toolbar:create:featured-image',
this.featuredImageToolbar,
this
);
this.on('content:render:edit-image', this.editState, this);

const FeaturedImageLibrary =
wp.media.controller.FeaturedImage.extend({
defaults: {
...wp.media.controller.FeaturedImage.prototype
.defaults,
date: false,
filterable: false,
// Note: These suggestions are shown in the media library image browser.
suggestedWidth: EXPECTED_WIDTH,
suggestedHeight: EXPECTED_HEIGHT,
},
});
},
this.frame
);

this.frame.on('open', this.onOpen);

this.frame
.state('featured-image')
.on('select', this.onSelectImage, this);
this.states.add([
new FeaturedImageLibrary(),
new wp.media.controller.EditImage({
model: this.options.editImage,
}),
]);
},
});
};

// See wp.media() for this.
wp.media.frame = this.frame;
}
/**
* Get attachment collection.
*
* @param {Array} ids Attachment IDs.
* @return {Object} The attachment collection.
*/
const getAttachmentsCollection = (ids) => {
const { wp } = window;

return wp.media.query({
order: 'ASC',
orderby: 'post__in',
post__in: ids,
posts_per_page: -1,
query: true,
type: 'image',
});
};

/**
* Extends the MediaUpload component to display a notice for small images.
*/
return class FeaturedImageMediaUpload extends InitialMediaUpload {
/**
* Ensure the selected image is the first item in the collection.
* Initializes the Media Library requirements for the featured image flow.
*
* @see https://github.com/WordPress/gutenberg/blob/c58b32266f8c950c5b9927d286608343078aee02/packages/media-utils/src/components/media-upload/index.js#L401-L417
*/
onOpen() {
const frameContent = this.frame.content.get();
if (frameContent && frameContent.collection) {
const collection = frameContent.collection;

// Clean all attachments we have in memory.
collection
.toArray()
.forEach((model) => model.trigger('destroy', model));

// Reset has more flag, if library had small amount of items all items may have been loaded before.
collection.mirroring._hasMore = true;

// Request items.
collection.more();
}
}

/**
* Handles image selection.
* @override
* @description Overrides the media upload component's initialize method for featured image.
*
* Modified from {@link https://github.com/WordPress/gutenberg/blob/debddee2ace15263c08c66b5f5a43a9e17bf5d0c/packages/media-utils/src/components/media-upload/index.js#L301-L316|Original MediaUpload buildAndSetFeatureImageFrame method}.
*
* @return {void}
*/
onSelectImage() {
const attachment = this.frame
.state('featured-image')
.get('selection')
.first()
.toJSON();
const dispatchImage = (attachmentId) => {
dispatch('core/editor').editPost({
featured_media: attachmentId,
});
};
const { onSelect } = this.props;
const { url, id, width, height } = attachment;
setImageFromURL({
url,
id,
width,
height,
onSelect,
dispatchImage,
buildAndSetFeatureImageFrame() {
const { wp } = window;
const FeaturedImageFrame = getFeaturedImageMediaFrame();
const attachments = getAttachmentsCollection(this.props.value);
const selection = new wp.media.model.Selection(attachments.models, {
props: attachments.props.toJSON(),
});

if (!wp.media.view.settings.post.featuredImageId) {
return;
}

wp.media.featuredImage.set(attachment ? attachment.id : -1);
this.frame = new FeaturedImageFrame({
mimeType: this.props.allowedTypes,
state: 'featured-image',
multiple: this.props.multiple,
selection,
editing: Boolean(this.props.value),
});
wp.media.frame = this.frame;
}
};
};
11 changes: 8 additions & 3 deletions tests/e2e/specs/block-editor/amp-preview-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import {
deactivatePlugin,
} from '../../utils/amp-settings-utils';

const postPreviewBtnSelector = '.components-button.editor-post-preview';
const postPreviewBtnSelector =
'.components-button.edit-post-header__post-preview-button';
const ampPreviewBtnSelector = `${postPreviewBtnSelector} + .amp-wrapper-post-preview > .amp-editor-post-preview`;

// Remove legacy selectors once changes of <https://github.com/WordPress/gutenberg/pull/56921> lands in WP core.
const legacyPreviewBtnSelector = '.components-button.editor-post-preview';
const legacyAmpPreviewBtnSelector = `${legacyPreviewBtnSelector} + .amp-wrapper-post-preview > .amp-editor-post-preview`;

describe('AMP Preview button', () => {
it('is rendered on a new post', async () => {
await createNewPost();
Expand All @@ -27,9 +32,9 @@ describe('AMP Preview button', () => {
await deactivatePlugin('gutenberg');

await createNewPost();
await page.waitForSelector(postPreviewBtnSelector);
await page.waitForSelector(legacyPreviewBtnSelector);

await expect(page).toMatchElement(ampPreviewBtnSelector);
await expect(page).toMatchElement(legacyAmpPreviewBtnSelector);

await activatePlugin('gutenberg');
});
Expand Down
Loading