зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1746014 - Pocket button refresh, saved panel. r=gvn,flod
Differential Revision: https://phabricator.services.mozilla.com/D138962
This commit is contained in:
Родитель
6ff7bd4003
Коммит
67a7ee7ede
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче