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 the AMP Preview button not being shown in the block editor #5441

Merged
merged 15 commits into from
Oct 5, 2020

Conversation

pierlon
Copy link
Contributor

@pierlon pierlon commented Sep 28, 2020

Summary

This PR fixes of the "Preview AMP" button no longer being shown on the edit post page (determined to be last working on Gutenberg v8.7.1). This has been tested on Gutenberg versions v6.8.0, v8.7.1, and v9.0.0.

The issue arises from the (non-AMP) "Preview" button no longer being available on DOM load (possibly due to async rendering of the component, but I have not confirmed). Previously, we would bail and not render the "Preview AMP" button if the "Preview" button was not found:

domReady( () => {
renderPreviewButton( AMPPreview );
} );

export const renderPreviewButton = ( PreviewComponent ) => {
const postPreviewButton = document.querySelector( `.${ POST_PREVIEW_CLASS }` );
const ampPreviewButtonWrapperId = 'amp-wrapper-post-preview';
// Exit if the non-AMP 'Preview' button doesn't exist.
if ( ! postPreviewButton || ! postPreviewButton.nextSibling ) {
return;
}

To fix this issue, the "Preview AMP" button component is no longer rendered on DOM load; the component is now registered as a block editor plugin. Once the block editor calls the component's render function, it will be rendered inside a DOM node we control (a portal), and not within the editor (yet). As the component is about to be mounted into the DOM node, a check is made to see if the "Preview" button is present, and if so, the component will be inserted immediately after the "Preview" button.

Upgrade Notice

For versions of WP prior to 5.2 or if Gutenberg 5.4+ is not running, then a warning is displayed prompting administrators to upgrade:

image

Checklist

  • My pull request is addressing an open issue (please create one otherwise).
  • My code is tested and passes existing tests.
  • My code follows the Engineering Guidelines (updates are often made to the guidelines, check it out periodically).

@pierlon pierlon added Bug Something isn't working Editor labels Sep 28, 2020
@pierlon pierlon added this to the v2.0.5 milestone Sep 28, 2020
@google-cla google-cla bot added the cla: yes Signed the Google CLA label Sep 28, 2020
@pierlon pierlon marked this pull request as ready for review September 29, 2020 05:05
@pierlon pierlon self-assigned this Sep 29, 2020
@github-actions
Copy link
Contributor

github-actions bot commented Sep 29, 2020

Plugin builds for 9321696 are ready 🛎️!

Copy link
Contributor

@johnwatkins0 johnwatkins0 left a comment

Choose a reason for hiding this comment

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

A couple of small pieces of feedback, @pierlon.

Also, while the approach here with createPortal and inserting an element into the DOM on component mount is working, I think there should be a little more separation of concerns so that the component doing all the preview work doesn't have to be so aware of the DOM context. Two possible ways to achieve this:

  1. Create and insert the DOM element at the start of the script, and then render the component into the created element using standard ReactDOM.render. This would require registering this particular editor plugin outside the loop where plugins are being registered, but I don't think that's a problem.
  2. If you still want to register the plugin inside the loop, I suggest doing the DOM manipulation work in a parent component that has that one job, and doing all the preview-related work in a child component.

this.openPreviewWindow = this.openPreviewWindow.bind( this );

this.root = document.createElement( 'div' );
this.root.id = 'amp-wrapper-post-preview';
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this should be a class instead of an ID. While unlikely, it's technically possible for this component to be rendered multiple times on a page.

@jwold jwold added the WS:Core Work stream for Plugin core label Sep 29, 2020
@pierlon
Copy link
Contributor Author

pierlon commented Sep 30, 2020

@johnwatkins0 I've opted for option #​2 from your review as I think it's the most applicable here. If I understand correctly, option #​1 would've entailed moving the rendered component next to the 'Preview' button once the component had been mounted. I'm not entirely sure what you meant by:

This would require registering this particular editor plugin outside the loop where plugins are being registered, but I don't think that's a problem.


export const name = 'amp-preview-button-wrapper';

export const render = pure(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've opted to make this a pure component as this does not warrant unnecessary re-rendering, unless I'm missing something. @johnwatkins0 thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a good idea. I've seen side effects from having createPortal inside components that re-render often. E.g., not applicable in this case, but if there were any CSS animations on any of the element inside the portal, the animation might restart on every rerender.

@johnwatkins0
Copy link
Contributor

johnwatkins0 commented Sep 30, 2020

This would require registering this particular editor plugin outside the loop where plugins are being registered, but I don't think that's a problem.

@pierlon I was referring to these lines:

plugins.keys().forEach( ( modulePath ) => {
const { name, render, icon } = plugins( modulePath );
registerPlugin( name, { icon, render } );
} );

All the plugin's editor plugins are expected to export the same variables to be registered in this loop. I already found this to be too limiting in a WIP branch I'm working on for the plugin sidebar, so I don't think we necessarily need to lock all editor plugins into this model. Performing DOM manipulation on the screen before registering the editor plugin is one use case that won't fit into the loop. But since your approach is working, this is a nonissue anyway.

Copy link
Contributor

@johnwatkins0 johnwatkins0 left a comment

Choose a reason for hiding this comment

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

Nice work!

@westonruter
Copy link
Member

There is a slight style difference between Core and GB:

Version Screenshot
Core image
GB 9.1 image

This seems to be resolved via:

.wp-core-ui .amp-editor-post-preview {
    margin-right: 0 !important;
}

In GB 9.1 these styles are causing the extra margin:

image

Should we fix the margins?

@pierlon
Copy link
Contributor Author

pierlon commented Oct 1, 2020

Ah good catch. That should be resolved in c2c883c.

Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

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

As discussed over chat, this is working back to WP 5.2:

image

However, in 5.1 and 5.0, neither the Preview button nor the AMP Enabled toggle appear:

image

sprintf(
'wp.domReady(
function () {
wp.data.dispatch( "core/notices" ).createWarningNotice( "%s" )
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
wp.data.dispatch( "core/notices" ).createWarningNotice( "%s" )
wp.data.dispatch( "core/notices" ).createWarningNotice( %s )

wp.data.dispatch( "core/notices" ).createWarningNotice( "%s" )
}
);',
__( 'AMP functionality is not available in the Block Editor as the current version installed is not supported. Please update the Block Editor plugin to the latest version or use the Classic Editor instead.', 'amp' )
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
__( 'AMP functionality is not available in the Block Editor as the current version installed is not supported. Please update the Block Editor plugin to the latest version or use the Classic Editor instead.', 'amp' )
wp_json_encode( __( 'AMP functionality is not available in the Block Editor as the current version installed is not supported. Please update the Block Editor plugin to the latest version or use the Classic Editor instead.', 'amp' ) )

@@ -213,6 +213,26 @@ public function enqueue_block_assets() {
return;
}

$gb_supported = defined( 'GUTENBERG_VERSION' ) && version_compare( GUTENBERG_VERSION, '5.3.0', '>=' );
Copy link
Member

Choose a reason for hiding this comment

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

Why 5.3.0 specifically?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was the first stable release that worked without any errors. I guess I could bump it to 5.4.0 since that was the version bundled with WP 5.2.


// Let the user know that block editor functionality is not available if the current Gutenberg or WordPress version is not supported.
if ( ! $gb_supported && ! $wp_supported ) {
wp_add_inline_script(
Copy link
Member

Choose a reason for hiding this comment

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

How about wrapping this in a current_user_can( 'manage_options' ) check? It doesn't do much good to show this warning to non-admin users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea that's a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 7d9ea2b.

@westonruter westonruter merged commit 7a41a7b into develop Oct 5, 2020
@westonruter westonruter deleted the fix/preview-button-not-displayed-in-editor branch October 5, 2020 20:27
@jwold jwold self-assigned this Oct 8, 2020
@jwold
Copy link
Collaborator

jwold commented Oct 8, 2020

@pierlon my testing steps were:

  1. Fresh install of WordPress
  2. Version 9.0.0 of Gutenberg
  3. Version 2.0 branch for QA
  4. Go to edit post and see preview button. https://d.pr/i/fQ8PuV

This is working as expected. Did I miss something though? Want to make sure I'm testing the right thing.

@westonruter
Copy link
Member

westonruter commented Oct 8, 2020

@jwold You need to switch to a Paired AMP mode (either Reader mode or Transitional mode). Then you should see an AMP-specific preview button like so:

image

@jwold
Copy link
Collaborator

jwold commented Oct 8, 2020

That worked! Thanks. QA passed.

Screen Shot 2020-10-08 at 14 54 55

@westonruter westonruter added the Changelogged Whether the issue/PR has been added to release notes. label Oct 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Changelogged Whether the issue/PR has been added to release notes. cla: yes Signed the Google CLA Editor WS:Core Work stream for Plugin core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants