зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1403215 - Fix broken Snippets pref, perceived performance and bug fixes to Activity Stream. r=ursula
MozReview-Commit-ID: JSvQB4nxduM --HG-- extra : rebase_source : 0a537c181ecf6b5e7fcaa1ced1ae5401abcee018
This commit is contained in:
Родитель
ef6aa2132c
Коммит
d9a2f3b235
|
@ -31,6 +31,7 @@ for (const type of [
|
|||
"DELETE_HISTORY_URL_CONFIRM",
|
||||
"DIALOG_CANCEL",
|
||||
"DIALOG_OPEN",
|
||||
"DISABLE_ONBOARDING",
|
||||
"INIT",
|
||||
"LOCALE_UPDATED",
|
||||
"MIGRATION_CANCEL",
|
||||
|
@ -49,8 +50,8 @@ for (const type of [
|
|||
"PLACES_BOOKMARK_CHANGED",
|
||||
"PLACES_BOOKMARK_REMOVED",
|
||||
"PLACES_HISTORY_CLEARED",
|
||||
"PLACES_LINKS_DELETED",
|
||||
"PLACES_LINK_BLOCKED",
|
||||
"PLACES_LINK_DELETED",
|
||||
"PREFS_INITIAL_VALUES",
|
||||
"PREF_CHANGED",
|
||||
"SAVE_SESSION_PERF_DATA",
|
||||
|
|
|
@ -74,8 +74,7 @@ this.PrerenderData = new _PrerenderData({
|
|||
icon: "pocket",
|
||||
id: "topstories",
|
||||
order: 1,
|
||||
title: {id: "header_recommended_by", values: {provider: "Pocket"}},
|
||||
topics: [{}]
|
||||
title: {id: "header_recommended_by", values: {provider: "Pocket"}}
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
|
|
|
@ -288,7 +288,9 @@ function Sections(prevState = INITIAL_STATE.Sections, action) {
|
|||
return item;
|
||||
})
|
||||
}));
|
||||
case at.PLACES_LINK_DELETED:
|
||||
case at.PLACES_LINKS_DELETED:
|
||||
return prevState.map(section => Object.assign({}, section,
|
||||
{rows: section.rows.filter(site => !action.data.includes(site.url))}));
|
||||
case at.PLACES_LINK_BLOCKED:
|
||||
return prevState.map(section =>
|
||||
Object.assign({}, section, {rows: section.rows.filter(site => site.url !== action.data.url)}));
|
||||
|
|
|
@ -138,9 +138,6 @@
|
|||
"enabled": true,
|
||||
"icon": "pocket",
|
||||
"id": "topstories",
|
||||
"topics": [
|
||||
{}
|
||||
],
|
||||
"initialized": false
|
||||
},
|
||||
{
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -94,7 +94,7 @@ const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS :
|
|||
// UNINIT: "UNINIT"
|
||||
// }
|
||||
const actionTypes = {};
|
||||
for (const type of ["BLOCK_URL", "BOOKMARK_URL", "DELETE_BOOKMARK_BY_ID", "DELETE_HISTORY_URL", "DELETE_HISTORY_URL_CONFIRM", "DIALOG_CANCEL", "DIALOG_OPEN", "INIT", "LOCALE_UPDATED", "MIGRATION_CANCEL", "MIGRATION_COMPLETED", "MIGRATION_START", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_CHANGED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SET_PREF", "SHOW_FIREFOX_ACCOUNTS", "SNIPPETS_DATA", "SNIPPETS_RESET", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_ADD", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_EDIT", "TOP_SITES_PIN", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "UNINIT"]) {
|
||||
for (const type of ["BLOCK_URL", "BOOKMARK_URL", "DELETE_BOOKMARK_BY_ID", "DELETE_HISTORY_URL", "DELETE_HISTORY_URL_CONFIRM", "DIALOG_CANCEL", "DIALOG_OPEN", "DISABLE_ONBOARDING", "INIT", "LOCALE_UPDATED", "MIGRATION_CANCEL", "MIGRATION_COMPLETED", "MIGRATION_START", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_CHANGED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_DELETED", "PLACES_LINK_BLOCKED", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SET_PREF", "SHOW_FIREFOX_ACCOUNTS", "SNIPPETS_DATA", "SNIPPETS_RESET", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_ADD", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_EDIT", "TOP_SITES_PIN", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "UNINIT"]) {
|
||||
actionTypes[type] = type;
|
||||
}
|
||||
|
||||
|
@ -638,7 +638,8 @@ function Sections(prevState = INITIAL_STATE.Sections, action) {
|
|||
return item;
|
||||
})
|
||||
}));
|
||||
case at.PLACES_LINK_DELETED:
|
||||
case at.PLACES_LINKS_DELETED:
|
||||
return prevState.map(section => Object.assign({}, section, { rows: section.rows.filter(site => !action.data.includes(site.url)) }));
|
||||
case at.PLACES_LINK_BLOCKED:
|
||||
return prevState.map(section => Object.assign({}, section, { rows: section.rows.filter(site => site.url !== action.data.url) }));
|
||||
default:
|
||||
|
@ -1511,10 +1512,14 @@ class TopSitesEdit extends React.PureComponent {
|
|||
"section",
|
||||
{ className: "edit-topsites-inner-wrapper" },
|
||||
React.createElement(
|
||||
"h3",
|
||||
{ className: "section-title" },
|
||||
React.createElement("span", { className: `icon icon-small-spacer icon-topsites` }),
|
||||
React.createElement(FormattedMessage, { id: "header_top_sites" })
|
||||
"div",
|
||||
{ className: "section-top-bar" },
|
||||
React.createElement(
|
||||
"h3",
|
||||
{ className: "section-title" },
|
||||
React.createElement("span", { className: `icon icon-small-spacer icon-topsites` }),
|
||||
React.createElement(FormattedMessage, { id: "header_top_sites" })
|
||||
)
|
||||
),
|
||||
React.createElement(
|
||||
"ul",
|
||||
|
@ -2569,7 +2574,10 @@ class Section extends React.PureComponent {
|
|||
contextMenuOptions, intl, initialized
|
||||
} = this.props;
|
||||
const maxCards = CARDS_PER_ROW * maxRows;
|
||||
const shouldShowTopics = id === "topstories" && this.props.topics && this.props.topics.length > 0;
|
||||
|
||||
// Show topics only for top stories and if it's not initialized yet (so
|
||||
// content doesn't shift when it is loaded) or has loaded with topics
|
||||
const shouldShowTopics = id === "topstories" && (!this.props.topics || this.props.topics.length > 0);
|
||||
|
||||
const infoOptionIconA11yAttrs = {
|
||||
"aria-haspopup": "true",
|
||||
|
@ -2694,6 +2702,9 @@ const { FormattedMessage } = __webpack_require__(2);
|
|||
const cardContextTypes = __webpack_require__(26);
|
||||
const { actionCreators: ac, actionTypes: at } = __webpack_require__(0);
|
||||
|
||||
// Keep track of pending image loads to only request once
|
||||
const gImageLoading = new Map();
|
||||
|
||||
/**
|
||||
* Card component.
|
||||
* Cards are found within a Section component and contain information about a link such
|
||||
|
@ -2706,11 +2717,47 @@ const { actionCreators: ac, actionTypes: at } = __webpack_require__(0);
|
|||
class Card extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { showContextMenu: false, activeCard: null };
|
||||
this.state = {
|
||||
activeCard: null,
|
||||
imageLoaded: false,
|
||||
showContextMenu: false
|
||||
};
|
||||
this.onMenuButtonClick = this.onMenuButtonClick.bind(this);
|
||||
this.onMenuUpdate = this.onMenuUpdate.bind(this);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to conditionally load an image and update state when it loads.
|
||||
*/
|
||||
async maybeLoadImage() {
|
||||
// No need to load if it's already loaded or no image
|
||||
const { image } = this.props.link;
|
||||
if (!this.state.imageLoaded && image) {
|
||||
// Initialize a promise to share a load across multiple card updates
|
||||
if (!gImageLoading.has(image)) {
|
||||
const loaderPromise = new Promise((resolve, reject) => {
|
||||
const loader = new Image();
|
||||
loader.addEventListener("load", resolve);
|
||||
loader.addEventListener("error", reject);
|
||||
loader.src = image;
|
||||
});
|
||||
|
||||
// Save and remove the promise only while it's pending
|
||||
gImageLoading.set(image, loaderPromise);
|
||||
loaderPromise.catch(ex => ex).then(() => gImageLoading.delete(image)).catch();
|
||||
}
|
||||
|
||||
// Wait for the image whether just started loading or reused promise
|
||||
await gImageLoading.get(image);
|
||||
|
||||
// Only update state if we're still waiting to load the original image
|
||||
if (this.props.link.image === image && !this.state.imageLoaded) {
|
||||
this.setState({ imageLoaded: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMenuButtonClick(event) {
|
||||
event.preventDefault();
|
||||
this.setState({
|
||||
|
@ -2742,6 +2789,18 @@ class Card extends React.PureComponent {
|
|||
onMenuUpdate(showContextMenu) {
|
||||
this.setState({ showContextMenu });
|
||||
}
|
||||
componentDidMount() {
|
||||
this.maybeLoadImage();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.maybeLoadImage();
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// Clear the image state if changing images
|
||||
if (nextProps.link.image !== this.props.link.image) {
|
||||
this.setState({ imageLoaded: false });
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { index, link, dispatch, contextMenuOptions, eventSource, shouldSendImpressionStats } = this.props;
|
||||
const { props } = this;
|
||||
|
@ -2763,7 +2822,7 @@ class Card extends React.PureComponent {
|
|||
hasImage && React.createElement(
|
||||
"div",
|
||||
{ className: "card-preview-image-outer" },
|
||||
React.createElement("div", { className: `card-preview-image${link.image ? " loaded" : ""}`, style: imageStyle })
|
||||
React.createElement("div", { className: `card-preview-image${this.state.imageLoaded ? " loaded" : ""}`, style: imageStyle })
|
||||
),
|
||||
React.createElement(
|
||||
"div",
|
||||
|
@ -2894,7 +2953,7 @@ class Topics extends React.PureComponent {
|
|||
React.createElement(
|
||||
"ul",
|
||||
null,
|
||||
topics.map(t => React.createElement(Topic, { key: t.name, url: t.url, name: t.name }))
|
||||
topics && topics.map(t => React.createElement(Topic, { key: t.name, url: t.url, name: t.name }))
|
||||
),
|
||||
read_more_endpoint && React.createElement(
|
||||
"a",
|
||||
|
@ -2985,8 +3044,7 @@ var PrerenderData = new _PrerenderData({
|
|||
icon: "pocket",
|
||||
id: "topstories",
|
||||
order: 1,
|
||||
title: { id: "header_recommended_by", values: { provider: "Pocket" } },
|
||||
topics: [{}]
|
||||
title: { id: "header_recommended_by", values: { provider: "Pocket" } }
|
||||
}, {
|
||||
enabled: true,
|
||||
id: "highlights",
|
||||
|
@ -3257,6 +3315,10 @@ class SnippetsMap extends Map {
|
|||
await this.set("blockList", blockList);
|
||||
}
|
||||
|
||||
disableOnboarding() {
|
||||
this._dispatch(ac.SendToMain({ type: at.DISABLE_ONBOARDING }));
|
||||
}
|
||||
|
||||
showFirefoxAccounts() {
|
||||
this._dispatch(ac.SendToMain({ type: at.SHOW_FIREFOX_ACCOUNTS }));
|
||||
}
|
||||
|
@ -3395,7 +3457,6 @@ class SnippetsProvider {
|
|||
if (needsUpdate && this.appData.snippetsURL) {
|
||||
this.snippetsMap.set("snippets-last-update", Date.now());
|
||||
try {
|
||||
// TODO: timeout?
|
||||
const response = await fetch(this.appData.snippetsURL);
|
||||
if (response.status === 200) {
|
||||
const payload = await response.text();
|
||||
|
@ -3409,10 +3470,18 @@ class SnippetsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
_showDefaultSnippets() {
|
||||
_noSnippetFallback() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
_forceOnboardingVisibility(shouldBeVisible) {
|
||||
const onboardingEl = document.getElementById("onboarding-notification-bar");
|
||||
|
||||
if (onboardingEl) {
|
||||
onboardingEl.style.display = shouldBeVisible ? "" : "none";
|
||||
}
|
||||
}
|
||||
|
||||
_showRemoteSnippets() {
|
||||
const snippetsEl = document.getElementById(this.elementId);
|
||||
const payload = this.snippetsMap.get("snippets");
|
||||
|
@ -3480,15 +3549,18 @@ class SnippetsProvider {
|
|||
try {
|
||||
this._showRemoteSnippets();
|
||||
} catch (e) {
|
||||
this._showDefaultSnippets(e);
|
||||
this._noSnippetFallback(e);
|
||||
}
|
||||
|
||||
window.dispatchEvent(new Event(SNIPPETS_ENABLED_EVENT));
|
||||
|
||||
this._forceOnboardingVisibility(true);
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
uninit() {
|
||||
window.dispatchEvent(new Event(SNIPPETS_DISABLED_EVENT));
|
||||
this._forceOnboardingVisibility(false);
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
@ -3508,16 +3580,16 @@ function addSnippetsSubscriber(store) {
|
|||
|
||||
store.subscribe(async () => {
|
||||
const state = store.getState();
|
||||
// state.Snippets.initialized: Should snippets be initialised?
|
||||
// snippets.initialized: Is SnippetsProvider currently initialised?
|
||||
if (state.Snippets.initialized && !snippets.initialized && state.Snippets.onboardingFinished) {
|
||||
// Don't call init multiple times
|
||||
if (!initializing) {
|
||||
initializing = true;
|
||||
await snippets.init({ appData: state.Snippets });
|
||||
initializing = false;
|
||||
}
|
||||
} else if (state.Snippets.initialized === false && snippets.initialized) {
|
||||
// state.Prefs.values["feeds.snippets"]: Should snippets be shown?
|
||||
// state.Snippets.initialized Is the snippets data initialized?
|
||||
// snippets.initialized: Is SnippetsProvider currently initialised?
|
||||
if (state.Prefs.values["feeds.snippets"] && state.Snippets.initialized && !snippets.initialized &&
|
||||
// Don't call init multiple times
|
||||
!initializing) {
|
||||
initializing = true;
|
||||
await snippets.init({ appData: state.Snippets });
|
||||
initializing = false;
|
||||
} else if (state.Prefs.values["feeds.snippets"] === false && snippets.initialized) {
|
||||
snippets.uninit();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -457,26 +457,24 @@ main {
|
|||
padding-inline-start: 3px; }
|
||||
|
||||
.topsite-form .form-wrapper {
|
||||
margin: auto;
|
||||
max-width: 350px;
|
||||
padding: 15px 0; }
|
||||
.topsite-form .form-wrapper .field {
|
||||
margin-inline-start: 205px;
|
||||
position: relative; }
|
||||
.topsite-form .form-wrapper .url input:not(:placeholder-shown):dir(rtl) {
|
||||
direction: ltr;
|
||||
text-align: right; }
|
||||
.topsite-form .form-wrapper .section-title {
|
||||
margin-bottom: 5px;
|
||||
margin-inline-start: 205px; }
|
||||
margin-bottom: 5px; }
|
||||
.topsite-form .form-wrapper input[type='text'] {
|
||||
border: solid 1px rgba(12, 12, 13, 0.2);
|
||||
border-radius: 2px;
|
||||
margin: 5px 0;
|
||||
padding: 7px;
|
||||
width: 350px; }
|
||||
width: 100%; }
|
||||
.topsite-form .form-wrapper input[type='text']:focus {
|
||||
border: solid 1px rgba(12, 12, 13, 0.4); }
|
||||
.topsite-form .form-wrapper input[type='text']::placeholder {
|
||||
font-style: italic; }
|
||||
.topsite-form .form-wrapper .invalid input[type='text'] {
|
||||
border: solid 1px #D70022;
|
||||
box-shadow: 0 0 0 2px rgba(215, 0, 34, 0.35); }
|
||||
|
@ -676,28 +674,19 @@ main {
|
|||
width: 100%;
|
||||
height: 36px; }
|
||||
.search-wrapper input {
|
||||
border: 0;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
border-radius: 3px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
padding-inline-end: 36px;
|
||||
padding-inline-start: 35px;
|
||||
width: 100%;
|
||||
font-size: 15px; }
|
||||
.search-wrapper input:focus {
|
||||
border-color: #0060DF;
|
||||
box-shadow: 0 0 0 2px #0060DF;
|
||||
z-index: 1; }
|
||||
.search-wrapper input:focus + .search-button {
|
||||
z-index: 1;
|
||||
background-color: #0060DF;
|
||||
background-image: url("chrome://browser/skin/forward.svg");
|
||||
fill: #FFF;
|
||||
-moz-context-properties: fill; }
|
||||
.search-wrapper:active input,
|
||||
.search-wrapper input:focus {
|
||||
border-color: #0A84FF;
|
||||
box-shadow: 0 0 0 2px #0A84FF; }
|
||||
.search-wrapper .search-label {
|
||||
background: url("chrome://browser/skin/search-glass.svg") no-repeat 12px center/16px;
|
||||
fill: rgba(12, 12, 13, 0.4);
|
||||
|
@ -705,8 +694,7 @@ main {
|
|||
position: absolute;
|
||||
offset-inline-start: 0;
|
||||
height: 100%;
|
||||
width: 35px;
|
||||
z-index: 2; }
|
||||
width: 35px; }
|
||||
.search-wrapper .search-button {
|
||||
background: url("chrome://browser/skin/forward.svg") no-repeat center center;
|
||||
border-radius: 0 3px 3px 0;
|
||||
|
@ -718,11 +706,11 @@ main {
|
|||
height: 100%;
|
||||
offset-inline-end: 0;
|
||||
position: absolute; }
|
||||
.search-wrapper .search-button:hover {
|
||||
z-index: 1;
|
||||
background-color: #0060DF;
|
||||
fill: #FFF;
|
||||
.search-wrapper .search-button:focus, .search-wrapper .search-button:hover {
|
||||
background-color: rgba(12, 12, 13, 0.1);
|
||||
cursor: pointer; }
|
||||
.search-wrapper .search-button:active {
|
||||
background-color: rgba(12, 12, 13, 0.15); }
|
||||
.search-wrapper .search-button:dir(rtl) {
|
||||
transform: scaleX(-1); }
|
||||
.search-wrapper .contentSearchSuggestionTable {
|
||||
|
@ -1009,13 +997,11 @@ main {
|
|||
.card-outer:-moz-any(:hover, :focus, .active):not(.placeholder) .card-title {
|
||||
color: #0060DF; }
|
||||
.card-outer .card-preview-image-outer {
|
||||
background-color: #F9F9FA;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #B1B1B3, #D7D7DB);
|
||||
height: 122px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
overflow: hidden; }
|
||||
.card-outer .card-preview-image-outer:dir(rtl) {
|
||||
background: linear-gradient(225deg, #B1B1B3, #D7D7DB); }
|
||||
.card-outer .card-preview-image-outer::after {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
bottom: 0;
|
||||
|
@ -1028,8 +1014,8 @@ main {
|
|||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
transition: opacity 1s;
|
||||
opacity: 0; }
|
||||
opacity: 0;
|
||||
transition: opacity 1s cubic-bezier(0.07, 0.95, 0, 1); }
|
||||
.card-outer .card-preview-image-outer .card-preview-image.loaded {
|
||||
opacity: 1; }
|
||||
.card-outer .card-details {
|
||||
|
|
|
@ -580,7 +580,51 @@
|
|||
"time_label_hour": "{number}e",
|
||||
"time_label_day": "{number}d",
|
||||
"settings_pane_button_label": "Personelait ho pajenn Ivinell Nevez",
|
||||
"settings_pane_header": "Gwellvezioù an ivinell nevez"
|
||||
"settings_pane_header": "Gwellvezioù an ivinell nevez",
|
||||
"settings_pane_body2": "Dibabit petra a welit war ar bajenn-mañ.",
|
||||
"settings_pane_search_header": "Klask",
|
||||
"settings_pane_search_body": "Klask er web adalek an ivinell nevez.",
|
||||
"settings_pane_topsites_header": "Lec'hiennoù gwellañ",
|
||||
"settings_pane_topsites_body": "Kit war al lec'hiennoù gweladennet ar muiañ ganeoc'h.",
|
||||
"settings_pane_topsites_options_showmore": "Diskouez daou vann",
|
||||
"settings_pane_bookmarks_header": "Sinedoù nevez",
|
||||
"settings_pane_bookmarks_body": "Ho sinedoù nevez strollet en ul lec'h aes da dizhout.",
|
||||
"settings_pane_visit_again_header": "Gweladenniñ en-dro",
|
||||
"settings_pane_visit_again_body": "Firefox a ziskouezo deoc'h ul lodenn eus ho roll istor a c'hallfec'h kaout c'hoant da zerc'hel soñj pe da zistreiñ eno.",
|
||||
"settings_pane_highlights_header": "Mareoù pouezus",
|
||||
"settings_pane_highlights_body2": "Adkavit an traoù dedennus gweladennet pe lakaet er sinedoù nevez ’zo.",
|
||||
"settings_pane_highlights_options_bookmarks": "Sinedoù",
|
||||
"settings_pane_highlights_options_visited": "Lec'hiennoù gweladennet",
|
||||
"settings_pane_snippets_header": "Notennigoù",
|
||||
"settings_pane_snippets_body": "Lennit an hizivadurioù berr ha dous graet gant Mozilla evit Firefox, sevenadur ar genrouedad, hag ur mem dre-zegouezh ur wech an amzer.",
|
||||
"settings_pane_done_button": "Graet",
|
||||
"edit_topsites_button_text": "Embann",
|
||||
"edit_topsites_button_label": "Personelaat ar gevrenn “lec'hiennoù gweladennet ar muiañ”",
|
||||
"edit_topsites_showmore_button": "Diskouez muioc'h",
|
||||
"edit_topsites_showless_button": "Diskouez nebeutoc'h",
|
||||
"edit_topsites_done_button": "Graet",
|
||||
"edit_topsites_pin_button": "Spilhennañ al lec'hienn-mañ",
|
||||
"edit_topsites_unpin_button": "Dispilhennañ al lec'hienn-mañ",
|
||||
"edit_topsites_edit_button": "Embann al lec'hienn-mañ",
|
||||
"edit_topsites_dismiss_button": "Dilemel al lec'hienn-mañ",
|
||||
"edit_topsites_add_button": "Ouzhpennañ",
|
||||
"topsites_form_add_header": "Lec'hiennoù gwellañ nevez",
|
||||
"topsites_form_edit_header": "Embann al Lec'hiennoù Gwellañ",
|
||||
"topsites_form_title_placeholder": "Enankañ un titl",
|
||||
"topsites_form_url_placeholder": "Skrivit pe pegit un URL",
|
||||
"topsites_form_add_button": "Ouzhpennañ",
|
||||
"topsites_form_save_button": "Enrollañ",
|
||||
"topsites_form_cancel_button": "Nullañ",
|
||||
"topsites_form_url_validation": "URL talvoudek azgoulennet",
|
||||
"pocket_read_more": "Danvezioù brudet:",
|
||||
"pocket_read_even_more": "Gwelet muioc'h a istorioù",
|
||||
"pocket_feedback_header": "Ar gwellañ eus ar web, dibabet gant ouzhpenn 25 milion a dud.",
|
||||
"pocket_description": "Dizoloit pennadoù eus an dibab ho pije gellout c'hwitout a-hent all warno, a-drugarez da bPocket, hag a zo bremañ ul lodenn deus Mozilla.",
|
||||
"highlights_empty_state": "Krogit da verdeiñ hag e tiskouezimp deoc’h pennadoù, videoioù ha pajennoù all gweladennet pe lakaet er sinedoù nevez ’zo.",
|
||||
"topstories_empty_state": "Aet oc'h betek penn. Distroit diwezhatoc'h evit muioc’h a istorioù digant {provider}. N’oc'h ket evit gortoz? Dibabit un danvez brudet evit klask muioc’h a bennadoù dedennus eus pep lec’h er web.",
|
||||
"manual_migration_explanation2": "Amprouit Firefox gant sinedoù, roll istor ha gerioù-tremen ur merdeer all.",
|
||||
"manual_migration_cancel_button": "N'am bo ket",
|
||||
"manual_migration_import_button": "Emporzhiañ bremañ"
|
||||
},
|
||||
"ca": {
|
||||
"newtab_page_title": "Pestanya nova",
|
||||
|
@ -955,6 +999,7 @@
|
|||
"default_label_loading": "Indlæser…",
|
||||
"header_top_sites": "Mest besøgte websider",
|
||||
"header_stories": "Tophistorier",
|
||||
"header_highlights": "Højdepunkter",
|
||||
"header_visit_again": "Besøg igen",
|
||||
"header_bookmarks": "Seneste bogmærker",
|
||||
"header_recommended_by": "Anbefalet af {provider}",
|
||||
|
@ -986,6 +1031,7 @@
|
|||
"search_web_placeholder": "Søg på internettet",
|
||||
"search_settings": "Skift søgeindstillinger",
|
||||
"section_info_option": "Info",
|
||||
"section_info_send_feedback": "Send feedback",
|
||||
"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",
|
||||
|
@ -995,7 +1041,6 @@
|
|||
"time_label_day": "{number} d.",
|
||||
"settings_pane_button_label": "Tilpas siden Nyt faneblad",
|
||||
"settings_pane_header": "Indstillinger for Nyt faneblad",
|
||||
"settings_pane_body": "Vælg, hvad der vises, når du åbner et nyt faneblad.",
|
||||
"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",
|
||||
|
@ -1005,8 +1050,6 @@
|
|||
"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_pocketstories_header": "Tophistorier",
|
||||
"settings_pane_pocketstories_body": "Pocket, en del af Mozilla-familien, hjælper dig med at opdage indhold af høj kvalitet, som du måske ellers ikke ville have fundet.",
|
||||
"settings_pane_done_button": "Færdig",
|
||||
"edit_topsites_button_text": "Rediger",
|
||||
"edit_topsites_button_label": "Tilpas afsnittet Mest besøgte websider",
|
||||
|
@ -1029,10 +1072,7 @@
|
|||
"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_feedback_body": "Pocket, en del af Mozilla-familien, hjælper dig med at opdage indhold af høj kvalitet, som du måske ellers ikke ville have fundet.",
|
||||
"pocket_send_feedback": "Send feedback",
|
||||
"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_explanation": "Prøv Firefox med dine favorit-websteder og bogmærker fra en anden browser.",
|
||||
"manual_migration_cancel_button": "Nej tak",
|
||||
"manual_migration_import_button": "Importer nu"
|
||||
},
|
||||
|
@ -3788,8 +3828,8 @@
|
|||
"kk": {
|
||||
"newtab_page_title": "Жаңа бет",
|
||||
"default_label_loading": "Жүктелуде…",
|
||||
"header_top_sites": "Топ сайттар",
|
||||
"header_stories": "Топ хикаялар",
|
||||
"header_top_sites": "Үздік сайттар",
|
||||
"header_stories": "Үздік хикаялар",
|
||||
"header_highlights": "Ерекше жаңалықтар",
|
||||
"header_visit_again": "Қайтадан шолу",
|
||||
"header_bookmarks": "Соңғы бетбелгілер",
|
||||
|
@ -3815,7 +3855,7 @@
|
|||
"menu_action_unpin": "Бекітуді алып тастау",
|
||||
"confirm_history_delete_p1": "Бұл парақтың барлық кездесулерін шолу тарихыңыздан өшіруді қалайсыз ба?",
|
||||
"confirm_history_delete_notice_p2": "Бұл әрекетті болдырмау мүмкін болмайды.",
|
||||
"menu_action_save_to_pocket": "Pocket-ке сақтау",
|
||||
"menu_action_save_to_pocket": "Pocket ішіне сақтау",
|
||||
"search_for_something_with": "{search_term} ұғымын көмегімен іздеу:",
|
||||
"search_button": "Іздеу",
|
||||
"search_header": "{search_engine_name} іздеуі",
|
||||
|
@ -3833,10 +3873,10 @@
|
|||
"time_label_day": "{number} күн",
|
||||
"settings_pane_button_label": "Жаңа бетті баптаңыз",
|
||||
"settings_pane_header": "Жаңа бет баптаулары",
|
||||
"settings_pane_body2": "Бұл парақта не көргіңіз келетінді таңдаңыз.",
|
||||
"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": "Соңғы бетбелгілер",
|
||||
|
@ -3848,7 +3888,7 @@
|
|||
"settings_pane_highlights_options_bookmarks": "Бетбелгілер",
|
||||
"settings_pane_highlights_options_visited": "Ашылған сайттар",
|
||||
"settings_pane_snippets_header": "Үзінділер",
|
||||
"settings_pane_snippets_body": "Mozilla-дан Firefox және интернет мәдениеті туралы қысқа жаңалықтарды, және кездейсоқ мемдерді оқыңыз.",
|
||||
"settings_pane_snippets_body": "Mozilla ұсынған Firefox және интернет мәдениеті туралы қысқа жаңалықтарды, және кездейсоқ мемдерді оқыңыз.",
|
||||
"settings_pane_done_button": "Дайын",
|
||||
"edit_topsites_button_text": "Түзету",
|
||||
"edit_topsites_button_label": "Топ сайттар санатын баптау",
|
||||
|
@ -3874,7 +3914,7 @@
|
|||
"pocket_description": "Ол болмаса, сіз жіберіп алатын мүмкіндігі бар жоғары сапалы құраманы Pocket көмегімен табыңыз, ол енді Mozilla-ның бөлігі болып табылады.",
|
||||
"highlights_empty_state": "Шолуды бастаңыз, сіз жақында шолған немесе бетбелгілерге қосқан тамаша мақалалар, видеолар немесе басқа парақтардың кейбіреулері осында көрсетіледі.",
|
||||
"topstories_empty_state": "Дайын. {provider} ұсынған көбірек мақалаларды алу үшін кейінірек тексеріңіз. Күте алмайсыз ба? Интернеттен көбірек тамаша мақалаларды алу үшін әйгілі теманы таңдаңыз.",
|
||||
"manual_migration_explanation2": "Firefox-ты басқа браузер бетбелгілері, тарихы және парольдерімен қолданып көріңіз.",
|
||||
"manual_migration_explanation2": "Firefox қолданбасын басқа браузер бетбелгілері, тарихы және парольдерімен қолданып көріңіз.",
|
||||
"manual_migration_cancel_button": "Жоқ, рахмет",
|
||||
"manual_migration_import_button": "Қазір импорттау"
|
||||
},
|
||||
|
@ -4203,13 +4243,15 @@
|
|||
"manual_migration_import_button": "Importuoti dabar"
|
||||
},
|
||||
"lv": {
|
||||
"newtab_page_title": "Jauna cilne"
|
||||
"newtab_page_title": "Jauna cilne",
|
||||
"default_label_loading": "Notiek ielāde…"
|
||||
},
|
||||
"mk": {
|
||||
"newtab_page_title": "Ново јазиче",
|
||||
"default_label_loading": "Се вчитува…",
|
||||
"header_top_sites": "Врвни мрежни места",
|
||||
"header_stories": "Врвни написи",
|
||||
"header_top_sites": "Популарни мрежни места",
|
||||
"header_stories": "Популарни написи",
|
||||
"header_highlights": "Интереси",
|
||||
"header_visit_again": "Посети повторно",
|
||||
"header_bookmarks": "Скорешни обележувачи",
|
||||
"header_recommended_by": "Препорачано од {provider}",
|
||||
|
@ -4232,7 +4274,7 @@
|
|||
"menu_action_delete": "Избриши од историја",
|
||||
"menu_action_pin": "Прикачи",
|
||||
"menu_action_unpin": "Откачи",
|
||||
"confirm_history_delete_p1": "Дали сте сигурни дека сакате да ја избришете оваа страница отсекаде во Вашата историја на прелистување?",
|
||||
"confirm_history_delete_p1": "Дали сте сигурни дека сакате да ја избришете оваа страница отсекаде во вашата историја на прелистување?",
|
||||
"confirm_history_delete_notice_p2": "Ова дејство не може да се одврати.",
|
||||
"menu_action_save_to_pocket": "Зачувај во Pocket",
|
||||
"search_for_something_with": "Пребарај за {search_term} со:",
|
||||
|
@ -4241,30 +4283,36 @@
|
|||
"search_web_placeholder": "Пребарајте на Интернет",
|
||||
"search_settings": "Промени поставувања за пребарување",
|
||||
"section_info_option": "Инфо",
|
||||
"section_info_send_feedback": "Испрати мислење",
|
||||
"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} ч",
|
||||
"time_label_day": "{number} д",
|
||||
"settings_pane_button_label": "Прилагодете ја страницата на Вашето Ново јазиче",
|
||||
"settings_pane_button_label": "Прилагодете ја страницата на вашето Ново јазиче",
|
||||
"settings_pane_header": "Преференци за Ново јазиче",
|
||||
"settings_pane_body": "Изберете што ќе гледате кога ќе отворите ново јазиче.",
|
||||
"settings_pane_body2": "Изберете што ќе гледате на оваа страница.",
|
||||
"settings_pane_search_header": "Пребарување",
|
||||
"settings_pane_search_body": "Пребарајте низ Интернет од Вашето ново јазиче.",
|
||||
"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": "Firefox ќе прикаже делови од Вашата историја на прелистување кои можеби би сакале да ги запомните или пак да им се навратите.",
|
||||
"settings_pane_pocketstories_header": "Врвни написи",
|
||||
"settings_pane_pocketstories_body": "Pocket, дел од семејството на Mozilla, ќе Ви помогне да стигнете до високо-квалитетни содржини кои можеби не би ги откриле на друг начин.",
|
||||
"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": "Прилагодете ги Вашите Врвни мрежни места",
|
||||
"edit_topsites_button_label": "Прилагодете ги вашите Популарни мрежни места",
|
||||
"edit_topsites_showmore_button": "Прикажи повеќе",
|
||||
"edit_topsites_showless_button": "Прикажи помалку",
|
||||
"edit_topsites_done_button": "Готово",
|
||||
|
@ -4284,10 +4332,10 @@
|
|||
"pocket_read_more": "Популарни теми:",
|
||||
"pocket_read_even_more": "Види повеќе написи",
|
||||
"pocket_feedback_header": "Најдоброто од Интернет, одбрано од повеќе од 25 милиони луѓе.",
|
||||
"pocket_feedback_body": "Pocket, дел од семејството на Mozilla, ќе Ви помогне да стигнете до високо-квалитетни содржини кои можеби не би ги откриле на друг начин.",
|
||||
"pocket_send_feedback": "Остави коментар",
|
||||
"pocket_description": "Откријте високо-квалитетни содржини, коишто инаку би можеле да ги пропуштите, со помош на Pocket, кој сега е дел од Mozilla.",
|
||||
"highlights_empty_state": "Започнете со прелистување и ние овде ќе ви прикажеме некои од одличните написи, видеа и други страници што неодамна сте ги поселите или обележале.",
|
||||
"topstories_empty_state": "Имате видено сѐ! Навратете се подоцна за нови содржини од {provider}. Не можете да чекате? Изберете популарна тема и откријте уште одлични содржини ширум Интернет.",
|
||||
"manual_migration_explanation": "Пробајте го Firefox со Вашите омилени мрежни места и обележувачи од друг прелистувач.",
|
||||
"manual_migration_explanation2": "Пробајте го Firefox со обележувачите, историјата и лозинките на друг прелистувач.",
|
||||
"manual_migration_cancel_button": "Не, благодарам",
|
||||
"manual_migration_import_button": "Увези сега"
|
||||
},
|
||||
|
@ -6092,7 +6140,7 @@
|
|||
"header_stories": "เรื่องราวเด่น",
|
||||
"header_highlights": "รายการเด่น",
|
||||
"header_visit_again": "เยี่ยมชมอีกครั้ง",
|
||||
"header_bookmarks": "ที่คั่นหน้าเมื่อเร็ว ๆ นี้",
|
||||
"header_bookmarks": "ที่คั่นหน้าล่าสุด",
|
||||
"header_recommended_by": "แนะนำโดย {provider}",
|
||||
"header_bookmarks_placeholder": "คุณยังไม่มีที่คั่นหน้าใด ๆ",
|
||||
"header_stories_from": "จาก",
|
||||
|
@ -6139,7 +6187,7 @@
|
|||
"settings_pane_topsites_header": "ไซต์เด่น",
|
||||
"settings_pane_topsites_body": "เข้าถึงเว็บไซต์ที่คุณเยี่ยมชมมากที่สุด",
|
||||
"settings_pane_topsites_options_showmore": "แสดงสองแถว",
|
||||
"settings_pane_bookmarks_header": "ที่คั่นหน้าเมื่อเร็ว ๆ นี้",
|
||||
"settings_pane_bookmarks_header": "ที่คั่นหน้าล่าสุด",
|
||||
"settings_pane_bookmarks_body": "ที่คั่นหน้าที่สร้างใหม่ของคุณในตำแหน่งที่ตั้งเดียวที่สะดวก",
|
||||
"settings_pane_visit_again_header": "เยี่ยมชมอีกครั้ง",
|
||||
"settings_pane_highlights_header": "รายการเด่น",
|
||||
|
@ -6617,8 +6665,8 @@
|
|||
"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_snippets_header": "只言片语",
|
||||
"settings_pane_snippets_body": "阅读 Mozilla 就 Firefox、互联网文化、偶尔还有模因提供的一些简短而有趣的小文章。",
|
||||
"settings_pane_done_button": "完成",
|
||||
"edit_topsites_button_text": "编辑",
|
||||
"edit_topsites_button_label": "定制您的“常用网站”区域",
|
||||
|
@ -6641,7 +6689,7 @@
|
|||
"pocket_read_more": "热门主题:",
|
||||
"pocket_read_even_more": "查看更多文章",
|
||||
"pocket_feedback_header": "由超过 2500 万人挑选出来的网上精华内容。",
|
||||
"pocket_description": "借助 Pocket(目前所属 Mozilla)发现有趣的高品质内容。",
|
||||
"pocket_description": "借助 Pocket(目前属 Mozilla 旗下)发现您不容错过的高品质内容。",
|
||||
"highlights_empty_state": "开始浏览旅程吧,之后这里会显示您最近看过或加了书签的精彩文章、视频以及其他页面。",
|
||||
"topstories_empty_state": "所有文章都读完啦!晚点再来,{provider} 将推荐更多热门文章。等不及了?选择一个热门话题,找到更多网上的好文章。",
|
||||
"manual_migration_explanation2": "把在其他浏览器中保存的书签、历史记录和密码带到 Firefox 吧。",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:unpack>false</em:unpack>
|
||||
<em:version>2017.09.22.1389-2ee94db4</em:version>
|
||||
<em:version>2017.09.27.1211-43262ffa</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>
|
||||
|
|
|
@ -160,7 +160,7 @@ this.HighlightsFeed = class HighlightsFeed {
|
|||
break;
|
||||
case at.MIGRATION_COMPLETED:
|
||||
case at.PLACES_HISTORY_CLEARED:
|
||||
case at.PLACES_LINK_DELETED:
|
||||
case at.PLACES_LINKS_DELETED:
|
||||
case at.PLACES_LINK_BLOCKED:
|
||||
this.fetchHighlights(true);
|
||||
break;
|
||||
|
|
|
@ -42,11 +42,24 @@ class HistoryObserver extends Observer {
|
|||
* @param {obj} uri A URI object representing the link's url
|
||||
* {str} uri.spec The URI as a string
|
||||
*/
|
||||
onDeleteURI(uri) {
|
||||
this.dispatch({
|
||||
type: at.PLACES_LINK_DELETED,
|
||||
data: {url: uri.spec}
|
||||
});
|
||||
async onDeleteURI(uri) {
|
||||
// Add to an existing array of links if we haven't dispatched yet
|
||||
const {spec} = uri;
|
||||
if (this._deletedLinks) {
|
||||
this._deletedLinks.push(spec);
|
||||
} else {
|
||||
// Store an array of synchronously deleted links
|
||||
this._deletedLinks = [spec];
|
||||
|
||||
// Only dispatch a single action when we've gotten all deleted urls
|
||||
await Promise.resolve().then(() => {
|
||||
this.dispatch({
|
||||
type: at.PLACES_LINKS_DELETED,
|
||||
data: this._deletedLinks
|
||||
});
|
||||
delete this._deletedLinks;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,6 +8,9 @@ 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", {});
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const ONBOARDING_FINISHED_PREF = "browser.onboarding.notification.finished";
|
||||
|
||||
this.PrefsFeed = class PrefsFeed {
|
||||
constructor(prefMap) {
|
||||
|
@ -27,11 +30,30 @@ this.PrefsFeed = class PrefsFeed {
|
|||
}
|
||||
}
|
||||
|
||||
_initOnboardingPref() {
|
||||
const snippetsEnabled = this._prefs.get("feeds.snippets");
|
||||
if (!snippetsEnabled) {
|
||||
this.setOnboardingDisabledDefault(true);
|
||||
}
|
||||
}
|
||||
|
||||
setOnboardingDisabledDefault(value) {
|
||||
const branch = Services.prefs.getDefaultBranch("");
|
||||
branch.setBoolPref(ONBOARDING_FINISHED_PREF, value);
|
||||
}
|
||||
|
||||
onPrefChanged(name, value) {
|
||||
if (this._prefMap.has(name)) {
|
||||
this.store.dispatch(ac.BroadcastToContent({type: at.PREF_CHANGED, data: {name, value}}));
|
||||
}
|
||||
|
||||
this._checkPrerender(name);
|
||||
|
||||
if (name === "feeds.snippets") {
|
||||
// If snippets are disabled, onboarding notifications should also be
|
||||
// disabled because they look like snippets.
|
||||
this.setOnboardingDisabledDefault(!value);
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -47,6 +69,7 @@ this.PrefsFeed = class PrefsFeed {
|
|||
this.store.dispatch(ac.BroadcastToContent({type: at.PREFS_INITIAL_VALUES, data: values}));
|
||||
|
||||
this._setPrerenderPref();
|
||||
this._initOnboardingPref();
|
||||
}
|
||||
removeListeners() {
|
||||
this._prefs.ignoreBranch(this);
|
||||
|
@ -62,6 +85,9 @@ this.PrefsFeed = class PrefsFeed {
|
|||
case at.SET_PREF:
|
||||
this._prefs.set(action.data.name, action.data.value);
|
||||
break;
|
||||
case at.DISABLE_ONBOARDING:
|
||||
this.setOnboardingDisabledDefault(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,8 +17,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
|
|||
// Url to fetch snippets, in the urlFormatter service format.
|
||||
const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl";
|
||||
const TELEMETRY_PREF = "datareporting.healthreport.uploadEnabled";
|
||||
const ONBOARDING_FINISHED_PREF = "browser.onboarding.notification.finished";
|
||||
const FXA_USERNAME_PREF = "services.sync.username";
|
||||
const ONBOARDING_FINISHED_PREF = "browser.onboarding.notification.finished";
|
||||
// Prefix for any target matching a search engine.
|
||||
const TARGET_SEARCHENGINE_PREFIX = "searchEngine-";
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
|
|||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
const ACTIVITY_STREAM_ID = "activity-stream";
|
||||
const ACTIVITY_STREAM_ENDPOINT_PREF = "browser.newtabpage.activity-stream.telemetry.ping.endpoint";
|
||||
|
||||
// This is a mapping table between the user preferences and its encoding code
|
||||
|
@ -160,12 +161,10 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
* Lazily initialize PingCentre to send pings
|
||||
*/
|
||||
get pingCentre() {
|
||||
const ACTIVITY_STREAM_ID = "activity-stream";
|
||||
Object.defineProperty(this, "pingCentre",
|
||||
{
|
||||
value: new PingCentre({
|
||||
topic: ACTIVITY_STREAM_ID,
|
||||
filter: ACTIVITY_STREAM_ID,
|
||||
overrideEndpointPref: ACTIVITY_STREAM_ENDPOINT_PREF
|
||||
})
|
||||
});
|
||||
|
@ -363,7 +362,8 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
|
||||
async sendEvent(event_object) {
|
||||
if (this.telemetryEnabled) {
|
||||
this.pingCentre.sendPing(event_object);
|
||||
this.pingCentre.sendPing(event_object,
|
||||
{filter: ACTIVITY_STREAM_ID});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,8 +264,8 @@ 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_DELETED:
|
||||
case at.PLACES_LINK_BLOCKED:
|
||||
case at.PLACES_LINKS_DELETED:
|
||||
this.frecentCache.expire();
|
||||
this.refresh();
|
||||
break;
|
||||
|
|
|
@ -358,13 +358,22 @@ describe("Reducers", () => {
|
|||
});
|
||||
it("should remove blocked and deleted urls from all rows in all sections", () => {
|
||||
const blockAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "www.foo.bar"}};
|
||||
const deleteAction = {type: at.PLACES_LINK_DELETED, data: {url: "www.foo.bar"}};
|
||||
const deleteAction = {type: at.PLACES_LINKS_DELETED, data: ["www.foo.bar"]};
|
||||
const newBlockState = Sections(oldState, blockAction);
|
||||
const newDeleteState = Sections(oldState, deleteAction);
|
||||
newBlockState.concat(newDeleteState).forEach(section => {
|
||||
assert.deepEqual(section.rows, [{url: "www.other.url"}]);
|
||||
});
|
||||
});
|
||||
it("should remove all deleted urls", () => {
|
||||
const deleteAction = {type: at.PLACES_LINKS_DELETED, data: ["www.foo.bar", "www.other.url"]};
|
||||
|
||||
const newState = Sections(oldState, deleteAction);
|
||||
|
||||
newState.forEach(section => {
|
||||
assert.lengthOf(section.rows, 0);
|
||||
});
|
||||
});
|
||||
it("should not update state for empty action.data on PLACES_BOOKMARK_ADDED", () => {
|
||||
const nextState = Sections(undefined, {type: at.PLACES_BOOKMARK_ADDED});
|
||||
assert.equal(nextState, INITIAL_STATE.Sections);
|
||||
|
|
|
@ -296,10 +296,10 @@ describe("Highlights Feed", () => {
|
|||
assert.calledOnce(feed.fetchHighlights);
|
||||
assert.calledWith(feed.fetchHighlights, true);
|
||||
});
|
||||
it("should fetch highlights on PLACES_LINK_DELETED", async () => {
|
||||
it("should fetch highlights on PLACES_LINKS_DELETED", async () => {
|
||||
await feed.fetchHighlights();
|
||||
feed.fetchHighlights = sinon.spy();
|
||||
feed.onAction({type: at.PLACES_LINK_DELETED});
|
||||
feed.onAction({type: at.PLACES_LINKS_DELETED});
|
||||
assert.calledOnce(feed.fetchHighlights);
|
||||
assert.calledWith(feed.fetchHighlights, true);
|
||||
});
|
||||
|
|
|
@ -179,9 +179,20 @@ describe("PlacesFeed", () => {
|
|||
assert.property(observer, "QueryInterface");
|
||||
});
|
||||
describe("#onDeleteURI", () => {
|
||||
it("should dispatch a PLACES_LINK_DELETED action with the right url", () => {
|
||||
it("should dispatch a PLACES_LINKS_DELETED action with the right url", async() => {
|
||||
await observer.onDeleteURI({spec: "foo.com"});
|
||||
|
||||
assert.calledWith(dispatch, {type: at.PLACES_LINKS_DELETED, data: ["foo.com"]});
|
||||
});
|
||||
it("should dispatch a PLACES_LINKS_DELETED action with multiple urls", async() => {
|
||||
const promise = observer.onDeleteURI({spec: "bar.com"});
|
||||
observer.onDeleteURI({spec: "foo.com"});
|
||||
assert.calledWith(dispatch, {type: at.PLACES_LINK_DELETED, data: {url: "foo.com"}});
|
||||
await promise;
|
||||
|
||||
const result = dispatch.firstCall.args[0].data;
|
||||
assert.lengthOf(result, 2);
|
||||
assert.equal(result[0], "bar.com");
|
||||
assert.equal(result[1], "foo.com");
|
||||
});
|
||||
});
|
||||
describe("#onClearHistory", () => {
|
||||
|
|
|
@ -4,6 +4,7 @@ const {PrerenderData} = require("common/PrerenderData.jsm");
|
|||
const {initialPrefs} = PrerenderData;
|
||||
|
||||
const PRERENDER_PREF_NAME = "prerender";
|
||||
const ONBOARDING_FINISHED_PREF = "browser.onboarding.notification.finished";
|
||||
|
||||
describe("PrefsFeed", () => {
|
||||
let feed;
|
||||
|
@ -62,6 +63,44 @@ describe("PrefsFeed", () => {
|
|||
assert.calledWith(feed._prefs.set, PRERENDER_PREF_NAME, false);
|
||||
});
|
||||
});
|
||||
describe("Onboarding", () => {
|
||||
let sandbox;
|
||||
let defaultBranch;
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
defaultBranch = {setBoolPref: sandbox.stub()};
|
||||
sandbox.stub(global.Services.prefs, "getDefaultBranch").returns(defaultBranch);
|
||||
});
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
it("should set ONBOARDING_FINISHED_PREF to true if prefs.feeds.snippets if false", () => {
|
||||
FAKE_PREFS.set("feeds.snippets", false);
|
||||
feed.onAction({type: at.INIT});
|
||||
assert.calledWith(defaultBranch.setBoolPref, ONBOARDING_FINISHED_PREF, true);
|
||||
});
|
||||
it("should not set ONBOARDING_FINISHED_PREF if prefs.feeds.snippets is true", () => {
|
||||
FAKE_PREFS.set("feeds.snippets", true);
|
||||
feed.onAction({type: at.INIT});
|
||||
assert.notCalled(defaultBranch.setBoolPref);
|
||||
});
|
||||
it("should set ONBOARDING_FINISHED_PREF to true if the feeds.snippets pref changes to false", () => {
|
||||
feed.onPrefChanged("feeds.snippets", false);
|
||||
assert.calledWith(defaultBranch.setBoolPref, ONBOARDING_FINISHED_PREF, true);
|
||||
});
|
||||
it("should set ONBOARDING_FINISHED_PREF to false if the feeds.snippets pref changes to true", () => {
|
||||
feed.onPrefChanged("feeds.snippets", true);
|
||||
assert.calledWith(defaultBranch.setBoolPref, ONBOARDING_FINISHED_PREF, false);
|
||||
});
|
||||
it("should not set ONBOARDING_FINISHED_PREF if an unrelated pref changes", () => {
|
||||
feed.onPrefChanged("foo", true);
|
||||
assert.notCalled(defaultBranch.setBoolPref);
|
||||
});
|
||||
it("should set ONBOARDING_FINISHED_PREF to true if a DISABLE_ONBOARDING action was received", () => {
|
||||
feed.onAction({type: at.DISABLE_ONBOARDING});
|
||||
assert.calledWith(defaultBranch.setBoolPref, ONBOARDING_FINISHED_PREF, true);
|
||||
});
|
||||
});
|
||||
describe("onPrefChanged prerendering", () => {
|
||||
it("should not change the prerender pref if the pref is not included in invalidatingPrefs", () => {
|
||||
feed.onPrefChanged("foo123", true);
|
||||
|
|
|
@ -507,9 +507,9 @@ describe("Top Sites Feed", () => {
|
|||
assert.calledOnce(feed.refresh);
|
||||
assert.equal(feed.refresh.firstCall.args[0], null);
|
||||
});
|
||||
it("should call refresh without a target on PLACES_LINK_DELETED action", async () => {
|
||||
it("should call refresh without a target on PLACES_LINKS_DELETED action", async () => {
|
||||
sinon.stub(feed, "refresh");
|
||||
await feed.onAction({type: at.PLACES_LINK_DELETED});
|
||||
await feed.onAction({type: at.PLACES_LINKS_DELETED});
|
||||
assert.calledOnce(feed.refresh);
|
||||
assert.equal(feed.refresh.firstCall.args[0], null);
|
||||
});
|
||||
|
|
|
@ -27,6 +27,8 @@ overrider.set({
|
|||
ContentSearchUIController: function() {}, // NB: This is a function/constructor
|
||||
dump() {},
|
||||
fetch() {},
|
||||
// eslint-disable-next-line object-shorthand
|
||||
Image: function() {}, // NB: This is a function/constructor
|
||||
Preferences: FakePrefs,
|
||||
Services: {
|
||||
locale: {
|
||||
|
|
|
@ -38,7 +38,6 @@ class PingCentre {
|
|||
}
|
||||
|
||||
this._topic = options.topic;
|
||||
this._filter = options.filter;
|
||||
this._prefs = Services.prefs.getBranch("");
|
||||
|
||||
this._setPingEndpoint(options.topic, options.overrideEndpointPref);
|
||||
|
@ -92,12 +91,12 @@ class PingCentre {
|
|||
this._fhrEnabled = this._prefs.getBoolPref(prefKey);
|
||||
}
|
||||
|
||||
_createExperimentsString(activeExperiments) {
|
||||
_createExperimentsString(activeExperiments, filter) {
|
||||
let experimentsString = "";
|
||||
for (let experimentID in activeExperiments) {
|
||||
if (!activeExperiments[experimentID] ||
|
||||
!activeExperiments[experimentID].branch ||
|
||||
(this._filter && !experimentID.includes(this._filter))) {
|
||||
(filter && !experimentID.includes(filter))) {
|
||||
continue;
|
||||
}
|
||||
let expString = `${experimentID}:${activeExperiments[experimentID].branch}`;
|
||||
|
@ -106,9 +105,10 @@ class PingCentre {
|
|||
return experimentsString;
|
||||
}
|
||||
|
||||
async sendPing(data) {
|
||||
async sendPing(data, options) {
|
||||
let filter = options && options.filter;
|
||||
let experiments = TelemetryEnvironment.getActiveExperiments();
|
||||
let experimentsString = this._createExperimentsString(experiments);
|
||||
let experimentsString = this._createExperimentsString(experiments, filter);
|
||||
if (!this.enabled) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче