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
More embed block fixes #1001
More embed block fixes #1001
Conversation
notnownikki
commented
Jun 2, 2017
- Loading the rendered html on loading a saved block moved into componentWillMount
- Removed '.includes' usage, as it's not polyfilled
- Added a new rendering state for when we're loading a saved block
- Replaced string manipulation of urls to extract the host, with url.parse
* Loading the rendered html on loading a saved block moved into componentWillMount * Removed '.includes' usage, as it's not polyfilled * Added a new rendering state for when we're loading a saved block * Replaced string manipulation of urls to extract the host, with url.parse
blocks/library/embed/index.js
Outdated
const { url, caption } = this.props.attributes; | ||
const { setAttributes, focus, setFocus } = this.props; | ||
|
||
if ( loadingFromSavedBlock ) { | ||
// we're loading from a saved block, but haven't fetched the HTML yet... | ||
return ( |
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.
@jasmussen what do you think should be the UX here? With this change it'd be the url as text shown until we can load the generated embed. Maybe a white box saying "Generating embed..." with the url in smaller text could be better?
blocks/library/embed/index.js
Outdated
} ); | ||
} | ||
); | ||
} | ||
|
||
render() { | ||
const { html, type, error, fetching } = this.state; | ||
const { html, type, error, fetching, loadingFromSavedBlock } = this.state; |
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.
I think ideally this should be the single loading
state, and it doesn't matter whether you just input the url in the embed field, or if it's loading from saved content.
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.
I think we need @jasmussen to cast a design spell on the loading state so it's suitable for both purposes 😄
Use the same UI state for fetching new embedded content and loading saved embed blocks in a post
blocks/library/embed/index.js
Outdated
return false; | ||
} | ||
host = host.replace( 'www.', '' ); | ||
for ( let i = 0; i < this.noPreview.length; i++ ) { |
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.
While we don't have native Array#includes
, we can still pull in the Lodash variation which dramatically simplifies the function:
isPreviewBlacklisted( host ) {
return includes( this.noPreview, host.replace( 'www.', '' ) );
}
Couple questions on the replace:
www
is a proper subdomain that can serve different content than the bare host. Is it appropriate in all cases to replace it? Are we expecting bothwww
and non-www
Facebook embeds?- If we want to keep
www.
replacing, probably want to test it at the beginning so that we don't get false positives likeisPreviewBlacklisted( 'facewww.book.com' )
. This would likely be a regular expression replace,host.replace( /^www\./, '' )
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.
oEmbed allows the user to embed with and without the www, even though facebook puts the www back in the embed html when its scripts run. So we need to account for that here.
blocks/library/embed/index.js
Outdated
@@ -85,8 +91,14 @@ registerBlockType( 'core/embed', { | |||
this.noPreview = [ | |||
'facebook.com', |
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.
I couldn't find much background on why we need to disable previews for some hosts. Should this be performed on the server instead of on the client? Also doesn't seem to need to be an instance variable assigned to each occurrence of the component but rather a top-level shared constant reference e.g. PREVIEW_HOST_BLACKLIST
.
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.
Eventually we'll move the embedded previews in the editor into sandbox iframes. Facebook embeds refused to run inside these iframes, and throw up errors, so we want to display a "sorry, preview not available" message instead.
Though, yeah, noPreview should be top level and named better. Will fix!
blocks/library/embed/index.js
Outdated
/** | ||
* External dependencies | ||
*/ | ||
import { parse } from 'url'; |
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.
Minor: There's a bit of an undocumented (semi-documented?) convention around ordering these blocks External
-> WordPress
-> Internal
(from most external to least external).
blocks/library/embed/index.js
Outdated
@@ -76,6 +81,7 @@ registerBlockType( 'core/embed', { | |||
constructor() { | |||
super( ...arguments ); | |||
this.doServerSideRender = this.doServerSideRender.bind( this ); | |||
this.isPreviewBlacklisted = this.isPreviewBlacklisted.bind( this ); |
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.
Technically this function may not need to be bound because it's never called in a context that would have a this
binding anything other than the current component instance (usually callbacks). But I think it's probably wise to err on the side of safety and bind
every component function.
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.
This is getting removed now that the noPreview domains are getting slightly reworked.
blocks/library/embed/index.js
Outdated
return ( | ||
<div className="blocks-embed__loading"> | ||
<Spinner /> | ||
<p className="blocks-embed__loading-text">{ wp.i18n.__( 'Embedding...' ) }</p> |
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.
Minor: Ellipsis character …
is more semantic than three dots for this purpose.
blocks/library/embed/index.js
Outdated
{ error && <p className="components-placeholder__error">{ wp.i18n.__( 'Sorry, we could not embed that content.' ) }</p> } | ||
</form> | ||
</Placeholder> | ||
); | ||
} | ||
|
||
const domain = url.split( '/' )[ 2 ].replace( /^www\./, '' ); | ||
const cannotPreview = this.noPreview.includes( domain ); | ||
const urlBits = parse( url ); |
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.
I might recommend a more meaningful name like parsedUrl
than "bits" here.
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.
But "bits" is cute! Sure, will change :)
* Elipsis character instead of ... * Removed cuteness from parsed url variable name * Moved "no preview" list of domains into top level const * Used lodash include * Fixed the www. removing regex * Fixed order of imports
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.
Good to go after modifier class change 👍
blocks/library/embed/index.js
Outdated
@@ -129,31 +140,38 @@ registerBlockType( 'core/embed', { | |||
const { url, caption } = this.props.attributes; | |||
const { setAttributes, focus, setFocus } = this.props; | |||
|
|||
if ( fetching ) { | |||
return ( | |||
<div className="blocks-embed__loading"> |
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 docs could probably do for some clarification, but it's intended that the root element of the return value should simply be top-level-folder
+ folder-name
, i.e. blocks-embed
. The treatment here is one reserved for descendants, or other components in the same folder (not index.js
).
https://github.com/WordPress/gutenberg/blob/master/docs/coding-guidelines.md#naming
Would be more appropriate to apply loading as a modifier class:
<div className="blocks-embed is-loading">