Bug 1398239 - Add prerendering capability, Highlights diversity and bug fixes to Activity Stream r=Mardak

MozReview-Commit-ID: DqKGqHeT0nS

--HG--
extra : rebase_source : 668d1b838b94d197e9631dcb78ce186ce62cefb2
This commit is contained in:
k88hudson 2017-09-11 17:17:35 -04:00
Родитель be1493b6fc
Коммит 60824fdfe2
28 изменённых файлов: 1067 добавлений и 688 удалений

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

@ -87,6 +87,10 @@ var whitelist = [
{file: "resource://app/modules/NewTabSearchProvider.jsm"},
{file: "resource://app/modules/NewTabWebChannel.jsm"},
// browser/extensions/activity-stream/data/content/activity-stream-prerendered.html
// This will used when Bug 1397875 lands
{file: "resource://activity-stream/data/content/activity-stream-prerendered.html"},
// layout/mathml/nsMathMLChar.cpp
{file: "resource://gre/res/fonts/mathfontSTIXGeneral.properties"},
{file: "resource://gre/res/fonts/mathfontUnicode.properties"},

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

@ -95,14 +95,9 @@ function promiseStateChangeURI() {
function promiseContentSearchReady(browser) {
return ContentTask.spawn(browser, {}, async function(args) {
return new Promise(resolve => {
content.addEventListener("ContentSearchService", function listener(aEvent) {
if (aEvent.detail.type == "State") {
content.removeEventListener("ContentSearchService", listener);
resolve();
}
});
});
await ContentTaskUtils.waitForCondition(() => content.wrappedJSObject.gContentSearchController &&
content.wrappedJSObject.gContentSearchController.defaultEngine
);
});
}

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

@ -39,6 +39,7 @@ for (const type of [
"NEW_TAB_INIT",
"NEW_TAB_INITIAL_STATE",
"NEW_TAB_LOAD",
"NEW_TAB_STATE_REQUEST",
"NEW_TAB_UNLOAD",
"OPEN_LINK",
"OPEN_NEW_WINDOW",

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

@ -1,26 +1,28 @@
/* globals Services */
"use strict";
let usablePerfObj;
let Cu;
const isRunningInChrome = typeof Window === "undefined";
/* istanbul ignore if */
if (isRunningInChrome) {
Cu = Components.utils;
} else {
Cu = {import() {}};
if (typeof Components !== "undefined" && Components.utils) {
Components.utils.import("resource://gre/modules/Services.jsm");
}
Cu.import("resource://gre/modules/Services.jsm");
let usablePerfObj;
/* istanbul ignore if */
if (isRunningInChrome) {
/* istanbul ignore else */
if (typeof Services !== "undefined") {
// Borrow the high-resolution timer from the hidden window....
usablePerfObj = Services.appShell.hiddenDOMWindow.performance;
} else { // we must be running in content space
} else if (typeof performance !== "undefined") {
// we must be running in content space
usablePerfObj = performance;
} else {
// This is a dummy object so this file doesn't crash in the node prerendering
// task.
usablePerfObj = {
now() {},
mark() {}
};
}
this._PerfService = function _PerfService(options) {

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

@ -0,0 +1,42 @@
const prefConfig = {
// Prefs listed with "invalidates: true" will prevent the prerendered version
// of AS from being used if their value is something other than what is listed
// here. This is required because some preferences cause the page layout to be
// too different for the prerendered version to be used. Unfortunately, this
// will result in users who have modified some of their preferences not being
// able to get the benefits of prerendering.
"migrationExpired": {value: true},
"showTopSites": {
value: true,
invalidates: true
},
"showSearch": {
value: true,
invalidates: true
},
"topSitesCount": {value: 6},
"feeds.section.topstories": {
value: true,
invalidates: true
}
};
this.PrerenderData = {
invalidatingPrefs: Object.keys(prefConfig).filter(key => prefConfig[key].invalidates),
initialPrefs: Object.keys(prefConfig).reduce((obj, key) => {
obj[key] = prefConfig[key].value;
return obj;
}, {}), // This creates an object of the form {prefName: value}
initialSections: [
{
enabled: true,
icon: "pocket",
id: "topstories",
order: 1,
title: {id: "header_recommended_by", values: {provider: "Pocket"}},
topics: [{}]
}
]
};
this.EXPORTED_SYMBOLS = ["PrerenderData"];

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

@ -5,6 +5,9 @@
const {actionTypes: at} = Components.utils.import("resource://activity-stream/common/Actions.jsm", {});
// Locales that should be displayed RTL
const RTL_LIST = ["ar", "he", "fa", "ur"];
const TOP_SITES_DEFAULT_LENGTH = 6;
const TOP_SITES_SHOWMORE_LENGTH = 12;
@ -16,6 +19,8 @@ const INITIAL_STATE = {
locale: "",
// Localized strings with defaults
strings: null,
// The text direction for the locale
textDirection: "",
// The version of the system-addon
version: null
},
@ -48,7 +53,8 @@ function App(prevState = INITIAL_STATE.App, action) {
let {locale, strings} = action.data;
return Object.assign({}, prevState, {
locale,
strings
strings,
textDirection: RTL_LIST.indexOf(locale.split("-")[0]) >= 0 ? "rtl" : "ltr"
});
}
default:

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

@ -0,0 +1,142 @@
// Note - this is a generated file.
window.gActivityStreamPrerenderedState = {
"TopSites": {
"initialized": false,
"rows": []
},
"App": {
"initialized": false,
"locale": "en-PRERENDER",
"strings": {
"newtab_page_title": " ",
"default_label_loading": " ",
"header_top_sites": " ",
"header_stories": " ",
"header_highlights": " ",
"header_visit_again": " ",
"header_bookmarks": " ",
"header_recommended_by": " ",
"header_bookmarks_placeholder": " ",
"header_stories_from": " ",
"type_label_visited": " ",
"type_label_bookmarked": " ",
"type_label_synced": " ",
"type_label_recommended": " ",
"type_label_open": " ",
"type_label_topic": " ",
"type_label_now": " ",
"menu_action_bookmark": " ",
"menu_action_remove_bookmark": " ",
"menu_action_copy_address": " ",
"menu_action_email_link": " ",
"menu_action_open_new_window": " ",
"menu_action_open_private_window": " ",
"menu_action_dismiss": " ",
"menu_action_delete": " ",
"menu_action_pin": " ",
"menu_action_unpin": " ",
"confirm_history_delete_p1": " ",
"confirm_history_delete_notice_p2": " ",
"menu_action_save_to_pocket": " ",
"search_for_something_with": " ",
"search_button": " ",
"search_header": " ",
"search_web_placeholder": "Search the Web",
"search_settings": " ",
"section_info_option": " ",
"section_info_send_feedback": " ",
"section_info_privacy_notice": " ",
"welcome_title": " ",
"welcome_body": " ",
"welcome_label": " ",
"time_label_less_than_minute": " ",
"time_label_minute": " ",
"time_label_hour": " ",
"time_label_day": " ",
"settings_pane_button_label": " ",
"settings_pane_header": " ",
"settings_pane_body2": " ",
"settings_pane_search_header": " ",
"settings_pane_search_body": " ",
"settings_pane_topsites_header": " ",
"settings_pane_topsites_body": " ",
"settings_pane_topsites_options_showmore": " ",
"settings_pane_bookmarks_header": " ",
"settings_pane_bookmarks_body": " ",
"settings_pane_visit_again_header": " ",
"settings_pane_visit_again_body": " ",
"settings_pane_highlights_header": " ",
"settings_pane_highlights_body2": " ",
"settings_pane_highlights_options_bookmarks": " ",
"settings_pane_highlights_options_visited": " ",
"settings_pane_snippets_header": " ",
"settings_pane_snippets_body": " ",
"settings_pane_done_button": " ",
"edit_topsites_button_text": " ",
"edit_topsites_button_label": " ",
"edit_topsites_showmore_button": " ",
"edit_topsites_showless_button": " ",
"edit_topsites_done_button": " ",
"edit_topsites_pin_button": " ",
"edit_topsites_unpin_button": " ",
"edit_topsites_edit_button": " ",
"edit_topsites_dismiss_button": " ",
"edit_topsites_add_button": " ",
"topsites_form_add_header": " ",
"topsites_form_edit_header": " ",
"topsites_form_title_placeholder": " ",
"topsites_form_url_placeholder": " ",
"topsites_form_add_button": " ",
"topsites_form_save_button": " ",
"topsites_form_cancel_button": " ",
"topsites_form_url_validation": " ",
"pocket_read_more": " ",
"pocket_read_even_more": " ",
"pocket_feedback_header": " ",
"pocket_description": " ",
"highlights_empty_state": " ",
"topstories_empty_state": " ",
"manual_migration_explanation2": " ",
"manual_migration_cancel_button": " ",
"manual_migration_import_button": " "
},
"textDirection": "ltr",
"version": null
},
"Snippets": {
"initialized": false
},
"Prefs": {
"initialized": true,
"values": {
"migrationExpired": true,
"showTopSites": true,
"showSearch": true,
"topSitesCount": 6,
"feeds.section.topstories": true
}
},
"Dialog": {
"visible": false,
"data": {}
},
"Sections": [
{
"title": {
"id": "header_recommended_by",
"values": {
"provider": "Pocket"
}
},
"rows": [],
"order": 1,
"enabled": true,
"icon": "pocket",
"id": "topstories",
"topics": [
{}
],
"initialized": false
}
]
};

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

@ -0,0 +1,25 @@
<!doctype html>
<html lang="" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy-Report-Only" content="script-src 'unsafe-inline'; img-src http: https: data: blob:; style-src 'unsafe-inline'; child-src 'none'; object-src 'none'; report-uri https://tiles.services.mozilla.com/v4/links/activity-stream/csp">
<title></title>
<link rel="icon" type="image/png" id="favicon" href="chrome://branding/content/icon32.png"/>
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
<link rel="stylesheet" href="resource://activity-stream/data/content/activity-stream.css" />
</head>
<body class="activity-stream">
<div id="root"><div class="outer-wrapper" data-reactroot="" data-reactid="1" data-react-checksum="57168132"><main data-reactid="2"><div class="search-wrapper" data-reactid="3"><label for="newtab-search-text" class="search-label" data-reactid="4"><span class="sr-only" data-reactid="5"><span data-reactid="6">Search the Web</span></span></label><input type="search" id="newtab-search-text" maxlength="256" placeholder="Search the Web" title="Search the Web" data-reactid="7"/><button id="searchSubmit" class="search-button" title=" " data-reactid="8"><span class="sr-only" data-reactid="9"><span data-reactid="10"> </span></span></button></div><section class="top-sites" data-reactid="11"><h3 class="section-title" data-reactid="12"><span class="icon icon-small-spacer icon-topsites" data-reactid="13"></span><span data-reactid="14"> </span></h3><ul class="top-sites-list" data-reactid="15"><li class="top-site-outer placeholder" data-reactid="16"><a data-reactid="17"><div class="tile" aria-hidden="true" data-reactid="18"><span class="letter-fallback" data-reactid="19"></span><div class="screenshot" style="background-image:none;" data-reactid="20"></div></div><div class="title " data-reactid="21"><span dir="auto" data-reactid="22"></span></div></a></li><li class="top-site-outer placeholder" data-reactid="23"><a data-reactid="24"><div class="tile" aria-hidden="true" data-reactid="25"><span class="letter-fallback" data-reactid="26"></span><div class="screenshot" style="background-image:none;" data-reactid="27"></div></div><div class="title " data-reactid="28"><span dir="auto" data-reactid="29"></span></div></a></li><li class="top-site-outer placeholder" data-reactid="30"><a data-reactid="31"><div class="tile" aria-hidden="true" data-reactid="32"><span class="letter-fallback" data-reactid="33"></span><div class="screenshot" style="background-image:none;" data-reactid="34"></div></div><div class="title " data-reactid="35"><span dir="auto" data-reactid="36"></span></div></a></li><li class="top-site-outer placeholder" data-reactid="37"><a data-reactid="38"><div class="tile" aria-hidden="true" data-reactid="39"><span class="letter-fallback" data-reactid="40"></span><div class="screenshot" style="background-image:none;" data-reactid="41"></div></div><div class="title " data-reactid="42"><span dir="auto" data-reactid="43"></span></div></a></li><li class="top-site-outer placeholder" data-reactid="44"><a data-reactid="45"><div class="tile" aria-hidden="true" data-reactid="46"><span class="letter-fallback" data-reactid="47"></span><div class="screenshot" style="background-image:none;" data-reactid="48"></div></div><div class="title " data-reactid="49"><span dir="auto" data-reactid="50"></span></div></a></li><li class="top-site-outer placeholder" data-reactid="51"><a data-reactid="52"><div class="tile" aria-hidden="true" data-reactid="53"><span class="letter-fallback" data-reactid="54"></span><div class="screenshot" style="background-image:none;" data-reactid="55"></div></div><div class="title " data-reactid="56"><span dir="auto" data-reactid="57"></span></div></a></li></ul></section><div class="sections-list" data-reactid="58"><section data-reactid="59"><div class="section-top-bar" data-reactid="60"><h3 class="section-title" data-reactid="61"><span class="icon icon-small-spacer icon-pocket" data-reactid="62"></span><span data-reactid="63"> </span></h3></div><ul class="section-list" style="padding:0;" data-reactid="64"><li class="card-outer placeholder" data-reactid="65"><a data-reactid="66"><div class="card" data-reactid="67"><div class="card-details no-image" data-reactid="68"><div class="card-text no-image no-host-name no-context" data-reactid="69"><h4 class="card-title" dir="auto" data-reactid="70"></h4><p class="card-description" dir="auto" data-reactid="71"></p></div></div></div></a></li><li class="card-outer placeholder" data-reactid="72"><a data-reactid="73"><div class="card" data-reactid="74"><div class="card-details no-image" data-reactid="75"><div class="card-text no-image no-host-name no-context" data-reactid="76"><h4 class="card-title" dir="auto" data-reactid="77"></h4><p class="card-description" dir="auto" data-reactid="78"></p></div></div></div></a></li><li class="card-outer placeholder" data-reactid="79"><a data-reactid="80"><div class="card" data-reactid="81"><div class="card-details no-image" data-reactid="82"><div class="card-text no-image no-host-name no-context" data-reactid="83"><h4 class="card-title" dir="auto" data-reactid="84"></h4><p class="card-description" dir="auto" data-reactid="85"></p></div></div></div></a></li></ul><div class="topic" data-reactid="86"><span data-reactid="87"><span data-reactid="88"> </span></span><ul data-reactid="89"><li data-reactid="90"><a class="topic-link" data-reactid="91"></a></li></ul></div></section></div><!-- react-empty: 92 --></main></div></div>
<div id="snippets-container">
<div id="snippets"></div>
</div>
<script src="resource://activity-stream/data/content/activity-stream-initial-state.js"></script>
<script src="chrome://browser/content/contentSearchUI.js"></script>
<script src="resource://activity-stream/vendor/react.js"></script>
<script src="resource://activity-stream/vendor/react-dom.js"></script>
<script src="resource://activity-stream/vendor/react-intl.js"></script>
<script src="resource://activity-stream/vendor/redux.js"></script>
<script src="resource://activity-stream/vendor/react-redux.js"></script>
<script src="resource://activity-stream/data/content/activity-stream.bundle.js"></script>
</body>
</html>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -64,7 +64,9 @@ input {
.icon.icon-historyItem {
background-image: url("assets/glyph-historyItem-16.svg"); }
.icon.icon-trending {
background-image: url("assets/glyph-trending-16.svg"); }
background-image: url("assets/glyph-trending-16.svg");
transform: translateY(2px);
/* trending bolt is visually top heavy */ }
.icon.icon-now {
background-image: url("chrome://browser/skin/history.svg"); }
.icon.icon-topsites {
@ -317,17 +319,26 @@ main {
opacity: 0; }
.top-sites-list .top-site-outer .screenshot.active {
opacity: 1; }
.top-sites-list .top-site-outer .tippy-top-icon {
.top-sites-list .top-site-outer .top-site-icon {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
border-radius: 6px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
background-position: center center;
background-size: 96px;
background-repeat: no-repeat; }
background-repeat: no-repeat;
background-color: #F9F9FA; }
.top-sites-list .top-site-outer .rich-icon {
top: 0;
offset-inline-start: 0;
height: 100%;
width: 100%;
background-size: 96px; }
.top-sites-list .top-site-outer .default-icon {
z-index: 1;
top: -6px;
offset-inline-start: -6px;
height: 42px;
width: 42px;
background-size: 32px; }
.top-sites-list .top-site-outer .title {
font: message-box;
height: 30px;
@ -1017,11 +1028,10 @@ main {
display: flex; }
.card-outer .card-context-icon {
fill: rgba(12, 12, 13, 0.6);
font-size: 13px;
margin-inline-end: 6px;
display: block; }
margin-inline-end: 6px; }
.card-outer .card-context-label {
flex-grow: 1;
line-height: 16px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }

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

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en-us" dir="ltr">
<html lang="" dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy-Report-Only" content="script-src 'unsafe-inline'; img-src http: https: data: blob:; style-src 'unsafe-inline'; child-src 'none'; object-src 'none'; report-uri https://tiles.services.mozilla.com/v4/links/activity-stream/csp">

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

@ -232,9 +232,11 @@
"settings_pane_visit_again_header": "Təkrar ziyarət et",
"settings_pane_visit_again_body": "Firefox tarixçənizdən yadda saxlamaq və ya geri qayıtmaq istəyə biləcəyiniz hissələri göstərəcək.",
"settings_pane_highlights_header": "Seçilmişlər",
"settings_pane_highlights_body2": "Son ziyarət etdiyiniz və ya əlfəcinlədiyiniz maraqlı məzmunlara rahat qayıdın.",
"settings_pane_highlights_options_bookmarks": "Əlfəcinlər",
"settings_pane_highlights_options_visited": "Baxılmış Saytlar",
"settings_pane_snippets_header": "Hissələr",
"settings_pane_snippets_body": "Mozilladan Firefox, internet mədəniyyəti və digər yeniliklər haqqında qısa bildirişlər oxuyun.",
"settings_pane_done_button": "Oldu",
"edit_topsites_button_text": "Redaktə et",
"edit_topsites_button_label": "Qabaqcıl Saytlar bölümünüzü fərdiləşdirin",
@ -257,6 +259,8 @@
"pocket_read_more": "Məşhur Mövzular:",
"pocket_read_even_more": "Daha çox hekayə gör",
"pocket_feedback_header": "25 milyon nəfərin dəstəyi ilə internetin ən yaxşıları.",
"pocket_description": "Mozilla ailəsinin yeni üzvü olan Pocket ilə yüksək keyfiyyətli məzmunları kəşf edin.",
"highlights_empty_state": "İnternetdə gəzməyə başlayın, burada ziyarət edəcəyiniz və ya əlfəcinləyəcəyiniz məqalə, video və digər səhifələri göstərəcəyik.",
"topstories_empty_state": "Hamısını oxudunuz. Yeni {provider} məqalələri üçün daha sonra təkrar yoxlayın. Gözləyə bilmirsiz? Məşhur mövzu seçərək internetdən daha çox gözəl məqalələr tapın.",
"manual_migration_explanation2": "Firefox səyyahını digər səyyahlardan olan əlfəcin, tarixçə və parollar ilə yoxlayın.",
"manual_migration_cancel_button": "Xeyr, Təşəkkürlər",
@ -414,9 +418,11 @@
"settings_pane_visit_again_header": "Посещаване",
"settings_pane_visit_again_body": "Firefox ще ви показва части от вашата история на разглеждане, към която бихте желали да се върнете или запомните.",
"settings_pane_highlights_header": "Акценти",
"settings_pane_highlights_body2": "Намерете интересните неща, които скоро сте посетили или отметнали.",
"settings_pane_highlights_options_bookmarks": "Отметки",
"settings_pane_highlights_options_visited": "Посетени страници",
"settings_pane_snippets_header": "Изрезки",
"settings_pane_snippets_body": "Четете кратки и радостни новини от Mozilla относно Firefox, интернет-културата и случайни мемета.",
"settings_pane_done_button": "Готово",
"edit_topsites_button_text": "Редактиране",
"edit_topsites_button_label": "Настройки на най-посещаваните",
@ -440,6 +446,7 @@
"pocket_read_even_more": "Повече статии",
"pocket_feedback_header": "Най-доброто от интернет, подбрано от над 25 милиона души.",
"pocket_description": "Открийте висококачествено съдържание, което иначе може да пропуснете, с помощта на Pocket, вече част от Mozilla.",
"highlights_empty_state": "Разглеждайте и тук ще ви покажем някои от най-добрите статии, видео и други страници, които сте посетили или отметнали наскоро.",
"topstories_empty_state": "Разгледахте всичко. Проверете по-късно за повече истории от {provider}. Нямате търпение? Изберете популярна тема, за да откриете повече истории из цялата Мрежа.",
"manual_migration_explanation2": "Опитайте Firefox с отметките, историята и паролите от друг четец.",
"manual_migration_cancel_button": "Не, благодаря",
@ -1055,10 +1062,10 @@
"menu_action_email_link": "Link per E-Mail versenden…",
"menu_action_open_new_window": "In neuem Fenster öffnen",
"menu_action_open_private_window": "In neuem privaten Fenster öffnen",
"menu_action_dismiss": "Schließen",
"menu_action_dismiss": "Entfernen",
"menu_action_delete": "Aus Chronik löschen",
"menu_action_pin": "Anheften",
"menu_action_unpin": "Lösen",
"menu_action_unpin": "Ablösen",
"confirm_history_delete_p1": "Soll wirklich jede Instanz dieser Seite aus Ihrer Chronik gelöscht werden?",
"confirm_history_delete_notice_p2": "Diese Aktion kann nicht rückgängig gemacht werden.",
"menu_action_save_to_pocket": "Bei Pocket speichern",
@ -1077,8 +1084,8 @@
"time_label_minute": "{number} m",
"time_label_hour": "{number} h",
"time_label_day": "{number} t",
"settings_pane_button_label": "Neuer-Tab-Seite anpassen",
"settings_pane_header": "Einstellungen zum neuen Tab",
"settings_pane_button_label": "Einstellungen für neue Tabs anpassen",
"settings_pane_header": "Einstellungen für neue Tabs",
"settings_pane_body2": "Wählen Sie aus, was auf dieser Seite angezeigt wird.",
"settings_pane_search_header": "Suche",
"settings_pane_search_body": "Suchen Sie aus einem neuen Tab im Internet.",
@ -1108,8 +1115,8 @@
"edit_topsites_add_button": "Hinzufügen",
"topsites_form_add_header": "Neue meistbesuchte Seite",
"topsites_form_edit_header": "Meistbesuchte Seite bearbeiten",
"topsites_form_title_placeholder": "Titel eingeben",
"topsites_form_url_placeholder": "Eine URL eingeben oder einfügen",
"topsites_form_title_placeholder": "Name eingeben",
"topsites_form_url_placeholder": "Eine Adresse eingeben oder einfügen",
"topsites_form_add_button": "Hinzufügen",
"topsites_form_save_button": "Speichern",
"topsites_form_cancel_button": "Abbrechen",
@ -1119,7 +1126,7 @@
"pocket_feedback_header": "Das Beste aus dem Web, zusammengetragen von 25 Millionen Menschen.",
"pocket_description": "Entdecken Sie qualitativ hochwertige Inhalte mithilfe von Pocket (jetzt Teil von von Mozilla), die Sie ansonsten verpassen würden.",
"highlights_empty_state": "Surfen Sie los und wir zeigen Ihnen hier tolle Artikel, Videos und andere Seiten, die Sie kürzlich besucht oder als Lesezeichen gespeichert haben.",
"topstories_empty_state": "Jetzt kennen Sie die Neuigkeiten. Schauen Sie später wieder vorbei, um neue Informationen von {provider} zu erhalten. Können sie nicht warten? Wählen Sie ein beliebtes Thema und lesen Sie weitere interessante Geschichten aus dem Internet.",
"topstories_empty_state": "Jetzt kennen Sie die Neuigkeiten. Schauen Sie später wieder vorbei, um neue Informationen von {provider} zu erhalten. Können Sie nicht warten? Wählen Sie ein beliebtes Thema und lesen Sie weitere interessante Geschichten aus dem Internet.",
"manual_migration_explanation2": "Probieren Sie Firefox aus und importieren Sie die Lesezeichen, Chronik und Passwörter eines anderen Browsers.",
"manual_migration_cancel_button": "Nein, danke",
"manual_migration_import_button": "Jetzt importieren"
@ -1763,6 +1770,7 @@
"default_label_loading": "Cargando…",
"header_top_sites": "Sitios favoritos",
"header_stories": "Historias populares",
"header_highlights": "Destacados",
"header_visit_again": "Visitar de nuevo",
"header_bookmarks": "Marcadores recientes",
"header_recommended_by": "Recomendado por {provider}",
@ -1794,6 +1802,8 @@
"search_web_placeholder": "Buscar en la Web",
"search_settings": "Cambiar ajustes de búsqueda",
"section_info_option": "Info",
"section_info_send_feedback": "Enviar comentario",
"section_info_privacy_notice": "Aviso de privacidad",
"welcome_title": "Bienvenido a la nueva pestaña",
"welcome_body": "Firefox utilizará este espacio para mostrarte los marcadores, artículos y vídeos más relevantes y las páginas que has visitado recientemente, para que puedas acceder más rápido.",
"welcome_label": "Identificar lo más destacado para ti",
@ -1803,7 +1813,7 @@
"time_label_day": "{number}d",
"settings_pane_button_label": "Personalizar la página Nueva pestaña",
"settings_pane_header": "Preferencias de nueva pestaña",
"settings_pane_body": "Elige qué quieres ver al abrir una nueva pestaña",
"settings_pane_body2": "Elige lo quieras ver en esta página.",
"settings_pane_search_header": "Buscar",
"settings_pane_search_body": "Busca en la Web desde tu nueva pestaña.",
"settings_pane_topsites_header": "Sitios populares",
@ -1813,8 +1823,12 @@
"settings_pane_bookmarks_body": "Tus marcadores recién creados, fácilmente accesibles.",
"settings_pane_visit_again_header": "Visitar de nuevo",
"settings_pane_visit_again_body": "Firefox te mostrará partes de tu historial de navegación que te gustaría recordar o volver a visitar.",
"settings_pane_pocketstories_header": "Historias populares",
"settings_pane_pocketstories_body": "Pocket, que forma parte de la familia de Mozilla, te ayudará a encontrar contenido de alta calidad que puede que no encuentres de otra forma.",
"settings_pane_highlights_header": "Destacados",
"settings_pane_highlights_body2": "Vuelve a encontrar todas las cosas interesantes que hayas visitado o marcado recientemente.",
"settings_pane_highlights_options_bookmarks": "Marcadores",
"settings_pane_highlights_options_visited": "Sitios visitados",
"settings_pane_snippets_header": "Fragmentos de código",
"settings_pane_snippets_body": "Lee actualizaciones breves de Mozilla sobre Firefox, la cultura de internet y el típico meme aleatorio.",
"settings_pane_done_button": "Hecho",
"edit_topsites_button_text": "Editar",
"edit_topsites_button_label": "Personalizar la sección de Sitios populares",
@ -1837,10 +1851,10 @@
"pocket_read_more": "Temas populares:",
"pocket_read_even_more": "Ver más historias",
"pocket_feedback_header": "Lo mejor de la web, confirmado por más de 25 millones de personas.",
"pocket_feedback_body": "Pocket, que forma parte de la familia de Mozilla, te ayudará a encontrar contenido de alta calidad que puede que no encuentres de otra forma.",
"pocket_send_feedback": "Enviar comentario",
"pocket_description": "Gracias a Pocket, que ahora forma parte de Mozilla, podrás descubrir contenido de alta calidad que de otra forma te perderías.",
"highlights_empty_state": "Empieza a navegar y nosotros te mostraremos aquí algunos de los mejores artículos, videos y otras páginas que hayas visitado recientemente o agregado a marcadores.",
"topstories_empty_state": "Ya estás al día. Vuelve luego y busca más historias de {provider}. ¿No puedes esperar? Selecciona un tema popular y encontrás más historias alucinantes por toda la web.",
"manual_migration_explanation": "Prueba Firefox con tusmarcadores y sitios favoritos importados desde otro navegador.",
"manual_migration_explanation2": "Prueba Firefox con los marcadores, historial y contraseñas de otro navegador.",
"manual_migration_cancel_button": "No, gracias",
"manual_migration_import_button": "Importar ahora"
},
@ -2363,7 +2377,7 @@
"settings_pane_visit_again_header": "Visiter à nouveau",
"settings_pane_visit_again_body": "Firefox affichera des extraits de votre historique de navigation dont vous pourriez vouloir vous souvenir ou que vous pourriez vouloir revisiter.",
"settings_pane_highlights_header": "Éléments-clés",
"settings_pane_highlights_body2": "Retrouvez des pages inintéressantes que vous avez déjà visitées récemment ou ajoutées aux marque-pages.",
"settings_pane_highlights_body2": "Retrouvez des pages intéressantes que vous avez visitées récemment ou ajoutées aux marque-pages.",
"settings_pane_highlights_options_bookmarks": "Marque-pages",
"settings_pane_highlights_options_visited": "Sites visités",
"settings_pane_snippets_header": "Brèves",
@ -3007,6 +3021,7 @@
"default_label_loading": "Betöltés…",
"header_top_sites": "Népszerű oldalak",
"header_stories": "Népszerű történetek",
"header_highlights": "Kiemelések",
"header_visit_again": "Látogasson el ismét",
"header_bookmarks": "Friss könyvjelzők",
"header_recommended_by": "A(z) {provider} ajánlásával",
@ -3038,6 +3053,8 @@
"search_web_placeholder": "Keresés a weben",
"search_settings": "Keresési beállítások módosítása",
"section_info_option": "Információ",
"section_info_send_feedback": "Visszajelzés küldése",
"section_info_privacy_notice": "Adatvédelmi nyilatkozat",
"welcome_title": "Üdvözöljük az új lapon",
"welcome_body": "A Firefox ezt a területet a leginkább releváns könyvjelzők, cikkek, videók és nemrég látogatott oldalak megjelenítésére fogja használni, így könnyedén visszatalálhat hozzájuk.",
"welcome_label": "A kiemeléseinek azonosítása",
@ -3047,7 +3064,7 @@
"time_label_day": "{number} n",
"settings_pane_button_label": "Az Új lap oldal személyre szabása",
"settings_pane_header": "Új lap beállításai",
"settings_pane_body": "Válassza ki, hogy mit lát, amikor megnyit egy új lapot.",
"settings_pane_body2": "Válassza ki, hogy mit akar látni ezen az oldalon.",
"settings_pane_search_header": "Keresés",
"settings_pane_search_body": "Keresés a weben az új lapon.",
"settings_pane_topsites_header": "Népszerű oldalak",
@ -3057,8 +3074,12 @@
"settings_pane_bookmarks_body": "A frissen létrehozott könyvjelzői egy praktikus helyen.",
"settings_pane_visit_again_header": "Látogasson el ismét",
"settings_pane_visit_again_body": "A Firefox megjeleníti a böngészési előzményeinek azt a részét, amelyet lehet hogy meg szeretne jegyezni, vagy ahová vissza akar térni.",
"settings_pane_pocketstories_header": "Népszerű történetek",
"settings_pane_pocketstories_body": "A Pocket a Mozilla család tagja, segít az olyan jó minőségű tartalmak fellelésében, melyekkel egyébként nem is találkozott volna.",
"settings_pane_highlights_header": "Kiemelések",
"settings_pane_highlights_body2": "Találjon vissza azokhoz az érdekes dolgokhoz, amelyeket meglátogatott vagy könyvjelzőzött.",
"settings_pane_highlights_options_bookmarks": "Könyvjelzők",
"settings_pane_highlights_options_visited": "Látogatott helyek",
"settings_pane_snippets_header": "Töredékek",
"settings_pane_snippets_body": "Olvasson rövid és érdekes híreket a Mozillától, a Firefoxról, az internetes kultúráról, és időnként kapjon mémeket.",
"settings_pane_done_button": "Kész",
"edit_topsites_button_text": "Szerkesztés",
"edit_topsites_button_label": "A Népszerű oldalak rész testreszabása",
@ -3081,10 +3102,10 @@
"pocket_read_more": "Népszerű témák:",
"pocket_read_even_more": "További történetek",
"pocket_feedback_header": "A web legjava, több mint 25 millió ember válogatásában.",
"pocket_feedback_body": "A Pocket a Mozilla család tagja, segít az olyan jó minőségű tartalmak fellelésében, melyekkel egyébként nem is találkozott volna.",
"pocket_send_feedback": "Visszajelzés küldése",
"pocket_description": "Fedezzen fel olyan, magas minőségű tartalmakat, amelyek egyébként elkerülnék a figyelmét, a Pocket segítségével, amely most már a Mozilla része.",
"highlights_empty_state": "Kezdjen el böngészni, és itt fognak megjelenni azok a nagyszerű cikkek, videók és más lapok, amelyeket nemrég meglátogatott vagy könyvjelzőzött.",
"topstories_empty_state": "Már felzárkózott. Nézzen vissza később a legújabb {provider} hírekért. Nem tud várni? Válasszon egy népszerű témát, hogy még több sztorit találjon a weben.",
"manual_migration_explanation": "Próbálja ki a Firefoxot egy másik böngészőben lévő kedvenc oldalaival és könyvjelzőivel.",
"manual_migration_explanation2": "Próbálja ki a Firefoxot másik böngészőből származó könyvjelzőkkel, előzményekkel és jelszavakkal.",
"manual_migration_cancel_button": "Köszönöm, nem",
"manual_migration_import_button": "Importálás most"
},
@ -3123,6 +3144,7 @@
"default_label_loading": "Memuat…",
"header_top_sites": "Situs Teratas",
"header_stories": "Cerita Utama",
"header_highlights": "Sorotan",
"header_visit_again": "Kunjungi Lagi",
"header_bookmarks": "Markah Terbaru",
"header_recommended_by": "Disarankan oleh {provider}",
@ -3154,6 +3176,8 @@
"search_web_placeholder": "Cari di Web",
"search_settings": "Ubah Pengaturan Pencarian",
"section_info_option": "Info",
"section_info_send_feedback": "Kirim Umpan Balik",
"section_info_privacy_notice": "Kebijakan Privasi",
"welcome_title": "Selamat datang di tab baru",
"welcome_body": "Firefox akan menggunakan ruang ini untuk menampilkan markah, artikel, video, dan laman yang baru-baru ini dikunjungi, yang paling relevan agar Anda bisa kembali mengunjunginya dengan mudah.",
"welcome_label": "Mengidentifikasi Sorotan Anda",
@ -3163,7 +3187,7 @@
"time_label_day": "{number} hr",
"settings_pane_button_label": "Ubahsuai laman Tab Baru Anda",
"settings_pane_header": "Preferensi Tab Baru",
"settings_pane_body": "Pilih apa yang Anda lihat ketika Anda membuka tab baru.",
"settings_pane_body2": "Pilih apa yang Anda lihat di halaman ini.",
"settings_pane_search_header": "Pencarian",
"settings_pane_search_body": "Cari Web dari tab baru Anda.",
"settings_pane_topsites_header": "Situs Teratas",
@ -3173,8 +3197,12 @@
"settings_pane_bookmarks_body": "Markah Anda dibuat di lokasi yang praktis.",
"settings_pane_visit_again_header": "Kunjungi Lagi",
"settings_pane_visit_again_body": "Firefox akan menunjukkan bagian dari riwayat penjelajahan yang mungkin ingin Anda ingat atau kunjungi lagi.",
"settings_pane_pocketstories_header": "Cerita Utama",
"settings_pane_pocketstories_body": "Pocket, bagian dari keluarga Mozilla, akan membantu hubungkan Anda dengan konten berkualitas tinggi yang tak dapat Anda temukan di tempat lain.",
"settings_pane_highlights_header": "Sorotan",
"settings_pane_highlights_body2": "Temukan jalan kembali ke hal menarik yang baru saja Anda kunjungi atau dimarkah.",
"settings_pane_highlights_options_bookmarks": "Markah",
"settings_pane_highlights_options_visited": "Situs Terkunjungi",
"settings_pane_snippets_header": "Catatan Kecil",
"settings_pane_snippets_body": "Baca info pendek terbaru dari Mozilla tentang Firefox, budaya internet dan beberapa meme acak.",
"settings_pane_done_button": "Selesai",
"edit_topsites_button_text": "Sunting",
"edit_topsites_button_label": "Ubahsuai bagian Situs Teratas Anda",
@ -3197,10 +3225,10 @@
"pocket_read_more": "Topik Populer:",
"pocket_read_even_more": "Lihat Cerita Lainnya",
"pocket_feedback_header": "Yang terbaik dari Web, dikurasi lebih dari 25 juta orang.",
"pocket_feedback_body": "Pocket, bagian dari keluarga Mozilla, akan membantu hubungkan Anda dengan konten berkualitas tinggi yang tak dapat Anda temukan di tempat lain.",
"pocket_send_feedback": "Kirim Umpanbalik",
"pocket_description": "Temukan konten berkualitas tinggi yang mungkin Anda lewatkan dengan bantuan Pocket, yang sekarang menjadi bagian dari Mozilla.",
"highlights_empty_state": "Mulai menjelajah, dan kami akan menampilkan beberapa artikel bagus, video, dan halaman lain yang baru saja Anda kunjungi atau termarkah di sini.",
"topstories_empty_state": "Maaf Anda tercegat. Periksa lagi nanti untuk lebih banyak cerita terbaik dari {provider}. Tidak mau menunggu? Pilih topik populer untuk menemukan lebih banyak cerita hebat dari seluruh web.",
"manual_migration_explanation": "Cobalah Firefox dengan situs dan markah kesukaan Anda dari peramban yang lain.",
"manual_migration_explanation2": "Coba Firefox dengan markah, riwayat, dan sandi dari peramban lain.",
"manual_migration_cancel_button": "Tidak, Terima kasih",
"manual_migration_import_button": "Impor Sekarang"
},
@ -3488,6 +3516,7 @@
"default_label_loading": "Asali…",
"header_top_sites": "Ismal ifazen",
"header_stories": "Tiqsiɣin ifazen",
"header_highlights": "Asebrureq",
"header_visit_again": "Rzu tikelt-nniḍen",
"header_bookmarks": "Ticraḍ n melmi kan",
"header_recommended_by": "Iwelleh-it-id {provider}",
@ -3519,6 +3548,8 @@
"search_web_placeholder": "Nadi di Web",
"search_settings": "Snifel iγewwaṛen n unadi",
"section_info_option": "Talɣut",
"section_info_send_feedback": "Azen tikti",
"section_info_privacy_notice": "Tasertit n tbaḍnit",
"welcome_title": "Ansuf ar yiccer amaynut",
"welcome_body": "Firefox ad iseqdec tallunt akken ad d-yesken akk ticraḍ n isebtar iwulmen, imagraden, tividyutin, akked isebtar aniɣer terziḍ melmi kan, ihi tzemreḍ ad d-uɣaleḍ ɣer-sen s wudem fessusen.",
"welcome_label": "Asulu n iferdisen tisura",
@ -3528,7 +3559,7 @@
"time_label_day": "{number}n wussan",
"settings_pane_button_label": "Sagen asebter n yiccer-ik amaynut",
"settings_pane_header": "Ismenyifen n yiccer amaynut",
"settings_pane_body": "Fren ayen ara twaliḍ ticki teldiḍ iccer imaynut.",
"settings_pane_body2": "Fren ayen ad twaliḍ deg usebter-agi.",
"settings_pane_search_header": "Nadi",
"settings_pane_search_body": "Nadi di Web seg iccer-ik amaynut.",
"settings_pane_topsites_header": "Ismal ifazen",
@ -3538,8 +3569,12 @@
"settings_pane_bookmarks_body": "Ticraḍ yettwarnan melmi kan deg iwen n umdiq ɣef afus.",
"settings_pane_visit_again_header": "Rzu tikelt-nniḍen",
"settings_pane_visit_again_body": "Firefox ad d-yesken tukkist n umazray-ik n tunigin i tzemreḍ ad twalid tikelt-nniḍen.",
"settings_pane_pocketstories_header": "Tiqsiɣin ifazen",
"settings_pane_pocketstories_body": "Pocket, aɛeggal n twaxult n Mozilla, ak-d-yefk afus ad twaliḍ agbur n tɣara meqqren i tzemred ad tzegleḍ.",
"settings_pane_highlights_header": "Asebrureq",
"settings_pane_highlights_body2": "Aff abrid-ik γer wayen i tḥemmleḍ i γef terziḍ yakan neγ tcerḍeḍ-t.",
"settings_pane_highlights_options_bookmarks": "Ticraḍ n isebtar",
"settings_pane_highlights_options_visited": "Ismal yettwarzan",
"settings_pane_snippets_header": "Tiwzillin",
"settings_pane_snippets_body": "Wali issalen n Mozilla γef Firefox, adlis internet, akked issalen nniṣen sya γer da.",
"settings_pane_done_button": "Immed",
"edit_topsites_button_text": "Ẓreg",
"edit_topsites_button_label": "Sagen tigezmi n ismal ifazen",
@ -3562,10 +3597,10 @@
"pocket_read_more": "Isental ittwasnen aṭas:",
"pocket_read_even_more": "Wali ugar n teqsiḍin",
"pocket_feedback_header": "D amezwaru n Web, ittwafren sγur ugar 25 imelyan n imdanen.",
"pocket_feedback_body": "Pocket, aɛeggal n twaxult n Mozilla, ak-d-yefk afus ad twaliḍ agbur n tɣara meqqren i tzemred ad tzegleḍ.",
"pocket_send_feedback": "Azen tikti",
"pocket_description": "S lmendad n Pocket n Mozillan wali aqbur ifazen aṭas, s ttawil-a werǧin ad tzegleḍ taγawsa.",
"highlights_empty_state": "Bdu tuniginn sakin nekkni ad k-n-sken imagraden, tividyutin, akked isebtar nniḍen i γef terziḍ yakan neγ i tceṛḍeḍ dagi.",
"topstories_empty_state": "Ulac wiyaḍ. Uɣal-d ticki s wugar n imagraden seg {provider}. Ur tebɣiḍ ara ad terǧuḍ? Fren asentel seg wid yettwasnen akken ad twaliḍ imagraden yelhan di Web.",
"manual_migration_explanation": "Ɛreḍ Firefox s ismal-ik inurifen akked ticraḍ seg iminig-nniḍen.",
"manual_migration_explanation2": "Σreḍ Firefox s ticṛaḍ n isebtar, amazray akked awalen uffiren sγur ilinigen nniḍen.",
"manual_migration_cancel_button": "Ala, tanemmirt",
"manual_migration_import_button": "Kter tura"
},
@ -3628,9 +3663,11 @@
"settings_pane_visit_again_header": "Қайтадан шолу",
"settings_pane_visit_again_body": "Firefox сізге есте сақтауды немесе қайта шолуды қалауыңыз мүмкін тарихыңыздың бөліктерін көрсетеді.",
"settings_pane_highlights_header": "Ерекше жаңалықтар",
"settings_pane_highlights_body2": "Сіз жақында қараған немесе бетбелгілерге қосқан қызықты нәрселерге қайтатын жолды табыңыз.",
"settings_pane_highlights_options_bookmarks": "Бетбелгілер",
"settings_pane_highlights_options_visited": "Ашылған сайттар",
"settings_pane_snippets_header": "Үзінділер",
"settings_pane_snippets_body": "Mozilla-дан Firefox және интернет мәдениеті туралы қысқа жаңалықтарды, және кездейсоқ мемдерді оқыңыз.",
"settings_pane_done_button": "Дайын",
"edit_topsites_button_text": "Түзету",
"edit_topsites_button_label": "Топ сайттар санатын баптау",
@ -3653,7 +3690,10 @@
"pocket_read_more": "Әйгілі тақырыптар:",
"pocket_read_even_more": "Көбірек хикаяларды қарау",
"pocket_feedback_header": "Интернеттің ең жақсысы, 25 миллион адаммен танылған.",
"pocket_description": "Ол болмаса, сіз жіберіп алатын мүмкіндігі бар жоғары сапалы құраманы Pocket көмегімен табыңыз, ол енді Mozilla-ның бөлігі болып табылады.",
"highlights_empty_state": "Шолуды бастаңыз, сіз жақында шолған немесе бетбелгілерге қосқан тамаша мақалалар, видеолар немесе басқа парақтардың кейбіреулері осында көрсетіледі.",
"topstories_empty_state": "Дайын. {provider} ұсынған көбірек мақалаларды алу үшін кейінірек тексеріңіз. Күте алмайсыз ба? Интернеттен көбірек тамаша мақалаларды алу үшін әйгілі теманы таңдаңыз.",
"manual_migration_explanation2": "Firefox-ты басқа браузер бетбелгілері, тарихы және парольдерімен қолданып көріңіз.",
"manual_migration_cancel_button": "Жоқ, рахмет",
"manual_migration_import_button": "Қазір импорттау"
},
@ -4376,6 +4416,7 @@
"pocket_read_more": "Populære emner:",
"pocket_read_even_more": "Vis flere saker",
"pocket_feedback_header": "Det beste av nettet, kurert av over 25 millioner mennesker.",
"pocket_description": "Oppdag høykvalitetsinnhold som du ellers ville gå glipp av, ved hjelp av Pocket, som nå er en del av Mozilla.",
"highlights_empty_state": "Begynn å surfe, og vi viser noen av de beste artiklene, videoer og andre sider du nylig har besøkt eller bokmerket her.",
"topstories_empty_state": "Du har tatt igjen. Kom tilbake senere for flere topphistorier fra {provider}. Kan du ikke vente? Velg et populært emne for å finne flere gode artikler fra hele Internett.",
"manual_migration_explanation2": "Prøv Firefox med bokmerkene, historikk og passord fra en annen nettleser.",
@ -4991,7 +5032,7 @@
"menu_action_email_link": "Trametter la colliaziun per e-mail…",
"menu_action_open_new_window": "Avrir en ina nova fanestra",
"menu_action_open_private_window": "Avrir en ina nova fanestra privata",
"menu_action_dismiss": "Serrar",
"menu_action_dismiss": "Sbittar",
"menu_action_delete": "Stizzar da la cronologia",
"menu_action_pin": "Fixar",
"menu_action_unpin": "Betg pli fixar",
@ -5371,6 +5412,8 @@
"settings_pane_highlights_body2": "Najdite pot nazaj do zanimivih strani, ki ste jih nedavno obiskali ali dodali med zaznamke.",
"settings_pane_highlights_options_bookmarks": "Zaznamki",
"settings_pane_highlights_options_visited": "Obiskane strani",
"settings_pane_snippets_header": "Izrezki",
"settings_pane_snippets_body": "Spremljajte kratke novice o Mozilli in Firefoxu, kulturi interneta in si občasno oglejte kak meme.",
"settings_pane_done_button": "Končano",
"edit_topsites_button_text": "Uredi",
"edit_topsites_button_label": "Prilagodite odsek Glavne strani",
@ -5384,8 +5427,8 @@
"edit_topsites_add_button": "Dodaj",
"topsites_form_add_header": "Nova glavna stran",
"topsites_form_edit_header": "Uredi glavno stran",
"topsites_form_title_placeholder": "Vnesite naslov",
"topsites_form_url_placeholder": "Vnesite ali prilepite URL",
"topsites_form_title_placeholder": "Vnesite ime",
"topsites_form_url_placeholder": "Vnesite ali prilepite spletni naslov",
"topsites_form_add_button": "Dodaj",
"topsites_form_save_button": "Shrani",
"topsites_form_cancel_button": "Prekliči",
@ -5725,6 +5768,7 @@
"default_label_loading": "వస్తోంది…",
"header_top_sites": "మేటి సైట్లు",
"header_stories": "ముఖ్య కథనాలు",
"header_highlights": "విశేషాలు",
"header_visit_again": "మళ్లీ సందర్శించండి",
"header_bookmarks": "ఇటీవలి ఇష్టాంశములు",
"header_recommended_by": "{provider}చే సిఫార్సు చేయబడినది",
@ -5756,6 +5800,8 @@
"search_web_placeholder": "జాలంలో వెతకండి",
"search_settings": "శోధన అమరికలు మార్చు",
"section_info_option": "సమాచారం",
"section_info_send_feedback": "అభిప్రాయాన్ని పంపండి",
"section_info_privacy_notice": "గోప్యతా విధానం",
"welcome_title": "కొత్త ట్యాబుకు స్వాగతం",
"welcome_body": "సముచితమైన మీ ఇష్టాంశాలను, వ్యాసాలను, వీడియోలను, ఇంకా మీరు ఇటీవలే చూసిన పేజీలను మీకు తేలిగ్గా అందుబాటులో ఉంచేందుకు Firefox ఈ జాగాని వాడుకుంటుంది.",
"welcome_label": "మీ ముఖ్యాంశాలను గుర్తిస్తున్నది",
@ -5765,7 +5811,7 @@
"time_label_day": "{number}రో",
"settings_pane_button_label": "మీ కొత్త ట్యాబు పేజీని మలచుకోండి",
"settings_pane_header": "కొత్త ట్యాబు అభిరుచులు",
"settings_pane_body": "మీరు కొత్త ట్యాబు తెరిచినప్పుడు ఏం చూడాలో ఎంచుకోండి.",
"settings_pane_body2": "మీరు ఈ పేజీలో చూసేదాన్ని ఎంచుకోండి.",
"settings_pane_search_header": "వెతకడం",
"settings_pane_search_body": "కొత్త ట్యాబు నుండే జాలంలో వెతకండి.",
"settings_pane_topsites_header": "మేటి సైట్లు",
@ -5775,8 +5821,9 @@
"settings_pane_bookmarks_body": "ఒక సులభ స్థానంలో మీ క్రొత్తగా సృష్టించిన బుక్మార్క్లు.",
"settings_pane_visit_again_header": "మళ్లీ సందర్శించండి",
"settings_pane_visit_again_body": "మీరు బ్రౌజింగ్ చరిత్రలో గుర్తుంచుకోవాల్సిన లేదా తిరిగి పొందవలసిన భాగాలను చూపిస్తుంది.",
"settings_pane_pocketstories_header": "ముఖ్య కథనాలు",
"settings_pane_pocketstories_body": "Mozilla కుటుంబం యొక్క Pocket, మీరు కనుగొనలేకపోయే అధిక-నాణ్యత విషయముకి మిమ్మల్ని అనుసంధానించడానికి సహాయపడుతుంది.",
"settings_pane_highlights_header": "విశేషాలు",
"settings_pane_highlights_options_bookmarks": "ఇష్టాంశాలు",
"settings_pane_highlights_options_visited": "చూసిన సైటులు",
"settings_pane_done_button": "పూర్తయింది",
"edit_topsites_button_text": "మార్చు",
"edit_topsites_button_label": "మీ మేటి సైట్ల విభాగాన్ని మలచుకోండి",
@ -5799,10 +5846,7 @@
"pocket_read_more": "ప్రముఖ అంశాలు:",
"pocket_read_even_more": "మరిన్ని కథలను వీక్షించండి",
"pocket_feedback_header": "వెబ్లో అత్యుత్తమమైనది, 25 మిలియన్లకు పైగా ప్రజలు పర్యవేక్షించినవి.",
"pocket_feedback_body": "Mozilla కుటుంబం యొక్క Pocket, మీరు కనుగొనలేకపోయే అధిక-నాణ్యత విషయముకి మిమ్మల్ని అనుసంధానించడానికి సహాయపడుతుంది.",
"pocket_send_feedback": "అభిప్రాయాన్ని పంపండి",
"topstories_empty_state": "మీరు పట్టుబడ్డారు. {provider} నుండి మరింత అగ్ర కథనాల కోసం తరువాత తనిఖీ చేయండి. వేచి ఉండలేరా? జాలములోని అంతటి నుండి మరింత గొప్ప కథనాలను కనుగొనడానికి ప్రసిద్ధ అంశం ఎంచుకోండి.",
"manual_migration_explanation": "మరొక విహరణి నుండి మీకు ఇష్టమైన సైట్లు మరియు ఇష్టంశాలతో Firefox ను ప్రయత్నించండి.",
"manual_migration_cancel_button": "అడిగినందుకు ధన్యవాదాలు, వద్దు",
"manual_migration_import_button": "ఇప్పుడే దిగుమతి చేయండి"
},
@ -5865,6 +5909,7 @@
"settings_pane_visit_again_header": "เยี่ยมชมอีกครั้ง",
"settings_pane_highlights_header": "รายการเด่น",
"settings_pane_highlights_options_bookmarks": "ที่คั่นหน้า",
"settings_pane_highlights_options_visited": "ไซต์ที่เยี่ยมชมแล้ว",
"settings_pane_done_button": "เสร็จสิ้น",
"edit_topsites_button_text": "แก้ไข",
"edit_topsites_button_label": "ปรับแต่งส่วนไซต์เด่นของคุณ",
@ -5887,6 +5932,7 @@
"pocket_read_more": "หัวข้อยอดนิยม:",
"pocket_read_even_more": "ดูเรื่องราวเพิ่มเติม",
"pocket_feedback_header": "ที่สุดของเว็บ จัดรายการโดยผู้คนกว่า 25 ล้านคน",
"manual_migration_explanation2": "ลอง Firefox ด้วยที่คั่นหน้า, ประวัติ และรหัสผ่านจากเบราว์เซอร์อื่น",
"manual_migration_cancel_button": "ไม่ ขอบคุณ",
"manual_migration_import_button": "นำเข้าตอนนี้"
},
@ -6294,8 +6340,8 @@
"menu_action_remove_bookmark": "移除书签",
"menu_action_copy_address": "复制地址",
"menu_action_email_link": "用邮件发送链接…",
"menu_action_open_new_window": "新窗口打开",
"menu_action_open_private_window": "在新的隐私窗口中打开",
"menu_action_open_new_window": "窗口打开",
"menu_action_open_private_window": "新建隐私浏览窗口打开",
"menu_action_dismiss": "隐藏",
"menu_action_delete": "从历史记录中删除",
"menu_action_pin": "固定",

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

@ -8,7 +8,7 @@
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<em:version>2017.09.08.0882-3dbf720c</em:version>
<em:version>2017.09.11.1306-373d9fc</em:version>
<em:name>Activity Stream</em:name>
<em:description>A rich visual history feed and a reimagined home page make it easier than ever to find exactly what you're looking for in Firefox.</em:description>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

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

@ -77,6 +77,10 @@ const PREFS_CONFIG = new Map([
title: "Number of days to show the manual migration message",
value: 4
}],
["prerender", {
title: "Use the prerendered version of activity-stream.html. This is set automatically by PrefsFeed.jsm.",
value: true
}],
["showSearch", {
title: "Show the Search bar on the New Tab page",
value: true

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

@ -10,6 +10,7 @@ const {actionTypes: at} = Cu.import("resource://activity-stream/common/Actions.j
const {shortURL} = Cu.import("resource://activity-stream/lib/ShortURL.jsm", {});
const {SectionsManager} = Cu.import("resource://activity-stream/lib/SectionsManager.jsm", {});
const {TOP_SITES_SHOWMORE_LENGTH} = Cu.import("resource://activity-stream/common/Reducers.jsm", {});
const {Dedupe} = Cu.import("resource://activity-stream/common/Dedupe.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
@ -17,6 +18,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
const HIGHLIGHTS_MAX_LENGTH = 9;
const HIGHLIGHTS_UPDATE_TIME = 15 * 60 * 1000; // 15 minutes
const MANY_EXTRA_LENGTH = HIGHLIGHTS_MAX_LENGTH * 5 + TOP_SITES_SHOWMORE_LENGTH;
const SECTION_ID = "highlights";
this.HighlightsFeed = class HighlightsFeed {
@ -43,18 +45,39 @@ this.HighlightsFeed = class HighlightsFeed {
}
async fetchHighlights(broadcast = false) {
this.highlights = await NewTabUtils.activityStreamLinks.getHighlights();
for (let highlight of this.highlights) {
highlight.hostname = shortURL(Object.assign({}, highlight, {url: highlight.url}));
highlight.image = highlight.preview_image_url;
if (highlight.bookmarkGuid) {
highlight.type = "bookmark";
}
}
// Request more than the expected length to allow for items being removed by
// deduping against Top Sites or multiple history from the same domain, etc.
const manyPages = await NewTabUtils.activityStreamLinks.getHighlights({numItems: MANY_EXTRA_LENGTH});
// Remove any Highlights that are in Top Sites already
const deduped = this.dedupe.group(this.store.getState().TopSites.rows, this.highlights);
this.highlights = deduped[1];
const deduped = this.dedupe.group(this.store.getState().TopSites.rows, manyPages)[1];
// Keep all "bookmark"s and at most one (most recent) "history" per host
this.highlights = [];
const hosts = new Set();
for (const page of deduped) {
const hostname = shortURL(page);
// Skip this history page if we already something from the same host
if (page.type === "history" && hosts.has(hostname)) {
continue;
}
// We want the page, so update various fields for UI
Object.assign(page, {
hostname,
image: page.preview_image_url,
type: page.bookmarkGuid ? "bookmark" : page.type
});
// Add the "bookmark" or not-skipped "history"
this.highlights.push(page);
hosts.add(hostname);
// Skip the rest if we have enough items
if (this.highlights.length === HIGHLIGHTS_MAX_LENGTH) {
break;
}
}
SectionsManager.updateSection(SECTION_ID, {rows: this.highlights}, this.highlightsLastUpdated === 0 || broadcast);
this.highlightsLastUpdated = Date.now();

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

@ -12,12 +12,30 @@ const {actionCreators: ac, actionTypes: at} = Cu.import("resource://activity-str
* newly opened tabs.
*/
this.NewTabInit = class NewTabInit {
constructor() {
this._queue = new Set();
}
reply(target) {
const action = {type: at.NEW_TAB_INITIAL_STATE, data: this.store.getState()};
this.store.dispatch(ac.SendToContent(action, target));
}
onAction(action) {
let newAction;
switch (action.type) {
case at.NEW_TAB_LOAD:
newAction = {type: at.NEW_TAB_INITIAL_STATE, data: this.store.getState()};
this.store.dispatch(ac.SendToContent(newAction, action.meta.fromTarget));
case at.NEW_TAB_STATE_REQUEST:
// If localization hasn't been loaded yet, we should wait for it.
if (!this.store.getState().App.strings) {
this._queue.add(action.meta.fromTarget);
return;
}
this.reply(action.meta.fromTarget);
break;
case at.LOCALE_UPDATED:
// If the queue is full because we were waiting for strings,
// dispatch them now.
if (this._queue.size > 0 && this.store.getState().App.strings) {
this._queue.forEach(target => this.reply(target));
this._queue.clear();
}
break;
}
}

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

@ -7,17 +7,39 @@ const {utils: Cu} = Components;
const {actionCreators: ac, actionTypes: at} = Cu.import("resource://activity-stream/common/Actions.jsm", {});
const {Prefs} = Cu.import("resource://activity-stream/lib/ActivityStreamPrefs.jsm", {});
const {PrerenderData} = Cu.import("resource://activity-stream/common/PrerenderData.jsm", {});
this.PrefsFeed = class PrefsFeed {
constructor(prefMap) {
this._prefMap = prefMap;
this._prefs = new Prefs();
}
// If the any prefs are set to something other than what the prerendered version
// of AS expects, we can't use it.
_setPrerenderPref() {
for (const prefName of PrerenderData.invalidatingPrefs) {
if (this._prefs.get(prefName) !== PrerenderData.initialPrefs[prefName]) {
this._prefs.set("prerender", false);
return;
}
}
this._prefs.set("prerender", true);
}
_checkPrerender(name) {
if (PrerenderData.invalidatingPrefs.includes(name)) {
this._setPrerenderPref();
}
}
onPrefChanged(name, value) {
if (this._prefMap.has(name)) {
this.store.dispatch(ac.BroadcastToContent({type: at.PREF_CHANGED, data: {name, value}}));
}
this._checkPrerender(name, value);
}
init() {
this._prefs.observeBranch(this);
@ -29,6 +51,8 @@ this.PrefsFeed = class PrefsFeed {
// Set the initial state of all prefs in redux
this.store.dispatch(ac.BroadcastToContent({type: at.PREFS_INITIAL_VALUES, data: values}));
this._setPrerenderPref();
}
removeListeners() {
this._prefs.ignoreBranch(this);

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

@ -48,7 +48,7 @@ const BUILT_IN_SECTIONS = {
icon: "highlights",
title: {id: "header_highlights"},
maxRows: 3,
availableContextMenuOptions: ["CheckBookmark", "SaveToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"],
availableContextMenuOptions: ["CheckBookmark", "SaveToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "DeleteUrl"],
emptyState: {
message: {id: "highlights_empty_state"},
icon: "highlights"

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

@ -121,7 +121,7 @@ this.SnippetsFeed = class SnippetsFeed {
Services.prefs.removeObserver(TELEMETRY_PREF, this._refresh);
Services.prefs.removeObserver(FXA_USERNAME_PREF, this._refresh);
Services.obs.removeObserver(this, SEARCH_ENGINE_OBSERVER_TOPIC);
this.store.dispatch({type: at.SNIPPETS_RESET});
this.store.dispatch(ac.BroadcastToContent({type: at.SNIPPETS_RESET}));
}
showFirefoxAccounts(browser) {

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

@ -21,6 +21,7 @@ const UPDATE_TIME = 15 * 60 * 1000; // 15 minutes
const DEFAULT_SITES_PREF = "default.sites";
const DEFAULT_TOP_SITES = [];
const FRECENCY_THRESHOLD = 100; // 1 visit (skip first-run/one-time pages)
const MIN_FAVICON_SIZE = 96;
this.TopSitesFeed = class TopSitesFeed {
constructor() {
@ -95,13 +96,13 @@ this.TopSitesFeed = class TopSitesFeed {
}
}
// Now, get a tippy top icon or screenshot for every item
// Now, get a tippy top icon, a rich icon, or screenshot for every item
for (let link of links) {
if (!link) { continue; }
// Check for tippy top icon.
// Check for tippy top icon or a rich icon.
link = this._tippyTopProvider.processSite(link);
if (link.tippyTopIcon) { continue; }
if (link.tippyTopIcon || link.faviconSize >= MIN_FAVICON_SIZE) { continue; }
// If no tippy top, then we get a screenshot.
if (currentScreenshots[link.url]) {

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

@ -0,0 +1,70 @@
const prerender = require("content-src/activity-stream-prerender");
const {prerenderStore} = prerender;
const {PrerenderData} = require("common/PrerenderData.jsm");
describe("prerenderStore", () => {
it("should create a store", () => {
const store = prerenderStore();
assert.isFunction(store.getState);
});
it("should start uninitialized", () => {
const store = prerenderStore();
const state = store.getState();
assert.equal(state.App.initialized, false);
});
it("should set the right locale, strings, and text direction", () => {
const strings = {foo: "foo"};
const store = prerenderStore("en-FOO", strings);
const state = store.getState();
assert.equal(state.App.locale, "en-FOO");
assert.equal(state.App.strings, strings);
assert.equal(state.App.textDirection, "ltr");
});
it("should add the right initial prefs", () => {
const store = prerenderStore();
const state = store.getState();
assert.equal(state.Prefs.values, PrerenderData.initialPrefs);
});
it("should add TopStories as the first section", () => {
const store = prerenderStore();
const state = store.getState();
// TopStories
const firstSection = state.Sections[0];
assert.equal(firstSection.id, "topstories");
// it should start uninitialized
assert.equal(firstSection.initialized, false);
});
});
describe("prerender", () => {
it("should set the locale and get the right strings of whatever is passed in", () => {
const {store} = prerender("en-US");
const state = store.getState();
assert.equal(state.App.locale, "en-US");
assert.equal(state.App.strings.newtab_page_title, "New Tab");
});
it("should throw if an unknown locale is passed in", () => {
assert.throws(() => prerender("en-FOO"));
});
it("should set the locale to en-PRERENDER and have empty strings if no locale is passed in", () => {
const {store} = prerender();
const state = store.getState();
assert.equal(state.App.locale, "en-PRERENDER");
assert.equal(state.App.strings.newtab_page_title, " ");
});
// # TODO: Remove when #3370 is resolved.
it("should render a real English string for search_web_placeholder", () => {
const {store} = prerender();
const state = store.getState();
assert.equal(state.App.strings.search_web_placeholder, "Search the Web");
});
});

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

@ -26,12 +26,20 @@ describe("Reducers", () => {
const nextState = App(undefined, {type: at.LOCALE_UPDATED});
assert.equal(nextState, INITIAL_STATE.App);
});
it("should set locale, strings on LOCALE_UPDATE", () => {
it("should set locale, strings and text direction on LOCALE_UPDATE", () => {
const strings = {};
const action = {type: "LOCALE_UPDATED", data: {locale: "zh-CN", strings}};
const nextState = App(undefined, action);
assert.propertyVal(nextState, "locale", "zh-CN");
assert.propertyVal(nextState, "strings", strings);
assert.propertyVal(nextState, "textDirection", "ltr");
});
it("should set rtl text direction for RTL locales", () => {
const action = {type: "LOCALE_UPDATED", data: {locale: "ar"}};
const nextState = App(undefined, action);
assert.propertyVal(nextState, "textDirection", "rtl");
});
});
describe("TopSites", () => {

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

@ -30,7 +30,7 @@ describe("Top Sites Feed", () => {
updateSection: sinon.spy(),
sections: new Map([["highlights", {}]])
};
shortURLStub = sinon.stub().callsFake(site => site.url);
shortURLStub = sinon.stub().callsFake(site => site.url.match(/\/([^/]+)/)[1]);
globals.set("NewTabUtils", fakeNewTabUtils);
({HighlightsFeed, HIGHLIGHTS_UPDATE_TIME, SECTION_ID} = injector({
"lib/ShortURL.jsm": {shortURL: shortURLStub},
@ -72,7 +72,7 @@ describe("Top Sites Feed", () => {
it("should add hostname and image to each link", async () => {
links = [{url: "https://mozilla.org", preview_image_url: "https://mozilla.org/preview.jog"}];
await feed.fetchHighlights();
assert.equal(feed.highlights[0].hostname, links[0].url);
assert.equal(feed.highlights[0].hostname, "mozilla.org");
assert.equal(feed.highlights[0].image, links[0].preview_image_url);
});
it("should not include any links already in Top Sites", async () => {
@ -86,6 +86,30 @@ describe("Top Sites Feed", () => {
assert.equal(feed.highlights.length, 1);
assert.deepEqual(feed.highlights[0], links[0]);
});
it("should not include history of same hostname as a bookmark", async () => {
links = [
{url: "https://site.com/bookmark", type: "bookmark"},
{url: "https://site.com/history", type: "history"}
];
await feed.fetchHighlights();
assert.equal(feed.highlights.length, 1);
assert.deepEqual(feed.highlights[0], links[0]);
});
it("should take the first history of a hostname", async () => {
links = [
{url: "https://site.com/first", type: "history"},
{url: "https://site.com/second", type: "history"},
{url: "https://other", type: "history"}
];
await feed.fetchHighlights();
assert.equal(feed.highlights.length, 2);
assert.deepEqual(feed.highlights[0], links[0]);
assert.deepEqual(feed.highlights[1], links[2]);
});
it("should set type to bookmark if there is a bookmarkGuid", async () => {
links = [{url: "https://mozilla.org", type: "history", bookmarkGuid: "1234567890"}];
await feed.fetchHighlights();

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

@ -0,0 +1,62 @@
const {NewTabInit} = require("lib/NewTabInit.jsm");
const {actionTypes: at, actionCreators: ac} = require("common/Actions.jsm");
describe("NewTabInit", () => {
let instance;
let store;
let STATE;
beforeEach(() => {
STATE = {};
store = {getState: sinon.stub().returns(STATE), dispatch: sinon.stub()};
instance = new NewTabInit();
instance.store = store;
});
it("should reply with a copy of the state immediately if localization is ready", () => {
STATE.App = {strings: {}};
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, 123));
const resp = ac.SendToContent({type: at.NEW_TAB_INITIAL_STATE, data: STATE}, 123);
assert.calledWith(store.dispatch, resp);
});
it("should not reply immediately if localization is not ready", () => {
STATE.App = {strings: null};
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, 123));
assert.notCalled(store.dispatch);
});
it("should dispatch responses for queued targets when LOCALE_UPDATED is received", () => {
STATE.App = {strings: null};
// Send requests before strings are ready
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "foo"));
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "bar"));
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "baz"));
assert.notCalled(store.dispatch);
// Update strings
STATE.App = {strings: {}};
instance.onAction({type: at.LOCALE_UPDATED});
assert.calledThrice(store.dispatch);
const action = {type: at.NEW_TAB_INITIAL_STATE, data: STATE};
assert.calledWith(store.dispatch, ac.SendToContent(action, "foo"));
assert.calledWith(store.dispatch, ac.SendToContent(action, "bar"));
assert.calledWith(store.dispatch, ac.SendToContent(action, "baz"));
});
it("should clear targets from the queue once they have been sent", () => {
STATE.App = {strings: null};
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "foo"));
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "bar"));
instance.onAction(ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST}, "baz"));
STATE.App = {strings: {}};
instance.onAction({type: at.LOCALE_UPDATED});
assert.calledThrice(store.dispatch);
store.dispatch.reset();
instance.onAction({type: at.LOCALE_UPDATED});
assert.notCalled(store.dispatch);
});
});

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

@ -1,16 +1,20 @@
const {PrefsFeed} = require("lib/PrefsFeed.jsm");
const {actionTypes: at, actionCreators: ac} = require("common/Actions.jsm");
const {PrerenderData} = require("common/PrerenderData.jsm");
const {initialPrefs} = PrerenderData;
const FAKE_PREFS = new Map([["foo", {value: 1}], ["bar", {value: 2}]]);
const PRERENDER_PREF_NAME = "prerender";
describe("PrefsFeed", () => {
let feed;
let FAKE_PREFS;
beforeEach(() => {
FAKE_PREFS = new Map([["foo", 1], ["bar", 2]]);
feed = new PrefsFeed(FAKE_PREFS);
feed.store = {dispatch: sinon.spy()};
feed._prefs = {
get: sinon.spy(item => FAKE_PREFS.get(item).value),
set: sinon.spy(),
get: sinon.spy(item => FAKE_PREFS.get(item)),
set: sinon.spy((name, value) => FAKE_PREFS.set(name, value)),
observe: sinon.spy(),
observeBranch: sinon.spy(),
ignore: sinon.spy(),
@ -41,4 +45,42 @@ describe("PrefsFeed", () => {
feed.onPrefChanged("foo", 2);
assert.calledWith(feed.store.dispatch, ac.BroadcastToContent({type: at.PREF_CHANGED, data: {name: "foo", value: 2}}));
});
describe("INIT prerendering", () => {
it("should set a prerender pref on init", () => {
feed.onAction({type: at.INIT});
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME);
});
it("should set prerender pref to true if prefs match initial values", () => {
Object.keys(initialPrefs).forEach(name => FAKE_PREFS.set(name, initialPrefs[name]));
feed.onAction({type: at.INIT});
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME, true);
});
it("should set prerender pref to false if a pref does not match its initial value", () => {
Object.keys(initialPrefs).forEach(name => FAKE_PREFS.set(name, initialPrefs[name]));
FAKE_PREFS.set("feeds.section.topstories", false);
feed.onAction({type: at.INIT});
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME, false);
});
});
describe("onPrefChanged prerendering", () => {
it("should not change the prerender pref if the pref is not included in invalidatingPrefs", () => {
feed.onPrefChanged("foo123", true);
assert.notCalled(feed._prefs.set);
});
it("should set the prerender pref to false if a pref in invalidatingPrefs is changed from its original value", () => {
Object.keys(initialPrefs).forEach(name => FAKE_PREFS.set(name, initialPrefs[name]));
feed._prefs.set("feeds.section.topstories", false);
feed.onPrefChanged("feeds.section.topstories", false);
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME, false);
});
it("should set the prerender pref back to true if the invalidatingPrefs are changed back to their original values", () => {
Object.keys(initialPrefs).forEach(name => FAKE_PREFS.set(name, initialPrefs[name]));
FAKE_PREFS.set("feeds.section.topstories", false);
feed._prefs.set("feeds.section.topstories", true);
feed.onPrefChanged("feeds.section.topstories", true);
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME, true);
});
});
});

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

@ -1,5 +1,5 @@
const {SnippetsFeed} = require("lib/SnippetsFeed.jsm");
const {actionTypes: at} = require("common/Actions.jsm");
const {actionCreators: ac, actionTypes: at} = require("common/Actions.jsm");
const {GlobalOverrider} = require("test/unit/utils");
const WEEK_IN_MS = 7 * 24 * 60 * 60 * 1000;
@ -78,13 +78,13 @@ describe("SnippetsFeed", () => {
feed.onAction({type: at.UNINIT});
assert.calledOnce(feed.uninit);
});
it("should dispatch a SNIPPETS_RESET on uninit", () => {
it("should broadcast a SNIPPETS_RESET on uninit", () => {
const feed = new SnippetsFeed();
feed.store = {dispatch: sandbox.stub()};
feed.uninit();
assert.calledWith(feed.store.dispatch, {type: at.SNIPPETS_RESET});
assert.calledWith(feed.store.dispatch, ac.BroadcastToContent({type: at.SNIPPETS_RESET}));
});
it("should dispatch an update event when the Search observer is called", async () => {
const feed = new SnippetsFeed();

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

@ -295,6 +295,22 @@ describe("Top Sites Feed", () => {
assert.calledOnce(feed.store.dispatch);
assert.notCalled(feed.getScreenshot);
});
it("should skip getting screenshot if there is an icon of size greater than 96x96 and no tippy top", async () => {
sandbox.stub(feed, "getScreenshot");
feed.getLinksWithDefaults = () => [{
url: "foo.com",
favicon: "data:foo",
faviconSize: 196
}];
feed._tippyTopProvider.processSite = site => {
site.tippyTopIcon = null;
site.backgroundColor = null;
return site;
};
await feed.refresh(action);
assert.calledOnce(feed.store.dispatch);
assert.notCalled(feed.getScreenshot);
});
});
describe("getScreenshot", () => {
it("should call Screenshots.getScreenshotForURL with the right url", async () => {

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

@ -1,6 +1,7 @@
const initStore = require("content-src/lib/init-store");
const {MERGE_STORE_ACTION, rehydrationMiddleware} = initStore;
const {GlobalOverrider, addNumberReducer} = require("test/unit/utils");
const {actionCreators: ac} = require("common/Actions.jsm");
const {actionCreators: ac, actionTypes: at} = require("common/Actions.jsm");
describe("initStore", () => {
let globals;
@ -16,20 +17,33 @@ describe("initStore", () => {
assert.ok(store);
assert.property(store.getState(), "number");
});
it("should add a listener for incoming actions", () => {
it("should add a listener that dispatches actions", () => {
assert.calledWith(global.addMessageListener, initStore.INCOMING_MESSAGE_NAME);
const callback = global.addMessageListener.firstCall.args[1];
const listener = global.addMessageListener.firstCall.args[1];
globals.sandbox.spy(store, "dispatch");
const message = {name: initStore.INCOMING_MESSAGE_NAME, data: {type: "FOO"}};
callback(message);
listener(message);
assert.calledWith(store.dispatch, message.data);
});
it("should not throw if addMessageListener is not defined", () => {
// Note: this is being set/restored by GlobalOverrider
delete global.addMessageListener;
assert.doesNotThrow(() => initStore({number: addNumberReducer}));
});
it("should initialize with an initial state if provided as the second argument", () => {
store = initStore({number: addNumberReducer}, {number: 42});
assert.equal(store.getState().number, 42);
});
it("should log errors from failed messages", () => {
const callback = global.addMessageListener.firstCall.args[1];
globals.sandbox.stub(global.console, "error");
globals.sandbox.stub(store, "dispatch").throws(Error("failed"));
const message = {name: initStore.INCOMING_MESSAGE_NAME, data: {type: "FOO"}};
const message = {name: initStore.INCOMING_MESSAGE_NAME, data: {type: MERGE_STORE_ACTION}};
callback(message);
assert.calledOnce(global.console.error);
@ -38,13 +52,60 @@ describe("initStore", () => {
store.dispatch({type: initStore.MERGE_STORE_ACTION, data: {number: 42}});
assert.deepEqual(store.getState(), {number: 42});
});
it("should send out SendToMain ations", () => {
it("should send out SendToMain actions", () => {
const action = ac.SendToMain({type: "FOO"});
store.dispatch(action);
assert.calledWith(global.sendAsyncMessage, initStore.OUTGOING_MESSAGE_NAME, action);
});
it("should not send out other types of ations", () => {
it("should not send out other types of actions", () => {
store.dispatch({type: "FOO"});
assert.notCalled(global.sendAsyncMessage);
});
describe("rehydrationMiddleware", () => {
it("should allow NEW_TAB_STATE_REQUEST to go through", () => {
const action = ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST});
const next = sinon.spy();
rehydrationMiddleware(store)(next)(action);
assert.calledWith(next, action);
});
it("should dispatch an additional NEW_TAB_STATE_REQUEST if INIT was received after a request", () => {
const requestAction = ac.SendToMain({type: at.NEW_TAB_STATE_REQUEST});
const next = sinon.spy();
rehydrationMiddleware(store)(next)(requestAction);
next.reset();
rehydrationMiddleware(store)(next)({type: at.INIT});
assert.calledWith(next, requestAction);
});
it("should allow MERGE_STORE_ACTION to go through", () => {
const action = {type: MERGE_STORE_ACTION};
const next = sinon.spy();
rehydrationMiddleware(store)(next)(action);
assert.calledWith(next, action);
});
it("should not allow actions from main to go through before MERGE_STORE_ACTION was received", () => {
const next = sinon.spy();
rehydrationMiddleware(store)(next)(ac.BroadcastToContent({type: "FOO"}));
rehydrationMiddleware(store)(next)(ac.SendToContent({type: "FOO"}, 123));
assert.notCalled(next);
});
it("should allow all local actions to go through", () => {
const action = {type: "FOO"};
const next = sinon.spy();
rehydrationMiddleware(store)(next)(action);
assert.calledWith(next, action);
});
it("should allow actions from main to go through after MERGE_STORE_ACTION has been received", () => {
const next = sinon.spy();
rehydrationMiddleware(store)(next)({type: MERGE_STORE_ACTION});
next.reset();
const action = ac.SendToContent({type: "FOO"}, 123);
rehydrationMiddleware(store)(next)(action);
assert.calledWith(next, action);
});
});
});