Bug 1932205 - Configure IAB Banner positions r=home-newtab-reviewers,reemhamz
Differential Revision: https://phabricator.services.mozilla.com/D231752
This commit is contained in:
@@ -134,6 +134,7 @@ export class DiscoveryStreamAdminUI extends React.PureComponent {
|
|||||||
this.refreshTopicSelectionCache.bind(this);
|
this.refreshTopicSelectionCache.bind(this);
|
||||||
this.toggleTBRFeed = this.toggleTBRFeed.bind(this);
|
this.toggleTBRFeed = this.toggleTBRFeed.bind(this);
|
||||||
this.handleSectionsToggle = this.handleSectionsToggle.bind(this);
|
this.handleSectionsToggle = this.handleSectionsToggle.bind(this);
|
||||||
|
this.toggleIABBanners = this.toggleIABBanners.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
toggledStories: {},
|
toggledStories: {},
|
||||||
weatherQuery: "",
|
weatherQuery: "",
|
||||||
@@ -228,6 +229,41 @@ export class DiscoveryStreamAdminUI extends React.PureComponent {
|
|||||||
this.props.dispatch(ac.SetPref("weather.query", weatherQuery));
|
this.props.dispatch(ac.SetPref("weather.query", weatherQuery));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleIABBanners(e) {
|
||||||
|
const { pressed, id } = e.target;
|
||||||
|
const billboardEnabled = this.props.otherPrefs["newtabAdSize.billboard"];
|
||||||
|
const leaderboardEnabled =
|
||||||
|
this.props.otherPrefs["newtabAdSize.leaderboard"];
|
||||||
|
let spocValue;
|
||||||
|
let spocCount;
|
||||||
|
|
||||||
|
if (id === "billboard") {
|
||||||
|
this.props.dispatch(ac.SetPref("newtabAdSize.billboard", pressed));
|
||||||
|
if (pressed) {
|
||||||
|
spocValue = `newtab_spocs, newtab_billboard${leaderboardEnabled ? ", newtab_leaderboard" : ""}`;
|
||||||
|
spocCount = `6,1${leaderboardEnabled ? ",1" : ""}`;
|
||||||
|
} else {
|
||||||
|
spocValue = `newtab_spocs${leaderboardEnabled ? ", newtab_leaderboard" : ""}`;
|
||||||
|
spocCount = `6${leaderboardEnabled ? ",1" : ""}`;
|
||||||
|
}
|
||||||
|
} else if (id === "leaderboard") {
|
||||||
|
this.props.dispatch(ac.SetPref("newtabAdSize.leaderboard", pressed));
|
||||||
|
if (pressed) {
|
||||||
|
spocValue = `newtab_spocs, newtab_leaderboard${billboardEnabled ? ", newtab_billboard" : ""}`;
|
||||||
|
spocCount = `6,1${billboardEnabled ? ",1" : ""}`;
|
||||||
|
} else {
|
||||||
|
spocValue = `newtab_spocs${billboardEnabled ? ", newtab_billboard" : ""}`;
|
||||||
|
spocCount = `6${billboardEnabled ? ",1" : ""}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.dispatch(
|
||||||
|
ac.SetPref("discoverystream.placements.spocs", spocValue)
|
||||||
|
);
|
||||||
|
this.props.dispatch(
|
||||||
|
ac.SetPref("discoverystream.placements.spocs.counts", spocCount)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
handleSectionsToggle(e) {
|
handleSectionsToggle(e) {
|
||||||
const { pressed } = e.target;
|
const { pressed } = e.target;
|
||||||
this.props.dispatch(
|
this.props.dispatch(
|
||||||
@@ -485,6 +521,17 @@ export class DiscoveryStreamAdminUI extends React.PureComponent {
|
|||||||
.split(",")
|
.split(",")
|
||||||
.map(s => s.trim())
|
.map(s => s.trim())
|
||||||
.filter(item => item);
|
.filter(item => item);
|
||||||
|
|
||||||
|
// Prefs for IAB Banners
|
||||||
|
const billboardsEnabled = this.props.otherPrefs["newtabAdSize.billboard"];
|
||||||
|
const leaderboardEnabled =
|
||||||
|
this.props.otherPrefs["newtabAdSize.leaderboard"];
|
||||||
|
const spocPlacements =
|
||||||
|
this.props.otherPrefs["discoverystream.placements.spocs"];
|
||||||
|
const billboardPressed =
|
||||||
|
billboardsEnabled && spocPlacements.includes("newtab_billboard");
|
||||||
|
const leaderboardPressed =
|
||||||
|
leaderboardEnabled && spocPlacements.includes("newtab_leaderboard");
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<button className="button" onClick={this.restorePrefDefaults}>
|
<button className="button" onClick={this.restorePrefDefaults}>
|
||||||
@@ -533,6 +580,26 @@ export class DiscoveryStreamAdminUI extends React.PureComponent {
|
|||||||
label="Toggle DS Sections"
|
label="Toggle DS Sections"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Collapsible Sections for experiments for easy on/off */}
|
||||||
|
<details className="details-section">
|
||||||
|
<summary>IAB Banner Ad Sizes</summary>
|
||||||
|
<div className="toggle-wrapper">
|
||||||
|
<moz-toggle
|
||||||
|
id="leaderboard"
|
||||||
|
pressed={leaderboardPressed || null}
|
||||||
|
onToggle={this.toggleIABBanners}
|
||||||
|
label="Enable IAB Leaderboard"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="toggle-wrapper">
|
||||||
|
<moz-toggle
|
||||||
|
id="billboard"
|
||||||
|
pressed={billboardPressed || null}
|
||||||
|
onToggle={this.toggleIABBanners}
|
||||||
|
label="Enable IAB Billboard"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{prefToggles.map(pref => (
|
{prefToggles.map(pref => (
|
||||||
|
|||||||
@@ -124,6 +124,14 @@
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.details-section {
|
||||||
|
margin-block: var(--space-large);
|
||||||
|
|
||||||
|
summary {
|
||||||
|
font-size: var(--font-size-large);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { SafeAnchor } from "../SafeAnchor/SafeAnchor";
|
|||||||
import { ImpressionStats } from "../../DiscoveryStreamImpressionStats/ImpressionStats";
|
import { ImpressionStats } from "../../DiscoveryStreamImpressionStats/ImpressionStats";
|
||||||
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
||||||
|
|
||||||
export const AdBanner = ({ spoc, dispatch, firstVisibleTimestamp }) => {
|
export const AdBanner = ({ spoc, dispatch, firstVisibleTimestamp, row }) => {
|
||||||
const getDimensions = format => {
|
const getDimensions = format => {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case "leaderboard":
|
case "leaderboard":
|
||||||
@@ -57,46 +57,56 @@ export const AdBanner = ({ spoc, dispatch, firstVisibleTimestamp }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// in the default card grid 1 would come before the 1st row of cards and 9 comes after the last row
|
||||||
|
// using clamp to make sure its between valid values (1-9)
|
||||||
|
const clampedRow = Math.max(1, Math.min(9, row));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={`ad-banner-wrapper ${spoc.format}`}>
|
<aside className={`ad-banner-wrapper`} style={{ gridRow: clampedRow }}>
|
||||||
<div className="ad-banner-dismiss">
|
<div className={`ad-banner-inner ${spoc.format}`}>
|
||||||
<button
|
<div className="ad-banner-dismiss">
|
||||||
className="icon icon-dismiss"
|
<button
|
||||||
onClick={handleDismissClick}
|
className="icon icon-dismiss"
|
||||||
data-l10n-id="newtab-toast-dismiss-button"
|
onClick={handleDismissClick}
|
||||||
></button>
|
data-l10n-id="newtab-toast-dismiss-button"
|
||||||
</div>
|
></button>
|
||||||
<SafeAnchor className="ad-banner-link" url={spoc.url} title={spoc.title}>
|
</div>
|
||||||
<ImpressionStats
|
<SafeAnchor
|
||||||
flightId={spoc.flight_id}
|
className="ad-banner-link"
|
||||||
rows={[
|
url={spoc.url}
|
||||||
{
|
title={spoc.title}
|
||||||
id: spoc.id,
|
>
|
||||||
pos: spoc.pos,
|
<ImpressionStats
|
||||||
corpus_item_id: spoc.corpus_item_id,
|
flightId={spoc.flight_id}
|
||||||
scheduled_corpus_item_id: spoc.scheduled_corpus_item_id,
|
rows={[
|
||||||
recommended_at: spoc.recommended_at,
|
{
|
||||||
received_rank: spoc.received_rank,
|
id: spoc.id,
|
||||||
},
|
pos: spoc.pos,
|
||||||
]}
|
corpus_item_id: spoc.corpus_item_id,
|
||||||
dispatch={dispatch}
|
scheduled_corpus_item_id: spoc.scheduled_corpus_item_id,
|
||||||
firstVisibleTimestamp={firstVisibleTimestamp}
|
recommended_at: spoc.recommended_at,
|
||||||
/>
|
received_rank: spoc.received_rank,
|
||||||
<div className="ad-banner-content">
|
},
|
||||||
<img
|
]}
|
||||||
src={spoc.raw_image_src}
|
dispatch={dispatch}
|
||||||
alt={spoc.alt_text}
|
firstVisibleTimestamp={firstVisibleTimestamp}
|
||||||
loading="lazy"
|
/>
|
||||||
width={imgWidth}
|
<div className="ad-banner-content">
|
||||||
height={imgHeight}
|
<img
|
||||||
|
src={spoc.raw_image_src}
|
||||||
|
alt={spoc.alt_text}
|
||||||
|
loading="eager"
|
||||||
|
width={imgWidth}
|
||||||
|
height={imgHeight}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SafeAnchor>
|
||||||
|
<div className="ad-banner-sponsored">
|
||||||
|
<span
|
||||||
|
className="ad-banner-sponsored-label"
|
||||||
|
data-l10n-id="newtab-topsite-sponsored"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</SafeAnchor>
|
|
||||||
<div className="ad-banner-sponsored">
|
|
||||||
<span
|
|
||||||
className="ad-banner-sponsored-label"
|
|
||||||
data-l10n-id="newtab-topsite-sponsored"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,63 +1,80 @@
|
|||||||
.ad-banner-wrapper {
|
.ad-banner-wrapper {
|
||||||
|
--billboard-width: 970px;
|
||||||
|
--billboard-height: 250px;
|
||||||
|
--leaderboard-width: 728px;
|
||||||
|
--leaderboard-height: 90px;
|
||||||
|
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
margin: 24px 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
// allow the ad banner to take up full width
|
||||||
|
// of screen rather than card-grid width
|
||||||
|
width: 100vw;
|
||||||
|
margin-inline-start: 50%;
|
||||||
|
transform: translate3d(-50%, 0, 0);
|
||||||
|
|
||||||
.ad-banner-dismiss {
|
.ad-banner-inner {
|
||||||
margin: 10px auto;
|
margin-inline: auto;
|
||||||
text-align: end;
|
|
||||||
margin-inline-end: 10px;
|
|
||||||
|
|
||||||
.icon-dismiss {
|
|
||||||
background-size: 20px;
|
|
||||||
border: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ad-banner-sponsored {
|
|
||||||
margin: 13px auto;
|
|
||||||
|
|
||||||
span {
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
color: var(--newtab-contextual-text-secondary-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.leaderboard {
|
|
||||||
.ad-banner-dismiss {
|
.ad-banner-dismiss {
|
||||||
width: 728px;
|
margin-block: 0 var(--space-small);
|
||||||
|
margin-inline: 0 var(--space-xxsmall);
|
||||||
|
text-align: end;
|
||||||
|
|
||||||
|
.icon-dismiss {
|
||||||
|
background-size: var(--size-item-small);
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ad-banner-content {
|
&.leaderboard {
|
||||||
height: 90px;
|
max-width: var(--leaderboard-width);
|
||||||
width: 728px;
|
|
||||||
margin: 0 auto;
|
.ad-banner-dismiss {
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-banner-content {
|
||||||
|
height: var(--leaderboard-height);
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-banner-sponsored {
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 758px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.billboard {
|
||||||
|
max-width: var(--billboard-width);
|
||||||
|
|
||||||
|
.ad-banner-content {
|
||||||
|
height: var(--billboard-height);
|
||||||
|
width: var(--billboard-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-banner-sponsored {
|
||||||
|
width: var(--billboard-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 1015px) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ad-banner-sponsored {
|
.ad-banner-sponsored {
|
||||||
width: 728px;
|
margin-block: var(--space-small) 0;
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $break-point-large) {
|
span {
|
||||||
display: none;
|
text-transform: uppercase;
|
||||||
}
|
font-size: var(--font-size-small);
|
||||||
}
|
color: var(--newtab-contextual-text-secondary-color);
|
||||||
|
}
|
||||||
&.billboard {
|
|
||||||
.ad-banner-content {
|
|
||||||
height: 250px;
|
|
||||||
width: 970px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ad-banner-sponsored {
|
|
||||||
width: 970px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $break-point-widest) {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ const PREF_LIST_FEED_SELECTED_FEED =
|
|||||||
"discoverystream.contextualContent.selectedFeed";
|
"discoverystream.contextualContent.selectedFeed";
|
||||||
const PREF_FAKESPOT_ENABLED =
|
const PREF_FAKESPOT_ENABLED =
|
||||||
"discoverystream.contextualContent.fakespot.enabled";
|
"discoverystream.contextualContent.fakespot.enabled";
|
||||||
|
const PREF_BILLBOARD_ENABLED = "newtabAdSize.billboard";
|
||||||
|
const PREF_LEADERBOARD_ENABLED = "newtabAdSize.leaderboard";
|
||||||
|
const PREF_LEADERBOARD_POSITION = "newtabAdSize.billboard.position";
|
||||||
|
const PREF_BILLBOARD_POSITION = "newtabAdSize.billboard.position";
|
||||||
const INTERSECTION_RATIO = 0.5;
|
const INTERSECTION_RATIO = 0.5;
|
||||||
const VISIBLE = "visible";
|
const VISIBLE = "visible";
|
||||||
const VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
const VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||||
@@ -354,6 +358,8 @@ export class _CardGrid extends React.PureComponent {
|
|||||||
const spocsStartupCacheEnabled = prefs[PREF_SPOCS_STARTUPCACHE_ENABLED];
|
const spocsStartupCacheEnabled = prefs[PREF_SPOCS_STARTUPCACHE_ENABLED];
|
||||||
const listFeedEnabled = prefs[PREF_LIST_FEED_ENABLED];
|
const listFeedEnabled = prefs[PREF_LIST_FEED_ENABLED];
|
||||||
const listFeedSelectedFeed = prefs[PREF_LIST_FEED_SELECTED_FEED];
|
const listFeedSelectedFeed = prefs[PREF_LIST_FEED_SELECTED_FEED];
|
||||||
|
const billboardEnabled = prefs[PREF_BILLBOARD_ENABLED];
|
||||||
|
const leaderboardEnabled = prefs[PREF_LEADERBOARD_ENABLED];
|
||||||
// filter out recs that should be in ListFeed
|
// filter out recs that should be in ListFeed
|
||||||
const recs = this.props.data.recommendations
|
const recs = this.props.data.recommendations
|
||||||
.filter(item => !item.feedName)
|
.filter(item => !item.feedName)
|
||||||
@@ -365,74 +371,61 @@ export class _CardGrid extends React.PureComponent {
|
|||||||
|
|
||||||
for (let index = 0; index < items; index++) {
|
for (let index = 0; index < items; index++) {
|
||||||
const rec = recs[index];
|
const rec = recs[index];
|
||||||
|
cards.push(
|
||||||
if (rec?.format === "billboard" || rec?.format === "leaderboard") {
|
topicsLoading ||
|
||||||
cards.push(
|
!rec ||
|
||||||
<AdBanner
|
rec.placeholder ||
|
||||||
spoc={rec}
|
(rec.flight_id &&
|
||||||
|
!spocsStartupCacheEnabled &&
|
||||||
|
this.props.App.isForStartupCache) ? (
|
||||||
|
<PlaceholderDSCard key={`dscard-${index}`} />
|
||||||
|
) : (
|
||||||
|
<DSCard
|
||||||
key={`dscard-${rec.id}`}
|
key={`dscard-${rec.id}`}
|
||||||
dispatch={this.props.dispatch}
|
pos={rec.pos}
|
||||||
|
flightId={rec.flight_id}
|
||||||
|
image_src={rec.image_src}
|
||||||
|
raw_image_src={rec.raw_image_src}
|
||||||
|
word_count={rec.word_count}
|
||||||
|
time_to_read={rec.time_to_read}
|
||||||
|
title={rec.title}
|
||||||
|
topic={rec.topic}
|
||||||
|
showTopics={showTopics}
|
||||||
|
selectedTopics={selectedTopics}
|
||||||
|
availableTopics={availableTopics}
|
||||||
|
excerpt={rec.excerpt}
|
||||||
|
url={rec.url}
|
||||||
|
id={rec.id}
|
||||||
|
shim={rec.shim}
|
||||||
|
fetchTimestamp={rec.fetchTimestamp}
|
||||||
type={this.props.type}
|
type={this.props.type}
|
||||||
|
context={rec.context}
|
||||||
|
sponsor={rec.sponsor}
|
||||||
|
sponsored_by_override={rec.sponsored_by_override}
|
||||||
|
dispatch={this.props.dispatch}
|
||||||
|
source={rec.domain}
|
||||||
|
publisher={rec.publisher}
|
||||||
|
pocket_id={rec.pocket_id}
|
||||||
|
context_type={rec.context_type}
|
||||||
|
bookmarkGuid={rec.bookmarkGuid}
|
||||||
|
is_collection={this.props.is_collection}
|
||||||
|
saveToPocketCard={saveToPocketCard}
|
||||||
|
ctaButtonSponsors={ctaButtonSponsors}
|
||||||
|
ctaButtonVariant={ctaButtonVariant}
|
||||||
|
spocMessageVariant={spocMessageVariant}
|
||||||
|
recommendation_id={rec.recommendation_id}
|
||||||
firstVisibleTimestamp={this.props.firstVisibleTimestamp}
|
firstVisibleTimestamp={this.props.firstVisibleTimestamp}
|
||||||
|
mayHaveThumbsUpDown={mayHaveThumbsUpDown}
|
||||||
|
mayHaveSectionsCards={mayHaveSectionsCards}
|
||||||
|
corpus_item_id={rec.corpus_item_id}
|
||||||
|
scheduled_corpus_item_id={rec.scheduled_corpus_item_id}
|
||||||
|
recommended_at={rec.recommended_at}
|
||||||
|
received_rank={rec.received_rank}
|
||||||
|
format={rec.format}
|
||||||
|
alt_text={rec.alt_text}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
} else {
|
);
|
||||||
cards.push(
|
|
||||||
topicsLoading ||
|
|
||||||
!rec ||
|
|
||||||
rec.placeholder ||
|
|
||||||
(rec.flight_id &&
|
|
||||||
!spocsStartupCacheEnabled &&
|
|
||||||
this.props.App.isForStartupCache) ? (
|
|
||||||
<PlaceholderDSCard key={`dscard-${index}`} />
|
|
||||||
) : (
|
|
||||||
<DSCard
|
|
||||||
key={`dscard-${rec.id}`}
|
|
||||||
pos={rec.pos}
|
|
||||||
flightId={rec.flight_id}
|
|
||||||
image_src={rec.image_src}
|
|
||||||
raw_image_src={rec.raw_image_src}
|
|
||||||
word_count={rec.word_count}
|
|
||||||
time_to_read={rec.time_to_read}
|
|
||||||
title={rec.title}
|
|
||||||
topic={rec.topic}
|
|
||||||
showTopics={showTopics}
|
|
||||||
selectedTopics={selectedTopics}
|
|
||||||
availableTopics={availableTopics}
|
|
||||||
excerpt={rec.excerpt}
|
|
||||||
url={rec.url}
|
|
||||||
id={rec.id}
|
|
||||||
shim={rec.shim}
|
|
||||||
fetchTimestamp={rec.fetchTimestamp}
|
|
||||||
type={this.props.type}
|
|
||||||
context={rec.context}
|
|
||||||
sponsor={rec.sponsor}
|
|
||||||
sponsored_by_override={rec.sponsored_by_override}
|
|
||||||
dispatch={this.props.dispatch}
|
|
||||||
source={rec.domain}
|
|
||||||
publisher={rec.publisher}
|
|
||||||
pocket_id={rec.pocket_id}
|
|
||||||
context_type={rec.context_type}
|
|
||||||
bookmarkGuid={rec.bookmarkGuid}
|
|
||||||
is_collection={this.props.is_collection}
|
|
||||||
saveToPocketCard={saveToPocketCard}
|
|
||||||
ctaButtonSponsors={ctaButtonSponsors}
|
|
||||||
ctaButtonVariant={ctaButtonVariant}
|
|
||||||
spocMessageVariant={spocMessageVariant}
|
|
||||||
recommendation_id={rec.recommendation_id}
|
|
||||||
firstVisibleTimestamp={this.props.firstVisibleTimestamp}
|
|
||||||
mayHaveThumbsUpDown={mayHaveThumbsUpDown}
|
|
||||||
mayHaveSectionsCards={mayHaveSectionsCards}
|
|
||||||
corpus_item_id={rec.corpus_item_id}
|
|
||||||
scheduled_corpus_item_id={rec.scheduled_corpus_item_id}
|
|
||||||
recommended_at={rec.recommended_at}
|
|
||||||
received_rank={rec.received_rank}
|
|
||||||
format={rec.format}
|
|
||||||
alt_text={rec.alt_text}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widgets?.positions?.length && widgets?.data?.length) {
|
if (widgets?.positions?.length && widgets?.data?.length) {
|
||||||
@@ -485,6 +478,38 @@ export class _CardGrid extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a banner ad is enabled and we have any available, place them in the grid
|
||||||
|
const { spocs } = this.props.DiscoveryStream;
|
||||||
|
if ((billboardEnabled || leaderboardEnabled) && spocs.data.newtab_spocs) {
|
||||||
|
const spocTypes = [
|
||||||
|
billboardEnabled && "billboard",
|
||||||
|
leaderboardEnabled && "leaderboard",
|
||||||
|
].filter(Boolean);
|
||||||
|
// We need to go through the billboards in `newtab_spocs` because they have been normalized
|
||||||
|
// in DiscoveryStreamFeed on line 1024
|
||||||
|
const bannerSpocs = spocs.data.newtab_spocs.items.filter(({ format }) =>
|
||||||
|
spocTypes.includes(format)
|
||||||
|
);
|
||||||
|
if (bannerSpocs.length) {
|
||||||
|
for (const spoc of bannerSpocs) {
|
||||||
|
const row =
|
||||||
|
spoc.format === "leaderboard"
|
||||||
|
? prefs[PREF_LEADERBOARD_POSITION]
|
||||||
|
: prefs[PREF_BILLBOARD_POSITION];
|
||||||
|
cards.push(
|
||||||
|
<AdBanner
|
||||||
|
spoc={spoc}
|
||||||
|
key={`dscard-${spoc.id}`}
|
||||||
|
dispatch={this.props.dispatch}
|
||||||
|
type={this.props.type}
|
||||||
|
firstVisibleTimestamp={this.props.firstVisibleTimestamp}
|
||||||
|
row={row}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let moreRecsHeader = "";
|
let moreRecsHeader = "";
|
||||||
// For now this is English only.
|
// For now this is English only.
|
||||||
if (showRecentSaves || (essentialReadsHeader && editorsPicksHeader)) {
|
if (showRecentSaves || (essentialReadsHeader && editorsPicksHeader)) {
|
||||||
|
|||||||
@@ -27,8 +27,11 @@ export const selectLayoutRender = ({ state = {}, prefs = {} }) => {
|
|||||||
const results = [...data];
|
const results = [...data];
|
||||||
for (let position of spocsPositions) {
|
for (let position of spocsPositions) {
|
||||||
const spoc = spocsData[spocIndexPlacementMap[placementName]];
|
const spoc = spocsData[spocIndexPlacementMap[placementName]];
|
||||||
|
const format = spoc?.format;
|
||||||
// If there are no spocs left, we can stop filling positions.
|
// If there are no spocs left, we can stop filling positions.
|
||||||
if (!spoc) {
|
// Since banner-type ads are placed by row and don't use the normal spoc-position,
|
||||||
|
// dont combine with content
|
||||||
|
if (!spoc || format === "billboard" || format === "leaderboard") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3618,6 +3618,12 @@ main section {
|
|||||||
margin-block: var(--space-large);
|
margin-block: var(--space-large);
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
.discoverystream-admin .details-section {
|
||||||
|
margin-block: var(--space-large);
|
||||||
|
}
|
||||||
|
.discoverystream-admin .details-section summary {
|
||||||
|
font-size: var(--font-size-large);
|
||||||
|
}
|
||||||
.discoverystream-admin table {
|
.discoverystream-admin table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -7622,54 +7628,69 @@ main section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ad-banner-wrapper {
|
.ad-banner-wrapper {
|
||||||
|
--billboard-width: 970px;
|
||||||
|
--billboard-height: 250px;
|
||||||
|
--leaderboard-width: 728px;
|
||||||
|
--leaderboard-height: 90px;
|
||||||
grid-column: 1/-1;
|
grid-column: 1/-1;
|
||||||
margin: 24px 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
width: 100vw;
|
||||||
|
margin-inline-start: 50%;
|
||||||
|
transform: translate3d(-50%, 0, 0);
|
||||||
}
|
}
|
||||||
.ad-banner-wrapper .ad-banner-dismiss {
|
.ad-banner-wrapper .ad-banner-inner {
|
||||||
margin: 10px auto;
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner .ad-banner-dismiss {
|
||||||
|
margin-block: 0 var(--space-small);
|
||||||
|
margin-inline: 0 var(--space-xxsmall);
|
||||||
text-align: end;
|
text-align: end;
|
||||||
margin-inline-end: 10px;
|
|
||||||
}
|
}
|
||||||
.ad-banner-wrapper .ad-banner-dismiss .icon-dismiss {
|
.ad-banner-wrapper .ad-banner-inner .ad-banner-dismiss .icon-dismiss {
|
||||||
background-size: 20px;
|
background-size: var(--size-item-small);
|
||||||
border: 0;
|
border: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.ad-banner-wrapper .ad-banner-sponsored {
|
.ad-banner-wrapper .ad-banner-inner.leaderboard {
|
||||||
margin: 13px auto;
|
max-width: var(--leaderboard-width);
|
||||||
}
|
}
|
||||||
.ad-banner-wrapper .ad-banner-sponsored span {
|
.ad-banner-wrapper .ad-banner-inner.leaderboard .ad-banner-dismiss {
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.leaderboard .ad-banner-content {
|
||||||
|
height: var(--leaderboard-height);
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.leaderboard .ad-banner-sponsored {
|
||||||
|
width: var(--leaderboard-width);
|
||||||
|
}
|
||||||
|
@media (width <= 758px) {
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.leaderboard {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.billboard {
|
||||||
|
max-width: var(--billboard-width);
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.billboard .ad-banner-content {
|
||||||
|
height: var(--billboard-height);
|
||||||
|
width: var(--billboard-width);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.billboard .ad-banner-sponsored {
|
||||||
|
width: var(--billboard-width);
|
||||||
|
}
|
||||||
|
@media (width <= 1015px) {
|
||||||
|
.ad-banner-wrapper .ad-banner-inner.billboard {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner .ad-banner-sponsored {
|
||||||
|
margin-block: var(--space-small) 0;
|
||||||
|
}
|
||||||
|
.ad-banner-wrapper .ad-banner-inner .ad-banner-sponsored span {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
color: var(--newtab-contextual-text-secondary-color);
|
color: var(--newtab-contextual-text-secondary-color);
|
||||||
}
|
}
|
||||||
.ad-banner-wrapper.leaderboard .ad-banner-dismiss {
|
|
||||||
width: 728px;
|
|
||||||
}
|
|
||||||
.ad-banner-wrapper.leaderboard .ad-banner-content {
|
|
||||||
height: 90px;
|
|
||||||
width: 728px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.ad-banner-wrapper.leaderboard .ad-banner-sponsored {
|
|
||||||
width: 728px;
|
|
||||||
}
|
|
||||||
@media (max-width: 866px) {
|
|
||||||
.ad-banner-wrapper.leaderboard {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ad-banner-wrapper.billboard .ad-banner-content {
|
|
||||||
height: 250px;
|
|
||||||
width: 970px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.ad-banner-wrapper.billboard .ad-banner-sponsored {
|
|
||||||
width: 970px;
|
|
||||||
}
|
|
||||||
@media (max-width: 1122px) {
|
|
||||||
.ad-banner-wrapper.billboard {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -700,6 +700,7 @@ class DiscoveryStreamAdminUI extends (external_React_default()).PureComponent {
|
|||||||
this.refreshTopicSelectionCache = this.refreshTopicSelectionCache.bind(this);
|
this.refreshTopicSelectionCache = this.refreshTopicSelectionCache.bind(this);
|
||||||
this.toggleTBRFeed = this.toggleTBRFeed.bind(this);
|
this.toggleTBRFeed = this.toggleTBRFeed.bind(this);
|
||||||
this.handleSectionsToggle = this.handleSectionsToggle.bind(this);
|
this.handleSectionsToggle = this.handleSectionsToggle.bind(this);
|
||||||
|
this.toggleIABBanners = this.toggleIABBanners.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
toggledStories: {},
|
toggledStories: {},
|
||||||
weatherQuery: ""
|
weatherQuery: ""
|
||||||
@@ -774,6 +775,37 @@ class DiscoveryStreamAdminUI extends (external_React_default()).PureComponent {
|
|||||||
} = this.state;
|
} = this.state;
|
||||||
this.props.dispatch(actionCreators.SetPref("weather.query", weatherQuery));
|
this.props.dispatch(actionCreators.SetPref("weather.query", weatherQuery));
|
||||||
}
|
}
|
||||||
|
toggleIABBanners(e) {
|
||||||
|
const {
|
||||||
|
pressed,
|
||||||
|
id
|
||||||
|
} = e.target;
|
||||||
|
const billboardEnabled = this.props.otherPrefs["newtabAdSize.billboard"];
|
||||||
|
const leaderboardEnabled = this.props.otherPrefs["newtabAdSize.leaderboard"];
|
||||||
|
let spocValue;
|
||||||
|
let spocCount;
|
||||||
|
if (id === "billboard") {
|
||||||
|
this.props.dispatch(actionCreators.SetPref("newtabAdSize.billboard", pressed));
|
||||||
|
if (pressed) {
|
||||||
|
spocValue = `newtab_spocs, newtab_billboard${leaderboardEnabled ? ", newtab_leaderboard" : ""}`;
|
||||||
|
spocCount = `6,1${leaderboardEnabled ? ",1" : ""}`;
|
||||||
|
} else {
|
||||||
|
spocValue = `newtab_spocs${leaderboardEnabled ? ", newtab_leaderboard" : ""}`;
|
||||||
|
spocCount = `6${leaderboardEnabled ? ",1" : ""}`;
|
||||||
|
}
|
||||||
|
} else if (id === "leaderboard") {
|
||||||
|
this.props.dispatch(actionCreators.SetPref("newtabAdSize.leaderboard", pressed));
|
||||||
|
if (pressed) {
|
||||||
|
spocValue = `newtab_spocs, newtab_leaderboard${billboardEnabled ? ", newtab_billboard" : ""}`;
|
||||||
|
spocCount = `6,1${billboardEnabled ? ",1" : ""}`;
|
||||||
|
} else {
|
||||||
|
spocValue = `newtab_spocs${billboardEnabled ? ", newtab_billboard" : ""}`;
|
||||||
|
spocCount = `6${billboardEnabled ? ",1" : ""}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.dispatch(actionCreators.SetPref("discoverystream.placements.spocs", spocValue));
|
||||||
|
this.props.dispatch(actionCreators.SetPref("discoverystream.placements.spocs.counts", spocCount));
|
||||||
|
}
|
||||||
handleSectionsToggle(e) {
|
handleSectionsToggle(e) {
|
||||||
const {
|
const {
|
||||||
pressed
|
pressed
|
||||||
@@ -928,6 +960,13 @@ class DiscoveryStreamAdminUI extends (external_React_default()).PureComponent {
|
|||||||
const selectedFeed = this.props.otherPrefs["discoverystream.contextualContent.selectedFeed"];
|
const selectedFeed = this.props.otherPrefs["discoverystream.contextualContent.selectedFeed"];
|
||||||
const sectionsEnabled = this.props.otherPrefs["discoverystream.sections.enabled"];
|
const sectionsEnabled = this.props.otherPrefs["discoverystream.sections.enabled"];
|
||||||
const TBRFeeds = this.props.otherPrefs["discoverystream.contextualContent.feeds"].split(",").map(s => s.trim()).filter(item => item);
|
const TBRFeeds = this.props.otherPrefs["discoverystream.contextualContent.feeds"].split(",").map(s => s.trim()).filter(item => item);
|
||||||
|
|
||||||
|
// Prefs for IAB Banners
|
||||||
|
const billboardsEnabled = this.props.otherPrefs["newtabAdSize.billboard"];
|
||||||
|
const leaderboardEnabled = this.props.otherPrefs["newtabAdSize.leaderboard"];
|
||||||
|
const spocPlacements = this.props.otherPrefs["discoverystream.placements.spocs"];
|
||||||
|
const billboardPressed = billboardsEnabled && spocPlacements.includes("newtab_billboard");
|
||||||
|
const leaderboardPressed = leaderboardEnabled && spocPlacements.includes("newtab_leaderboard");
|
||||||
return /*#__PURE__*/external_React_default().createElement("div", null, /*#__PURE__*/external_React_default().createElement("button", {
|
return /*#__PURE__*/external_React_default().createElement("div", null, /*#__PURE__*/external_React_default().createElement("button", {
|
||||||
className: "button",
|
className: "button",
|
||||||
onClick: this.restorePrefDefaults
|
onClick: this.restorePrefDefaults
|
||||||
@@ -966,7 +1005,23 @@ class DiscoveryStreamAdminUI extends (external_React_default()).PureComponent {
|
|||||||
pressed: sectionsEnabled || null,
|
pressed: sectionsEnabled || null,
|
||||||
onToggle: this.handleSectionsToggle,
|
onToggle: this.handleSectionsToggle,
|
||||||
label: "Toggle DS Sections"
|
label: "Toggle DS Sections"
|
||||||
})), /*#__PURE__*/external_React_default().createElement("table", null, /*#__PURE__*/external_React_default().createElement("tbody", null, prefToggles.map(pref => /*#__PURE__*/external_React_default().createElement(Row, {
|
})), /*#__PURE__*/external_React_default().createElement("details", {
|
||||||
|
className: "details-section"
|
||||||
|
}, /*#__PURE__*/external_React_default().createElement("summary", null, "IAB Banner Ad Sizes"), /*#__PURE__*/external_React_default().createElement("div", {
|
||||||
|
className: "toggle-wrapper"
|
||||||
|
}, /*#__PURE__*/external_React_default().createElement("moz-toggle", {
|
||||||
|
id: "leaderboard",
|
||||||
|
pressed: leaderboardPressed || null,
|
||||||
|
onToggle: this.toggleIABBanners,
|
||||||
|
label: "Enable IAB Leaderboard"
|
||||||
|
})), /*#__PURE__*/external_React_default().createElement("div", {
|
||||||
|
className: "toggle-wrapper"
|
||||||
|
}, /*#__PURE__*/external_React_default().createElement("moz-toggle", {
|
||||||
|
id: "billboard",
|
||||||
|
pressed: billboardPressed || null,
|
||||||
|
onToggle: this.toggleIABBanners,
|
||||||
|
label: "Enable IAB Billboard"
|
||||||
|
}))), /*#__PURE__*/external_React_default().createElement("table", null, /*#__PURE__*/external_React_default().createElement("tbody", null, prefToggles.map(pref => /*#__PURE__*/external_React_default().createElement(Row, {
|
||||||
key: pref
|
key: pref
|
||||||
}, /*#__PURE__*/external_React_default().createElement("td", null, /*#__PURE__*/external_React_default().createElement(TogglePrefCheckbox, {
|
}, /*#__PURE__*/external_React_default().createElement("td", null, /*#__PURE__*/external_React_default().createElement(TogglePrefCheckbox, {
|
||||||
checked: config[pref],
|
checked: config[pref],
|
||||||
@@ -4110,7 +4165,8 @@ function ListFeed({
|
|||||||
const AdBanner = ({
|
const AdBanner = ({
|
||||||
spoc,
|
spoc,
|
||||||
dispatch,
|
dispatch,
|
||||||
firstVisibleTimestamp
|
firstVisibleTimestamp,
|
||||||
|
row
|
||||||
}) => {
|
}) => {
|
||||||
const getDimensions = format => {
|
const getDimensions = format => {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
@@ -4156,8 +4212,17 @@ const AdBanner = ({
|
|||||||
}]
|
}]
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// in the default card grid 1 would come before the 1st row of cards and 9 comes after the last row
|
||||||
|
// using clamp to make sure its between valid values (1-9)
|
||||||
|
const clampedRow = Math.max(1, Math.min(9, row));
|
||||||
return /*#__PURE__*/external_React_default().createElement("aside", {
|
return /*#__PURE__*/external_React_default().createElement("aside", {
|
||||||
className: `ad-banner-wrapper ${spoc.format}`
|
className: `ad-banner-wrapper`,
|
||||||
|
style: {
|
||||||
|
gridRow: clampedRow
|
||||||
|
}
|
||||||
|
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||||
|
className: `ad-banner-inner ${spoc.format}`
|
||||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||||
className: "ad-banner-dismiss"
|
className: "ad-banner-dismiss"
|
||||||
}, /*#__PURE__*/external_React_default().createElement("button", {
|
}, /*#__PURE__*/external_React_default().createElement("button", {
|
||||||
@@ -4185,7 +4250,7 @@ const AdBanner = ({
|
|||||||
}, /*#__PURE__*/external_React_default().createElement("img", {
|
}, /*#__PURE__*/external_React_default().createElement("img", {
|
||||||
src: spoc.raw_image_src,
|
src: spoc.raw_image_src,
|
||||||
alt: spoc.alt_text,
|
alt: spoc.alt_text,
|
||||||
loading: "lazy",
|
loading: "eager",
|
||||||
width: imgWidth,
|
width: imgWidth,
|
||||||
height: imgHeight
|
height: imgHeight
|
||||||
}))), /*#__PURE__*/external_React_default().createElement("div", {
|
}))), /*#__PURE__*/external_React_default().createElement("div", {
|
||||||
@@ -4193,7 +4258,7 @@ const AdBanner = ({
|
|||||||
}, /*#__PURE__*/external_React_default().createElement("span", {
|
}, /*#__PURE__*/external_React_default().createElement("span", {
|
||||||
className: "ad-banner-sponsored-label",
|
className: "ad-banner-sponsored-label",
|
||||||
"data-l10n-id": "newtab-topsite-sponsored"
|
"data-l10n-id": "newtab-topsite-sponsored"
|
||||||
})));
|
}))));
|
||||||
};
|
};
|
||||||
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx
|
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
@@ -4221,6 +4286,10 @@ const PREF_SPOCS_STARTUPCACHE_ENABLED = "discoverystream.spocs.startupCache.enab
|
|||||||
const PREF_LIST_FEED_ENABLED = "discoverystream.contextualContent.enabled";
|
const PREF_LIST_FEED_ENABLED = "discoverystream.contextualContent.enabled";
|
||||||
const PREF_LIST_FEED_SELECTED_FEED = "discoverystream.contextualContent.selectedFeed";
|
const PREF_LIST_FEED_SELECTED_FEED = "discoverystream.contextualContent.selectedFeed";
|
||||||
const PREF_FAKESPOT_ENABLED = "discoverystream.contextualContent.fakespot.enabled";
|
const PREF_FAKESPOT_ENABLED = "discoverystream.contextualContent.fakespot.enabled";
|
||||||
|
const PREF_BILLBOARD_ENABLED = "newtabAdSize.billboard";
|
||||||
|
const PREF_LEADERBOARD_ENABLED = "newtabAdSize.leaderboard";
|
||||||
|
const PREF_LEADERBOARD_POSITION = "newtabAdSize.billboard.position";
|
||||||
|
const PREF_BILLBOARD_POSITION = "newtabAdSize.billboard.position";
|
||||||
const CardGrid_INTERSECTION_RATIO = 0.5;
|
const CardGrid_INTERSECTION_RATIO = 0.5;
|
||||||
const CardGrid_VISIBLE = "visible";
|
const CardGrid_VISIBLE = "visible";
|
||||||
const CardGrid_VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
const CardGrid_VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||||
@@ -4501,6 +4570,8 @@ class _CardGrid extends (external_React_default()).PureComponent {
|
|||||||
const spocsStartupCacheEnabled = prefs[PREF_SPOCS_STARTUPCACHE_ENABLED];
|
const spocsStartupCacheEnabled = prefs[PREF_SPOCS_STARTUPCACHE_ENABLED];
|
||||||
const listFeedEnabled = prefs[PREF_LIST_FEED_ENABLED];
|
const listFeedEnabled = prefs[PREF_LIST_FEED_ENABLED];
|
||||||
const listFeedSelectedFeed = prefs[PREF_LIST_FEED_SELECTED_FEED];
|
const listFeedSelectedFeed = prefs[PREF_LIST_FEED_SELECTED_FEED];
|
||||||
|
const billboardEnabled = prefs[PREF_BILLBOARD_ENABLED];
|
||||||
|
const leaderboardEnabled = prefs[PREF_LEADERBOARD_ENABLED];
|
||||||
// filter out recs that should be in ListFeed
|
// filter out recs that should be in ListFeed
|
||||||
const recs = this.props.data.recommendations.filter(item => !item.feedName).slice(0, items);
|
const recs = this.props.data.recommendations.filter(item => !item.feedName).slice(0, items);
|
||||||
const cards = [];
|
const cards = [];
|
||||||
@@ -4508,62 +4579,52 @@ class _CardGrid extends (external_React_default()).PureComponent {
|
|||||||
let editorsPicksCards = [];
|
let editorsPicksCards = [];
|
||||||
for (let index = 0; index < items; index++) {
|
for (let index = 0; index < items; index++) {
|
||||||
const rec = recs[index];
|
const rec = recs[index];
|
||||||
if (rec?.format === "billboard" || rec?.format === "leaderboard") {
|
cards.push(topicsLoading || !rec || rec.placeholder || rec.flight_id && !spocsStartupCacheEnabled && this.props.App.isForStartupCache ? /*#__PURE__*/external_React_default().createElement(PlaceholderDSCard, {
|
||||||
cards.push( /*#__PURE__*/external_React_default().createElement(AdBanner, {
|
key: `dscard-${index}`
|
||||||
spoc: rec,
|
}) : /*#__PURE__*/external_React_default().createElement(DSCard, {
|
||||||
key: `dscard-${rec.id}`,
|
key: `dscard-${rec.id}`,
|
||||||
dispatch: this.props.dispatch,
|
pos: rec.pos,
|
||||||
type: this.props.type,
|
flightId: rec.flight_id,
|
||||||
firstVisibleTimestamp: this.props.firstVisibleTimestamp
|
image_src: rec.image_src,
|
||||||
}));
|
raw_image_src: rec.raw_image_src,
|
||||||
} else {
|
word_count: rec.word_count,
|
||||||
cards.push(topicsLoading || !rec || rec.placeholder || rec.flight_id && !spocsStartupCacheEnabled && this.props.App.isForStartupCache ? /*#__PURE__*/external_React_default().createElement(PlaceholderDSCard, {
|
time_to_read: rec.time_to_read,
|
||||||
key: `dscard-${index}`
|
title: rec.title,
|
||||||
}) : /*#__PURE__*/external_React_default().createElement(DSCard, {
|
topic: rec.topic,
|
||||||
key: `dscard-${rec.id}`,
|
showTopics: showTopics,
|
||||||
pos: rec.pos,
|
selectedTopics: selectedTopics,
|
||||||
flightId: rec.flight_id,
|
availableTopics: availableTopics,
|
||||||
image_src: rec.image_src,
|
excerpt: rec.excerpt,
|
||||||
raw_image_src: rec.raw_image_src,
|
url: rec.url,
|
||||||
word_count: rec.word_count,
|
id: rec.id,
|
||||||
time_to_read: rec.time_to_read,
|
shim: rec.shim,
|
||||||
title: rec.title,
|
fetchTimestamp: rec.fetchTimestamp,
|
||||||
topic: rec.topic,
|
type: this.props.type,
|
||||||
showTopics: showTopics,
|
context: rec.context,
|
||||||
selectedTopics: selectedTopics,
|
sponsor: rec.sponsor,
|
||||||
availableTopics: availableTopics,
|
sponsored_by_override: rec.sponsored_by_override,
|
||||||
excerpt: rec.excerpt,
|
dispatch: this.props.dispatch,
|
||||||
url: rec.url,
|
source: rec.domain,
|
||||||
id: rec.id,
|
publisher: rec.publisher,
|
||||||
shim: rec.shim,
|
pocket_id: rec.pocket_id,
|
||||||
fetchTimestamp: rec.fetchTimestamp,
|
context_type: rec.context_type,
|
||||||
type: this.props.type,
|
bookmarkGuid: rec.bookmarkGuid,
|
||||||
context: rec.context,
|
is_collection: this.props.is_collection,
|
||||||
sponsor: rec.sponsor,
|
saveToPocketCard: saveToPocketCard,
|
||||||
sponsored_by_override: rec.sponsored_by_override,
|
ctaButtonSponsors: ctaButtonSponsors,
|
||||||
dispatch: this.props.dispatch,
|
ctaButtonVariant: ctaButtonVariant,
|
||||||
source: rec.domain,
|
spocMessageVariant: spocMessageVariant,
|
||||||
publisher: rec.publisher,
|
recommendation_id: rec.recommendation_id,
|
||||||
pocket_id: rec.pocket_id,
|
firstVisibleTimestamp: this.props.firstVisibleTimestamp,
|
||||||
context_type: rec.context_type,
|
mayHaveThumbsUpDown: mayHaveThumbsUpDown,
|
||||||
bookmarkGuid: rec.bookmarkGuid,
|
mayHaveSectionsCards: mayHaveSectionsCards,
|
||||||
is_collection: this.props.is_collection,
|
corpus_item_id: rec.corpus_item_id,
|
||||||
saveToPocketCard: saveToPocketCard,
|
scheduled_corpus_item_id: rec.scheduled_corpus_item_id,
|
||||||
ctaButtonSponsors: ctaButtonSponsors,
|
recommended_at: rec.recommended_at,
|
||||||
ctaButtonVariant: ctaButtonVariant,
|
received_rank: rec.received_rank,
|
||||||
spocMessageVariant: spocMessageVariant,
|
format: rec.format,
|
||||||
recommendation_id: rec.recommendation_id,
|
alt_text: rec.alt_text
|
||||||
firstVisibleTimestamp: this.props.firstVisibleTimestamp,
|
}));
|
||||||
mayHaveThumbsUpDown: mayHaveThumbsUpDown,
|
|
||||||
mayHaveSectionsCards: mayHaveSectionsCards,
|
|
||||||
corpus_item_id: rec.corpus_item_id,
|
|
||||||
scheduled_corpus_item_id: rec.scheduled_corpus_item_id,
|
|
||||||
recommended_at: rec.recommended_at,
|
|
||||||
received_rank: rec.received_rank,
|
|
||||||
format: rec.format,
|
|
||||||
alt_text: rec.alt_text
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (widgets?.positions?.length && widgets?.data?.length) {
|
if (widgets?.positions?.length && widgets?.data?.length) {
|
||||||
let positionIndex = 0;
|
let positionIndex = 0;
|
||||||
@@ -4602,6 +4663,32 @@ class _CardGrid extends (external_React_default()).PureComponent {
|
|||||||
cards.splice(2, 1, this.renderListFeed(this.props.data.recommendations, listFeedSelectedFeed));
|
cards.splice(2, 1, this.renderListFeed(this.props.data.recommendations, listFeedSelectedFeed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a banner ad is enabled and we have any available, place them in the grid
|
||||||
|
const {
|
||||||
|
spocs
|
||||||
|
} = this.props.DiscoveryStream;
|
||||||
|
if ((billboardEnabled || leaderboardEnabled) && spocs.data.newtab_spocs) {
|
||||||
|
const spocTypes = [billboardEnabled && "billboard", leaderboardEnabled && "leaderboard"].filter(Boolean);
|
||||||
|
// We need to go through the billboards in `newtab_spocs` because they have been normalized
|
||||||
|
// in DiscoveryStreamFeed on line 1024
|
||||||
|
const bannerSpocs = spocs.data.newtab_spocs.items.filter(({
|
||||||
|
format
|
||||||
|
}) => spocTypes.includes(format));
|
||||||
|
if (bannerSpocs.length) {
|
||||||
|
for (const spoc of bannerSpocs) {
|
||||||
|
const row = spoc.format === "leaderboard" ? prefs[PREF_LEADERBOARD_POSITION] : prefs[PREF_BILLBOARD_POSITION];
|
||||||
|
cards.push( /*#__PURE__*/external_React_default().createElement(AdBanner, {
|
||||||
|
spoc: spoc,
|
||||||
|
key: `dscard-${spoc.id}`,
|
||||||
|
dispatch: this.props.dispatch,
|
||||||
|
type: this.props.type,
|
||||||
|
firstVisibleTimestamp: this.props.firstVisibleTimestamp,
|
||||||
|
row: row
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let moreRecsHeader = "";
|
let moreRecsHeader = "";
|
||||||
// For now this is English only.
|
// For now this is English only.
|
||||||
if (showRecentSaves || essentialReadsHeader && editorsPicksHeader) {
|
if (showRecentSaves || essentialReadsHeader && editorsPicksHeader) {
|
||||||
@@ -9372,8 +9459,11 @@ const selectLayoutRender = ({ state = {}, prefs = {} }) => {
|
|||||||
const results = [...data];
|
const results = [...data];
|
||||||
for (let position of spocsPositions) {
|
for (let position of spocsPositions) {
|
||||||
const spoc = spocsData[spocIndexPlacementMap[placementName]];
|
const spoc = spocsData[spocIndexPlacementMap[placementName]];
|
||||||
|
const format = spoc?.format;
|
||||||
// If there are no spocs left, we can stop filling positions.
|
// If there are no spocs left, we can stop filling positions.
|
||||||
if (!spoc) {
|
// Since banner-type ads are placed by row and don't use the normal spoc-position,
|
||||||
|
// dont combine with content
|
||||||
|
if (!spoc || format === "billboard" || format === "leaderboard") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -436,6 +436,14 @@ export const PREFS_CONFIG = new Map([
|
|||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"newtabAdSize.leaderboard.position",
|
||||||
|
{
|
||||||
|
title:
|
||||||
|
"CSV string of positions for leaderboard spocs - should corralate to a row in DS grid",
|
||||||
|
value: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"newtabAdSize.billboard",
|
"newtabAdSize.billboard",
|
||||||
{
|
{
|
||||||
@@ -443,6 +451,14 @@ export const PREFS_CONFIG = new Map([
|
|||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
"newtabAdSize.billboard.position",
|
||||||
|
{
|
||||||
|
title:
|
||||||
|
"number string of positions for billboard spocs - should corralate to a row in DS grid",
|
||||||
|
value: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"newtabLayouts.variant-a",
|
"newtabLayouts.variant-a",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -858,6 +858,13 @@ newtabAdSizingExperiment:
|
|||||||
pref: browser.newtabpage.activity-stream.newtabAdSize.leaderboard
|
pref: browser.newtabpage.activity-stream.newtabAdSize.leaderboard
|
||||||
description: >-
|
description: >-
|
||||||
Leaderboard ad size and UI.
|
Leaderboard ad size and UI.
|
||||||
|
leaderboard_position:
|
||||||
|
type: string
|
||||||
|
setPref:
|
||||||
|
branch: user
|
||||||
|
pref: browser.newtabpage.activity-stream.newtabAdSize.leaderboard.position
|
||||||
|
description: >-
|
||||||
|
Leaderboard row position.
|
||||||
billboard:
|
billboard:
|
||||||
type: boolean
|
type: boolean
|
||||||
setPref:
|
setPref:
|
||||||
@@ -865,6 +872,14 @@ newtabAdSizingExperiment:
|
|||||||
pref: browser.newtabpage.activity-stream.newtabAdSize.billboard
|
pref: browser.newtabpage.activity-stream.newtabAdSize.billboard
|
||||||
description: >-
|
description: >-
|
||||||
Billboard ad size and UI.
|
Billboard ad size and UI.
|
||||||
|
billboard_position:
|
||||||
|
type: string
|
||||||
|
setPref:
|
||||||
|
branch: user
|
||||||
|
pref: browser.newtabpage.activity-stream.newtabAdSize.billboard.position
|
||||||
|
description: >-
|
||||||
|
Billboard row position.
|
||||||
|
|
||||||
newtabLayoutExperiment:
|
newtabLayoutExperiment:
|
||||||
description: >-
|
description: >-
|
||||||
Change the default layout of new tab by adjusting sizes and spacing of elements.
|
Change the default layout of new tab by adjusting sizes and spacing of elements.
|
||||||
|
|||||||
Reference in New Issue
Block a user