Bug 1726385 - CTA + Recs variant r=thecount

Differential Revision: https://phabricator.services.mozilla.com/D123679
This commit is contained in:
Gavin Lazar Suntop 2021-09-28 18:12:17 +00:00
Родитель 461b6bb1e9
Коммит 2f6a4680e7
5 изменённых файлов: 344 добавлений и 23 удалений

Просмотреть файл

@ -19,6 +19,11 @@ ChromeUtils.defineModuleGetter(
"ReaderMode",
"resource://gre/modules/ReaderMode.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"pktApi",
"chrome://pocket/content/pktApi.jsm"
);
const gStringBundle = Services.strings.createBundle(
"chrome://global/locale/aboutReader.properties"
@ -109,6 +114,45 @@ class AboutReaderParent extends JSWindowActorParent {
gCachedArticles.delete(message.data.url);
return cachedArticle;
}
case "Reader:PocketLoginStatusRequest": {
return pktApi.isUserLoggedIn();
}
case "Reader:PocketGetArticleInfo": {
return new Promise(resolve => {
pktApi.getArticleInfo(message.data.url, {
success: data => {
resolve(data);
},
error: error => {
resolve(null);
},
});
});
}
case "Reader:PocketGetArticleRecs": {
return new Promise(resolve => {
pktApi.getRecsForItem(message.data.itemID, {
success: data => {
resolve(data);
},
error: error => {
resolve(null);
},
});
});
}
case "Reader:PocketSaveArticle": {
return new Promise(resolve => {
pktApi.addLink(message.data.url, {
success: data => {
resolve(data);
},
error: error => {
resolve(null);
},
});
});
}
case "Reader:FaviconRequest": {
try {
let preferredWidth = message.data.preferredWidth || 0;

Просмотреть файл

@ -90,9 +90,6 @@ if (AppConstants.NIGHTLY_BUILD) {
// referencing the whitelisted file in a way that the test can't detect, or a
// bug number to remove or use the file if it is indeed currently unreferenced.
var whitelist = [
// pocket/content/panels/tmpl/loggedoutvariants/variant_a.handlebars
{ file: "chrome://pocket/content/panels/img/glyph.svg" },
// toolkit/components/pdfjs/content/PdfStreamConverter.jsm
{ file: "chrome://pdf.js/locale/chrome.properties" },
{ file: "chrome://pdf.js/locale/viewer.properties" },

Просмотреть файл

@ -795,6 +795,41 @@ AboutReader.prototype = {
this._showContent(article);
},
async _requestPocketLoginStatus() {
let isLoggedIn = await this._actor.sendQuery(
"Reader:PocketLoginStatusRequest"
);
return isLoggedIn;
},
async _requestPocketArticleInfo(url) {
let articleInfo = await this._actor.sendQuery(
"Reader:PocketGetArticleInfo",
{
url,
}
);
return articleInfo?.item_preview?.item_id;
},
async _requestPocketArticleRecs(itemID) {
let recs = await this._actor.sendQuery("Reader:PocketGetArticleRecs", {
itemID,
});
return recs;
},
async _savePocketArticle(url) {
let result = await this._actor.sendQuery("Reader:PocketSaveArticle", {
url,
});
return result;
},
async _requestFavicon() {
let iconDetails = await this._actor.sendQuery("Reader:FaviconRequest", {
url: this._article.url,
@ -1237,23 +1272,142 @@ AboutReader.prototype = {
}
},
_setupPocketCTA() {
_enableDismissCTA() {
let elDismissCta = this._doc.querySelector(`.pocket-dismiss-cta`);
elDismissCta?.addEventListener(`click`, e => {
this._doc.querySelector("#pocket-cta-container").hidden = true;
});
},
_enableRecShowHide() {
let elPocketRecs = this._doc.querySelector(`.pocket-recs`);
let elCollapseRecs = this._doc.querySelector(`.pocket-collapse-recs`);
let toggleRecsVisibility = () => {
let isClosed = elPocketRecs.classList.contains(`closed`);
isClosed = !isClosed; // Toggle
if (isClosed) {
elPocketRecs.classList.add(`closed`);
elCollapseRecs.classList.add(`closed`);
} else {
elPocketRecs.classList.remove(`closed`);
elCollapseRecs.classList.remove(`closed`);
}
};
elCollapseRecs?.addEventListener(`click`, e => {
toggleRecsVisibility();
});
},
_buildPocketRec(title, url, publisher, thumb, time) {
let fragment = this._doc.createDocumentFragment();
let elContainer = this._doc.createElement(`div`);
let elTitle = this._doc.createElement(`header`);
let elMetadata = this._doc.createElement(`p`);
let elThumb = this._doc.createElement(`img`);
let elSideWrap = this._doc.createElement(`div`);
let elTop = this._doc.createElement(`a`);
let elBottom = this._doc.createElement(`div`);
let elAdd = this._doc.createElement(`button`);
elAdd.classList.add(`pocket-btn-add`);
elBottom.classList.add(`pocket-rec-bottom`);
elTop.classList.add(`pocket-rec-top`);
elSideWrap.classList.add(`pocket-rec-side`);
elContainer.classList.add(`pocket-rec`);
elTitle.classList.add(`pocket-rec-title`);
elMetadata.classList.add(`pocket-rec-meta`);
elTop.setAttribute(`href`, url);
elThumb.classList.add(`pocket-rec-thumb`);
elThumb.setAttribute(`loading`, `lazy`);
elThumb.setAttribute(
`src`,
`https://img-getpocket.cdn.mozilla.net/132x132/filters:format(jpeg):quality(60):no_upscale():strip_exif()/${thumb}`
);
elAdd.textContent = `Save`;
elTitle.textContent = title;
if (publisher && time) {
elMetadata.textContent = `${publisher} · ${time} min`;
} else if (publisher) {
elMetadata.textContent = `${publisher}`;
} else if (time) {
elMetadata.textContent = `${time} min`;
}
elSideWrap.appendChild(elTitle);
elSideWrap.appendChild(elMetadata);
elTop.appendChild(elSideWrap);
elTop.appendChild(elThumb);
elBottom.appendChild(elAdd);
elContainer.appendChild(elTop);
elContainer.appendChild(elBottom);
fragment.appendChild(elContainer);
elAdd.addEventListener(`click`, e => {
this._savePocketArticle(url);
elAdd.textContent = `Saved`;
elAdd.classList.add(`saved`);
});
return fragment;
},
async _getAndBuildPocketRecs() {
let elTarget = this._doc.querySelector(`.pocket-recs`);
let url = this._getOriginalUrl();
let itemID = await this._requestPocketArticleInfo(url);
let articleRecs = await this._requestPocketArticleRecs(itemID);
articleRecs.recommendations.forEach(rec => {
// Parse a domain from the article URL in case the Publisher name isn't available
let parsedDomain = new URL(rec.item?.normal_url)?.hostname;
// Calculate read time from word count in case it's not available
let calculatedReadTime = Math.ceil(rec.item?.word_count / 220);
let elRec = this._buildPocketRec(
rec.item?.title,
rec.item?.normal_url,
rec.item?.domain_metadata?.name || parsedDomain,
rec.item?.top_image_url,
rec.item?.time_to_read || calculatedReadTime
);
elTarget.appendChild(elRec);
});
},
async _setupPocketCTA() {
let ctaVersion = NimbusFeatures.readerMode.getAllVariables()
?.pocketCTAVersion;
let isLoggedInUser = await this._requestPocketLoginStatus();
let elPocketCTAWrapper = this._doc.querySelector("#pocket-cta-container");
// Show the Pocket CTA container if the pref is set
if (ctaVersion) {
// Show the Pocket CTA container if the pref is set and valid
if (ctaVersion === `cta-and-recs` || ctaVersion === `cta-only`) {
if (ctaVersion === `cta-and-recs` && isLoggedInUser) {
this._getAndBuildPocketRecs();
this._enableRecShowHide();
} else if (ctaVersion === `cta-and-recs` && !isLoggedInUser) {
// Fall back to cta only for logged out users:
ctaVersion = `cta-only`;
}
if (ctaVersion == `cta-only`) {
this._enableDismissCTA();
}
elPocketCTAWrapper.hidden = false;
// TODO: Show the corresponding CTA version. This is just a placeholder visualization.
elPocketCTAWrapper.classList.add(`pocket-cta-container-${ctaVersion}`);
this._doc
.querySelector(`.pocket-dismiss-cta`)
.addEventListener(`click`, e => {
elPocketCTAWrapper.hidden = true;
});
}
},
};

Просмотреть файл

@ -77,10 +77,28 @@
<div class="pocket-cta">
<header class="pocket-cta-header">Save anything from across the web in Pocket, your personal library.</header>
<p class="pocket-cta-subhead">As part of the Firefox family, Pocket provides a quiet, calm space thats perfect for reading. It strips away all the distractions of the internet so you can really focus.</p>
<a href="https://getpocket.com/signup" class="pocket-button pocket-sign-up"><strong>Sign Up</strong> - it's free</a>
<a href="https://getpocket.com/signup" class="pocket-btn pocket-sign-up"><strong>Sign Up</strong> - it's free</a>
</div>
<button class="pocket-dismiss-cta"></button>
</div>
<div class="pocket-cta-inner" id="pocket-cta-and-recs">
<div class="pocket-recs-top">
<div class="col">
<header class="pocket-cta-header">Discover the most thought-provoking stories out there, curated by Pocket.</header>
<p class="pocket-cta-subhead">As part of the Firefox family, Pocket surfaces the best articles out there—new perspectives, intriguing deep-dives, timeless classics—and we do this with the same dedication to privacy youve come to expect from Firefox and Mozilla. </p>
</div>
<div class="col">
<button class="pocket-collapse-recs"></button>
</div>
</div>
<div class="pocket-recs"></div>
<div class="pocket-sign-up">
<a href="https://getpocket.com/signup" class="pocket-btn pocket-sign-up"><strong>Sign Up</strong> - it's free</a>
</div>
</div>
</div>
</body>

Просмотреть файл

@ -10,11 +10,8 @@
position: relative;
}
#pocket-cta-only {
display: none;
}
.pocket-cta-container-cta-only #pocket-cta-only {
.pocket-cta-container-cta-only #pocket-cta-only,
.pocket-cta-container-cta-and-recs #pocket-cta-and-recs {
display: block;
}
@ -26,13 +23,14 @@
.pocket-cta-inner {
width: 936px;
margin: auto;
display: none;
}
.pocket-cta-header {
font-weight: 900;
}
.pocket-button {
.pocket-btn {
background: #008078;
border-radius: 4px;
border: 0;
@ -40,6 +38,7 @@
font-size: 16px;
line-height: 24px;
padding: 8px 24px;
text-decoration: none;
}
.pocket-dismiss-cta {
@ -54,6 +53,93 @@
background: no-repeat center/contain url("chrome://global/skin/icons/close.svg");
}
.pocket-btn-add {
background: no-repeat left center url("chrome://pocket/content/panels/img/glyph.svg");
background-size: 16px;
border: 0;
padding-inline-start: 20px;
font-size: 16px;
color: #5B5B66;
cursor: pointer;
}
.pocket-btn-add.saved {
background-image: url("chrome://global/skin/icons/pocket.svg");
}
.pocket-collapse-recs {
cursor: pointer;
background: no-repeat center/contain url("chrome://global/skin/icons/arrow-down.svg");
padding: 0;
margin: 0;
border: 0;
width: 18px;
height: 30px;
}
.pocket-collapse-recs.closed {
transform: rotate(-90deg);
}
.pocket-recs-top {
display: flex;
}
.pocket-recs-top .col:nth-child(2) {
padding-inline-start: 68px;
}
.pocket-recs {
display: flex;
justify-content: space-between;
}
.pocket-recs.closed {
display: none;
}
.pocket-recs p {
text-align: start;
}
.pocket-rec {
padding: 30px 0;
width: 31%;
}
.pocket-rec-top {
display: flex;
text-decoration: none;
}
.pocket-sign-up {
text-align: center;
}
.pocket-rec .pocket-rec-title {
font-style: normal;
font-weight: bold;
font-size: 16px;
line-height: 24px;
color: #000000;
}
.pocket-rec .pocket-rec-thumb {
width: 66px;
height: 66px;
filter: drop-shadow(0px 2px 6px rgba(58, 57, 68, 0.2));
border-radius: 4px;
margin-inline-start: 16px;
}
.pocket-rec .pocket-rec-meta {
font-style: normal;
font-weight: normal;
font-size: 14px;
line-height: 20px;
color: #5B5B66;
}
/* Medium breakpoint */
@media (max-width: 1128px) {
.pocket-cta-inner {
@ -63,6 +149,14 @@
.pocket-dismiss-cta {
inset-inline-end: 40px;
}
.pocket-rec {
width: 48%;
}
.pocket-rec:nth-child(2) {
display: none;
}
}
/* Small breakpoint */
@ -73,7 +167,9 @@
}
.pocket-cta-header,
.pocket-cta-subhead {
.pocket-cta-subhead,
.pocket-rec-bottom,
.pocket-rec-title {
text-align: start;
}
@ -82,7 +178,7 @@
background: url("chrome://global/skin/reader/RM-Pocket-Glyph.svg") no-repeat center 0;
}
.pocket-button {
.pocket-btn {
padding: 8px;
}
@ -90,4 +186,16 @@
inset-inline-end: 20px;
top: 20px;
}
.pocket-recs {
display: block;
}
.pocket-rec {
width: 100%;
}
.pocket-rec:nth-child(2) {
display: block;
}
}