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

Add amp-story-page element #11510

Merged
merged 11 commits into from
Oct 3, 2017
Merged

Add amp-story-page element #11510

merged 11 commits into from
Oct 3, 2017

Conversation

newmuis
Copy link
Contributor

@newmuis newmuis commented Sep 29, 2017

Implements the page level of the amp-story component.

Depends on #11330, #11485, #11509, and #11525




export class PageElement {

Choose a reason for hiding this comment

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

This is an interesting file. Was adding functionality/events to existing classes like amp-img.js not tenable?

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'm not sure whether the information we're seeking is general-purpose enough to port to those classes. We very likely need some kind of definition of "loaded" that is specific to amp-story, as the tradeoff between seeing loading indicators vs. seeing stuttering video is likely different in the story use-case than the article use-case.

/**
* The delay (in milliseconds) to wait between polling for loaded resources.
*/
const LOAD_TIMER_POLL_DELAY_MS = 250;

Choose a reason for hiding this comment

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

This seems coarse and will probably add ~125ms latency due to imprecision. Is avoiding polling altogether possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, should be possible. The first pass at this implementation used browser events (e.g. canplaythrough, loadeddata, and progress) and that didn't work well (seems like in practice, browsers differ pretty greatly in how they implement this, and it results in pretty poor results, especially on Android Chrome).

An intermediate implementation used events from each PageElement to the AmpStoryPage, but each element polled internally, since there were no events that got us the desired result. The code written here was a refactor of that to allow only creating a single timer per page, rather than a single timer per element (n timers per page).

Choose a reason for hiding this comment

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

Fair enough. Consider including this under an area for future optimization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed #11532

this.element.appendChild(loadingScreen);

// Build a list of page elements and poll until they are all loaded.
this.pageElements_ = PageElement.getElementsFromPage(this);

Choose a reason for hiding this comment

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

Do we know how performant this is in practice?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's a timeout (8s), but in practice it seems to be working reasonably, depending on the elements on the page.

We need to do something like this, though; having all the descendants loaded asynchronously whenever they are ready doesn't work well for this format. A potential future optimization is to use the hero attribute (or similar) to allow publishers to mark up which element(s) to wait for, but I think we'll need to default to a conservative approach, as partially loaded pages are very problematic for the format.

Choose a reason for hiding this comment

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

8ms I hope? 😅 Is that on a workstation with CPU throttling or on a low-end mobile device?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I guess it depends which part you're asking about the performance of. I don't think we've evaluated the performance of the PageElement.getElementsFromPage(this) call, but if you're talking about the comment // Build a list of page elements and poll until they are all loaded., then that's what has the 8s timeout. We'll show a loading indicator/screen for up to 8s after the user has started looking at the screen. It takes so long because we're actually waiting for the assets (i.e. mostly videos) to be fetched over the network.

Choose a reason for hiding this comment

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

I see. I was actually curious about the DOM queries. Generally we try to avoid DOM scans in favor of custom element API. For instance, forms would be more robust to dynamic markup changes (e.g. new form elements created from amp-list) if it used an <amp-form> instead of <form> as it does now.

We could devise a kind of dynamic add-on system to avoid the need for scanning here. Only justifiable if the scan is slow or we foresee dynamic markup in STAMP.

Copy link

@dreamofabear dreamofabear left a comment

Choose a reason for hiding this comment

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

Some small things that can be fixed. As discussed, feel free to address these in follow-up PRs.

* @return {!Promise}
* @private
*/
maybeApplyFirstAnimationFrame() {

Choose a reason for hiding this comment

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

Suffix private functions with _.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was meant to be public

}
}

/** */

Choose a reason for hiding this comment

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

Please document this function.

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



/**
* @return {boolean} True if animations were stopped.

Choose a reason for hiding this comment

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

@private?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is actually unused; deleted


/**
* Initializes the loading screen for this amp-story-page, and the listeners
* to remove it once loaded.

Choose a reason for hiding this comment

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

@private

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



/**
* Marks any AMP elements that represent media elements with preload="auto".

Choose a reason for hiding this comment

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

@private

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

isVideoInterfaceVideo_(el) {
// TODO(newmuis): Check whether the element has the
// i-amphtml-video-interface class, after #11015 from amphtml is merged
// into amphtml-story.

Choose a reason for hiding this comment

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

This can be fixed now.

* advance.
* @param {?Element} el
* @param {!function()} callback
* @return {!Element}

Choose a reason for hiding this comment

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

This function doesn't seem to return anything.

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

this.element.appendChild(loadingScreen);

// Build a list of page elements and poll until they are all loaded.
this.pageElements_ = PageElement.getElementsFromPage(this);

Choose a reason for hiding this comment

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

8ms I hope? 😅 Is that on a workstation with CPU throttling or on a low-end mobile device?

class VideoInterfaceElement extends PageElement {
constructor(element, page) {
super(element, page);
}

Choose a reason for hiding this comment

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

Minor: Can be removed.

/**
* The delay (in milliseconds) to wait between polling for loaded resources.
*/
const LOAD_TIMER_POLL_DELAY_MS = 250;

Choose a reason for hiding this comment

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

Fair enough. Consider including this under an area for future optimization.

@newmuis newmuis added this to Merge in Stories - By Type Oct 2, 2017
@newmuis newmuis moved this from Pending to Ready to Merge in Stories - By Type Oct 2, 2017
@newmuis newmuis moved this from Approved to Needs Work in Stories - By Type Oct 2, 2017
@ampprojectbot ampprojectbot added this to the Pending Triage milestone Oct 2, 2017
@newmuis newmuis moved this from Needs Work to Awaiting Review in Stories - By Type Oct 3, 2017
@newmuis
Copy link
Contributor Author

newmuis commented Oct 3, 2017

I think this is ready to be merged once the dependency PR #11509 is merged.

@newmuis newmuis moved this from Awaiting Review to Ready to Merge (approved + comments addressed) in Stories - By Type Oct 3, 2017
@alanorozco alanorozco merged commit d9b081d into ampproject:master Oct 3, 2017
@newmuis newmuis moved this from Ready to Merge (approved + comments addressed) to Merged in Stories - By Type Oct 3, 2017
@newmuis newmuis moved this from Migration to amphtml repo to Done in Stories - By Type Jan 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants