summaryrefslogtreecommitdiffstats
path: root/browser/components/pocket/content/panels/js/main.bundle.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/pocket/content/panels/js/main.bundle.js')
-rw-r--r--browser/components/pocket/content/panels/js/main.bundle.js1355
1 files changed, 1355 insertions, 0 deletions
diff --git a/browser/components/pocket/content/panels/js/main.bundle.js b/browser/components/pocket/content/panels/js/main.bundle.js
new file mode 100644
index 0000000000..3bd91b9472
--- /dev/null
+++ b/browser/components/pocket/content/panels/js/main.bundle.js
@@ -0,0 +1,1355 @@
+/******/ (() => { // webpackBootstrap
+/******/ "use strict";
+/******/ var __webpack_modules__ = ({
+
+/***/ 299:
+/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {
+
+
+// EXTERNAL MODULE: ./node_modules/react/index.js
+var react = __webpack_require__(294);
+// EXTERNAL MODULE: ./node_modules/react-dom/index.js
+var react_dom = __webpack_require__(935);
+;// CONCATENATED MODULE: ./content/panels/js/components/Header/Header.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+function Header(props) {
+ return /*#__PURE__*/react.createElement("h1", {
+ className: "stp_header"
+ }, /*#__PURE__*/react.createElement("div", {
+ className: "stp_header_logo"
+ }), props.children);
+}
+
+/* harmony default export */ const Header_Header = (Header);
+;// CONCATENATED MODULE: ./content/panels/js/messages.js
+/* global RPMRemoveMessageListener:false, RPMAddMessageListener:false, RPMSendAsyncMessage:false */
+var pktPanelMessaging = {
+ removeMessageListener(messageId, callback) {
+ RPMRemoveMessageListener(messageId, callback);
+ },
+
+ addMessageListener(messageId, callback = () => {}) {
+ RPMAddMessageListener(messageId, callback);
+ },
+
+ sendMessage(messageId, payload = {}, callback) {
+ if (callback) {
+ // If we expect something back, we use RPMSendAsyncMessage and not RPMSendQuery.
+ // Even though RPMSendQuery returns something, our frame could be closed at any moment,
+ // and we don't want to close a RPMSendQuery promise loop unexpectedly.
+ // So instead we setup a response event.
+ const responseMessageId = `${messageId}_response`;
+
+ var responseListener = responsePayload => {
+ callback(responsePayload);
+ this.removeMessageListener(responseMessageId, responseListener);
+ };
+
+ this.addMessageListener(responseMessageId, responseListener);
+ } // Send message
+
+
+ RPMSendAsyncMessage(messageId, payload);
+ },
+
+ // Click helper to reduce bugs caused by oversight
+ // from different implementations of similar code.
+ clickHelper(element, {
+ source = "",
+ position
+ }) {
+ element?.addEventListener(`click`, event => {
+ event.preventDefault();
+ this.sendMessage("PKT_openTabWithUrl", {
+ url: event.currentTarget.getAttribute(`href`),
+ source,
+ position
+ });
+ });
+ },
+
+ log() {
+ RPMSendAsyncMessage("PKT_log", arguments);
+ }
+
+};
+/* harmony default export */ const messages = (pktPanelMessaging);
+;// CONCATENATED MODULE: ./content/panels/js/components/TelemetryLink/TelemetryLink.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+function TelemetryLink(props) {
+ function onClick(event) {
+ if (props.onClick) {
+ props.onClick(event);
+ } else {
+ event.preventDefault();
+ messages.sendMessage("PKT_openTabWithUrl", {
+ url: event.currentTarget.getAttribute(`href`),
+ source: props.source,
+ model: props.model,
+ position: props.position
+ });
+ }
+ }
+
+ return /*#__PURE__*/react.createElement("a", {
+ href: props.href,
+ onClick: onClick,
+ target: "_blank",
+ className: props.className
+ }, props.children);
+}
+
+/* harmony default export */ const TelemetryLink_TelemetryLink = (TelemetryLink);
+;// CONCATENATED MODULE: ./content/panels/js/components/ArticleList/ArticleList.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+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(TelemetryLink_TelemetryLink, {
+ className: "stp_article_list_link",
+ href: props.url,
+ source: props.source,
+ position: props.position,
+ model: props.model
+ }, 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 [thumbnailLoaded, setThumbnailLoaded] = (0,react.useState)(false);
+ const [thumbnailLoadFailed, setThumbnailLoadFailed] = (0,react.useState)(false);
+ const {
+ article,
+ savedArticle,
+ position,
+ source,
+ model,
+ utmParams,
+ openInPocketReader
+ } = props;
+
+ if (!article.url && !article.resolved_url && !article.given_url) {
+ return null;
+ }
+
+ const url = new URL(article.url || article.resolved_url || article.given_url);
+ const urlSearchParams = new URLSearchParams(utmParams);
+
+ if (openInPocketReader && article.item_id && !url.href.match(/getpocket\.com\/read/)) {
+ url.href = `https://getpocket.com/read/${article.item_id}`;
+ }
+
+ for (let [key, val] of urlSearchParams.entries()) {
+ url.searchParams.set(key, val);
+ } // 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 || article.given_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.href,
+ savedArticle: savedArticle,
+ position: position,
+ source: source,
+ model: model,
+ utmParams: utmParams
+ }, /*#__PURE__*/react.createElement(react.Fragment, null, thumbnail && !thumbnailLoadFailed ? /*#__PURE__*/react.createElement("img", {
+ className: "stp_article_list_thumb",
+ src: thumbnail,
+ alt: alt,
+ width: "40",
+ height: "40",
+ onLoad: () => {
+ setThumbnailLoaded(true);
+ },
+ onError: () => {
+ setThumbnailLoadFailed(true);
+ },
+ style: {
+ visibility: thumbnailLoaded ? `visible` : `hidden`
+ }
+ }) : /*#__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"
+ }, title), /*#__PURE__*/react.createElement("p", {
+ className: "stp_article_list_publisher"
+ }, publisher)))));
+}
+
+function ArticleList(props) {
+ return /*#__PURE__*/react.createElement("ul", {
+ className: "stp_article_list"
+ }, props.articles?.map((article, position) => /*#__PURE__*/react.createElement(Article, {
+ article: article,
+ savedArticle: props.savedArticle,
+ position: position,
+ source: props.source,
+ model: props.model,
+ utmParams: props.utmParams,
+ openInPocketReader: props.openInPocketReader
+ })));
+}
+
+/* harmony default export */ const ArticleList_ArticleList = (ArticleList);
+;// CONCATENATED MODULE: ./content/panels/js/components/PopularTopics/PopularTopics.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+function PopularTopics(props) {
+ return /*#__PURE__*/react.createElement("ul", {
+ className: "stp_popular_topics"
+ }, props.topics?.map((topic, position) => /*#__PURE__*/react.createElement("li", {
+ key: `item-${topic.topic}`,
+ className: "stp_popular_topic"
+ }, /*#__PURE__*/react.createElement(TelemetryLink_TelemetryLink, {
+ className: "stp_popular_topic_link",
+ href: `https://${props.pockethost}/explore/${topic.topic}?${props.utmParams}`,
+ source: props.source,
+ position: position
+ }, topic.title))));
+}
+
+/* harmony default export */ const PopularTopics_PopularTopics = (PopularTopics);
+;// CONCATENATED MODULE: ./content/panels/js/components/Button/Button.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+function Button(props) {
+ return /*#__PURE__*/react.createElement(TelemetryLink_TelemetryLink, {
+ href: props.url,
+ onClick: props.onClick,
+ className: `stp_button${props?.style && ` stp_button_${props.style}`}`,
+ source: props.source
+ }, props.children);
+}
+
+/* harmony default export */ const Button_Button = (Button);
+;// CONCATENATED MODULE: ./content/panels/js/components/Home/Home.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+
+
+
+
+function Home(props) {
+ const {
+ locale,
+ topics,
+ pockethost,
+ hideRecentSaves,
+ utmSource,
+ utmCampaign,
+ utmContent
+ } = props;
+ const [{
+ articles,
+ status
+ }, setArticlesState] = (0,react.useState)({
+ articles: [],
+ // Can be success, loading, or error.
+ status: ""
+ });
+ const utmParams = `utm_source=${utmSource}${utmCampaign && utmContent ? `&utm_campaign=${utmCampaign}&utm_content=${utmContent}` : ``}`;
+ (0,react.useEffect)(() => {
+ if (!hideRecentSaves) {
+ // We don't display the loading message until instructed. This is because cache
+ // loads should be fast, so using the loading message for cache just adds loading jank.
+ messages.addMessageListener("PKT_loadingRecentSaves", function (resp) {
+ setArticlesState({
+ articles,
+ status: "loading"
+ });
+ });
+ messages.addMessageListener("PKT_renderRecentSaves", function (resp) {
+ const {
+ data
+ } = resp;
+
+ if (data.status === "error") {
+ setArticlesState({
+ articles: [],
+ status: "error"
+ });
+ return;
+ }
+
+ setArticlesState({
+ articles: data,
+ status: "success"
+ });
+ });
+ } // tell back end we're ready
+
+
+ messages.sendMessage("PKT_show_home");
+ }, []);
+ let recentSavesSection = null;
+
+ if (status === "error" || hideRecentSaves) {
+ recentSavesSection = /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium",
+ "data-l10n-id": "pocket-panel-home-new-user-cta"
+ });
+ } else if (status === "loading") {
+ recentSavesSection = /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-home-most-recent-saves-loading"
+ });
+ } else if (status === "success") {
+ if (articles?.length) {
+ recentSavesSection = /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium",
+ "data-l10n-id": "pocket-panel-home-most-recent-saves"
+ }), articles.length > 3 ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
+ articles: articles.slice(0, 3),
+ source: "home_recent_save",
+ utmParams: utmParams,
+ openInPocketReader: true
+ }), /*#__PURE__*/react.createElement("span", {
+ className: "stp_button_wide"
+ }, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "secondary",
+ url: `https://${pockethost}/a?${utmParams}`,
+ source: "home_view_list"
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-button-show-all"
+ })))) : /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
+ articles: articles,
+ source: "home_recent_save",
+ utmParams: utmParams
+ }));
+ } else {
+ recentSavesSection = /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium",
+ "data-l10n-id": "pocket-panel-home-new-user-cta"
+ }), /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium",
+ "data-l10n-id": "pocket-panel-home-new-user-message"
+ }));
+ }
+ }
+
+ 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(Button_Button, {
+ style: "primary",
+ url: `https://${pockethost}/a?${utmParams}`,
+ source: "home_view_list"
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-header-my-saves"
+ }))), /*#__PURE__*/react.createElement("hr", null), recentSavesSection, /*#__PURE__*/react.createElement("hr", null), pockethost && locale?.startsWith("en") && topics?.length && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium"
+ }, "Explore popular topics:"), /*#__PURE__*/react.createElement(PopularTopics_PopularTopics, {
+ topics: topics,
+ pockethost: pockethost,
+ utmParams: utmParams,
+ source: "home_popular_topic"
+ }))));
+}
+
+/* harmony default export */ const Home_Home = (Home);
+;// CONCATENATED MODULE: ./content/panels/js/home/overlay.js
+/* global Handlebars:false */
+
+/*
+HomeOverlay is the view itself and contains all of the methods to manipute the overlay and messaging.
+It does not contain any logic for saving or communication with the extension or server.
+*/
+
+
+
+
+var HomeOverlay = function (options) {
+ this.inited = false;
+ this.active = false;
+};
+
+HomeOverlay.prototype = {
+ create({
+ pockethost
+ }) {
+ const {
+ searchParams
+ } = new URL(window.location.href);
+ const locale = searchParams.get(`locale`) || ``;
+ const hideRecentSaves = searchParams.get(`hiderecentsaves`) === `true`;
+ const utmSource = searchParams.get(`utmSource`);
+ const utmCampaign = searchParams.get(`utmCampaign`);
+ const utmContent = searchParams.get(`utmContent`);
+
+ if (this.active) {
+ return;
+ }
+
+ this.active = true;
+ react_dom.render( /*#__PURE__*/react.createElement(Home_Home, {
+ locale: locale,
+ hideRecentSaves: hideRecentSaves,
+ pockethost: pockethost,
+ utmSource: utmSource,
+ utmCampaign: utmCampaign,
+ utmContent: utmContent,
+ topics: [{
+ title: "Technology",
+ topic: "technology"
+ }, {
+ title: "Self Improvement",
+ topic: "self-improvement"
+ }, {
+ title: "Food",
+ topic: "food"
+ }, {
+ title: "Parenting",
+ topic: "parenting"
+ }, {
+ title: "Science",
+ topic: "science"
+ }, {
+ title: "Entertainment",
+ topic: "entertainment"
+ }, {
+ title: "Career",
+ topic: "career"
+ }, {
+ title: "Health",
+ topic: "health"
+ }, {
+ title: "Travel",
+ topic: "travel"
+ }, {
+ title: "Must-Reads",
+ topic: "must-reads"
+ }]
+ }), document.querySelector(`body`));
+
+ if (window?.matchMedia(`(prefers-color-scheme: dark)`).matches) {
+ document.querySelector(`body`).classList.add(`theme_dark`);
+ }
+ }
+
+};
+/* harmony default export */ const overlay = (HomeOverlay);
+;// CONCATENATED MODULE: ./content/panels/js/components/Signup/Signup.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+
+function Signup(props) {
+ const {
+ locale,
+ pockethost,
+ utmSource,
+ utmCampaign,
+ utmContent
+ } = props;
+ const utmParams = `utm_source=${utmSource}${utmCampaign && utmContent ? `&utm_campaign=${utmCampaign}&utm_content=${utmContent}` : ``}`;
+ return /*#__PURE__*/react.createElement("div", {
+ className: "stp_panel_container"
+ }, /*#__PURE__*/react.createElement("div", {
+ className: "stp_panel stp_panel_signup"
+ }, /*#__PURE__*/react.createElement(Header_Header, null, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "secondary",
+ url: `https://${pockethost}/login?${utmParams}`,
+ source: "log_in"
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-signup-login"
+ }))), /*#__PURE__*/react.createElement("hr", null), locale?.startsWith("en") ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
+ className: "stp_signup_content_wrapper"
+ }, /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium",
+ "data-l10n-id": "pocket-panel-signup-cta-a-fix"
+ }), /*#__PURE__*/react.createElement("p", {
+ "data-l10n-id": "pocket-panel-signup-cta-b-updated"
+ })), /*#__PURE__*/react.createElement("div", {
+ className: "stp_signup_content_wrapper"
+ }, /*#__PURE__*/react.createElement("hr", null)), /*#__PURE__*/react.createElement("div", {
+ className: "stp_signup_content_wrapper"
+ }, /*#__PURE__*/react.createElement("div", {
+ className: "stp_signup_img_rainbow_reader"
+ }), /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium"
+ }, "Get thought-provoking article recommendations"), /*#__PURE__*/react.createElement("p", null, "Find stories that go deep into a subject or offer a new perspective."))) : /*#__PURE__*/react.createElement("div", {
+ className: "stp_signup_content_wrapper"
+ }, /*#__PURE__*/react.createElement("h3", {
+ className: "header_large",
+ "data-l10n-id": "pocket-panel-signup-cta-a-fix"
+ }), /*#__PURE__*/react.createElement("p", {
+ "data-l10n-id": "pocket-panel-signup-cta-b-short"
+ }), /*#__PURE__*/react.createElement("strong", null, /*#__PURE__*/react.createElement("p", {
+ "data-l10n-id": "pocket-panel-signup-cta-c-updated"
+ }))), /*#__PURE__*/react.createElement("hr", null), /*#__PURE__*/react.createElement("span", {
+ className: "stp_button_wide"
+ }, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "primary",
+ url: `https://${pockethost}/ff_signup?${utmParams}`,
+ source: "sign_up_1"
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-button-activate"
+ })))));
+}
+
+/* harmony default export */ const Signup_Signup = (Signup);
+;// CONCATENATED MODULE: ./content/panels/js/signup/overlay.js
+/*
+SignupOverlay is the view itself and contains all of the methods to manipute the overlay and messaging.
+It does not contain any logic for saving or communication with the extension or server.
+*/
+
+
+
+
+
+var SignupOverlay = function (options) {
+ this.inited = false;
+ this.active = false;
+
+ this.create = function ({
+ pockethost
+ }) {
+ // Extract local variables passed into template via URL query params
+ const {
+ searchParams
+ } = new URL(window.location.href);
+ const locale = searchParams.get(`locale`) || ``;
+ const utmSource = searchParams.get(`utmSource`);
+ const utmCampaign = searchParams.get(`utmCampaign`);
+ const utmContent = searchParams.get(`utmContent`);
+
+ if (this.active) {
+ return;
+ }
+
+ this.active = true; // Create actual content
+
+ react_dom.render( /*#__PURE__*/react.createElement(Signup_Signup, {
+ pockethost: pockethost,
+ utmSource: utmSource,
+ utmCampaign: utmCampaign,
+ utmContent: utmContent,
+ locale: locale
+ }), document.querySelector(`body`));
+
+ if (window?.matchMedia(`(prefers-color-scheme: dark)`).matches) {
+ document.querySelector(`body`).classList.add(`theme_dark`);
+ } // tell back end we're ready
+
+
+ messages.sendMessage("PKT_show_signup");
+ };
+};
+
+/* harmony default export */ const signup_overlay = (SignupOverlay);
+;// CONCATENATED MODULE: ./content/panels/js/components/TagPicker/TagPicker.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+function TagPicker(props) {
+ const [tags, setTags] = (0,react.useState)(props.tags); // New tag group to store
+
+ const [allTags, setAllTags] = (0,react.useState)([]); // All tags ever used (in no particular order)
+
+ const [recentTags, setRecentTags] = (0,react.useState)([]); // Most recently used tags
+
+ const [duplicateTag, setDuplicateTag] = (0,react.useState)(null);
+ const [inputValue, setInputValue] = (0,react.useState)(""); // Status can be success, waiting, or error.
+
+ const [{
+ tagInputStatus,
+ tagInputErrorMessage
+ }, setTagInputStatus] = (0,react.useState)({
+ tagInputStatus: "",
+ tagInputErrorMessage: ""
+ });
+
+ let handleKeyDown = e => {
+ const enterKey = e.keyCode === 13;
+ const commaKey = e.keyCode === 188;
+ const tabKey = inputValue && e.keyCode === 9; // Submit tags on enter with no input.
+ // Enter tag on comma, tab, or enter with input.
+ // Tab to next element with no input.
+
+ if (commaKey || enterKey || tabKey) {
+ e.preventDefault();
+
+ if (inputValue) {
+ addTag(inputValue.trim());
+ setInputValue(``); // Clear out input
+ } else if (enterKey) {
+ submitTags();
+ }
+ }
+ };
+
+ let addTag = tagToAdd => {
+ if (!tagToAdd?.length) {
+ return;
+ }
+
+ let newDuplicateTag = tags.find(item => item === tagToAdd);
+
+ if (!newDuplicateTag) {
+ setTags([...tags, tagToAdd]);
+ } else {
+ setDuplicateTag(newDuplicateTag);
+ setTimeout(() => {
+ setDuplicateTag(null);
+ }, 1000);
+ }
+ };
+
+ let removeTag = index => {
+ let updatedTags = tags.slice(0); // Shallow copied array
+
+ updatedTags.splice(index, 1);
+ setTags(updatedTags);
+ };
+
+ let submitTags = () => {
+ let tagsToSubmit = [];
+
+ if (tags?.length) {
+ tagsToSubmit = tags;
+ } // Capture tags that have been typed in but not explicitly added to the tag collection
+
+
+ if (inputValue?.trim().length) {
+ tagsToSubmit.push(inputValue.trim());
+ }
+
+ if (!props.itemUrl || !tagsToSubmit?.length) {
+ return;
+ }
+
+ setTagInputStatus({
+ tagInputStatus: "waiting",
+ tagInputErrorMessage: ""
+ });
+ messages.sendMessage("PKT_addTags", {
+ url: props.itemUrl,
+ tags: tagsToSubmit
+ }, function (resp) {
+ const {
+ data
+ } = resp;
+
+ if (data.status === "success") {
+ setTagInputStatus({
+ tagInputStatus: "success",
+ tagInputErrorMessage: ""
+ });
+ } else if (data.status === "error") {
+ setTagInputStatus({
+ tagInputStatus: "error",
+ tagInputErrorMessage: data.error.message
+ });
+ }
+ });
+ };
+
+ (0,react.useEffect)(() => {
+ messages.sendMessage("PKT_getTags", {}, resp => {
+ setAllTags(resp?.data?.tags);
+ });
+ }, []);
+ (0,react.useEffect)(() => {
+ messages.sendMessage("PKT_getRecentTags", {}, resp => {
+ setRecentTags(resp?.data?.recentTags);
+ });
+ }, []);
+ return /*#__PURE__*/react.createElement("div", {
+ className: "stp_tag_picker"
+ }, !tagInputStatus && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("h3", {
+ className: "header_small",
+ "data-l10n-id": "pocket-panel-signup-add-tags"
+ }), /*#__PURE__*/react.createElement("div", {
+ className: "stp_tag_picker_tags"
+ }, tags.map((tag, i) => /*#__PURE__*/react.createElement("div", {
+ className: `stp_tag_picker_tag${duplicateTag === tag ? ` stp_tag_picker_tag_duplicate` : ``}`
+ }, /*#__PURE__*/react.createElement("button", {
+ onClick: () => removeTag(i),
+ className: `stp_tag_picker_tag_remove`
+ }, "X"), tag)), /*#__PURE__*/react.createElement("div", {
+ className: "stp_tag_picker_input_wrapper"
+ }, /*#__PURE__*/react.createElement("input", {
+ className: "stp_tag_picker_input",
+ type: "text",
+ list: "tag-list",
+ value: inputValue,
+ onChange: e => setInputValue(e.target.value),
+ onKeyDown: e => handleKeyDown(e),
+ maxlength: "25"
+ }), /*#__PURE__*/react.createElement("datalist", {
+ id: "tag-list"
+ }, allTags.sort((a, b) => a.search(inputValue) - b.search(inputValue)).map(item => /*#__PURE__*/react.createElement("option", {
+ key: item,
+ value: item
+ }))), /*#__PURE__*/react.createElement("button", {
+ className: "stp_tag_picker_button",
+ disabled: !inputValue?.length && !tags.length,
+ "data-l10n-id": "pocket-panel-saved-save-tags",
+ onClick: () => submitTags()
+ }))), /*#__PURE__*/react.createElement("div", {
+ className: "recent_tags"
+ }, recentTags.slice(0, 3).filter(recentTag => {
+ return !tags.find(item => item === recentTag);
+ }).map(tag => /*#__PURE__*/react.createElement("div", {
+ className: "stp_tag_picker_tag"
+ }, /*#__PURE__*/react.createElement("button", {
+ className: "stp_tag_picker_tag_remove",
+ onClick: () => addTag(tag)
+ }, "+ ", tag))))), tagInputStatus === "waiting" && /*#__PURE__*/react.createElement("h3", {
+ className: "header_large",
+ "data-l10n-id": "pocket-panel-saved-processing-tags"
+ }), tagInputStatus === "success" && /*#__PURE__*/react.createElement("h3", {
+ className: "header_large",
+ "data-l10n-id": "pocket-panel-saved-tags-saved"
+ }), tagInputStatus === "error" && /*#__PURE__*/react.createElement("h3", {
+ className: "header_small"
+ }, tagInputErrorMessage));
+}
+
+/* harmony default export */ const TagPicker_TagPicker = (TagPicker);
+;// CONCATENATED MODULE: ./content/panels/js/components/Saved/Saved.jsx
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+
+
+
+
+
+
+function Saved(props) {
+ const {
+ locale,
+ pockethost,
+ utmSource,
+ utmCampaign,
+ utmContent
+ } = props; // savedStatus can be success, loading, or error.
+
+ const [{
+ savedStatus,
+ savedErrorId,
+ itemId,
+ itemUrl
+ }, 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 [articleInfoAttempted, setArticleInfoAttempted] = (0,react.useState)();
+ const [{
+ similarRecs,
+ similarRecsModel
+ }, setSimilarRecsState] = (0,react.useState)({});
+ const utmParams = `utm_source=${utmSource}${utmCampaign && utmContent ? `&utm_campaign=${utmCampaign}&utm_content=${utmContent}` : ``}`;
+
+ 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,
+ itemUrl: data.item?.given_url,
+ savedErrorId: ""
+ });
+ });
+ messages.addMessageListener("PKT_articleInfoFetched", function (resp) {
+ setSavedStoryState(resp?.data?.item_preview);
+ });
+ messages.addMessageListener("PKT_getArticleInfoAttempted", function (resp) {
+ setArticleInfoAttempted(true);
+ });
+ messages.addMessageListener("PKT_renderItemRecs", function (resp) {
+ const {
+ data
+ } = resp; // This is the ML model used to recommend the story.
+ // Right now this value is the same for all three items returned together,
+ // so we can just use the first item's value for all.
+
+ const model = data?.recommendations?.[0]?.experiment || "";
+ setSimilarRecsState({
+ similarRecs: data?.recommendations?.map(rec => rec.item),
+ similarRecsModel: model
+ });
+ }); // 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_saved"
+ }, /*#__PURE__*/react.createElement(Header_Header, null, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "primary",
+ url: `https://${pockethost}/a?${utmParams}`,
+ source: "view_list"
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-header-my-saves"
+ }))), /*#__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",
+ onClick: removeItem
+ }, /*#__PURE__*/react.createElement("span", {
+ "data-l10n-id": "pocket-panel-button-remove"
+ }))), savedStory && /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
+ articles: [savedStory],
+ openInPocketReader: true,
+ utmParams: utmParams
+ }), articleInfoAttempted && /*#__PURE__*/react.createElement(TagPicker_TagPicker, {
+ tags: [],
+ itemUrl: itemUrl
+ }), articleInfoAttempted && 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,
+ source: "on_save_recs",
+ model: similarRecsModel,
+ utmParams: utmParams
+ }))), 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-updated"
+ }), 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);
+;// CONCATENATED MODULE: ./content/panels/js/saved/overlay.js
+/*
+SavedOverlay is the view itself and contains all of the methods to manipute the overlay and messaging.
+It does not contain any logic for saving or communication with the extension or server.
+*/
+
+
+
+
+var SavedOverlay = function (options) {
+ this.inited = false;
+ this.active = false;
+};
+
+SavedOverlay.prototype = {
+ create({
+ pockethost
+ }) {
+ if (this.active) {
+ return;
+ }
+
+ this.active = true;
+ const {
+ searchParams
+ } = new URL(window.location.href);
+ const locale = searchParams.get(`locale`) || ``;
+ const utmSource = searchParams.get(`utmSource`);
+ const utmCampaign = searchParams.get(`utmCampaign`);
+ const utmContent = searchParams.get(`utmContent`);
+ react_dom.render( /*#__PURE__*/react.createElement(Saved_Saved, {
+ locale: locale,
+ pockethost: pockethost,
+ utmSource: utmSource,
+ utmCampaign: utmCampaign,
+ utmContent: utmContent
+ }), document.querySelector(`body`));
+
+ if (window?.matchMedia(`(prefers-color-scheme: dark)`).matches) {
+ document.querySelector(`body`).classList.add(`theme_dark`);
+ }
+ }
+
+};
+/* harmony default export */ const saved_overlay = (SavedOverlay);
+;// CONCATENATED MODULE: ./content/panels/js/style-guide/overlay.js
+
+
+
+
+
+
+
+
+var StyleGuideOverlay = function (options) {};
+
+StyleGuideOverlay.prototype = {
+ create() {
+ // TODO: Wrap popular topics component in JSX to work without needing an explicit container hierarchy for styling
+ react_dom.render( /*#__PURE__*/react.createElement("div", null, /*#__PURE__*/react.createElement("h3", null, "JSX Components:"), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "Buttons"), /*#__PURE__*/react.createElement("h5", {
+ className: "stp_styleguide_h5"
+ }, "text"), /*#__PURE__*/react.createElement(Button_Button, {
+ style: "text",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "Text Button"), /*#__PURE__*/react.createElement("h5", {
+ className: "stp_styleguide_h5"
+ }, "primary"), /*#__PURE__*/react.createElement(Button_Button, {
+ style: "primary",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "Primary Button"), /*#__PURE__*/react.createElement("h5", {
+ className: "stp_styleguide_h5"
+ }, "secondary"), /*#__PURE__*/react.createElement(Button_Button, {
+ style: "secondary",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "Secondary Button"), /*#__PURE__*/react.createElement("h5", {
+ className: "stp_styleguide_h5"
+ }, "primary wide"), /*#__PURE__*/react.createElement("span", {
+ className: "stp_button_wide"
+ }, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "primary",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "Primary Wide Button")), /*#__PURE__*/react.createElement("h5", {
+ className: "stp_styleguide_h5"
+ }, "secondary wide"), /*#__PURE__*/react.createElement("span", {
+ className: "stp_button_wide"
+ }, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "secondary",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "Secondary Wide Button")), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "Header"), /*#__PURE__*/react.createElement(Header_Header, null, /*#__PURE__*/react.createElement(Button_Button, {
+ style: "primary",
+ url: "https://example.org",
+ source: "styleguide"
+ }, "View My List")), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "PopularTopics"), /*#__PURE__*/react.createElement(PopularTopics_PopularTopics, {
+ pockethost: `getpocket.com`,
+ source: `styleguide`,
+ utmParams: `utm_source=styleguide`,
+ topics: [{
+ title: "Self Improvement",
+ topic: "self-improvement"
+ }, {
+ title: "Food",
+ topic: "food"
+ }, {
+ title: "Entertainment",
+ topic: "entertainment"
+ }, {
+ title: "Science",
+ topic: "science"
+ }]
+ }), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "ArticleList"), /*#__PURE__*/react.createElement(ArticleList_ArticleList, {
+ source: `styleguide`,
+ articles: [{
+ title: "Article Title",
+ publisher: "Publisher",
+ thumbnail: "https://img-getpocket.cdn.mozilla.net/80x80/https://www.raritanheadwaters.org/wp-content/uploads/2020/04/red-fox.jpg",
+ url: "https://example.org",
+ alt: "Alt Text"
+ }, {
+ title: "Article Title (No Publisher)",
+ thumbnail: "https://img-getpocket.cdn.mozilla.net/80x80/https://www.raritanheadwaters.org/wp-content/uploads/2020/04/red-fox.jpg",
+ url: "https://example.org",
+ alt: "Alt Text"
+ }, {
+ title: "Article Title (No Thumbnail)",
+ publisher: "Publisher",
+ url: "https://example.org",
+ alt: "Alt Text"
+ }]
+ }), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "TagPicker"), /*#__PURE__*/react.createElement(TagPicker_TagPicker, {
+ tags: [`futurism`, `politics`, `mozilla`]
+ }), /*#__PURE__*/react.createElement("h3", null, "Typography:"), /*#__PURE__*/react.createElement("h2", {
+ className: "header_large"
+ }, ".header_large"), /*#__PURE__*/react.createElement("h3", {
+ className: "header_medium"
+ }, ".header_medium"), /*#__PURE__*/react.createElement("p", null, "paragraph"), /*#__PURE__*/react.createElement("h3", null, "Native Elements:"), /*#__PURE__*/react.createElement("h4", {
+ className: "stp_styleguide_h4"
+ }, "Horizontal Rule"), /*#__PURE__*/react.createElement("hr", null)), document.querySelector(`#stp_style_guide_components`));
+ }
+
+};
+/* harmony default export */ const style_guide_overlay = (StyleGuideOverlay);
+;// CONCATENATED MODULE: ./content/panels/js/main.js
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+/* global RPMGetStringPref:false */
+
+
+
+
+
+
+var PKT_PANEL = function () {};
+
+PKT_PANEL.prototype = {
+ initHome() {
+ this.overlay = new overlay();
+ this.init();
+ },
+
+ initSignup() {
+ this.overlay = new signup_overlay();
+ this.init();
+ },
+
+ initSaved() {
+ this.overlay = new saved_overlay();
+ this.init();
+ },
+
+ initStyleGuide() {
+ this.overlay = new style_guide_overlay();
+ this.init();
+ },
+
+ setupObservers() {
+ this.setupMutationObserver(); // Mutation observer isn't always enough for fast loading, static pages.
+ // Sometimes the mutation observer fires before the page is totally visible.
+ // In this case, the resize tries to fire with 0 height,
+ // and because it's a static page, it only does one mutation.
+ // So in this case, we have a backup intersection observer that fires when
+ // the page is first visible, and thus, the page is going to guarantee a height.
+
+ this.setupIntersectionObserver();
+ },
+
+ init() {
+ if (this.inited) {
+ return;
+ }
+
+ this.setupObservers();
+ this.inited = true;
+ },
+
+ resizeParent() {
+ let clientHeight = document.body.clientHeight;
+
+ if (this.overlay.tagsDropdownOpen) {
+ clientHeight = Math.max(clientHeight, 252);
+ } // We can ignore 0 height here.
+ // We rely on intersection observer to do the
+ // resize for 0 height loads.
+
+
+ if (clientHeight) {
+ messages.sendMessage("PKT_resizePanel", {
+ width: document.body.clientWidth,
+ height: clientHeight
+ });
+ }
+ },
+
+ setupIntersectionObserver() {
+ const observer = new IntersectionObserver(entries => {
+ if (entries.find(e => e.isIntersecting)) {
+ this.resizeParent();
+ observer.unobserve(document.body);
+ }
+ });
+ observer.observe(document.body);
+ },
+
+ setupMutationObserver() {
+ // Select the node that will be observed for mutations
+ const targetNode = document.body; // Options for the observer (which mutations to observe)
+
+ const config = {
+ attributes: false,
+ childList: true,
+ subtree: true
+ }; // Callback function to execute when mutations are observed
+
+ const callback = (mutationList, observer) => {
+ mutationList.forEach(mutation => {
+ switch (mutation.type) {
+ case "childList":
+ {
+ /* One or more children have been added to and/or removed
+ from the tree.
+ (See mutation.addedNodes and mutation.removedNodes.) */
+ this.resizeParent();
+ break;
+ }
+ }
+ });
+ }; // Create an observer instance linked to the callback function
+
+
+ const observer = new MutationObserver(callback); // Start observing the target node for configured mutations
+
+ observer.observe(targetNode, config);
+ },
+
+ create() {
+ const pockethost = RPMGetStringPref("extensions.pocket.site") || "getpocket.com";
+ this.overlay.create({
+ pockethost
+ });
+ }
+
+};
+window.PKT_PANEL = PKT_PANEL;
+window.pktPanelMessaging = messages;
+
+/***/ })
+
+/******/ });
+/************************************************************************/
+/******/ // The module cache
+/******/ var __webpack_module_cache__ = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/ // Check if module is in cache
+/******/ var cachedModule = __webpack_module_cache__[moduleId];
+/******/ if (cachedModule !== undefined) {
+/******/ return cachedModule.exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = __webpack_module_cache__[moduleId] = {
+/******/ // no module.id needed
+/******/ // no module.loaded needed
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = __webpack_modules__;
+/******/
+/************************************************************************/
+/******/ /* webpack/runtime/chunk loaded */
+/******/ (() => {
+/******/ var deferred = [];
+/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ if(chunkIds) {
+/******/ priority = priority || 0;
+/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ deferred[i] = [chunkIds, fn, priority];
+/******/ return;
+/******/ }
+/******/ var notFulfilled = Infinity;
+/******/ for (var i = 0; i < deferred.length; i++) {
+/******/ var [chunkIds, fn, priority] = deferred[i];
+/******/ var fulfilled = true;
+/******/ for (var j = 0; j < chunkIds.length; j++) {
+/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ chunkIds.splice(j--, 1);
+/******/ } else {
+/******/ fulfilled = false;
+/******/ if(priority < notFulfilled) notFulfilled = priority;
+/******/ }
+/******/ }
+/******/ if(fulfilled) {
+/******/ deferred.splice(i--, 1)
+/******/ var r = fn();
+/******/ if (r !== undefined) result = r;
+/******/ }
+/******/ }
+/******/ return result;
+/******/ };
+/******/ })();
+/******/
+/******/ /* webpack/runtime/hasOwnProperty shorthand */
+/******/ (() => {
+/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ })();
+/******/
+/******/ /* webpack/runtime/jsonp chunk loading */
+/******/ (() => {
+/******/ // no baseURI
+/******/
+/******/ // object to store loaded and loading chunks
+/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ var installedChunks = {
+/******/ 179: 0
+/******/ };
+/******/
+/******/ // no chunk on demand loading
+/******/
+/******/ // no prefetching
+/******/
+/******/ // no preloaded
+/******/
+/******/ // no HMR
+/******/
+/******/ // no HMR manifest
+/******/
+/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/
+/******/ // install a JSONP callback for chunk loading
+/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ var [chunkIds, moreModules, runtime] = data;
+/******/ // add "moreModules" to the modules object,
+/******/ // then flag all "chunkIds" as loaded and fire callback
+/******/ var moduleId, chunkId, i = 0;
+/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ for(moduleId in moreModules) {
+/******/ if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ }
+/******/ }
+/******/ if(runtime) var result = runtime(__webpack_require__);
+/******/ }
+/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ for(;i < chunkIds.length; i++) {
+/******/ chunkId = chunkIds[i];
+/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ installedChunks[chunkId][0]();
+/******/ }
+/******/ installedChunks[chunkId] = 0;
+/******/ }
+/******/ return __webpack_require__.O(result);
+/******/ }
+/******/
+/******/ var chunkLoadingGlobal = self["webpackChunksave_to_pocket_ff"] = self["webpackChunksave_to_pocket_ff"] || [];
+/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ })();
+/******/
+/************************************************************************/
+/******/
+/******/ // startup
+/******/ // Load entry module and return exports
+/******/ // This entry module depends on other loaded chunks and execution need to be delayed
+/******/ var __webpack_exports__ = __webpack_require__.O(undefined, [736], () => (__webpack_require__(299)))
+/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/
+/******/ })()
+; \ No newline at end of file