diff --git a/extensions/amp-story/0.1/amp-story-render-service.js b/extensions/amp-story/0.1/amp-story-render-service.js new file mode 100644 index 000000000000..1bf215172c1c --- /dev/null +++ b/extensions/amp-story/0.1/amp-story-render-service.js @@ -0,0 +1,50 @@ +/** + * Copyright 2019 The AMP HTML Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {CommonSignals} from '../../../src/common-signals'; +import {whenUpgradedToCustomElement} from '../../../src/dom'; + +/** @implements {../../../src/render-delaying-services.RenderDelayingService} */ +export class AmpStoryRenderService { + /** + * @param {!../../../src/service/ampdoc-impl.AmpDoc} ampdoc + */ + constructor(ampdoc) { + /** + * @private {!../../../src/service/ampdoc-impl.AmpDoc} + */ + this.ampdoc_ = ampdoc; + } + + /** + * Function to return a promise for when it is finished delaying render, and + * is ready. Implemented from RenderDelayingService + * @return {!Promise} + */ + whenReady() { + return this.ampdoc_.whenReady().then(body => { + const storyEl = body.querySelector('amp-story[standalone]'); + + if (!storyEl) { + return; + } + + return whenUpgradedToCustomElement(storyEl).then(() => { + return storyEl.signals().whenSignal(CommonSignals.LOAD_END); + }); + }); + } +} diff --git a/extensions/amp-story/0.1/amp-story.js b/extensions/amp-story/0.1/amp-story.js index a1a2d6bbc46c..aa2ad94e6ea6 100644 --- a/extensions/amp-story/0.1/amp-story.js +++ b/extensions/amp-story/0.1/amp-story.js @@ -40,6 +40,7 @@ import {AmpStoryCtaLayer} from './amp-story-cta-layer'; import {AmpStoryGridLayer} from './amp-story-grid-layer'; import {AmpStoryHint} from './amp-story-hint'; import {AmpStoryPage} from './amp-story-page'; +import {AmpStoryRenderService} from './amp-story-render-service'; import {AmpStoryRequestService} from './amp-story-request-service'; import {AmpStoryVariableService} from './variable-service'; import {Bookend} from './amp-story-bookend'; @@ -78,6 +79,7 @@ import { matches, removeElement, scopedQuerySelectorAll, + whenUpgradedToCustomElement, } from '../../../src/dom'; import { computedStyle, @@ -650,6 +652,15 @@ export class AmpStory extends AMP.BaseElement { this.validateConsent_(); + // Story is being prerendered: resolve the layoutCallback when the first + // page is built. Other pages will only build if the document becomes + // visible. + if (!Services.viewerForDoc(this.element).hasBeenVisible()) { + return whenUpgradedToCustomElement(firstPageEl).then(() => + firstPageEl.whenBuilt() + ); + } + return storyLayoutPromise; } @@ -1728,4 +1739,5 @@ AMP.extension('amp-story', '0.1', AMP => { AMP.registerElement('amp-story-grid-layer', AmpStoryGridLayer); AMP.registerElement('amp-story-cta-layer', AmpStoryCtaLayer); AMP.registerElement('amp-story-consent', AmpStoryConsent); + AMP.registerServiceForDoc('amp-story-render', AmpStoryRenderService); });