Bug 1746014 - Pocket button refresh, saved panel. r=gvn,flod

Differential Revision: https://phabricator.services.mozilla.com/D138962
This commit is contained in:
Scott 2022-03-24 15:36:26 +00:00
Родитель 6ff7bd4003
Коммит 67a7ee7ede
13 изменённых файлов: 506 добавлений и 99 удалений

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

@ -33,6 +33,22 @@ hr {
line-height: 1.23em;
}
.header_small {
margin: 12px 0 8px;
font-size: 0.84em;
line-height: 1.07em;
}
.header_flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.header_center {
text-align: center;
}
p {
margin: 8px 0;
font-size: 0.84em;

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

@ -417,6 +417,22 @@ hr {
line-height: 1.23em;
}
.header_small {
margin: 12px 0 8px;
font-size: 0.84em;
line-height: 1.07em;
}
.header_flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.header_center {
text-align: center;
}
p {
margin: 8px 0;
font-size: 0.84em;
@ -2070,6 +2086,7 @@ body.theme_dark .stp_popular_topics .stp_popular_topic .stp_popular_topic_link {
padding: 0;
list-style: none;
}
.stp_article_list .stp_article_list_saved_article,
.stp_article_list .stp_article_list_link {
display: flex;
border-radius: 4px;
@ -2091,6 +2108,10 @@ body.theme_dark .stp_article_list .stp_article_list_link:hover {
margin-inline-end: 8px;
background-color: #ECECEE;
}
.stp_article_list .stp_article_list_thumb:-moz-broken,
.stp_article_list .stp_article_list_thumb_placeholder:-moz-broken {
display: none;
}
.stp_article_list .stp_article_list_header {
font-style: normal;
font-weight: 600;
@ -2098,6 +2119,11 @@ body.theme_dark .stp_article_list .stp_article_list_link:hover {
line-height: 1.27em;
color: #15141A;
margin: 0 0 4px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
word-break: break-word;
}
body.theme_dark .stp_article_list .stp_article_list_header {
color: #FBFBFE;
@ -2219,4 +2245,16 @@ body.stp_signup_body {
margin-inline-start: 16px;
}
.stp_panel_error {
margin: 23px 0 32px;
}
.stp_panel_error .stp_panel_error_icon {
float: inline-start;
margin-block: 6px 16px;
margin-inline: 7px 17px;
background-image: url(../img/pocketerror@1x.png);
height: 44px;
width: 44px;
}
/*# sourceMappingURL=main.compiled.css.map */

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

@ -14,3 +14,4 @@
@import "../js/components/Header/Header";
@import "../js/components/Button/Button";
@import "../js/components/Signup/Signup";
@import "../js/components/Saved/Saved";

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

@ -4,29 +4,66 @@
import React from "react";
function ArticleUrl(props) {
// We turn off the link if we're either a saved article, or if the url doesn't exist.
if (props.savedArticle || !props.url) {
return (
<div className="stp_article_list_saved_article">{props.children}</div>
);
}
return (
<a className="stp_article_list_link" href={props.url}>
{props.children}
</a>
);
}
function Article(props) {
function encodeThumbnail(rawSource) {
return rawSource
? `https://img-getpocket.cdn.mozilla.net/80x80/filters:format(jpeg):quality(60):no_upscale():strip_exif()/${encodeURIComponent(
rawSource
)}`
: null;
}
const { article } = props;
const url = article.url || article.resolved_url;
// Using array notation because there is a key titled `1` (`images` is an object)
const thumbnail =
article.thumbnail ||
encodeThumbnail(article?.top_image_url || article?.images?.["1"]?.src);
const alt = article.alt || "thumbnail image";
const title = article.title || article.resolved_title;
// Sometimes domain_metadata is not there, depending on the source.
const publisher =
article.publisher ||
article.domain_metadata?.name ||
article.resolved_domain;
return (
<li className="stp_article_list_item">
<ArticleUrl url={url} savedArticle={props.savedArticle}>
<>
{thumbnail ? (
<img className="stp_article_list_thumb" src={thumbnail} alt={alt} />
) : (
<div className="stp_article_list_thumb_placeholder" />
)}
<div className="stp_article_list_meta">
<header className="stp_article_list_header">{title}</header>
<p className="stp_article_list_publisher">{publisher}</p>
</div>
</>
</ArticleUrl>
</li>
);
}
function ArticleList(props) {
return (
<ul className="stp_article_list">
{props.articles?.map(article => (
<li className="stp_article_list_item">
<a className="stp_article_list_link" href={article.url}>
{article.thumbnail ? (
<img
className="stp_article_list_thumb"
src={article.thumbnail}
alt={article.alt}
/>
) : (
<div className="stp_article_list_thumb_placeholder" />
)}
<div className="stp_article_list_meta">
<header className="stp_article_list_header">
{article.title}
</header>
<p className="stp_article_list_publisher">{article.publisher}</p>
</div>
</a>
</li>
<Article article={article} savedArticle={props.savedArticle} />
))}
</ul>
);

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

@ -2,11 +2,14 @@
padding: 0;
list-style: none;
.stp_article_list_saved_article,
.stp_article_list_link {
display: flex;
border-radius: 4px;
padding: 8px;
}
.stp_article_list_link {
&:hover {
text-decoration: none;
background-color: #ECECEE;
@ -24,6 +27,9 @@
border-radius: 4px;
margin-inline-end: 8px;
background-color: #ECECEE;
&:-moz-broken {
display: none;
}
}
.stp_article_list_header {
@ -34,6 +40,12 @@
color: #15141A;
margin: 0 0 4px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
display: -webkit-box;
overflow: hidden;
word-break: break-word;
@include theme_dark {
color: #FBFBFE;
}

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

@ -8,6 +8,7 @@ function Button(props) {
return (
<a
href={props.url}
onClick={props.onClick}
className={`stp_button${props?.style && ` stp_button_${props.style}`}`}
>
{props.children}

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

@ -9,14 +9,6 @@ import PopularTopics from "../PopularTopics/PopularTopics";
import Button from "../Button/Button";
import panelMessaging from "../../messages";
function encodeThumbnail(rawSource) {
return rawSource
? `https://img-getpocket.cdn.mozilla.net/80x80/filters:format(jpeg):quality(60):no_upscale():strip_exif()/${encodeURIComponent(
rawSource
)}`
: null;
}
function Home(props) {
const { locale, topics, pockethost, hideRecentSaves } = props;
const [{ articles, status }, setArticlesState] = useState({
@ -52,16 +44,7 @@ function Home(props) {
}
setArticlesState({
articles: data.map(item => ({
url: item.resolved_url,
// Using array notation because there is a key titled `1` (`images` is an object)
thumbnail: encodeThumbnail(
item?.top_image_url || item?.images?.["1"]?.src
),
alt: "thumbnail image",
title: item.resolved_title,
publisher: item.domain_metadata?.name,
})),
articles: data,
status: "success",
});
});

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

@ -2,31 +2,165 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import React, { useState, useEffect } from "react";
import Header from "../Header/Header";
import Button from "../Button/Button";
import ArticleList from "../ArticleList/ArticleList";
import panelMessaging from "../../messages";
function Saved(props) {
const { similarRecs, savedStory } = props;
const { locale } = props;
// savedStatus can be success, loading, or error.
const [
{ savedStatus, savedErrorId, itemId },
setSavedStatusState,
] = useState({ savedStatus: "loading" });
// removedStatus can be removed, removing, or error.
const [
{ removedStatus, removedErrorMessage },
setRemovedStatusState,
] = useState({});
const [savedStory, setSavedStoryState] = useState();
const [similarRecs, setSimilarRecsState] = useState();
function removeItem(event) {
event.preventDefault();
setRemovedStatusState({ removedStatus: "removing" });
panelMessaging.sendMessage(
"PKT_deleteItem",
{
itemId,
},
function(resp) {
const { data } = resp;
if (data.status == "success") {
setRemovedStatusState({ removedStatus: "removed" });
} else if (data.status == "error") {
let errorMessage = "";
// The server returns English error messages, so in the case of
// non English, we do our best with a generic translated error.
if (data.error.message && locale?.startsWith("en")) {
errorMessage = data.error.message;
}
setRemovedStatusState({
removedStatus: "error",
removedErrorMessage: errorMessage,
});
}
}
);
}
useEffect(() => {
// Wait confirmation of save before flipping to final saved state
panelMessaging.addMessageListener("PKT_saveLink", function(resp) {
const { data } = resp;
if (data.status == "error") {
// Use localizedKey or fallback to a generic catch all error.
setSavedStatusState({
savedStatus: "error",
savedErrorId:
data?.error?.localizedKey || "pocket-panel-saved-error-generic",
});
return;
}
// Success, so no localized error id needed.
setSavedStatusState({
savedStatus: "success",
itemId: data.item.item_id,
savedErrorId: "",
});
});
panelMessaging.addMessageListener("PKT_renderSavedStory", function(resp) {
setSavedStoryState(resp?.data?.item_preview);
});
panelMessaging.addMessageListener("PKT_renderItemRecs", function(resp) {
const { data } = resp;
setSimilarRecsState(data?.recommendations?.map(rec => rec.item));
});
// tell back end we're ready
panelMessaging.sendMessage("PKT_show_saved");
}, []);
if (savedStatus === "error") {
return (
<div className="stp_panel_container">
<div className="stp_panel stp_panel_error">
<div className="stp_panel_error_icon" />
<h3
className="header_large"
data-l10n-id="pocket-panel-saved-error-not-saved"
/>
<p data-l10n-id={savedErrorId} />
</div>
</div>
);
}
return (
<div className="stp_panel_container">
<div className="stp_panel stp_panel_home">
<div className="stp_panel stp_panel_saved">
<Header>
<a>
<Button style="primary">
<span data-l10n-id="pocket-panel-header-my-list"></span>
</a>
</Button>
</Header>
<hr />
{savedStory && (
{!removedStatus && savedStatus === "success" && (
<>
<p data-l10n-id="pocket-panel-saved-page-saved"></p>
<ArticleList articles={[savedStory]} />
<span data-l10n-id="pocket-panel-button-add-tags"></span>
<span data-l10n-id="pocket-panel-saved-remove-page"></span>
<h3 className="header_large header_flex">
<span data-l10n-id="pocket-panel-saved-page-saved-b" />
<Button style="text" url="google.com" onClick={removeItem}>
<span data-l10n-id="pocket-panel-button-remove"></span>
</Button>
</h3>
{savedStory && (
<ArticleList articles={[savedStory]} savedArticle={true} />
)}
<h3
className="header_small"
data-l10n-id="pocket-panel-cta-add-tags"
/>
{similarRecs?.length && locale?.startsWith("en") && (
<>
<hr />
<h3 className="header_medium">Similar Stories</h3>
<ArticleList articles={similarRecs} />
</>
)}
</>
)}
{savedStatus === "loading" && (
<h3
className="header_large"
data-l10n-id="pocket-panel-saved-saving-tags"
/>
)}
{removedStatus === "removing" && (
<h3
className="header_large header_center"
data-l10n-id="pocket-panel-saved-processing-remove"
/>
)}
{removedStatus === "removed" && (
<h3
className="header_large header_center"
data-l10n-id="pocket-panel-saved-removed"
/>
)}
{removedStatus === "error" && (
<>
<h3
className="header_large"
data-l10n-id="pocket-panel-saved-error-remove"
/>
{removedErrorMessage && <p>{removedErrorMessage}</p>}
</>
)}
<hr />
{similarRecs?.length && <ArticleList articles={similarRecs} />}
</div>
</div>
);

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

@ -0,0 +1,11 @@
.stp_panel_error {
margin: 23px 0 32px;
.stp_panel_error_icon {
float: inline-start;
margin-block: 6px 16px;
margin-inline: 7px 17px;
background-image: url(../img/pocketerror@1x.png);
height: 44px;
width: 44px;
}
}

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

@ -55,27 +55,62 @@ function Header(props) {
* You can obtain one at http://mozilla.org/MPL/2.0/. */
function ArticleList(props) {
return /*#__PURE__*/react.createElement("ul", {
className: "stp_article_list"
}, props.articles?.map(article => /*#__PURE__*/react.createElement("li", {
className: "stp_article_list_item"
}, /*#__PURE__*/react.createElement("a", {
function ArticleUrl(props) {
// We turn off the link if we're either a saved article, or if the url doesn't exist.
if (props.savedArticle || !props.url) {
return /*#__PURE__*/react.createElement("div", {
className: "stp_article_list_saved_article"
}, props.children);
}
return /*#__PURE__*/react.createElement("a", {
className: "stp_article_list_link",
href: article.url
}, article.thumbnail ? /*#__PURE__*/react.createElement("img", {
href: props.url
}, props.children);
}
function Article(props) {
function encodeThumbnail(rawSource) {
return rawSource ? `https://img-getpocket.cdn.mozilla.net/80x80/filters:format(jpeg):quality(60):no_upscale():strip_exif()/${encodeURIComponent(rawSource)}` : null;
}
const {
article
} = props;
const url = article.url || article.resolved_url; // Using array notation because there is a key titled `1` (`images` is an object)
const thumbnail = article.thumbnail || encodeThumbnail(article?.top_image_url || article?.images?.["1"]?.src);
const alt = article.alt || "thumbnail image";
const title = article.title || article.resolved_title; // Sometimes domain_metadata is not there, depending on the source.
const publisher = article.publisher || article.domain_metadata?.name || article.resolved_domain;
return /*#__PURE__*/react.createElement("li", {
className: "stp_article_list_item"
}, /*#__PURE__*/react.createElement(ArticleUrl, {
url: url,
savedArticle: props.savedArticle
}, /*#__PURE__*/react.createElement(react.Fragment, null, thumbnail ? /*#__PURE__*/react.createElement("img", {
className: "stp_article_list_thumb",
src: article.thumbnail,
alt: article.alt
src: thumbnail,
alt: alt
}) : /*#__PURE__*/react.createElement("div", {
className: "stp_article_list_thumb_placeholder"
}), /*#__PURE__*/react.createElement("div", {
className: "stp_article_list_meta"
}, /*#__PURE__*/react.createElement("header", {
className: "stp_article_list_header"
}, article.title), /*#__PURE__*/react.createElement("p", {
}, title), /*#__PURE__*/react.createElement("p", {
className: "stp_article_list_publisher"
}, article.publisher))))));
}, publisher)))));
}
function ArticleList(props) {
return /*#__PURE__*/react.createElement("ul", {
className: "stp_article_list"
}, props.articles?.map(article => /*#__PURE__*/react.createElement(Article, {
article: article,
savedArticle: props.savedArticle
})));
}
/* harmony default export */ const ArticleList_ArticleList = (ArticleList);
@ -107,6 +142,7 @@ function PopularTopics(props) {
function Button(props) {
return /*#__PURE__*/react.createElement("a", {
href: props.url,
onClick: props.onClick,
className: `stp_button${props?.style && ` stp_button_${props.style}`}`
}, props.children);
}
@ -177,10 +213,6 @@ var pktPanelMessaging = {
function encodeThumbnail(rawSource) {
return rawSource ? `https://img-getpocket.cdn.mozilla.net/80x80/filters:format(jpeg):quality(60):no_upscale():strip_exif()/${encodeURIComponent(rawSource)}` : null;
}
function Home(props) {
const {
locale,
@ -220,14 +252,7 @@ function Home(props) {
}
setArticlesState({
articles: data.map(item => ({
url: item.resolved_url,
// Using array notation because there is a key titled `1` (`images` is an object)
thumbnail: encodeThumbnail(item?.top_image_url || item?.images?.["1"]?.src),
alt: "thumbnail image",
title: item.resolved_title,
publisher: item.domain_metadata?.name
})),
articles: data,
status: "success"
});
});
@ -580,28 +605,152 @@ var SignupOverlay = function (options) {
function Saved(props) {
const {
similarRecs,
savedStory
} = props;
locale
} = props; // savedStatus can be success, loading, or error.
const [{
savedStatus,
savedErrorId,
itemId
}, setSavedStatusState] = (0,react.useState)({
savedStatus: "loading"
}); // removedStatus can be removed, removing, or error.
const [{
removedStatus,
removedErrorMessage
}, setRemovedStatusState] = (0,react.useState)({});
const [savedStory, setSavedStoryState] = (0,react.useState)();
const [similarRecs, setSimilarRecsState] = (0,react.useState)();
function removeItem(event) {
event.preventDefault();
setRemovedStatusState({
removedStatus: "removing"
});
messages.sendMessage("PKT_deleteItem", {
itemId
}, function (resp) {
const {
data
} = resp;
if (data.status == "success") {
setRemovedStatusState({
removedStatus: "removed"
});
} else if (data.status == "error") {
let errorMessage = ""; // The server returns English error messages, so in the case of
// non English, we do our best with a generic translated error.
if (data.error.message && locale?.startsWith("en")) {
errorMessage = data.error.message;
}
setRemovedStatusState({
removedStatus: "error",
removedErrorMessage: errorMessage
});
}
});
}
(0,react.useEffect)(() => {
// Wait confirmation of save before flipping to final saved state
messages.addMessageListener("PKT_saveLink", function (resp) {
const {
data
} = resp;
if (data.status == "error") {
// Use localizedKey or fallback to a generic catch all error.
setSavedStatusState({
savedStatus: "error",
savedErrorId: data?.error?.localizedKey || "pocket-panel-saved-error-generic"
});
return;
} // Success, so no localized error id needed.
setSavedStatusState({
savedStatus: "success",
itemId: data.item.item_id,
savedErrorId: ""
});
});
messages.addMessageListener("PKT_renderSavedStory", function (resp) {
setSavedStoryState(resp?.data?.item_preview);
});
messages.addMessageListener("PKT_renderItemRecs", function (resp) {
const {
data
} = resp;
setSimilarRecsState(data?.recommendations?.map(rec => rec.item));
}); // tell back end we're ready
messages.sendMessage("PKT_show_saved");
}, []);
if (savedStatus === "error") {
return /*#__PURE__*/react.createElement("div", {
className: "stp_panel_container"
}, /*#__PURE__*/react.createElement("div", {
className: "stp_panel stp_panel_error"
}, /*#__PURE__*/react.createElement("div", {
className: "stp_panel_error_icon"
}), /*#__PURE__*/react.createElement("h3", {
className: "header_large",
"data-l10n-id": "pocket-panel-saved-error-not-saved"
}), /*#__PURE__*/react.createElement("p", {
"data-l10n-id": savedErrorId
})));
}
return /*#__PURE__*/react.createElement("div", {
className: "stp_panel_container"
}, /*#__PURE__*/react.createElement("div", {
className: "stp_panel stp_panel_home"
}, /*#__PURE__*/react.createElement(Header_Header, null, /*#__PURE__*/react.createElement("a", null, /*#__PURE__*/react.createElement("span", {
className: "stp_panel stp_panel_saved"
}, /*#__PURE__*/react.createElement(Header_Header, null, /*#__PURE__*/react.createElement(Button_Button, {
style: "primary"
}, /*#__PURE__*/react.createElement("span", {
"data-l10n-id": "pocket-panel-header-my-list"
}))), /*#__PURE__*/react.createElement("hr", null), savedStory && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("p", {
"data-l10n-id": "pocket-panel-saved-page-saved"
}), /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
articles: [savedStory]
}), /*#__PURE__*/react.createElement("span", {
"data-l10n-id": "pocket-panel-button-add-tags"
}), /*#__PURE__*/react.createElement("span", {
"data-l10n-id": "pocket-panel-saved-remove-page"
})), /*#__PURE__*/react.createElement("hr", null), similarRecs?.length && /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
}))), /*#__PURE__*/react.createElement("hr", null), !removedStatus && savedStatus === "success" && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
className: "header_large header_flex"
}, /*#__PURE__*/react.createElement("span", {
"data-l10n-id": "pocket-panel-saved-page-saved-b"
}), /*#__PURE__*/react.createElement(Button_Button, {
style: "text",
url: "google.com",
onClick: removeItem
}, /*#__PURE__*/react.createElement("span", {
"data-l10n-id": "pocket-panel-button-remove"
}))), savedStory && /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
articles: [savedStory],
savedArticle: true
}), /*#__PURE__*/react.createElement("h3", {
className: "header_small",
"data-l10n-id": "pocket-panel-cta-add-tags"
}), similarRecs?.length && locale?.startsWith("en") && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("hr", null), /*#__PURE__*/react.createElement("h3", {
className: "header_medium"
}, "Similar Stories"), /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
articles: similarRecs
})));
}))), savedStatus === "loading" && /*#__PURE__*/react.createElement("h3", {
className: "header_large",
"data-l10n-id": "pocket-panel-saved-saving-tags"
}), removedStatus === "removing" && /*#__PURE__*/react.createElement("h3", {
className: "header_large header_center",
"data-l10n-id": "pocket-panel-saved-processing-remove"
}), removedStatus === "removed" && /*#__PURE__*/react.createElement("h3", {
className: "header_large header_center",
"data-l10n-id": "pocket-panel-saved-removed"
}), removedStatus === "error" && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
className: "header_large",
"data-l10n-id": "pocket-panel-saved-error-remove"
}), removedErrorMessage && /*#__PURE__*/react.createElement("p", null, removedErrorMessage))));
}
/* harmony default export */ const Saved_Saved = (Saved);
@ -1129,10 +1278,14 @@ SavedOverlay.prototype = {
const layoutRefresh = searchParams.get(`layoutRefresh`) === `true`;
if (layoutRefresh) {
// Create actual content
// For now, we need to do a little work on the body element
// to support both old and new versions.
document.querySelector(`.pkt_ext_containersaved`)?.classList.add(`stp_saved_body`);
document.querySelector(`.pkt_ext_containersaved`)?.classList.remove(`pkt_ext_containersaved`); // Create actual content
react_dom.render( /*#__PURE__*/react.createElement(Saved_Saved, {
pockethost: pockethost,
savedStory: {}
locale: locale
}), document.querySelector(`body`));
} else {
// set host
@ -1183,11 +1336,10 @@ SavedOverlay.prototype = {
data
} = resp;
myself.renderItemRecs(data);
});
} // tell back end we're ready
}); // tell back end we're ready
messages.sendMessage("PKT_show_saved");
messages.sendMessage("PKT_show_saved");
}
}
};

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

@ -667,9 +667,17 @@ SavedOverlay.prototype = {
const layoutRefresh = searchParams.get(`layoutRefresh`) === `true`;
if (layoutRefresh) {
// For now, we need to do a little work on the body element
// to support both old and new versions.
document
.querySelector(`.pkt_ext_containersaved`)
?.classList.add(`stp_saved_body`);
document
.querySelector(`.pkt_ext_containersaved`)
?.classList.remove(`pkt_ext_containersaved`);
// Create actual content
ReactDOM.render(
<Saved pockethost={pockethost} savedStory={{}} />,
<Saved pockethost={pockethost} locale={locale} />,
document.querySelector(`body`)
);
} else {
@ -748,10 +756,10 @@ SavedOverlay.prototype = {
const { data } = resp;
myself.renderItemRecs(data);
});
}
// tell back end we're ready
pktPanelMessaging.sendMessage("PKT_show_saved");
// tell back end we're ready
pktPanelMessaging.sendMessage("PKT_show_saved");
}
},
};

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

@ -367,6 +367,14 @@ var pktUI = (function() {
pktUIMessaging.sendMessageToPanel(saveLinkMessageId, successResponse);
SaveToPocket.itemSaved();
if (item?.resolved_id && item?.resolved_id !== "0") {
pktApi.getArticleInfo(item.resolved_url, {
success(data) {
pktUIMessaging.sendMessageToPanel("PKT_renderSavedStory", data);
},
});
}
getAndShowRecsForItem(item, {
success(data) {
pktUIMessaging.sendMessageToPanel("PKT_renderItemRecs", data);

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

@ -15,9 +15,12 @@ pocket-panel-saved-error-tag-length = Tags are limited to 25 characters
pocket-panel-saved-error-only-links = Only links can be saved
pocket-panel-saved-error-not-saved = Page Not Saved
pocket-panel-saved-error-no-internet = You must be connected to the Internet in order to save to { -pocket-brand-name }. Please connect to the Internet and try again.
pocket-panel-saved-error-remove = There was an error while trying to remove this page.
pocket-panel-saved-page-removed = Page Removed
pocket-panel-saved-page-saved = Saved to { -pocket-brand-name }
pocket-panel-saved-page-saved-b = Saved to { -pocket-brand-name }!
pocket-panel-saved-processing-remove = Removing Page…
pocket-panel-saved-removed = Page Removed from My List
pocket-panel-saved-processing-tags = Adding tags…
pocket-panel-saved-remove-page = Remove Page
pocket-panel-saved-save-tags = Save
@ -26,6 +29,9 @@ pocket-panel-saved-suggested-tags = Suggested Tags
pocket-panel-saved-tags-saved = Tags Added
pocket-panel-signup-view-list = View List
# This is displayed above a field where the user can add tags
pocket-panel-signup-add-tags = Add Tags:
## about:pocket-signup panel
pocket-panel-signup-already-have = Already a { -pocket-brand-name } user?
@ -65,5 +71,5 @@ pocket-panel-header-sign-in = Sign In
## Pocket panel buttons
pocket-panel-button-show-all = Show All
pocket-panel-button-add-tags = Add Tags
pocket-panel-button-activate = Activate { -pocket-brand-name } in { -brand-product-name }
pocket-panel-button-remove = Remove