Bug 1405539 - Add info doorhanger, collapsible sections and bug fixes to Activity Stream. r=k88hudson

MozReview-Commit-ID: C5LXhbuI0EA
This commit is contained in:
Ed Lee
2017-10-05 15:38:54 -07:00
parent 823b49bf3e
commit bedf127313
17 changed files with 1373 additions and 897 deletions

View File

@@ -87,6 +87,15 @@ let allowedImageReferences = [
{file: "chrome://devtools/skin/images/dock-bottom-maximize@2x.png",
from: "chrome://devtools/skin/toolbox.css",
isFromDevTools: true},
// Bug 1405539
{file: "chrome://global/skin/arrow/panelarrow-vertical@2x.png",
from: "resource://activity-stream/data/content/activity-stream.css",
isFromDevTools: false,
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/panelarrow-vertical-themed.svg",
from: "resource://activity-stream/data/content/activity-stream.css",
isFromDevTools: false,
platforms: ["macosx"]},
];
// Add suffix to stylesheets' URI so that we always load them here and

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -82,6 +82,19 @@ input {
background-image: url("assets/glyph-webextension-16.svg"); }
.icon.icon-highlights {
background-image: url("assets/glyph-highlights-16.svg"); }
.icon.icon-arrowhead-down {
background-image: url("assets/glyph-arrowhead-down-12.svg");
background-size: 12px;
height: 12px;
width: 12px; }
.icon.icon-arrowhead-forward {
background-image: url("assets/glyph-arrowhead-down-12.svg");
background-size: 12px;
height: 12px;
transform: rotate(270deg);
width: 12px; }
.icon.icon-arrowhead-forward:dir(rtl) {
transform: rotate(90deg); }
html,
body,
@@ -197,7 +210,7 @@ main {
.section-top-bar {
height: 16px;
margin-bottom: 12px; }
margin-bottom: 16px; }
.section-title {
font-size: 13px;
@@ -421,11 +434,17 @@ main {
opacity: 1; }
.edit-topsites-wrapper .edit-topsites-button {
position: absolute;
offset-inline-end: 21px;
top: -2px;
border-right: 1px solid #D7D7DB;
line-height: 13px;
offset-inline-end: 24px;
opacity: 0;
padding: 0 10px;
position: absolute;
top: 2px;
transition: opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.edit-topsites-wrapper .edit-topsites-button:dir(rtl) {
border-left: 1px solid #D7D7DB;
border-right: 0; }
.edit-topsites-wrapper .edit-topsites-button:focus, .edit-topsites-wrapper .edit-topsites-button:active {
opacity: 1; }
.edit-topsites-wrapper .edit-topsites-button button {
@@ -528,93 +547,6 @@ section.top-sites:hover .edit-topsites-button {
opacity: 1;
transform: translateY(0); } }
.section-top-bar {
position: relative; }
.section-top-bar .section-info-option {
offset-inline-end: 0;
position: absolute;
top: 0; }
.section-top-bar .info-option-icon {
background-image: url("assets/glyph-info-option-12.svg");
background-size: 12px 12px;
background-repeat: no-repeat;
background-position: center;
fill: rgba(12, 12, 13, 0.6);
-moz-context-properties: fill;
height: 16px;
width: 16px;
display: inline-block;
margin-bottom: -2px;
opacity: 0;
transition: opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.section-top-bar .info-option-icon:focus, .section-top-bar .info-option-icon:active {
opacity: 1; }
.section-top-bar .info-option-icon[aria-expanded="true"] {
fill: rgba(12, 12, 13, 0.8); }
.section-top-bar .section-info-option .info-option {
visibility: hidden;
opacity: 0;
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.section-top-bar .section-info-option .info-option::before {
content: "";
display: block;
height: 32px;
left: 50%;
position: absolute;
right: 0;
top: -32px; }
.section-top-bar .info-option-icon[aria-expanded="true"] + .info-option {
visibility: visible;
opacity: 1;
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.section-top-bar .info-option {
z-index: 9999;
position: absolute;
background: #FFF;
border: 1px solid #D7D7DB;
border-radius: 3px;
font-size: 13px;
line-height: 120%;
margin-inline-end: -9px;
offset-inline-end: 0;
top: 20px;
width: 320px;
padding: 24px;
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
-moz-user-select: none; }
.section-top-bar .info-option-header {
font-size: 15px;
font-weight: 600; }
.section-top-bar .info-option-body {
margin: 0;
margin-top: 12px; }
.section-top-bar .info-option-link {
color: #0060DF;
margin-left: 7px; }
.section-top-bar .info-option-manage {
margin-top: 24px; }
.section-top-bar .info-option-manage button {
background: none;
border: none;
color: #0060DF;
cursor: pointer;
margin: 0;
padding: 0; }
.section-top-bar .info-option-manage button::after {
background-image: url("assets/topic-show-more-12.svg");
background-repeat: no-repeat;
content: '';
-moz-context-properties: fill;
display: inline-block;
fill: #0060DF;
height: 16px;
margin-inline-start: 5px;
margin-top: 1px;
vertical-align: middle;
width: 12px; }
.section-top-bar .info-option-manage button:dir(rtl)::after {
transform: scaleX(-1); }
.sections-list .section-list {
margin: 0;
display: grid;
@@ -666,9 +598,6 @@ section.top-sites:hover .edit-topsites-button {
color: #737373;
text-align: center; }
section.section:hover .info-option-icon {
opacity: 1; }
.topic {
font-size: 12px;
color: #737373;
@@ -758,7 +687,7 @@ section.section:hover .info-option-icon {
background-color: rgba(12, 12, 13, 0.1);
cursor: pointer; }
.search-wrapper .search-button:active {
background-color: rgba(12, 12, 13, 0.15); }
background-color: rgba(12, 12, 13, 0.2); }
.search-wrapper .search-button:dir(rtl) {
transform: scaleX(-1); }
.search-wrapper .contentSearchSuggestionTable {
@@ -840,7 +769,7 @@ section.section:hover .info-option-icon {
.prefs-pane .prefs-modal-inner-wrapper section {
margin: 20px 0; }
.prefs-pane .prefs-modal-inner-wrapper section p {
margin: 5px 0 5px 30px; }
margin: 5px 0 20px 30px; }
.prefs-pane .prefs-modal-inner-wrapper section label {
display: inline-block;
position: relative;
@@ -1161,3 +1090,129 @@ section.section:hover .info-option-icon {
height: 26px;
margin-inline-start: 20px;
padding: 0 12px; }
.collapsible-section .section-title .click-target {
cursor: pointer; }
.collapsible-section .section-title .icon.icon-arrowhead-down {
margin: -3px 0 0 8px; }
.collapsible-section .section-title .icon.icon-arrowhead-forward {
margin: -2px 0 0 8px; }
.collapsible-section .section-top-bar {
position: relative; }
.collapsible-section .section-top-bar .section-info-option {
offset-inline-end: 0;
position: absolute;
top: 0; }
.collapsible-section .section-top-bar .info-option-icon {
background-image: url("assets/glyph-info-option-12.svg");
background-size: 12px 12px;
background-repeat: no-repeat;
background-position: center;
fill: rgba(12, 12, 13, 0.6);
-moz-context-properties: fill;
height: 16px;
width: 16px;
display: inline-block;
margin-bottom: -2px;
opacity: 0;
transition: opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.collapsible-section .section-top-bar .info-option-icon:focus, .collapsible-section .section-top-bar .info-option-icon:active {
opacity: 1; }
.collapsible-section .section-top-bar .info-option-icon[aria-expanded="true"] {
background-color: rgba(12, 12, 13, 0.1);
border-radius: 1px;
box-shadow: 0 0 0 5px rgba(12, 12, 13, 0.1);
fill: rgba(12, 12, 13, 0.8); }
.collapsible-section .section-top-bar .section-info-option .info-option {
visibility: hidden;
opacity: 0;
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.collapsible-section .section-top-bar .section-info-option .info-option::after, .collapsible-section .section-top-bar .section-info-option .info-option::before {
content: "";
offset-inline-end: 0;
position: absolute; }
.collapsible-section .section-top-bar .section-info-option .info-option::before {
background-image: url(chrome://global/skin/arrow/panelarrow-vertical-themed.svg), url(chrome://global/skin/arrow/panelarrow-vertical@2x.png);
background-position: calc(100% - 7px) bottom;
background-repeat: no-repeat;
background-size: 18px 10px;
height: 32px;
top: -32px;
width: 43px; }
.collapsible-section .section-top-bar .section-info-option .info-option:dir(rtl)::before {
background-position-x: 7px; }
.collapsible-section .section-top-bar .section-info-option .info-option::after {
height: 10px;
offset-inline-start: 0;
top: -10px; }
.collapsible-section .section-top-bar .info-option-icon[aria-expanded="true"] + .info-option {
visibility: visible;
opacity: 1;
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
.collapsible-section .section-top-bar .info-option-icon:not([aria-expanded="true"]) + .info-option {
pointer-events: none; }
.collapsible-section .section-top-bar .info-option {
z-index: 9999;
position: absolute;
background: #FFF;
border: 1px solid #D7D7DB;
border-radius: 3px;
font-size: 13px;
line-height: 120%;
margin-inline-end: -9px;
offset-inline-end: 0;
top: 26px;
width: 320px;
padding: 24px;
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
-moz-user-select: none; }
.collapsible-section .section-top-bar .info-option-header {
font-size: 15px;
font-weight: 600; }
.collapsible-section .section-top-bar .info-option-body {
margin: 0;
margin-top: 12px; }
.collapsible-section .section-top-bar .info-option-link {
color: #0060DF;
margin-left: 7px; }
.collapsible-section .section-top-bar .info-option-manage {
margin-top: 24px; }
.collapsible-section .section-top-bar .info-option-manage button {
background: none;
border: none;
color: #0060DF;
cursor: pointer;
margin: 0;
padding: 0; }
.collapsible-section .section-top-bar .info-option-manage button::after {
background-image: url("assets/topic-show-more-12.svg");
background-repeat: no-repeat;
content: '';
-moz-context-properties: fill;
display: inline-block;
fill: #0060DF;
height: 16px;
margin-inline-start: 5px;
margin-top: 1px;
vertical-align: middle;
width: 12px; }
.collapsible-section .section-top-bar .info-option-manage button:dir(rtl)::after {
transform: scaleX(-1); }
.collapsible-section .section-body {
max-height: 900px;
margin-inline-end: -7px; }
.collapsible-section .section-body.animation-enabled {
transition: max-height 0.5s cubic-bezier(0.07, 0.95, 0, 1); }
.collapsible-section .section-body.animating {
overflow: hidden; }
.collapsible-section.collapsed .section-body {
max-height: 0;
overflow: hidden; }
.collapsible-section:hover .info-option-icon {
opacity: 1; }

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><path class="cls-1" d="M6 9a1 1 0 0 1-.707-.293l-3-3a1 1 0 0 1 1.414-1.414L6 6.586l2.293-2.293a1 1 0 0 1 1.414 1.414l-3 3A1 1 0 0 1 6 9z" fill="context-fill"/></svg>

After

Width:  |  Height:  |  Size: 248 B

View File

@@ -4,6 +4,7 @@
"default_label_loading": "Tye ka cano…",
"header_top_sites": "Kakube maloyo",
"header_stories": "Lok madito",
"header_highlights": "Wiye madito",
"header_visit_again": "Lim doki",
"header_bookmarks": "Alamabuk ma cok coki",
"header_recommended_by": "Lami tam obedo {provider}",
@@ -35,6 +36,8 @@
"search_web_placeholder": "Yeny kakube",
"search_settings": "Lok ter me yeny",
"section_info_option": "Ngec",
"section_info_send_feedback": "Cwal adwogi",
"section_info_privacy_notice": "Ngec me mung",
"welcome_title": "Wajoli i dirica matidi manyen",
"welcome_body": "Firefox bi tic ki kabedo man me nyuto alamabukke mamegi, coc akwana, vidio, ki potbukke ma ilimo cokcoki ma pi gi tego loyo, wek i dok ii gi ma yot.",
"welcome_label": "Tye ka kube ki wiye madito mamegi",
@@ -44,6 +47,7 @@
"time_label_day": "nino{number}",
"settings_pane_button_label": "Yub potbuk me dirica matidi mamegi manyen",
"settings_pane_header": "Ter me dirica matidi manyen",
"settings_pane_body2": "Yer ngo ma i neno i potbuk man.",
"settings_pane_search_header": "Yeny",
"settings_pane_search_body": "Yeny Kakube ki i dirica ni matidi manyen.",
"settings_pane_topsites_header": "Kakube ma gi loyo",
@@ -53,6 +57,12 @@
"settings_pane_bookmarks_body": "Alamabukke ni ma kicweyo manyen i kabedo acel macek.",
"settings_pane_visit_again_header": "Lim Kidoco",
"settings_pane_visit_again_body": "Firefox bi nyuti but gin mukato me yeny mamegi ma itwero mito me poo ikome onyo dok cen iyie.",
"settings_pane_highlights_header": "Wiye madito",
"settings_pane_highlights_body2": "Nong yoo ni cen i jami mamit ma ilimo gi cokcokki onyo iketo alamabuk.",
"settings_pane_highlights_options_bookmarks": "Alamabuk",
"settings_pane_highlights_options_visited": "Kakube ma kilimo",
"settings_pane_snippets_header": "Kwena macek",
"settings_pane_snippets_body": "Kwan ngec manyen macego dok mamit ki bot Mozilla ikom Firefox, kwo me intanet, ki meme mabino atata.",
"settings_pane_done_button": "Otum",
"edit_topsites_button_text": "Yubi",
"edit_topsites_button_label": "Yub bute pi kakubi ni ma giloyo",
@@ -75,8 +85,10 @@
"pocket_read_more": "Lok macuk gi lamal:",
"pocket_read_even_more": "Nen Lok mapol",
"pocket_feedback_header": "Kakube maber loyo, dano makato milion 25 aye oyubo.",
"pocket_description": "Nong jami me rwom ma lamal ma itwero keng woko, ki kony ma aa ki bot Pocket, dong tye but Mozilla.",
"highlights_empty_state": "Cak yeny, ka wa binyuto coc akwana mabeco, video, ki potbuk mukene ma ilimo cokcokki onyo ma kiketo alamabuk kany.",
"topstories_empty_state": "Ityeko weng. Rot doki lacen pi lok madito mapol ki bot {provider}. Pe itwero kuro? Yer lok macuke lamal me nongo lok mabeco mapol ki i but kakube.",
"manual_migration_explanation2": "Tem Firefox ki alamabuk, gin mukato ki mung me donyo ki ii layeny mukene.",
"manual_migration_cancel_button": "Pe Apwoyo",
"manual_migration_import_button": "Kel kombedi"
},
@@ -163,10 +175,54 @@
"newtab_page_title": "Llingüeta nueva",
"default_label_loading": "Cargando…",
"header_top_sites": "Sitios destacaos",
"header_stories": "Histories destacaes",
"header_highlights": "Los destacaos",
"header_visit_again": "Visitar de nueves",
"header_bookmarks": "Marcadores recientes",
"header_bookmarks_placeholder": "Entá nun tienes dengún marcador.",
"header_stories_from": "de",
"type_label_visited": "Visitóse",
"type_label_bookmarked": "Amestóse a marcadores",
"type_label_synced": "Sincronizóse dende otru preséu",
"type_label_recommended": "Tendencia",
"type_label_open": "Abrir",
"type_label_topic": "Tema",
"welcome_title": "Bienllegáu/ada a la llingüeta nueva",
"welcome_body": "Firefox usará esti espaciu p'amosate los marcadores, artículos, vídeos y páxines más relevantes de los que visitares apocayá, asina pues volver a ello de mou cenciellu."
"type_label_now": "Agora",
"menu_action_bookmark": "Amestar a marcadores",
"menu_action_remove_bookmark": "Desaniciar marcador",
"menu_action_copy_address": "Copiar direición",
"menu_action_email_link": "Unviar enllaz per corréu…",
"menu_action_open_new_window": "Abrir nuna ventana nueva",
"menu_action_open_private_window": "Abrir nuna ventana privada nueva",
"menu_action_dismiss": "Escartar",
"menu_action_delete": "Desaniciar del historial",
"menu_action_pin": "Fixar",
"menu_action_unpin": "Desfixar",
"confirm_history_delete_p1": "¿De xuru que quies desaniciar cada instancia d'esta páxina del to historial?",
"confirm_history_delete_notice_p2": "Esta aición nun pue desfacese.",
"menu_action_save_to_pocket": "Guardar en Pocket",
"search_for_something_with": "Guetar {search_term} con:",
"search_button": "Guetar",
"search_header": "Gueta en {search_engine_name}",
"search_web_placeholder": "Guetar na web",
"search_settings": "Camudar axustes de gueta",
"section_info_option": "Información",
"section_info_send_feedback": "Unviar comentarios",
"section_info_privacy_notice": "Nota de privacidá",
"welcome_title": "Afáyate na llingüeta nueva",
"welcome_body": "Firefox usará esti espaciu p'amosate los marcadores, artículos, vídeos y páxines más relevantes que visitares apocayá, asina pues volver a ellos de mou cenciellu.",
"time_label_less_than_minute": "<1m",
"time_label_minute": "{number}m",
"time_label_hour": "{number}h",
"time_label_day": "{number}d",
"settings_pane_done_button": "Fecho",
"edit_topsites_showmore_button": "Amosar más",
"edit_topsites_done_button": "Fecho",
"topsites_form_add_button": "Amestar",
"topsites_form_save_button": "Guardar",
"topsites_form_cancel_button": "Encaboxar",
"pocket_read_more": "Temes populares:",
"pocket_read_even_more": "Ver más histories"
},
"az": {
"newtab_page_title": "Yeni Vərəq",
@@ -626,6 +682,99 @@
"manual_migration_cancel_button": "N'am bo ket",
"manual_migration_import_button": "Emporzhiañ bremañ"
},
"bs": {
"newtab_page_title": "Novi tab",
"default_label_loading": "Učitavam…",
"header_top_sites": "Najbolje stranice",
"header_stories": "Najbolje priče",
"header_highlights": "Istaknuto",
"header_visit_again": "Posjeti ponovo",
"header_bookmarks": "Nedavne zabilješke",
"header_recommended_by": "Preporučeno od {provider}",
"header_bookmarks_placeholder": "Nemate nijednu zabilješku.",
"header_stories_from": "od",
"type_label_visited": "Posjećeno",
"type_label_bookmarked": "Zabilježeno",
"type_label_synced": "Sinhronizovano s drugog uređaja",
"type_label_recommended": "Popularno",
"type_label_open": "Otvoreno",
"type_label_topic": "Tema",
"type_label_now": "Sada",
"menu_action_bookmark": "Zabilježi",
"menu_action_remove_bookmark": "Ukloni zabilješku",
"menu_action_copy_address": "Kopiraj adresu",
"menu_action_email_link": "Pošalji vezu e-poštom…",
"menu_action_open_new_window": "Otvori u novom prozoru",
"menu_action_open_private_window": "Otvori u novom privatnom prozoru",
"menu_action_dismiss": "Odbaci",
"menu_action_delete": "Izbriši iz historije",
"menu_action_pin": "Zakači",
"menu_action_unpin": "Otkači",
"confirm_history_delete_p1": "Jeste li sigurni da želite izbrisati sve primjere ove stranice iz vaše historije?",
"confirm_history_delete_notice_p2": "Ova radnja se ne može opozvati.",
"menu_action_save_to_pocket": "Sačuvaj na Pocket",
"search_for_something_with": "Traži za {search_term} sa:",
"search_button": "Traži",
"search_header": "{search_engine_name} pretraga",
"search_web_placeholder": "Pretraži web",
"search_settings": "Promijeni postavke pretrage",
"section_info_option": "Informacije",
"section_info_send_feedback": "Pošaljite povratnu informaciju",
"section_info_privacy_notice": "Napomena o privatnosti",
"welcome_title": "Dobrodošli u novi tab",
"welcome_body": "Firefox će koristiti ovaj prostor da vam prikaže vaše najrelevantnije zabilješke, članke, video i stranice koje ste nedavno posjetili, da bi im mogli lahko ponovo pristupiti.",
"welcome_label": "Identificiram vaše istaknute stavke",
"time_label_less_than_minute": "<1m",
"time_label_minute": "{number}m",
"time_label_hour": "{number}h",
"time_label_day": "{number}d",
"settings_pane_button_label": "Prilagodite svoju početnu stranicu novog taba",
"settings_pane_header": "Postavke novog taba",
"settings_pane_body2": "Izaberite šta želite vidjeti na ovoj stranici.",
"settings_pane_search_header": "Traži",
"settings_pane_search_body": "Pretražite web iz novog taba.",
"settings_pane_topsites_header": "Najbolje stranice",
"settings_pane_topsites_body": "Pristupite stranicama koje najčešće posjećujete.",
"settings_pane_topsites_options_showmore": "Prikaži dva reda",
"settings_pane_bookmarks_header": "Nedavne zabilješke",
"settings_pane_bookmarks_body": "Vaše novo stvorene zabilješke na jednom praktičnom mjestu.",
"settings_pane_visit_again_header": "Posjetite ponovo",
"settings_pane_visit_again_body": "Firefox će vam prikazati dijelove vaše historije pretraživanja koje možda želite zapamtiti ili posjetiti ponovo.",
"settings_pane_highlights_header": "Istaknuto",
"settings_pane_highlights_body2": "Pronađite put natrag do zanimljivih stvari koje ste nedavno posjetili ili zabilježili.",
"settings_pane_highlights_options_bookmarks": "Zabilješke",
"settings_pane_highlights_options_visited": "Posjećene stranice",
"settings_pane_snippets_header": "Isječci",
"settings_pane_snippets_body": "Pročitajte kratke i slatke obavijesti od Mozille o Firefoxu, internet kulturi i povremenim nasumičnim temama.",
"settings_pane_done_button": "Gotovo",
"edit_topsites_button_text": "Uredi",
"edit_topsites_button_label": "Prilagodite odjel s najboljim stranicama",
"edit_topsites_showmore_button": "Prikaži više",
"edit_topsites_showless_button": "Prikaži manje",
"edit_topsites_done_button": "Gotovo",
"edit_topsites_pin_button": "Zakači ovu stranicu",
"edit_topsites_unpin_button": "Otkači ovu stranicu",
"edit_topsites_edit_button": "Uredi ovu stranicu",
"edit_topsites_dismiss_button": "Odbaci ovu stranicu",
"edit_topsites_add_button": "Dodaj",
"topsites_form_add_header": "Nova najbolja stranica",
"topsites_form_edit_header": "Uredi najbolju stranicu",
"topsites_form_title_placeholder": "Unesi naslov",
"topsites_form_url_placeholder": "Upišite ili zalijepite URL",
"topsites_form_add_button": "Dodaj",
"topsites_form_save_button": "Sačuvaj",
"topsites_form_cancel_button": "Otkaži",
"topsites_form_url_validation": "Potrebno je unijeti ispravan URL",
"pocket_read_more": "Popularne teme:",
"pocket_read_even_more": "Prikaži više priča",
"pocket_feedback_header": "Najbolje od interneta, birano od preko 25 miliona ljudi.",
"pocket_description": "Otkrijte visoko kvalitetan sadržaj koji ste možda propustili, uz pomoć Pocketa koji je sada dio Mozille.",
"highlights_empty_state": "Započnite pretraživati i pokazat ćemo vam neke od izvrsnih članaka, videa i drugih web stranica prema vašim nedavno posjećenim stranicama ili zabilješkama.",
"topstories_empty_state": "Provjerite kasnije za više najpopularnijih priča od {provider}. Ne možete čekati? Odaberite popularne teme kako biste pronašli više kvalitetnih priča s cijelog weba.",
"manual_migration_explanation2": "Probajte Firefox s zabilješkama, historijom i lozinkama iz drugog pretraživača.",
"manual_migration_cancel_button": "Ne, hvala",
"manual_migration_import_button": "Uvezi sada"
},
"ca": {
"newtab_page_title": "Pestanya nova",
"default_label_loading": "S'està carregant…",
@@ -999,7 +1148,7 @@
"default_label_loading": "Indlæser…",
"header_top_sites": "Mest besøgte websider",
"header_stories": "Tophistorier",
"header_highlights": "Højdepunkter",
"header_highlights": "Fremhævede",
"header_visit_again": "Besøg igen",
"header_bookmarks": "Seneste bogmærker",
"header_recommended_by": "Anbefalet af {provider}",
@@ -1032,15 +1181,17 @@
"search_settings": "Skift søgeindstillinger",
"section_info_option": "Info",
"section_info_send_feedback": "Send feedback",
"section_info_privacy_notice": "Privatlivspolitik",
"welcome_title": "Velkommen til nyt faneblad",
"welcome_body": "Firefox vil bruge denne plads til at vise dine mest relevante bogmærker, artikler, videoer og sider, du har besøgt for nylig - så kan du nemmere finde dem.",
"welcome_label": "Finder dine højdepunkter",
"welcome_label": "Finder dine vigtigste sider",
"time_label_less_than_minute": "<1 m.",
"time_label_minute": "{number} m.",
"time_label_hour": "{number} t.",
"time_label_day": "{number} d.",
"settings_pane_button_label": "Tilpas siden Nyt faneblad",
"settings_pane_header": "Indstillinger for Nyt faneblad",
"settings_pane_body2": "Vælg, hvad du vil se på denne side.",
"settings_pane_search_header": "Søgning",
"settings_pane_search_body": "Søg på nettet fra Nyt faneblad.",
"settings_pane_topsites_header": "Mest besøgte websider",
@@ -1050,6 +1201,12 @@
"settings_pane_bookmarks_body": "Dine seneste bogmærker samlet ét sted.",
"settings_pane_visit_again_header": "Besøg igen",
"settings_pane_visit_again_body": "Firefox viser dig dele af din browserhistorik, som du måske vil huske på eller vende tilbage til.",
"settings_pane_highlights_header": "Fremhævede",
"settings_pane_highlights_body2": "Find tilbage til interessant indhold, du har besøgt eller gemt et bogmærke til for nylig.",
"settings_pane_highlights_options_bookmarks": "Bogmærker",
"settings_pane_highlights_options_visited": "Besøgte websider",
"settings_pane_snippets_header": "Notitser",
"settings_pane_snippets_body": "Læs korte opdateringer fra Mozilla om Firefox, internet-kultur og lidt underholdning fra tid til anden.",
"settings_pane_done_button": "Færdig",
"edit_topsites_button_text": "Rediger",
"edit_topsites_button_label": "Tilpas afsnittet Mest besøgte websider",
@@ -1072,7 +1229,10 @@
"pocket_read_more": "Populære emner:",
"pocket_read_even_more": "Se flere historier",
"pocket_feedback_header": "Det bedste fra nettet, udvalgt af mere end 25 millioner mennesker.",
"pocket_description": "Opdag indhold af høj kvalitet, som du måske ellers ikke ville have opdaget. Indholdet kommer fra Pocket, der nu er en del af Mozilla.",
"highlights_empty_state": "Gå i gang med at browse, så vil vi vise dig nogle af de artikler, videoer og andre sider, du har besøgt eller gemt et bogmærke til for nylig.",
"topstories_empty_state": "Der er ikke flere nye historier. Kom tilbage senere for at se flere tophistorier fra {provider}. Kan du ikke vente? Vælg et populært emne og find flere spændende historier fra hele verden.",
"manual_migration_explanation2": "Prøv Firefox med bogmærkerne, historikken og adgangskoderne fra en anden browser.",
"manual_migration_cancel_button": "Nej tak",
"manual_migration_import_button": "Importer nu"
},
@@ -2404,7 +2564,7 @@
"time_label_day": "{number} j",
"settings_pane_button_label": "Personnaliser la page Nouvel onglet",
"settings_pane_header": "Préférences Nouvel onglet",
"settings_pane_body2": "Choisissez les éléments à afficher sur cette page.",
"settings_pane_body2": "Choisissez les éléments à afficher sur la page.",
"settings_pane_search_header": "Recherche",
"settings_pane_search_body": "Effectuez une recherche sur le Web depuis le nouvel onglet.",
"settings_pane_topsites_header": "Sites les plus visités",
@@ -3285,19 +3445,19 @@
"header_stories": "Historias popular",
"header_highlights": "In evidentia",
"header_visit_again": "Visita de novo",
"header_bookmarks": "Paginas marcate recentemente",
"header_bookmarks": "Marcapaginas recente",
"header_recommended_by": "Recommendate per {provider}",
"header_bookmarks_placeholder": "Tu ha ancora nulle paginas marcate.",
"header_bookmarks_placeholder": "Tu ha ancora nulle marcapaginas.",
"header_stories_from": "de",
"type_label_visited": "Visitate",
"type_label_bookmarked": "Marcate",
"type_label_bookmarked": "Marcapaginas addite",
"type_label_synced": "Synchronisate de altere apparato",
"type_label_recommended": "Tendentias",
"type_label_open": "Aperite",
"type_label_topic": "Subjecto",
"type_label_now": "Ora",
"menu_action_bookmark": "Marcar le pagina",
"menu_action_remove_bookmark": "Dismarcar le pagina",
"menu_action_bookmark": "Adder marcapaginas",
"menu_action_remove_bookmark": "Remover le marcapaginas",
"menu_action_copy_address": "Copiar le adresse",
"menu_action_email_link": "Inviar le ligamine per email…",
"menu_action_open_new_window": "Aperir in un nove fenestra",
@@ -3318,7 +3478,7 @@
"section_info_send_feedback": "Inviar feedback",
"section_info_privacy_notice": "Advertentia de privacitate",
"welcome_title": "Benvenite al nove scheda",
"welcome_body": "Firefox usara iste spatio pro monstrar tu paginas marcate le plus relevante, articulos, videos e paginas que tu ha visitate recentemente, de sorta que tu pote revider los facilemente.",
"welcome_body": "Firefox usara iste spatio pro monstrar tu marcapaginas le plus relevante, articulos, videos e paginas que tu ha visitate recentemente, de sorta que tu pote revider los facilemente.",
"welcome_label": "Identificante tu evidentias",
"time_label_less_than_minute": "<1 min",
"time_label_minute": "{number} min",
@@ -3332,13 +3492,13 @@
"settings_pane_topsites_header": "Sitos popular",
"settings_pane_topsites_body": "Acceder al sitos web que tu plus visita.",
"settings_pane_topsites_options_showmore": "Monstrar duo lineas",
"settings_pane_bookmarks_header": "Paginas marcate recentemente",
"settings_pane_bookmarks_body": "Tu paginas marcate recentemente a un sol loco.",
"settings_pane_bookmarks_header": "Marcapaginas recente",
"settings_pane_bookmarks_body": "Tu marcapaginas le plus recente a un sol loco.",
"settings_pane_visit_again_header": "Visitar de novo",
"settings_pane_visit_again_body": "Firefox te monstrara partes de tu chronologia de navigation que tu pote voler rememorar o visitar novemente.",
"settings_pane_highlights_header": "In evidentia",
"settings_pane_highlights_body2": "Retrova cosas interessante que tu ha recentemente visitate o marcate.",
"settings_pane_highlights_options_bookmarks": "Paginas marcate",
"settings_pane_highlights_body2": "Retrova cosas interessante que tu ha recentemente visitate o addite marcapaginas.",
"settings_pane_highlights_options_bookmarks": "Marcapaginas",
"settings_pane_highlights_options_visited": "Sitos visitate",
"settings_pane_snippets_header": "Breve novas",
"settings_pane_snippets_body": "Lege breve e legier novas de Mozilla super Firefox, cultura internet e occasionalmente super alcun meme.",
@@ -3365,9 +3525,9 @@
"pocket_read_even_more": "Vider plus historias",
"pocket_feedback_header": "Le melior del web, selectionate per 25 milliones de personas.",
"pocket_description": "Discoperir contento de alte qualitate que tu poterea alteremente non cognoscer, con le adjuta de Pocket, ora parte de Mozilla.",
"highlights_empty_state": "Comencia navigar e nos te monstrara alcun del grande articulos, videos e altere paginas que tu ha recentemente visitate o marcate hic.",
"highlights_empty_state": "Comencia navigar e nos te monstrara alcun del grande articulos, videos e altere paginas que tu ha recentemente visitate o addite marcapaginas hic.",
"topstories_empty_state": "Tu ja es in die con toto. Reveni plus tarde pro plus historias popular de {provider}. Non vole attender? Selectiona un subjecto popular pro trovar plus altere historias interessante del web.",
"manual_migration_explanation2": "Essaya Firefox con le paginas marcate, le chronologia e le contrasignos de altere navigator.",
"manual_migration_explanation2": "Essaya Firefox con le marcapaginas, le chronologia e le contrasignos de un altere navigator.",
"manual_migration_cancel_button": "No, gratias",
"manual_migration_import_button": "Importar ora"
},
@@ -3655,7 +3815,7 @@
"default_label_loading": "იტვირთება…",
"header_top_sites": "რჩეული საიტები",
"header_stories": "რჩეული სტატიები",
"header_highlights": "მნიშველოვანი სიახლეები",
"header_highlights": "მნიშველოვანი საიტები",
"header_visit_again": "ხელახლა ნახვა",
"header_bookmarks": "ბოლოს ჩანიშნულები",
"header_recommended_by": "რეკომენდებულია {provider}-ის მიერ",
@@ -3691,7 +3851,7 @@
"section_info_privacy_notice": "პირადი მონაცემების დაცვა",
"welcome_title": "მოგესალმებით ახალ ჩანართზე",
"welcome_body": "Firefox ამ სივრცეს გამოიყენებს თქვენთვის ყველაზე საჭირო სანიშნეების, სტატიების, ვიდეოებისა და ბოლოს მონახულებული გვერდებისთვის, რომ ადვილად შეძლოთ მათზე დაბრუნება.",
"welcome_label": "რჩეული ვებგვერდების დადგენა",
"welcome_label": "მნიშვნელოვანი საიტების დადგენა",
"time_label_less_than_minute": "<1წთ",
"time_label_minute": "{number}წთ",
"time_label_hour": "{number}სთ",
@@ -3708,8 +3868,8 @@
"settings_pane_bookmarks_body": "ახლად შექმნილი სანიშნეები, ერთი ხელის გაწვდენაზე.",
"settings_pane_visit_again_header": "ხელახლა ნახვა",
"settings_pane_visit_again_body": "Firefox გაჩვენებთ მონახულებული გვერდების ისტორიიდან იმას, რისი გახსენებაც ან რაზე დაბრუნებაც გენდომებათ.",
"settings_pane_highlights_header": "მნიშველოვანი სიახლეები",
"settings_pane_highlights_body2": "მარტივად დაუბრუნდით ბოლოს მონახულებულ, ან ჩანიშნულ საიტებს.",
"settings_pane_highlights_header": "მნიშველოვანი საიტები",
"settings_pane_highlights_body2": "მარტივად დაუბრუნდით ბოლოს მონახულებულ, ან ჩანიშნულ გვერდებს.",
"settings_pane_highlights_options_bookmarks": "სანიშნეები",
"settings_pane_highlights_options_visited": "მონახულებული საიტები",
"settings_pane_snippets_header": "ცნობები",
@@ -3717,8 +3877,8 @@
"settings_pane_done_button": "მზადაა",
"edit_topsites_button_text": "ჩასწორება",
"edit_topsites_button_label": "მოირგეთ რჩეული საიტების განყოფილება",
"edit_topsites_showmore_button": "მეტის ჩვენება",
"edit_topsites_showless_button": "ნაკლების ჩვენება",
"edit_topsites_showmore_button": "მეტის გამოჩენა",
"edit_topsites_showless_button": "ნაკლების გამოჩენა",
"edit_topsites_done_button": "მზადაა",
"edit_topsites_pin_button": "საიტის მიმაგრება",
"edit_topsites_unpin_button": "მიმაგრების მოხსნა",
@@ -4308,7 +4468,7 @@
"settings_pane_body2": "Изберете што ќе гледате на оваа страница.",
"settings_pane_search_header": "Пребарување",
"settings_pane_search_body": "Пребарајте низ Интернет од вашето ново јазиче.",
"settings_pane_topsites_header": "Врвни мрежни места",
"settings_pane_topsites_header": "Популарни мрежни места",
"settings_pane_topsites_body": "Пристапете до мрежните места што ги посетувате најмногу.",
"settings_pane_topsites_options_showmore": "Прикажи два реда",
"settings_pane_bookmarks_header": "Скорешни обележувачи",
@@ -4354,8 +4514,11 @@
"newtab_page_title": "പുതിയ ടാബ്",
"default_label_loading": "ലോഡ്ചെയ്യുന്നു…",
"header_top_sites": "മികച്ച സൈറ്റുകൾ",
"header_highlights": "ഹൈലൈറ്റുകൾ",
"header_stories": "മികച്ച ലേഖനങ്ങൾ",
"header_highlights": "ഹൈലൈറ്റുകൾ",
"header_visit_again": "വീണ്ടും സന്ദർശിക്കുക",
"header_bookmarks": "അടുത്തിടെയുള്ള ബുക്ക്മാർക്കുകൾ",
"header_bookmarks_placeholder": "നിങ്ങൾക്ക് ഇതുവരെ ബുക്ക്മാർക്കുകൾ ഇല്ല.",
"header_stories_from": "എവിടെ നിന്നും",
"type_label_visited": "സന്ദർശിച്ചത്‌",
"type_label_bookmarked": "അടയാളപ്പെടുത്തിയത്",
@@ -4363,6 +4526,7 @@
"type_label_recommended": "ട്രെൻഡിംഗ്",
"type_label_open": "തുറക്കുക",
"type_label_topic": "വിഷയം",
"type_label_now": "ഇപ്പോൾ",
"menu_action_bookmark": "അടയാളം",
"menu_action_remove_bookmark": "അടയാളം മാറ്റുക",
"menu_action_copy_address": "വിലാസം പകർത്തുക",
@@ -4371,12 +4535,17 @@
"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_term} : എന്നത് ഉപയോഗിയ്ക്കുക",
"search_button": "തിരയുക",
"search_header": "{search_engine_name} തിരയുക",
"search_web_placeholder": "ഇൻറർനെറ്റിൽ തിരയുക",
"search_settings": "തിരയാനുള്ള രീതികൾ മാറ്റുക",
"section_info_option": "വിവരം",
"welcome_title": "പുതിയ ജാലകത്തിലേക്കു സ്വാഗതം",
"welcome_body": "നിങ്ങളുടെ ഏറ്റവും ശ്രദ്ധേയമായ അടയാളങ്ങൾ, ലേഖനങ്ങൾ, വീഡിയോകൾ, കൂടാതെ നിങ്ങൾ സമീപകാലത്ത് സന്ദർശിച്ച താളുകൾ എന്നിവ കാണിക്കുന്നതിനായി ഫയർഫോക്സ് ഈ ഇടം ഉപയോഗിക്കും, അതിനാൽ നിങ്ങൾക്ക് എളുപ്പത്തിൽ അവയിലേക്ക് തിരിച്ചു പോകാം.",
"welcome_label": "താങ്കളുടെ ഹൈലൈറ്റ്സ് തിരിച്ചറിയുന്നു",
@@ -4386,16 +4555,15 @@
"time_label_day": "{number} മിനിറ്റ്",
"settings_pane_button_label": "നിങ്ങളുടെ പുതിയ ടാബ് താള് ഇഷ്ടാനുസൃതമാക്കുക",
"settings_pane_header": "പുതിയ ടാബിന്റെ മുൻഗണനകൾ",
"settings_pane_body": "പുതിയ ടാബ് തുറക്കുമ്പോൾ എന്ത് കാണണമെന്ന് തീരുമാനിക്കുക.",
"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_highlights_header": "ഹൈലൈറ്റുകൾ",
"settings_pane_highlights_body": "നിങ്ങളുടെ സമീപകാല ബ്രൗസിംഗ് ചരിത്രവും പുതുതായി സൃഷ്ടിച്ച അടയാളങ്ങളും കാണുക.",
"settings_pane_pocketstories_header": "മികച്ച ലേഖനങ്ങൾ",
"settings_pane_pocketstories_body": "മോസില്ല‌ കുടുംബാംഗമായ പോക്കറ്റ്, വിട്ടുപോയേയ്ക്കാവുന്ന മികച്ച ലേഖനങ്ങൾ നിങ്ങളുടെ ശ്രദ്ധയിൽ എത്തിയ്ക്കുന്നു.",
"settings_pane_done_button": "തീർന്നു",
"edit_topsites_button_text": "തിരുത്തുക",
"edit_topsites_button_label": "നിങ്ങളുടെ മുന്നേറിയ സൈറ്റുകളുടെ വിഭാഗം ഇഷ്ടാനുസൃതമാക്കുക",
@@ -4418,8 +4586,8 @@
"pocket_read_more": "ജനപ്രിയ വിഷയങ്ങൾ:",
"pocket_read_even_more": "കൂടുതൽ ലേഖനങ്ങൾ കാണുക",
"pocket_feedback_header": "250 ലക്ഷം പേരാൽ തെരഞ്ഞെടുക്കപ്പെട്ട വെബിലെ ഏറ്റവും മികച്ചവയാണിവ.",
"pocket_feedback_body": "മോസില്ല‌ കുടുംബാംഗമായ പോക്കറ്റ്, വിട്ടുപോയേയ്ക്കാവുന്ന മികച്ച ലേഖനങ്ങൾ നിങ്ങളുടെ ശ്രദ്ധയിൽ എത്തിയ്ക്കുന്നു.",
"pocket_send_feedback": "പ്രതികരണം അയയ്ക്കുക"
"manual_migration_cancel_button": "വേണ്ട, നന്ദി",
"manual_migration_import_button": "പ്പോൾ ഇറക്കുമതി ചെയ്യുക"
},
"mr": {
"newtab_page_title": "नवीन टॅब",
@@ -4555,12 +4723,20 @@
"newtab_page_title": "တပ်ဗ်အသစ်ဖွင့်",
"default_label_loading": "ရယူနေသှ်…",
"header_top_sites": "အများဆုံးသုံးဆိုက်များ",
"header_highlights": "အသားပေးဖော်ပြချက်များ",
"header_stories": "အကြည့်အများဆုံးသတင်းများ",
"header_highlights": "ဦးစားပေးအကြောင်းအရာများ",
"header_visit_again": "ထပ်မံလည်ပတ်ရန်",
"header_bookmarks": "လတ်တလော စာမှတ်များ",
"header_recommended_by": "{provider} က အကြံပြုထားသည်",
"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": "လိပ်စာအားကူးယူပါ",
@@ -4569,11 +4745,19 @@
"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": "Pocket သို့ သိမ်းရန်",
"search_for_something_with": "{search_term} အားရှာပါ -",
"search_button": "ရှာ",
"search_header": "{search_engine_name} ရှာဖွေမှု",
"search_web_placeholder": "ဝတ်ဘ်ပေါ်တွင် ရှာဖွေခြင်း",
"search_settings": "ရှာဖွေမှုအပြင်အဆင်အားပြောင်းလဲပါ",
"section_info_option": "အချက်အလက်",
"section_info_send_feedback": "အကြံပေးချက် ပေးပို့ရန်",
"section_info_privacy_notice": "ကိုယ်ရေးကာကွယ်မှု သတိပေးချက်",
"welcome_title": "တပ်ဗ်အသစ်တစ်ခုမှကြိုဆိုပါတယ်",
"welcome_body": "ယခုနေရာအား Firefox မှ အသင့်လျော်ဆုံး သင်သွားလည်ခဲ့ဖူးသော စာအမှတ်များ၊ ဆောင်းပါးများ၊ ရုပ်ရှင်များ နှင့် စာမျက်နှာများအား ပြသဖို့အသုံးပြုမည်ဖြစ်ပါတယ်။",
"welcome_label": "သင့် အသားပေးဖော်ပြချက်များကိုသတိထားမည်",
@@ -4583,14 +4767,21 @@
"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": "ထိပ်တန်းဝတ်ဘ်ဆိုက်များ",
"settings_pane_topsites_body": "သင်အများဆုံးသွားလည်သော ဝတ်ဘ်ဆိုက်များကို ရယူပါ",
"settings_pane_topsites_options_showmore": "အတန်းနှစ်တန်းနှင့်ပြပါ",
"settings_pane_highlights_header": "အသားပေးဖော်ပြချက်များ",
"settings_pane_highlights_body": "သင်လတ်တလောသွားလည်ထားသော မှတ်တမ်းနှင့် အသစ်ဖန်တီးထားသော စာအမှတ်များအား ပြန်ကြည့်ပါ",
"settings_pane_bookmarks_header": "လတ်တလော စာမှတ်များ",
"settings_pane_bookmarks_body": "အသစ်မှတ်သားထားသော စာမှတ်များကို တစ်နေရာတည်းတွင် စုစည်းထားသည်။",
"settings_pane_visit_again_header": "ထပ်မံလည်ပတ်ရန်",
"settings_pane_visit_again_body": "မှတ်ထားလိုသော သို့မဟုတ် ပြန်ဖွင့်လိုသော လည်ပတ်မှတ်တမ်းထဲမှ တချို့ကို Firefox က ပြပါမည်။",
"settings_pane_highlights_header": "ဦးစားပေးအကြောင်းအရာများ",
"settings_pane_highlights_options_bookmarks": "စာမှတ်များ",
"settings_pane_highlights_options_visited": "လည်ပတ်ထားသော ဆိုက်များ",
"settings_pane_snippets_header": "မှတ်စုတိုများ",
"settings_pane_snippets_body": "Mozilla မှ Firefox အကြောင်း၊ အင်တာနက်ယဉ်ကျေးမှုနှင့် အခါအားလျော်စွာ ဖြစ်ပေါ်လာသော ကျပန်း meme စသည့် နောက်ဆုံးရသတင်းများကို ဖတ်ရှုပါ။",
"settings_pane_done_button": "ပြီးပြီ",
"edit_topsites_button_text": "ပြင်ဆင်မည်",
"edit_topsites_button_label": "သင့်ထိပ်တန်းဆိုက် အမြင်အားပြင်ဆင်ပါ",
@@ -4598,8 +4789,23 @@
"edit_topsites_showless_button": "ချုံ့ပြရန်",
"edit_topsites_done_button": "ပြီးပြီ",
"edit_topsites_pin_button": "တ်ဆိုဒ်အားpinလုပ်ထားမည်",
"edit_topsites_unpin_button": "ယခုဆိုက်ကို တွယ်ဖြုတ်ရန်",
"edit_topsites_edit_button": "ဆိုက်အားပြင်မည်",
"edit_topsites_dismiss_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": "URL ကို ရိုက်ပါ သို့မဟုတ် ပွားထည့်ပါ",
"topsites_form_add_button": "ထည့်ရန်",
"topsites_form_save_button": "သိမ်းရန်",
"topsites_form_cancel_button": "မလုပ်တော့ပါ",
"topsites_form_url_validation": "URL အမှန် လိုအပ်သည်",
"pocket_read_more": "လူကြိုက်များခေါင်းစဉ်များ",
"pocket_read_even_more": "နောက်ထပ်သတင်းများ ကြည့်ရန်",
"manual_migration_explanation2": "အခြားဘရောင်ဇာမှ စာမှတ်များ၊ မှတ်တမ်းများ၊ စကားဝှက်များနှင့်အတူ Firefox တွင် စမ်းသုံးကြည့်ပါ။",
"manual_migration_cancel_button": "မလိုတော့ပါ၊ ကျေးဇူးတင်ပါသည်။",
"manual_migration_import_button": "ထည့်သွင်းရန်"
},
"nb-NO": {
"newtab_page_title": "Ny fane",
@@ -4742,6 +4948,7 @@
"time_label_day": "{number} दिन",
"settings_pane_button_label": "तपाईंको नयाँ ट्याब पृष्ठ अनुकूलन गर्नुहोस्",
"settings_pane_header": "नयाँ ट्याब प्राथमिकताहरू",
"settings_pane_body2": "तपाईँले यो पृष्ठमा के देख्नुभयो छनौट गर्नुहोस् ।",
"settings_pane_search_header": "खोजी गर्नुहोस्",
"settings_pane_search_body": "तपाईंको नयाँ ट्याबबाट वेबमा खोज्नुहोस् ।",
"settings_pane_topsites_header": "शीर्ष साइटहरू",
@@ -6220,10 +6427,13 @@
"settings_pane_bookmarks_header": "ที่คั่นหน้าล่าสุด",
"settings_pane_bookmarks_body": "ที่คั่นหน้าที่สร้างใหม่ของคุณในตำแหน่งที่ตั้งเดียวที่สะดวก",
"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": "ปรับแต่งส่วนไซต์เด่นของคุณ",
@@ -6246,7 +6456,9 @@
"pocket_read_more": "หัวข้อยอดนิยม:",
"pocket_read_even_more": "ดูเรื่องราวเพิ่มเติม",
"pocket_feedback_header": "ที่สุดของเว็บ จัดรายการโดยผู้คนกว่า 25 ล้านคน",
"highlights_empty_state": "เริ่มการท่องเว็บและเราจะแสดงบทความ, วิดีโอ และหน้าอื่น ๆ บางส่วนที่ยอดเยี่ยมที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้เมื่อเร็ว ๆ นี้ที่นี่",
"pocket_description": "ค้นพบเนื้อหาคุณภาพสูงที่คุณอาจจะพลาดไปด้วยความช่วยเหลือจาก Pocket ซึ่งขณะนี้เป็นส่วนหนึ่งของ Mozilla",
"highlights_empty_state": "เริ่มการท่องเว็บและเราจะแสดงบทความ, วิดีโอ และหน้าอื่น ๆ บางส่วนที่ยอดเยี่ยมที่คุณได้เยี่ยมชมหรือเพิ่มที่คั่นหน้าไว้ล่าสุดที่นี่",
"topstories_empty_state": "คุณได้อ่านเรื่องราวครบทั้งหมดแล้ว คุณสามารถกลับมาตรวจดูเรื่องราวเด่นจาก {provider} ได้ภายหลัง อดใจรอไม่ได้งั้นหรือ? เลือกหัวข้อยอดนิยมเพื่อค้นหาเรื่องราวที่ยอดเยี่ยมจากเว็บต่าง ๆ",
"manual_migration_explanation2": "ลอง Firefox ด้วยที่คั่นหน้า, ประวัติ และรหัสผ่านจากเบราว์เซอร์อื่น",
"manual_migration_cancel_button": "ไม่ ขอบคุณ",
"manual_migration_import_button": "นำเข้าตอนนี้"

View File

@@ -8,7 +8,7 @@
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<em:version>2017.10.05.1066-43726d35</em:version>
<em:version>2017.10.06.1105-fbbf9d84</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>

View File

@@ -90,13 +90,17 @@ const PREFS_CONFIG = new Map([
value: true
}],
["showSearch", {
title: "Show the Search bar on the New Tab page",
title: "Show the Search bar",
value: true
}],
["showTopSites", {
title: "Show the Top Sites section on the New Tab page",
title: "Show the Top Sites section",
value: true
}],
["collapseTopSites", {
title: "Collapse the Top Sites section",
value: false
}],
["topSitesCount", {
title: "Number of Top Sites to display",
value: 6
@@ -121,6 +125,14 @@ const PREFS_CONFIG = new Map([
["telemetry.ping.endpoint", {
title: "Telemetry server endpoint",
value: "https://tiles.services.mozilla.com/v4/links/activity-stream"
}],
["section.highlights.collapsed", {
title: "Collapse the Highlights section",
value: false
}],
["section.topstories.collapsed", {
title: "Collapse the Top Stories section",
value: false
}]
]);

View File

@@ -33,15 +33,7 @@ this.HighlightsFeed = class HighlightsFeed {
this.highlightsLength = 0;
this.dedupe = new Dedupe(this._dedupeKey);
this.linksCache = new LinksCache(NewTabUtils.activityStreamLinks,
"getHighlights", (oldLink, newLink) => {
// Migrate any pending images or images to the new link
for (const property of ["__fetchingScreenshot", "image"]) {
const oldValue = oldLink[property];
if (oldValue) {
newLink[property] = oldValue;
}
}
});
"getHighlights", ["image"]);
}
_dedupeKey(site) {
@@ -117,9 +109,8 @@ this.HighlightsFeed = class HighlightsFeed {
highlights.push(page);
hosts.add(hostname);
// Remove any internal properties
delete page.__fetchingScreenshot;
delete page.__updateCache;
// Remove internal properties that might be updated after dispatch
delete page.__sharedCache;
// Skip the rest if we have enough items
if (highlights.length === HIGHLIGHTS_MAX_LENGTH) {
@@ -139,7 +130,7 @@ this.HighlightsFeed = class HighlightsFeed {
async fetchImage(page) {
// Request a screenshot if we don't already have one pending
const {preview_image_url: imageUrl, url} = page;
Screenshots.maybeGetAndSetScreenshot(page, imageUrl || url, "image", image => {
Screenshots.maybeCacheScreenshot(page, imageUrl || url, "image", image => {
SectionsManager.updateSectionCard(SECTION_ID, url, {image}, true);
});
}

View File

@@ -19,19 +19,21 @@ this.LinksCache = class LinksCache {
*
* @param {object} linkObject Object containing the link property
* @param {string} linkProperty Name of property on object to access
* @param {function} migrator Optional callback receiving the old and new link
* to allow custom migrating data from old to new.
* @param {array} properties Optional properties list to migrate to new links.
* @param {function} shouldRefresh Optional callback receiving the old and new
* options to refresh even when not expired.
*/
constructor(linkObject, linkProperty, migrator = () => {}, shouldRefresh = () => {}) {
constructor(linkObject, linkProperty, properties = [], shouldRefresh = () => {}) {
this.clear();
// Allow getting links from both methods and array properties
this.linkGetter = options => {
const ret = linkObject[linkProperty];
return typeof ret === "function" ? ret.call(linkObject, options) : ret;
};
this.migrator = migrator;
// Always migrate the shared cache data in addition to any custom properties
this.migrateProperties = ["__sharedCache", ...properties];
this.shouldRefresh = shouldRefresh;
}
@@ -78,37 +80,38 @@ this.LinksCache = class LinksCache {
}
}
// Make a shallow copy of each resulting link to allow direct edits
const copied = (await this.linkGetter(options)).map(link => link &&
Object.assign({}, link));
// Update the cache with migrated links without modifying source objects
resolve((await this.linkGetter(options)).map(link => {
// Keep original array hole positions
if (!link) {
return link;
}
// Migrate data to the new link if we have an old link
for (const newLink of copied) {
if (newLink) {
const oldLink = toMigrate.get(newLink.url);
if (oldLink) {
this.migrator(oldLink, newLink);
// Migrate data to the new link copy if we have an old link
const newLink = Object.assign({}, link);
const oldLink = toMigrate.get(newLink.url);
if (oldLink) {
for (const property of this.migrateProperties) {
const oldValue = oldLink[property];
if (oldValue) {
newLink[property] = oldValue;
}
}
// Add a method that can be copied to cloned links that will update
// the original cached link's property with the current one
newLink.__updateCache = function(prop) {
const val = this[prop];
if (val === undefined) {
delete newLink[prop];
} else {
newLink[prop] = val;
} else {
// Share data among link copies and new links from future requests
newLink.__sharedCache = {
// Provide a helper to update the cached link
updateLink(property, value) {
newLink[property] = value;
}
};
}
}
// Update cache with the copied links migrated
resolve(copied);
return newLink;
}));
});
}
// Return the promise of the links array
return this.cache;
// Provide a shallow copy of the cached link objects for callers to modify
return (await this.cache).map(link => link && Object.assign({}, link));
}
};

View File

@@ -65,36 +65,31 @@ this.Screenshots = {
/**
* Conditionally get a screenshot for a link if there's no existing pending
* screenshot. Updates the link object's desired property with the result.
* screenshot. Updates the cached link's desired property with the result.
*
* @param link {object} Link object to update
* @param url {string} Url to get a screenshot of
* @param property {string} Name of property on object to set
@ @param onScreenshot {function} Callback for when the screenshot loads
*/
async maybeGetAndSetScreenshot(link, url, property, onScreenshot) {
// Make a link copy so we can stash internal properties to cache
const updateCache = link.__updateCache ? link.__updateCache.bind(link) :
() => {};
// Request a screenshot if we don't already have one pending
if (!link.__fetchingScreenshot) {
link.__fetchingScreenshot = this.getScreenshotForURL(url);
updateCache("__fetchingScreenshot");
// Trigger this callback only when first requesting
link.__fetchingScreenshot.then(onScreenshot).catch();
async maybeCacheScreenshot(link, url, property, onScreenshot) {
// Nothing to do if we already have a pending screenshot
const cache = link.__sharedCache;
if (cache.fetchingScreenshot) {
return;
}
// Clean up now that we got the screenshot
const screenshot = await link.__fetchingScreenshot;
delete link.__fetchingScreenshot;
updateCache("__fetchingScreenshot");
// Save the promise to the cache so other links get it immediately
cache.fetchingScreenshot = this.getScreenshotForURL(url);
// Update the link so the screenshot is in the cache
// Clean up now that we got the screenshot
const screenshot = await cache.fetchingScreenshot;
delete cache.fetchingScreenshot;
// Update the cache for future links and call back for existing content
if (screenshot) {
link[property] = screenshot;
updateCache(property);
cache.updateLink(property, screenshot);
onScreenshot(screenshot);
}
}
};

View File

@@ -21,7 +21,7 @@ const BUILT_IN_SECTIONS = {
titleString: {id: "header_recommended_by", values: {provider: options.provider_name}},
descString: {id: options.provider_description || "pocket_feedback_body"}
},
shouldHidePref: options.hidden,
shouldHidePref: options.hidden,
eventSource: "TOP_STORIES",
icon: options.provider_icon,
title: {id: "header_recommended_by", values: {provider: options.provider_name}},

View File

@@ -28,7 +28,9 @@ const ACTIVITY_STREAM_ENDPOINT_PREF = "browser.newtabpage.activity-stream.teleme
const USER_PREFS_ENCODING = {
"showSearch": 1 << 0,
"showTopSites": 1 << 1,
"feeds.section.topstories": 1 << 2
"feeds.section.topstories": 1 << 2,
"feeds.section.highlights": 1 << 3,
"feeds.snippets": 1 << 4
};
const IMPRESSION_STATS_RESET_TIME = 60 * 60 * 1000; // 60 minutes

View File

@@ -33,11 +33,11 @@ this.TopSitesFeed = class TopSitesFeed {
this._tippyTopProvider = new TippyTopProvider();
this.dedupe = new Dedupe(this._dedupeKey);
this.frecentCache = new LinksCache(NewTabUtils.activityStreamLinks,
"getTopSites", this.getLinkMigrator(), (oldOptions, newOptions) =>
"getTopSites", ["screenshot"], (oldOptions, newOptions) =>
// Refresh if no old options or requesting more items
!(oldOptions.numItems >= newOptions.numItems));
this.pinnedCache = new LinksCache(NewTabUtils.pinnedLinks,
"links", this.getLinkMigrator(["favicon", "faviconSize"]));
this.pinnedCache = new LinksCache(NewTabUtils.pinnedLinks, "links",
["favicon", "faviconSize", "screenshot"]);
}
_dedupeKey(site) {
return site && site.hostname;
@@ -59,22 +59,6 @@ this.TopSitesFeed = class TopSitesFeed {
}
}
/**
* Make a cached link data migrator by copying over screenshots and others.
*
* @param others {array} Optional extra properties to copy
*/
getLinkMigrator(others = []) {
const properties = ["__fetchingScreenshot", "screenshot", ...others];
return (oldLink, newLink) => {
for (const property of properties) {
const oldValue = oldLink[property];
if (oldValue) {
newLink[property] = oldValue;
}
}
};
}
async getLinksWithDefaults(action) {
// Get at least SHOWMORE amount so toggling between 1 and 2 rows has sites
const numItems = Math.max(this.store.getState().Prefs.values.topSitesCount,
@@ -107,8 +91,8 @@ this.TopSitesFeed = class TopSitesFeed {
try {
NewTabUtils.activityStreamProvider._faviconBytesToDataURI(await
NewTabUtils.activityStreamProvider._addFavicons([copy]));
copy.__updateCache("favicon");
copy.__updateCache("faviconSize");
copy.__sharedCache.updateLink("favicon", copy.favicon);
copy.__sharedCache.updateLink("faviconSize", copy.faviconSize);
} catch (e) {
// Some issue with favicon, so just continue without one
}
@@ -134,9 +118,8 @@ this.TopSitesFeed = class TopSitesFeed {
if (link) {
this._fetchIcon(link);
// Remove any internal properties
delete link.__fetchingScreenshot;
delete link.__updateCache;
// Remove internal properties that might be updated after dispatch
delete link.__sharedCache;
}
}
@@ -176,12 +159,11 @@ this.TopSitesFeed = class TopSitesFeed {
(!link.favicon || link.faviconSize < MIN_FAVICON_SIZE) &&
!link.screenshot) {
const {url} = link;
Screenshots.maybeGetAndSetScreenshot(link, url, "screenshot", screenshot => {
this.store.dispatch(ac.BroadcastToContent({
await Screenshots.maybeCacheScreenshot(link, url, "screenshot",
screenshot => this.store.dispatch(ac.BroadcastToContent({
data: {screenshot, url},
type: at.SCREENSHOT_UPDATED
}));
});
})));
}
}
@@ -264,11 +246,15 @@ this.TopSitesFeed = class TopSitesFeed {
// All these actions mean we need new top sites
case at.MIGRATION_COMPLETED:
case at.PLACES_HISTORY_CLEARED:
case at.PLACES_LINK_BLOCKED:
case at.PLACES_LINKS_DELETED:
this.frecentCache.expire();
this.refresh();
break;
case at.PLACES_LINK_BLOCKED:
this.frecentCache.expire();
this.pinnedCache.expire();
this.refresh();
break;
case at.PREF_CHANGED:
if (action.data.name === DEFAULT_SITES_PREF) {
this.refreshDefaults(action.data.value);

View File

@@ -42,7 +42,7 @@ describe("Highlights Feed", () => {
};
fakeScreenshot = {
getScreenshotForURL: sandbox.spy(() => Promise.resolve(FAKE_IMAGE)),
maybeGetAndSetScreenshot: Screenshots.maybeGetAndSetScreenshot
maybeCacheScreenshot: Screenshots.maybeCacheScreenshot
};
filterAdultStub = sinon.stub().returns([]);
shortURLStub = sinon.stub().callsFake(site => site.url.match(/\/([^/]+)/)[1]);
@@ -215,8 +215,12 @@ describe("Highlights Feed", () => {
describe("#fetchImage", () => {
const FAKE_URL = "https://mozilla.org";
const FAKE_IMAGE_URL = "https://mozilla.org/preview.jpg";
function fetchImage(page) {
return feed.fetchImage(Object.assign({__sharedCache: {updateLink() {}}},
page));
}
it("should capture the image, if available", async () => {
await feed.fetchImage({
await fetchImage({
preview_image_url: FAKE_IMAGE_URL,
url: FAKE_URL
});
@@ -225,13 +229,13 @@ describe("Highlights Feed", () => {
assert.calledWith(fakeScreenshot.getScreenshotForURL, FAKE_IMAGE_URL);
});
it("should fall back to capturing a screenshot", async () => {
await feed.fetchImage({url: FAKE_URL});
await fetchImage({url: FAKE_URL});
assert.calledOnce(fakeScreenshot.getScreenshotForURL);
assert.calledWith(fakeScreenshot.getScreenshotForURL, FAKE_URL);
});
it("should call SectionsManager.updateSectionCard with the right arguments", async () => {
await feed.fetchImage({
await fetchImage({
preview_image_url: FAKE_IMAGE_URL,
url: FAKE_URL
});
@@ -239,7 +243,7 @@ describe("Highlights Feed", () => {
assert.calledOnce(sectionsManagerStub.updateSectionCard);
assert.calledWith(sectionsManagerStub.updateSectionCard, "highlights", FAKE_URL, {image: FAKE_IMAGE}, true);
});
it("should update the card with the image", async () => {
it("should not update the card with the image", async () => {
const card = {
preview_image_url: FAKE_IMAGE_URL,
url: FAKE_URL
@@ -247,7 +251,7 @@ describe("Highlights Feed", () => {
await feed.fetchImage(card);
assert.propertyVal(card, "image", FAKE_IMAGE);
assert.notProperty(card, "image");
});
});
describe("#uninit", () => {

View File

@@ -3,7 +3,6 @@ const injector = require("inject!lib/TopSitesFeed.jsm");
const {Screenshots} = require("lib/Screenshots.jsm");
const {UPDATE_TIME} = require("lib/TopSitesFeed.jsm");
const {FakePrefs, GlobalOverrider} = require("test/unit/utils");
const action = {meta: {fromTarget: {}}};
const {actionTypes: at} = require("common/Actions.jsm");
const {insertPinned, TOP_SITES_SHOWMORE_LENGTH} = require("common/Reducers.jsm");
@@ -61,7 +60,7 @@ describe("Top Sites Feed", () => {
};
fakeScreenshot = {
getScreenshotForURL: sandbox.spy(() => Promise.resolve(FAKE_SCREENSHOT)),
maybeGetAndSetScreenshot: Screenshots.maybeGetAndSetScreenshot
maybeCacheScreenshot: Screenshots.maybeCacheScreenshot
};
filterAdultStub = sinon.stub().returns([]);
shortURLStub = sinon.stub().callsFake(site => site.url);
@@ -95,6 +94,10 @@ describe("Top Sites Feed", () => {
clock.restore();
});
function stubFaviconsToUseScreenshots() {
fakeNewTabUtils.activityStreamProvider._addFavicons = sandbox.stub();
}
describe("#refreshDefaults", () => {
it("should add defaults on PREFS_INITIAL_VALUES", () => {
feed.onAction({type: at.PREFS_INITIAL_VALUES, data: {"default.sites": "https://foo.com"}});
@@ -136,7 +139,7 @@ describe("Top Sites Feed", () => {
describe("general", () => {
beforeEach(() => {
sandbox.stub(fakeScreenshot, "maybeGetAndSetScreenshot");
sandbox.stub(fakeScreenshot, "maybeCacheScreenshot");
});
it("should get the links from NewTabUtils", async () => {
const result = await feed.getLinksWithDefaults();
@@ -214,7 +217,7 @@ describe("Top Sites Feed", () => {
it("should not throw if NewTabUtils returns null", () => {
links = null;
assert.doesNotThrow(() => {
feed.getLinksWithDefaults(action);
feed.getLinksWithDefaults();
});
});
it("should get more if the user has asked for more", async () => {
@@ -241,8 +244,7 @@ describe("Top Sites Feed", () => {
assert.calledTwice(global.NewTabUtils.activityStreamLinks.getTopSites);
});
it("should migrate frecent screenshot data without getting screenshots again", async () => {
// Don't add favicons so we fall back to screenshots
fakeNewTabUtils.activityStreamProvider._addFavicons = sandbox.stub();
stubFaviconsToUseScreenshots();
await feed.getLinksWithDefaults();
const {callCount} = fakeScreenshot.getScreenshotForURL;
feed.frecentCache.expire();
@@ -271,6 +273,36 @@ describe("Top Sites Feed", () => {
const internal = Object.keys(result[0]).filter(key => key.startsWith("__"));
assert.equal(internal.join(""), "");
});
describe("concurrency", () => {
let resolvers;
beforeEach(() => {
stubFaviconsToUseScreenshots();
resolvers = [];
fakeScreenshot.getScreenshotForURL = sandbox.spy(() => new Promise(
resolve => resolvers.push(resolve)));
});
const getTwice = () => Promise.all([feed.getLinksWithDefaults(), feed.getLinksWithDefaults()]);
const resolveAll = () => resolvers.forEach(resolve => resolve(FAKE_SCREENSHOT));
it("should call the backing data once", async () => {
await getTwice();
assert.calledOnce(global.NewTabUtils.activityStreamLinks.getTopSites);
});
it("should get screenshots once per link", async () => {
await getTwice();
assert.callCount(fakeScreenshot.getScreenshotForURL, FAKE_LINKS.length);
});
it("should dispatch once per link screenshot fetched", async () => {
await getTwice();
await resolveAll();
assert.callCount(feed.store.dispatch, FAKE_LINKS.length);
});
});
});
describe("deduping", () => {
beforeEach(() => {
@@ -334,7 +366,7 @@ describe("Top Sites Feed", () => {
it("should call _fetchIcon for each link", async () => {
sinon.spy(feed, "_fetchIcon");
const results = await feed.getLinksWithDefaults(action);
const results = await feed.getLinksWithDefaults();
assert.callCount(feed._fetchIcon, results.length);
results.forEach(link => {
@@ -348,11 +380,27 @@ describe("Top Sites Feed", () => {
});
it("should initialise _tippyTopProvider if it's not already initialised", async () => {
feed._tippyTopProvider.initialized = false;
await feed.refresh(action);
await feed.refresh();
assert.ok(feed._tippyTopProvider.initialized);
});
it("should broadcast with no target", async () => {
sinon.stub(feed, "getLinksWithDefaults").returns(Promise.resolve([]));
await feed.refresh();
assert.calledOnce(feed.store.dispatch);
assert.notProperty(feed.store.dispatch.firstCall.args[0].meta, "toTarget");
});
it("should respond to a specific target", async () => {
sinon.stub(feed, "getLinksWithDefaults").returns(Promise.resolve([]));
await feed.refresh({meta: {fromTarget: {}}});
assert.calledOnce(feed.store.dispatch);
assert.property(feed.store.dispatch.firstCall.args[0].meta, "toTarget");
});
it("should dispatch an action with the links returned", async () => {
await feed.refresh(action);
await feed.refresh();
const reference = links.map(site => Object.assign({}, site, {hostname: shortURLStub(site)}));
assert.calledOnce(feed.store.dispatch);
@@ -362,7 +410,7 @@ describe("Top Sites Feed", () => {
it("should handle empty slots in the resulting top sites array", async () => {
links = [FAKE_LINKS[0]];
fakeNewTabUtils.pinnedLinks.links = [null, null, FAKE_LINKS[1], null, null, null, null, null, FAKE_LINKS[2]];
await feed.refresh(action);
await feed.refresh();
assert.calledOnce(feed.store.dispatch);
});
});
@@ -376,26 +424,26 @@ describe("Top Sites Feed", () => {
assert.propertyVal(link, "screenshot", "reuse.png");
});
it("should reuse existing fetching screenshot on the link", async () => {
const link = {__fetchingScreenshot: Promise.resolve("fetching.png")};
const link = {__sharedCache: {fetchingScreenshot: Promise.resolve("fetching.png")}};
await feed._fetchIcon(link);
assert.notCalled(fakeScreenshot.getScreenshotForURL);
assert.propertyVal(link, "screenshot", "fetching.png");
});
it("should get a screenshot if the link is missing it", () => {
feed._fetchIcon(FAKE_LINKS[0]);
feed._fetchIcon(Object.assign({__sharedCache: {}}, FAKE_LINKS[0]));
assert.calledOnce(fakeScreenshot.getScreenshotForURL);
assert.calledWith(fakeScreenshot.getScreenshotForURL, FAKE_LINKS[0].url);
});
it("should update the link's cache if it can be updated", () => {
const link = {__updateCache: sandbox.stub()};
it("should update the link's cache with a screenshot", async () => {
const updateLink = sandbox.stub();
const link = {__sharedCache: {updateLink}};
feed._fetchIcon(link);
await feed._fetchIcon(link);
assert.calledOnce(link.__updateCache);
assert.calledWith(link.__updateCache, "__fetchingScreenshot");
assert.calledOnce(updateLink);
assert.calledWith(updateLink, "screenshot", FAKE_SCREENSHOT);
});
it("should skip getting a screenshot if there is a tippy top icon", () => {
feed._tippyTopProvider.processSite = site => {
@@ -579,4 +627,33 @@ describe("Top Sites Feed", () => {
assert.calledWith(fakeNewTabUtils.pinnedLinks.pin, site, 2);
});
});
describe("integration", () => {
let resolvers = [];
beforeEach(() => {
feed.store.dispatch = sandbox.stub().callsFake(() => {
resolvers.shift()();
});
fakeScreenshot.getScreenshotForURL = sandbox.spy();
});
const forDispatch = action => new Promise(resolve => {
resolvers.push(resolve);
feed.onAction(action);
});
it("should add a pinned site and remove it", async () => {
const url = "pin.me";
fakeNewTabUtils.pinnedLinks.pin = sandbox.stub().callsFake(link => {
fakeNewTabUtils.pinnedLinks.links.push(link);
});
await forDispatch({type: at.TOP_SITES_ADD, data: {site: {url}}});
fakeNewTabUtils.pinnedLinks.links.pop();
await forDispatch({type: at.PLACES_LINK_BLOCKED});
assert.calledTwice(feed.store.dispatch);
assert.equal(feed.store.dispatch.firstCall.args[0].data[0].url, url);
assert.equal(feed.store.dispatch.secondCall.args[0].data[0].url, FAKE_LINKS[0].url);
});
});
});