зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1726385 - CTA + Recs variant r=thecount
Differential Revision: https://phabricator.services.mozilla.com/D123679
This commit is contained in:
Родитель
461b6bb1e9
Коммит
2f6a4680e7
|
@ -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 that’s 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 you’ve 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;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче