Skip to content

Commit

Permalink
✨[story ads] Introduce new progress bar (ampproject#33972)
Browse files Browse the repository at this point in the history
* works

* test

* z index
  • Loading branch information
calebcordry authored Apr 23, 2021
1 parent 0c1b1f5 commit 583a733
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 32 deletions.
1 change: 1 addition & 0 deletions build-system/compile/bundles.config.extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,7 @@
"amp-story-auto-ads-attribution",
"amp-story-auto-ads-cta-button",
"amp-story-auto-ads-inabox",
"amp-story-auto-ads-progress-bar",
"amp-story-auto-ads-shared"
]
}
Expand Down
1 change: 1 addition & 0 deletions css/Z_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
`amp-story[standalone] .i-amphtml-story-developer-log` | 100002 | [extensions/amp-story/1.0/amp-story.css](/extensions/amp-story/1.0/amp-story.css)
`.i-amphtml-story-button-container` | 100002 | [extensions/amp-story/1.0/pagination-buttons.css](/extensions/amp-story/1.0/pagination-buttons.css)
`.i-amphtml-ad-overlay-container` | 100001 | [extensions/amp-story-auto-ads/0.1/amp-story-auto-ads-ad-badge.css](/extensions/amp-story-auto-ads/0.1/amp-story-auto-ads-ad-badge.css)
`.i-amphtml-story-ad-progress-background` | 100001 | [extensions/amp-story-auto-ads/0.1/amp-story-auto-ads-progress-bar.css](/extensions/amp-story-auto-ads/0.1/amp-story-auto-ads-progress-bar.css)
`.i-amphtml-story-bookend` | 100001 | [extensions/amp-story/1.0/amp-story-bookend.css](/extensions/amp-story/1.0/amp-story-bookend.css)
`.i-amphtml-story-info-dialog` | 100001 | [extensions/amp-story/1.0/amp-story-info-dialog.css](/extensions/amp-story/1.0/amp-story-info-dialog.css)
`.i-amphtml-story-progress-bar` | 100001 | [extensions/amp-story/1.0/amp-story-system-layer.css](/extensions/amp-story/1.0/amp-story-system-layer.css)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright 2021 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.
*/

.i-amphtml-story-ad-progress-background {
background: hsla(0, 0%, 100%, 0.4) !important;
border-radius: 1px !important;
height: 2px !important;
left: 4px !important;
margin: 4px auto !important;
opacity: 0 !important;
position: absolute !important;
width: calc(100% - 8px) !important;
visibility: hidden !important;
z-index: 100001 !important;
}

.i-amphtml-story-ad-progress-background[ad-showing] {
opacity: 1 !important;
visibility: visible !important;
}

.i-amphtml-story-ad-progress-background[desktop-panels] {
/* On desktop a story page has a width of 45vh. */
/* And a height of 75 vh. */
left: calc(50vw - 22.5vh + 4px) !important;
top: 12.5vh !important;
width: calc(45vh - 8px) !important;
/* Have to wait for page to slide in. */
transition: opacity 0.1s linear 0.3s;
}

.i-amphtml-story-ad-progress-bar {
background: #fff !important;
height: 2px !important;
}

[ad-showing] .i-amphtml-story-ad-progress-bar {
animation: grow linear;
}

@keyframes grow {
from {
width: 0%;
}
to {
width: 100%;
}
}
71 changes: 56 additions & 15 deletions extensions/amp-story-auto-ads/0.1/amp-story-auto-ads.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import {dict} from '../../../src/core/types/object';
import {divertStoryAdPlacements} from '../../../src/experiments/story-ad-placements';
import {getPlacementAlgo} from './algorithm-utils';
import {getServicePromiseForDoc} from '../../../src/service';
import {isExperimentOn} from '../../../src/experiments';
import {CSS as progessBarCSS} from '../../../build/amp-story-auto-ads-progress-bar-0.1.css';
import {setStyle} from '../../../src/style';
import {CSS as sharedCSS} from '../../../build/amp-story-auto-ads-shared-0.1.css';

/** @const {string} */
Expand Down Expand Up @@ -78,6 +81,9 @@ export class AmpStoryAutoAds extends AMP.BaseElement {
/** @private {?Element} */
this.adBadgeContainer_ = null;

/** @private {?Element} */
this.progressBarBackground_ = null;

/** @private {?../../amp-story/1.0/amp-story-store-service.AmpStoryStoreService} */
this.storeService_ = null;

Expand Down Expand Up @@ -149,6 +155,7 @@ export class AmpStoryAutoAds extends AMP.BaseElement {
STORY_AD_ANALYTICS
);
this.createAdOverlay_();
this.maybeCreateProgressBar_();
this.initializeListeners_();
this.initializePages_();
});
Expand Down Expand Up @@ -261,9 +268,17 @@ export class AmpStoryAutoAds extends AMP.BaseElement {
*/
onAdStateUpdate_(isAd) {
this.mutateElement(() => {
isAd
? this.adBadgeContainer_.setAttribute(Attributes.AD_SHOWING, '')
: this.adBadgeContainer_.removeAttribute(Attributes.AD_SHOWING);
if (isAd) {
this.adBadgeContainer_.setAttribute(Attributes.AD_SHOWING, '');
// TODO(#33969) can no longer be null when launched.
this.progressBarBackground_ &&
this.progressBarBackground_.setAttribute(Attributes.AD_SHOWING, '');
} else {
this.adBadgeContainer_.removeAttribute(Attributes.AD_SHOWING);
// TODO(#33969) can no longer be null when launched.
this.progressBarBackground_ &&
this.progressBarBackground_.removeAttribute(Attributes.AD_SHOWING);
}
});
}

Expand All @@ -289,24 +304,19 @@ export class AmpStoryAutoAds extends AMP.BaseElement {
onUIStateUpdate_(uiState) {
this.mutateElement(() => {
const {DESKTOP_PANELS} = Attributes;
const root = this.adBadgeContainer_;

root.removeAttribute(DESKTOP_PANELS);
this.adBadgeContainer_.removeAttribute(DESKTOP_PANELS);
// TODO(#33969) can no longer be null when launched.
this.progressBarBackground_ &&
this.progressBarBackground_.removeAttribute(DESKTOP_PANELS);

if (uiState === UIType.DESKTOP_PANELS) {
root.setAttribute(DESKTOP_PANELS, '');
this.adBadgeContainer_.setAttribute(DESKTOP_PANELS, '');
this.progressBarBackground_ &&
this.progressBarBackground_.setAttribute(DESKTOP_PANELS, '');
}
});
}

/**
* @visibleForTesting
* @return {Element}
*/
getAdBadgeRoot() {
return this.adBadgeContainer_;
}

/**
* Create a hidden UI that will be shown when ad is displayed
* @private
Expand All @@ -326,6 +336,37 @@ export class AmpStoryAutoAds extends AMP.BaseElement {
this.ampStory_.element.appendChild(root);
}

/**
* Create progress bar if auto advance exp is on.
*/
maybeCreateProgressBar_() {
// TODO(ccordry): use experiment branch to set time value.
if (isExperimentOn(this.win, 'story-ad-auto-advance')) {
this.createProgressBar_('6s');
}
}

/**
* Create progress bar that will be shown when ad is advancing.
* @param {string} time
*/
createProgressBar_(time) {
const progressBar = this.doc_.createElement('div');
progressBar.className = 'i-amphtml-story-ad-progress-bar';
setStyle(progressBar, 'animationDuration', time);

this.progressBarBackground_ = this.doc_.createElement('div');
this.progressBarBackground_.className =
'i-amphtml-story-ad-progress-background';

const host = this.doc_.createElement('div');
host.className = 'i-amphtml-story-ad-progress-bar-host';

this.progressBarBackground_.appendChild(progressBar);
createShadowRootWithStyle(host, this.progressBarBackground_, progessBarCSS);
this.ampStory_.element.appendChild(host);
}

/**
* Create new page containing ad and start preloading.
* @private
Expand Down
61 changes: 44 additions & 17 deletions extensions/amp-story-auto-ads/0.1/test/test-amp-story-auto-ads.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {Services} from '../../../../src/services';
import {StoryAdPage} from '../story-ad-page';
import {macroTask} from '../../../../testing/yield';
import {registerServiceBuilder} from '../../../../src/service';
import {toggleExperiment} from '../../../../src/experiments';

const NOOP = () => {};

Expand Down Expand Up @@ -266,8 +267,10 @@ describes.realWin(
});
});

describe('ad badge', () => {
describe('system layer', () => {
beforeEach(async () => {
// TODO(#33969) remove when launched.
toggleExperiment(win, 'story-ad-auto-advance', true);
// Force sync mutateElement.
env.sandbox.stub(autoAds, 'mutateElement').callsArg(0);
addStoryAutoAdsConfig(adElement);
Expand All @@ -279,33 +282,57 @@ describes.realWin(
await autoAds.layoutCallback();
});

it('should propigate the ad-showing attribute', () => {
expect(autoAds.getAdBadgeRoot()).not.to.have.attribute(
Attributes.AD_SHOWING
it('should create ad badge', () => {
const adBadge = doc.querySelector('.i-amphtml-story-ad-badge');
expect(adBadge).to.exist;
});

it('should create progress bar', () => {
const progressBar = doc.querySelector(
'.i-amphtml-story-ad-progress-bar'
);
storeService.dispatch(Action.TOGGLE_AD, true);
expect(autoAds.getAdBadgeRoot()).to.have.attribute(
Attributes.AD_SHOWING
expect(progressBar).to.exist;
});

it('should propagate the ad-showing attribute to badge & progress bar', () => {
const adBadgeContainer = doc.querySelector(
'.i-amphtml-ad-overlay-container'
);
const progressBackground = doc.querySelector(
'.i-amphtml-story-ad-progress-background'
);
expect(adBadgeContainer).not.to.have.attribute(Attributes.AD_SHOWING);
expect(progressBackground).not.to.have.attribute(Attributes.AD_SHOWING);
storeService.dispatch(Action.TOGGLE_AD, true);
expect(adBadgeContainer).to.have.attribute(Attributes.AD_SHOWING);
expect(progressBackground).to.have.attribute(Attributes.AD_SHOWING);
});

it('should propigate the desktop-panels attribute', () => {
expect(autoAds.getAdBadgeRoot()).not.to.have.attribute(
it('should propagate the desktop-panels attribute to badge & progress bar', () => {
const adBadgeContainer = doc.querySelector(
'.i-amphtml-ad-overlay-container'
);
const progressBackground = doc.querySelector(
'.i-amphtml-story-ad-progress-background'
);
expect(adBadgeContainer).not.to.have.attribute(
Attributes.DESKTOP_PANELS
);
storeService.dispatch(Action.TOGGLE_UI, UIType.DESKTOP_PANELS);
expect(autoAds.getAdBadgeRoot()).to.have.attribute(
expect(progressBackground).not.to.have.attribute(
Attributes.DESKTOP_PANELS
);
storeService.dispatch(Action.TOGGLE_UI, UIType.DESKTOP_PANELS);
expect(adBadgeContainer).to.have.attribute(Attributes.DESKTOP_PANELS);
expect(progressBackground).to.have.attribute(Attributes.DESKTOP_PANELS);
});

it('should propigate the dir=rtl attribute', () => {
expect(autoAds.getAdBadgeRoot()).not.to.have.attribute(Attributes.DIR);
storeService.dispatch(Action.TOGGLE_RTL, true);
expect(autoAds.getAdBadgeRoot()).to.have.attribute(
Attributes.DIR,
'rtl'
it('should propagate the dir=rtl attribute', () => {
const adBadgeContainer = doc.querySelector(
'.i-amphtml-ad-overlay-container'
);
expect(adBadgeContainer).not.to.have.attribute(Attributes.DIR);
storeService.dispatch(Action.TOGGLE_RTL, true);
expect(adBadgeContainer).to.have.attribute(Attributes.DIR, 'rtl');
});
});

Expand Down

0 comments on commit 583a733

Please sign in to comment.