gecko-dev/browser/components/newtab/common/Reducers.jsm

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

629 строки
20 KiB
JavaScript
Исходник Обычный вид История

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Bug 1514594: Part 3 - Change ChromeUtils.import API. *** Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8 This changes the behavior of ChromeUtils.import() to return an exports object, rather than a module global, in all cases except when `null` is passed as a second argument, and changes the default behavior not to pollute the global scope with the module's exports. Thus, the following code written for the old model: ChromeUtils.import("resource://gre/modules/Services.jsm"); is approximately the same as the following, in the new model: var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); Since the two behaviors are mutually incompatible, this patch will land with a scripted rewrite to update all existing callers to use the new model rather than the old. *** Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs This was done using the followng script: https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm *** Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D16747 *** Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16748 *** Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16749 *** Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs *** Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16750 --HG-- extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895 extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
2019-01-17 21:18:31 +03:00
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm");
const {Dedupe} = ChromeUtils.import("resource://activity-stream/common/Dedupe.jsm");
const TOP_SITES_DEFAULT_ROWS = 1;
const TOP_SITES_MAX_SITES_PER_ROW = 8;
const dedupe = new Dedupe(site => site && site.url);
const INITIAL_STATE = {
App: {
// Have we received real data from the app yet?
initialized: false,
},
ASRouter: {
initialized: false,
allowLegacySnippets: null,
},
Snippets: {initialized: false},
TopSites: {
// Have we received real data from history yet?
initialized: false,
// The history (and possibly default) links
rows: [],
// Used in content only to dispatch action to TopSiteForm.
editForm: null,
// Used in content only to open the SearchShortcutsForm modal.
showSearchShortcutsForm: false,
// The list of available search shortcuts.
searchShortcuts: [],
},
Prefs: {
initialized: false,
values: {},
},
Dialog: {
visible: false,
data: {},
},
Sections: [],
Pocket: {
isUserLoggedIn: null,
pocketCta: {},
waitingForSpoc: true,
},
// This is the new pocket configurable layout state.
DiscoveryStream: {
// This is a JSON-parsed copy of the discoverystream.config pref value.
config: {enabled: false, layout_endpoint: ""},
layout: [],
lastUpdated: null,
feeds: {
data: {
// "https://foo.com/feed1": {lastUpdated: 123, data: []}
},
loaded: false,
},
spocs: {
spocs_endpoint: "",
lastUpdated: null,
data: {}, // {spocs: []}
loaded: false,
frequency_caps: [],
},
},
Search: {
// When search hand-off is enabled, we render a big button that is styled to
// look like a search textbox. If the button is clicked, we style
// the button as if it was a focused search box and show a fake cursor but
// really focus the awesomebar without the focus styles ("hidden focus").
fakeFocus: false,
// Hide the search box after handing off to AwesomeBar and user starts typing.
hide: false,
},
};
function App(prevState = INITIAL_STATE.App, action) {
switch (action.type) {
case at.INIT:
return Object.assign({}, prevState, action.data || {}, {initialized: true});
default:
return prevState;
}
}
function ASRouter(prevState = INITIAL_STATE.ASRouter, action) {
switch (action.type) {
case at.AS_ROUTER_INITIALIZED:
return {...action.data, initialized: true};
case at.AS_ROUTER_PREF_CHANGED:
return {...prevState, ...action.data};
default:
return prevState;
}
}
/**
* insertPinned - Inserts pinned links in their specified slots
*
* @param {array} a list of links
* @param {array} a list of pinned links
* @return {array} resulting list of links with pinned links inserted
*/
function insertPinned(links, pinned) {
// Remove any pinned links
const pinnedUrls = pinned.map(link => link && link.url);
let newLinks = links.filter(link => (link ? !pinnedUrls.includes(link.url) : false));
newLinks = newLinks.map(link => {
if (link && link.isPinned) {
delete link.isPinned;
delete link.pinIndex;
}
return link;
});
// Then insert them in their specified location
pinned.forEach((val, index) => {
if (!val) { return; }
let link = Object.assign({}, val, {isPinned: true, pinIndex: index});
if (index > newLinks.length) {
newLinks[index] = link;
} else {
newLinks.splice(index, 0, link);
}
});
return newLinks;
}
function TopSites(prevState = INITIAL_STATE.TopSites, action) {
let hasMatch;
let newRows;
switch (action.type) {
case at.TOP_SITES_UPDATED:
if (!action.data || !action.data.links) {
return prevState;
}
return Object.assign({}, prevState, {initialized: true, rows: action.data.links}, action.data.pref ? {pref: action.data.pref} : {});
case at.TOP_SITES_PREFS_UPDATED:
return Object.assign({}, prevState, {pref: action.data.pref});
case at.TOP_SITES_EDIT:
return Object.assign({}, prevState, {
editForm: {
index: action.data.index,
previewResponse: null,
},
});
case at.TOP_SITES_CANCEL_EDIT:
return Object.assign({}, prevState, {editForm: null});
case at.TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL:
return Object.assign({}, prevState, {showSearchShortcutsForm: true});
case at.TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL:
return Object.assign({}, prevState, {showSearchShortcutsForm: false});
case at.PREVIEW_RESPONSE:
if (!prevState.editForm || action.data.url !== prevState.editForm.previewUrl) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: action.data.preview,
previewUrl: action.data.url,
},
});
case at.PREVIEW_REQUEST:
if (!prevState.editForm) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: null,
previewUrl: action.data.url,
},
});
case at.PREVIEW_REQUEST_CANCEL:
if (!prevState.editForm) {
return prevState;
}
return Object.assign({}, prevState, {
editForm: {
index: prevState.editForm.index,
previewResponse: null,
},
});
case at.SCREENSHOT_UPDATED:
newRows = prevState.rows.map(row => {
if (row && row.url === action.data.url) {
hasMatch = true;
return Object.assign({}, row, {screenshot: action.data.screenshot});
}
return row;
});
return hasMatch ? Object.assign({}, prevState, {rows: newRows}) : prevState;
case at.PLACES_BOOKMARK_ADDED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.map(site => {
if (site && site.url === action.data.url) {
const {bookmarkGuid, bookmarkTitle, dateAdded} = action.data;
return Object.assign({}, site, {bookmarkGuid, bookmarkTitle, bookmarkDateCreated: dateAdded});
}
return site;
});
return Object.assign({}, prevState, {rows: newRows});
case at.PLACES_BOOKMARK_REMOVED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.map(site => {
if (site && site.url === action.data.url) {
const newSite = Object.assign({}, site);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
return newSite;
}
return site;
});
return Object.assign({}, prevState, {rows: newRows});
case at.PLACES_LINK_DELETED:
if (!action.data) {
return prevState;
}
newRows = prevState.rows.filter(site => action.data.url !== site.url);
return Object.assign({}, prevState, {rows: newRows});
case at.UPDATE_SEARCH_SHORTCUTS:
return {...prevState, searchShortcuts: action.data.searchShortcuts};
case at.SNIPPETS_PREVIEW_MODE:
return {...prevState, rows: []};
default:
return prevState;
}
}
function Dialog(prevState = INITIAL_STATE.Dialog, action) {
switch (action.type) {
case at.DIALOG_OPEN:
return Object.assign({}, prevState, {visible: true, data: action.data});
case at.DIALOG_CANCEL:
return Object.assign({}, prevState, {visible: false});
case at.DELETE_HISTORY_URL:
return Object.assign({}, INITIAL_STATE.Dialog);
default:
return prevState;
}
}
function Prefs(prevState = INITIAL_STATE.Prefs, action) {
let newValues;
switch (action.type) {
case at.PREFS_INITIAL_VALUES:
return Object.assign({}, prevState, {initialized: true, values: action.data});
case at.PREF_CHANGED:
newValues = Object.assign({}, prevState.values);
newValues[action.data.name] = action.data.value;
return Object.assign({}, prevState, {values: newValues});
default:
return prevState;
}
}
function Sections(prevState = INITIAL_STATE.Sections, action) {
let hasMatch;
let newState;
switch (action.type) {
case at.SECTION_DEREGISTER:
return prevState.filter(section => section.id !== action.data);
case at.SECTION_REGISTER:
// If section exists in prevState, update it
newState = prevState.map(section => {
if (section && section.id === action.data.id) {
hasMatch = true;
return Object.assign({}, section, action.data);
}
return section;
});
// Otherwise, append it
if (!hasMatch) {
const initialized = !!(action.data.rows && action.data.rows.length > 0);
const section = Object.assign({title: "", rows: [], enabled: false}, action.data, {initialized});
newState.push(section);
}
return newState;
case at.SECTION_UPDATE:
newState = prevState.map(section => {
if (section && section.id === action.data.id) {
// If the action is updating rows, we should consider initialized to be true.
// This can be overridden if initialized is defined in the action.data
const initialized = action.data.rows ? {initialized: true} : {};
// Make sure pinned cards stay at their current position when rows are updated.
// Disabling a section (SECTION_UPDATE with empty rows) does not retain pinned cards.
if (action.data.rows && action.data.rows.length > 0 && section.rows.find(card => card.pinned)) {
const rows = Array.from(action.data.rows);
section.rows.forEach((card, index) => {
if (card.pinned) {
// Only add it if it's not already there.
if (rows[index].guid !== card.guid) {
rows.splice(index, 0, card);
}
}
});
return Object.assign({}, section, initialized, Object.assign({}, action.data, {rows}));
}
return Object.assign({}, section, initialized, action.data);
}
return section;
});
if (!action.data.dedupeConfigurations) {
return newState;
}
action.data.dedupeConfigurations.forEach(dedupeConf => {
newState = newState.map(section => {
if (section.id === dedupeConf.id) {
const dedupedRows = dedupeConf.dedupeFrom.reduce((rows, dedupeSectionId) => {
const dedupeSection = newState.find(s => s.id === dedupeSectionId);
const [, newRows] = dedupe.group(dedupeSection.rows, rows);
return newRows;
}, section.rows);
return Object.assign({}, section, {rows: dedupedRows});
}
return section;
});
});
return newState;
case at.SECTION_UPDATE_CARD:
return prevState.map(section => {
if (section && section.id === action.data.id && section.rows) {
const newRows = section.rows.map(card => {
if (card.url === action.data.url) {
return Object.assign({}, card, action.data.options);
}
return card;
});
return Object.assign({}, section, {rows: newRows});
}
return section;
});
case at.PLACES_BOOKMARK_ADDED:
if (!action.data) {
return prevState;
}
return prevState.map(section => Object.assign({}, section, {
rows: section.rows.map(item => {
// find the item within the rows that is attempted to be bookmarked
if (item.url === action.data.url) {
const {bookmarkGuid, bookmarkTitle, dateAdded} = action.data;
return Object.assign({}, item, {
bookmarkGuid,
bookmarkTitle,
bookmarkDateCreated: dateAdded,
type: "bookmark",
});
}
return item;
}),
}));
case at.PLACES_SAVED_TO_POCKET:
if (!action.data) {
return prevState;
}
return prevState.map(section => Object.assign({}, section, {
rows: section.rows.map(item => {
if (item.url === action.data.url) {
return Object.assign({}, item, {
open_url: action.data.open_url,
pocket_id: action.data.pocket_id,
title: action.data.title,
type: "pocket",
});
}
return item;
}),
}));
case at.PLACES_BOOKMARK_REMOVED:
if (!action.data) {
return prevState;
}
return prevState.map(section => Object.assign({}, section, {
rows: section.rows.map(item => {
// find the bookmark within the rows that is attempted to be removed
if (item.url === action.data.url) {
const newSite = Object.assign({}, item);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
if (!newSite.type || newSite.type === "bookmark") {
newSite.type = "history";
}
return newSite;
}
return item;
}),
}));
case at.PLACES_LINK_DELETED:
case at.PLACES_LINK_BLOCKED:
if (!action.data) {
return prevState;
}
return prevState.map(section =>
Object.assign({}, section, {rows: section.rows.filter(site => site.url !== action.data.url)}));
case at.DELETE_FROM_POCKET:
case at.ARCHIVE_FROM_POCKET:
return prevState.map(section =>
Object.assign({}, section, {rows: section.rows.filter(site => site.pocket_id !== action.data.pocket_id)}));
case at.SNIPPETS_PREVIEW_MODE:
return prevState.map(section => ({...section, rows: []}));
default:
return prevState;
}
}
function Snippets(prevState = INITIAL_STATE.Snippets, action) {
switch (action.type) {
case at.SNIPPETS_DATA:
return Object.assign({}, prevState, {initialized: true}, action.data);
case at.SNIPPET_BLOCKED:
return Object.assign({}, prevState, {blockList: prevState.blockList.concat(action.data)});
case at.SNIPPETS_BLOCKLIST_CLEARED:
return Object.assign({}, prevState, {blockList: []});
case at.SNIPPETS_RESET:
return INITIAL_STATE.Snippets;
default:
return prevState;
}
}
function Pocket(prevState = INITIAL_STATE.Pocket, action) {
switch (action.type) {
case at.POCKET_WAITING_FOR_SPOC:
return {...prevState, waitingForSpoc: action.data};
case at.POCKET_LOGGED_IN:
return {...prevState, isUserLoggedIn: !!action.data};
case at.POCKET_CTA:
return {
...prevState,
pocketCta: {
ctaButton: action.data.cta_button,
ctaText: action.data.cta_text,
ctaUrl: action.data.cta_url,
useCta: action.data.use_cta,
},
};
default:
return prevState;
}
}
function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
Bug 1541502 - Add Pocket menu, triggering improvements and bug fixes to Activity Stream r=k88hudson Differential Revision: https://phabricator.services.mozilla.com/D25984 --HG-- rename : browser/components/newtab/locales-src/bn-BD/strings.properties => browser/components/newtab/locales-src/bn/strings.properties rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-strings.js => browser/components/newtab/prerendered/locales/bn/activity-stream-strings.js rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream.html => browser/components/newtab/prerendered/locales/bn/activity-stream.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/trs/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream.html => browser/components/newtab/prerendered/locales/trs/activity-stream.html extra : moz-landing-system : lando
2019-04-04 17:32:55 +03:00
// Return if action data is empty, or spocs or feeds data is not loaded
const isNotReady = () =>
!action.data || !prevState.spocs.loaded || !prevState.feeds.loaded;
const nextState = handleSites => (
{
...prevState,
spocs: {
...prevState.spocs,
data: prevState.spocs.data.spocs ? {
spocs: handleSites(prevState.spocs.data.spocs),
} : {},
},
feeds: {
...prevState.feeds,
data: Object.keys(prevState.feeds.data).reduce((accumulator, feed_url) => {
accumulator[feed_url] = {
data: {
...prevState.feeds.data[feed_url].data,
recommendations: handleSites(prevState.feeds.data[feed_url].data.recommendations),
},
};
return accumulator;
}, {}),
},
});
switch (action.type) {
case at.DISCOVERY_STREAM_CONFIG_CHANGE:
// The reason this is a separate action is so it doesn't trigger a listener update on init
case at.DISCOVERY_STREAM_CONFIG_SETUP:
return {...prevState, config: action.data || {}};
case at.DISCOVERY_STREAM_LAYOUT_UPDATE:
return {...prevState, lastUpdated: action.data.lastUpdated || null, layout: action.data.layout || []};
case at.DISCOVERY_STREAM_LAYOUT_RESET:
Bug 1541502 - Add Pocket menu, triggering improvements and bug fixes to Activity Stream r=k88hudson Differential Revision: https://phabricator.services.mozilla.com/D25984 --HG-- rename : browser/components/newtab/locales-src/bn-BD/strings.properties => browser/components/newtab/locales-src/bn/strings.properties rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-strings.js => browser/components/newtab/prerendered/locales/bn/activity-stream-strings.js rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream.html => browser/components/newtab/prerendered/locales/bn/activity-stream.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/trs/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream.html => browser/components/newtab/prerendered/locales/trs/activity-stream.html extra : moz-landing-system : lando
2019-04-04 17:32:55 +03:00
return {...INITIAL_STATE.DiscoveryStream, config: prevState.config};
case at.DISCOVERY_STREAM_FEEDS_UPDATE:
return {
...prevState,
feeds: {
...prevState.feeds,
data: action.data || prevState.feeds.data,
loaded: true,
},
};
case at.DISCOVERY_STREAM_SPOCS_CAPS:
return {
...prevState,
spocs: {
...prevState.spocs,
frequency_caps: [...prevState.spocs.frequency_caps, ...action.data],
},
};
case at.DISCOVERY_STREAM_SPOCS_ENDPOINT:
return {
...prevState,
spocs: {
...INITIAL_STATE.DiscoveryStream.spocs,
spocs_endpoint: action.data || INITIAL_STATE.DiscoveryStream.spocs.spocs_endpoint,
},
};
case at.DISCOVERY_STREAM_SPOCS_UPDATE:
if (action.data) {
return {
...prevState,
spocs: {
...prevState.spocs,
lastUpdated: action.data.lastUpdated,
data: action.data.spocs,
loaded: true,
},
};
}
return prevState;
Bug 1541502 - Add Pocket menu, triggering improvements and bug fixes to Activity Stream r=k88hudson Differential Revision: https://phabricator.services.mozilla.com/D25984 --HG-- rename : browser/components/newtab/locales-src/bn-BD/strings.properties => browser/components/newtab/locales-src/bn/strings.properties rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered-noscripts.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered-noscripts.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-prerendered.html => browser/components/newtab/prerendered/locales/bn/activity-stream-prerendered.html rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream-strings.js => browser/components/newtab/prerendered/locales/bn/activity-stream-strings.js rename : browser/components/newtab/prerendered/locales/bn-BD/activity-stream.html => browser/components/newtab/prerendered/locales/bn/activity-stream.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream-noscripts.html => browser/components/newtab/prerendered/locales/trs/activity-stream-noscripts.html rename : browser/components/newtab/prerendered/locales/mai/activity-stream.html => browser/components/newtab/prerendered/locales/trs/activity-stream.html extra : moz-landing-system : lando
2019-04-04 17:32:55 +03:00
case at.PLACES_LINK_BLOCKED:
return isNotReady() ? prevState :
nextState(items => items.filter(item => item.url !== action.data.url));
case at.PLACES_SAVED_TO_POCKET:
const addPocketInfo = item => {
if (item.url === action.data.url) {
return Object.assign({}, item, {
open_url: action.data.open_url,
pocket_id: action.data.pocket_id,
});
}
return item;
};
return isNotReady() ? prevState :
nextState(items => items.map(addPocketInfo));
case at.DELETE_FROM_POCKET:
case at.ARCHIVE_FROM_POCKET:
return isNotReady() ? prevState :
nextState(items => items.filter(item => item.pocket_id !== action.data.pocket_id));
case at.PLACES_BOOKMARK_ADDED:
const updateBookmarkInfo = item => {
if (item.url === action.data.url) {
const {bookmarkGuid, bookmarkTitle, dateAdded} = action.data;
return Object.assign({}, item, {
bookmarkGuid,
bookmarkTitle,
bookmarkDateCreated: dateAdded,
});
}
return item;
};
return isNotReady() ? prevState :
nextState(items => items.map(updateBookmarkInfo));
case at.PLACES_BOOKMARK_REMOVED:
const removeBookmarkInfo = item => {
if (item.url === action.data.url) {
const newSite = Object.assign({}, item);
delete newSite.bookmarkGuid;
delete newSite.bookmarkTitle;
delete newSite.bookmarkDateCreated;
return newSite;
}
return item;
};
return isNotReady() ? prevState :
nextState(items => items.map(removeBookmarkInfo));
default:
return prevState;
}
}
function Search(prevState = INITIAL_STATE.Search, action) {
switch (action.type) {
case at.HIDE_SEARCH:
return Object.assign({...prevState, hide: true});
case at.FAKE_FOCUS_SEARCH:
return Object.assign({...prevState, fakeFocus: true});
case at.SHOW_SEARCH:
return Object.assign({...prevState, hide: false, fakeFocus: false});
default:
return prevState;
}
}
this.INITIAL_STATE = INITIAL_STATE;
this.TOP_SITES_DEFAULT_ROWS = TOP_SITES_DEFAULT_ROWS;
this.TOP_SITES_MAX_SITES_PER_ROW = TOP_SITES_MAX_SITES_PER_ROW;
this.reducers = {
TopSites,
App,
ASRouter,
Snippets,
Prefs,
Dialog,
Sections,
Pocket,
DiscoveryStream,
Search,
};
const EXPORTED_SYMBOLS = [
"reducers",
"INITIAL_STATE",
"insertPinned",
"TOP_SITES_DEFAULT_ROWS",
"TOP_SITES_MAX_SITES_PER_ROW",
];