2017-04-04 19:57:53 +03:00
|
|
|
/* 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";
|
|
|
|
|
2018-01-30 02:20:18 +03:00
|
|
|
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});
|
|
|
|
const {Dedupe} = ChromeUtils.import("resource://activity-stream/common/Dedupe.jsm", {});
|
2017-04-25 23:31:29 +03:00
|
|
|
|
2018-02-09 22:23:51 +03:00
|
|
|
const TOP_SITES_DEFAULT_ROWS = 1;
|
|
|
|
const TOP_SITES_MAX_SITES_PER_ROW = 8;
|
2017-08-17 21:10:59 +03:00
|
|
|
|
2017-10-14 00:22:17 +03:00
|
|
|
const dedupe = new Dedupe(site => site && site.url);
|
|
|
|
|
2017-04-25 23:31:29 +03:00
|
|
|
const INITIAL_STATE = {
|
2017-05-10 02:09:43 +03:00
|
|
|
App: {
|
|
|
|
// Have we received real data from the app yet?
|
2018-09-20 21:36:20 +03:00
|
|
|
initialized: false,
|
|
|
|
},
|
|
|
|
ASRouter: {
|
|
|
|
initialized: false,
|
|
|
|
allowLegacySnippets: null,
|
2017-05-10 02:09:43 +03:00
|
|
|
},
|
2017-07-20 23:59:59 +03:00
|
|
|
Snippets: {initialized: false},
|
2017-04-04 19:57:53 +03:00
|
|
|
TopSites: {
|
2017-05-10 02:09:43 +03:00
|
|
|
// Have we received real data from history yet?
|
|
|
|
initialized: false,
|
|
|
|
// The history (and possibly default) links
|
2017-09-20 22:45:26 +03:00
|
|
|
rows: [],
|
2018-02-03 01:09:17 +03:00
|
|
|
// Used in content only to dispatch action to TopSiteForm.
|
2018-08-11 01:59:54 +03:00
|
|
|
editForm: null,
|
|
|
|
// Used in content only to open the SearchShortcutsForm modal.
|
|
|
|
showSearchShortcutsForm: false,
|
|
|
|
// The list of available search shortcuts.
|
2018-09-20 21:36:20 +03:00
|
|
|
searchShortcuts: [],
|
2017-06-13 00:26:21 +03:00
|
|
|
},
|
|
|
|
Prefs: {
|
|
|
|
initialized: false,
|
2018-09-20 21:36:20 +03:00
|
|
|
values: {},
|
2017-06-29 02:47:23 +03:00
|
|
|
},
|
|
|
|
Dialog: {
|
|
|
|
visible: false,
|
2018-09-20 21:36:20 +03:00
|
|
|
data: {},
|
2017-07-20 23:59:59 +03:00
|
|
|
},
|
2018-08-29 17:08:31 +03:00
|
|
|
Sections: [],
|
2018-08-31 21:19:47 +03:00
|
|
|
Pocket: {
|
2018-09-20 21:36:20 +03:00
|
|
|
isUserLoggedIn: null,
|
2018-08-31 21:19:47 +03:00
|
|
|
pocketCta: {},
|
2018-09-20 21:36:20 +03:00
|
|
|
waitingForSpoc: true,
|
|
|
|
},
|
2019-01-03 04:23:21 +03:00
|
|
|
// 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: [],
|
2019-01-07 23:25:46 +03:00
|
|
|
lastUpdated: null,
|
|
|
|
feeds: {
|
|
|
|
// "https://foo.com/feed1": {lastUpdated: 123, data: []}
|
|
|
|
},
|
2019-01-16 17:56:28 +03:00
|
|
|
spocs: {
|
|
|
|
spocs_endpoint: "",
|
|
|
|
lastUpdated: null,
|
2019-01-17 23:53:45 +03:00
|
|
|
data: {}, // {spocs: []}
|
2019-01-16 17:56:28 +03:00
|
|
|
},
|
2019-01-03 04:23:21 +03:00
|
|
|
},
|
|
|
|
Search: {
|
|
|
|
// Pretend the search box is focused after handing off to AwesomeBar.
|
|
|
|
focus: false,
|
|
|
|
// Hide the search box after handing off to AwesomeBar and user starts typing.
|
|
|
|
hide: false,
|
|
|
|
},
|
2017-04-04 19:57:53 +03:00
|
|
|
};
|
|
|
|
|
2017-05-10 02:09:43 +03:00
|
|
|
function App(prevState = INITIAL_STATE.App, action) {
|
|
|
|
switch (action.type) {
|
|
|
|
case at.INIT:
|
2017-08-02 08:24:42 +03:00
|
|
|
return Object.assign({}, prevState, action.data || {}, {initialized: true});
|
2017-05-10 02:09:43 +03:00
|
|
|
default:
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-20 21:36:20 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-10 03:04:38 +03:00
|
|
|
/**
|
|
|
|
* 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; }
|
2017-08-17 21:10:59 +03:00
|
|
|
let link = Object.assign({}, val, {isPinned: true, pinIndex: index});
|
2017-07-10 03:04:38 +03:00
|
|
|
if (index > newLinks.length) {
|
|
|
|
newLinks[index] = link;
|
|
|
|
} else {
|
|
|
|
newLinks.splice(index, 0, link);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return newLinks;
|
|
|
|
}
|
|
|
|
|
2017-04-04 19:57:53 +03:00
|
|
|
function TopSites(prevState = INITIAL_STATE.TopSites, action) {
|
2017-04-25 23:31:29 +03:00
|
|
|
let hasMatch;
|
|
|
|
let newRows;
|
|
|
|
switch (action.type) {
|
|
|
|
case at.TOP_SITES_UPDATED:
|
2018-03-29 21:21:54 +03:00
|
|
|
if (!action.data || !action.data.links) {
|
2017-04-25 23:31:29 +03:00
|
|
|
return prevState;
|
|
|
|
}
|
2018-03-29 21:21:54 +03:00
|
|
|
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});
|
2017-09-20 22:45:26 +03:00
|
|
|
case at.TOP_SITES_EDIT:
|
2018-03-23 22:20:10 +03:00
|
|
|
return Object.assign({}, prevState, {
|
|
|
|
editForm: {
|
|
|
|
index: action.data.index,
|
2018-09-20 21:36:20 +03:00
|
|
|
previewResponse: null,
|
|
|
|
},
|
2018-03-23 22:20:10 +03:00
|
|
|
});
|
2017-09-20 22:45:26 +03:00
|
|
|
case at.TOP_SITES_CANCEL_EDIT:
|
2018-02-03 01:09:17 +03:00
|
|
|
return Object.assign({}, prevState, {editForm: null});
|
2018-08-11 01:59:54 +03:00
|
|
|
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});
|
2018-03-23 22:20:10 +03:00
|
|
|
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,
|
2018-09-20 21:36:20 +03:00
|
|
|
previewUrl: action.data.url,
|
|
|
|
},
|
2018-03-23 22:20:10 +03:00
|
|
|
});
|
|
|
|
case at.PREVIEW_REQUEST:
|
|
|
|
if (!prevState.editForm) {
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
return Object.assign({}, prevState, {
|
|
|
|
editForm: {
|
|
|
|
index: prevState.editForm.index,
|
|
|
|
previewResponse: null,
|
2018-09-20 21:36:20 +03:00
|
|
|
previewUrl: action.data.url,
|
|
|
|
},
|
2018-03-23 22:20:10 +03:00
|
|
|
});
|
|
|
|
case at.PREVIEW_REQUEST_CANCEL:
|
|
|
|
if (!prevState.editForm) {
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
return Object.assign({}, prevState, {
|
|
|
|
editForm: {
|
|
|
|
index: prevState.editForm.index,
|
2018-09-20 21:36:20 +03:00
|
|
|
previewResponse: null,
|
|
|
|
},
|
2018-03-23 22:20:10 +03:00
|
|
|
});
|
2017-04-25 23:31:29 +03:00
|
|
|
case at.SCREENSHOT_UPDATED:
|
|
|
|
newRows = prevState.rows.map(row => {
|
2017-07-10 03:04:38 +03:00
|
|
|
if (row && row.url === action.data.url) {
|
2017-04-25 23:31:29 +03:00
|
|
|
hasMatch = true;
|
|
|
|
return Object.assign({}, row, {screenshot: action.data.screenshot});
|
|
|
|
}
|
|
|
|
return row;
|
|
|
|
});
|
|
|
|
return hasMatch ? Object.assign({}, prevState, {rows: newRows}) : prevState;
|
2017-05-10 02:09:43 +03:00
|
|
|
case at.PLACES_BOOKMARK_ADDED:
|
2017-07-20 23:59:59 +03:00
|
|
|
if (!action.data) {
|
|
|
|
return prevState;
|
|
|
|
}
|
2017-05-10 02:09:43 +03:00
|
|
|
newRows = prevState.rows.map(site => {
|
2017-07-10 03:04:38 +03:00
|
|
|
if (site && site.url === action.data.url) {
|
2017-09-08 17:43:37 +03:00
|
|
|
const {bookmarkGuid, bookmarkTitle, dateAdded} = action.data;
|
|
|
|
return Object.assign({}, site, {bookmarkGuid, bookmarkTitle, bookmarkDateCreated: dateAdded});
|
2017-05-10 02:09:43 +03:00
|
|
|
}
|
|
|
|
return site;
|
|
|
|
});
|
|
|
|
return Object.assign({}, prevState, {rows: newRows});
|
|
|
|
case at.PLACES_BOOKMARK_REMOVED:
|
2017-07-20 23:59:59 +03:00
|
|
|
if (!action.data) {
|
|
|
|
return prevState;
|
|
|
|
}
|
2017-05-10 02:09:43 +03:00
|
|
|
newRows = prevState.rows.map(site => {
|
2017-07-10 03:04:38 +03:00
|
|
|
if (site && site.url === action.data.url) {
|
2017-05-10 02:09:43 +03:00
|
|
|
const newSite = Object.assign({}, site);
|
|
|
|
delete newSite.bookmarkGuid;
|
|
|
|
delete newSite.bookmarkTitle;
|
|
|
|
delete newSite.bookmarkDateCreated;
|
|
|
|
return newSite;
|
|
|
|
}
|
|
|
|
return site;
|
|
|
|
});
|
|
|
|
return Object.assign({}, prevState, {rows: newRows});
|
2018-03-29 21:21:54 +03:00
|
|
|
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});
|
2018-08-11 01:59:54 +03:00
|
|
|
case at.UPDATE_SEARCH_SHORTCUTS:
|
|
|
|
return {...prevState, searchShortcuts: action.data.searchShortcuts};
|
2018-09-20 21:36:20 +03:00
|
|
|
case at.SNIPPETS_PREVIEW_MODE:
|
|
|
|
return {...prevState, rows: []};
|
2017-04-25 23:31:29 +03:00
|
|
|
default:
|
|
|
|
return prevState;
|
|
|
|
}
|
2017-04-04 19:57:53 +03:00
|
|
|
}
|
|
|
|
|
2017-06-29 02:47:23 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 00:26:21 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-20 23:59:59 +03:00
|
|
|
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;
|
|
|
|
});
|
2018-03-08 20:15:11 +03:00
|
|
|
// Otherwise, append it
|
2017-07-20 23:59:59 +03:00
|
|
|
if (!hasMatch) {
|
2017-09-02 00:52:57 +03:00
|
|
|
const initialized = !!(action.data.rows && action.data.rows.length > 0);
|
2018-03-08 20:15:11 +03:00
|
|
|
const section = Object.assign({title: "", rows: [], enabled: false}, action.data, {initialized});
|
|
|
|
newState.push(section);
|
2017-07-20 23:59:59 +03:00
|
|
|
}
|
|
|
|
return newState;
|
2017-08-25 13:37:52 +03:00
|
|
|
case at.SECTION_UPDATE:
|
2017-10-14 00:22:17 +03:00
|
|
|
newState = prevState.map(section => {
|
2017-07-20 23:59:59 +03:00
|
|
|
if (section && section.id === action.data.id) {
|
2017-09-02 00:52:57 +03:00
|
|
|
// 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} : {};
|
2018-03-01 22:21:00 +03:00
|
|
|
|
|
|
|
// 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) {
|
2018-11-06 18:43:41 +03:00
|
|
|
// Only add it if it's not already there.
|
|
|
|
if (rows[index].guid !== card.guid) {
|
|
|
|
rows.splice(index, 0, card);
|
|
|
|
}
|
2018-03-01 22:21:00 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return Object.assign({}, section, initialized, Object.assign({}, action.data, {rows}));
|
|
|
|
}
|
|
|
|
|
2017-09-02 00:52:57 +03:00
|
|
|
return Object.assign({}, section, initialized, action.data);
|
2017-07-20 23:59:59 +03:00
|
|
|
}
|
|
|
|
return section;
|
|
|
|
});
|
2017-10-14 00:22:17 +03:00
|
|
|
|
|
|
|
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;
|
2017-09-13 02:00:14 +03:00
|
|
|
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;
|
|
|
|
});
|
2017-07-25 01:31:35 +03:00
|
|
|
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) {
|
2017-09-08 17:43:37 +03:00
|
|
|
const {bookmarkGuid, bookmarkTitle, dateAdded} = action.data;
|
2017-10-14 00:22:17 +03:00
|
|
|
return Object.assign({}, item, {
|
|
|
|
bookmarkGuid,
|
|
|
|
bookmarkTitle,
|
|
|
|
bookmarkDateCreated: dateAdded,
|
2018-09-20 21:36:20 +03:00
|
|
|
type: "bookmark",
|
2017-10-14 00:22:17 +03:00
|
|
|
});
|
2017-07-25 01:31:35 +03:00
|
|
|
}
|
|
|
|
return item;
|
2018-09-20 21:36:20 +03:00
|
|
|
}),
|
2017-07-25 01:31:35 +03:00
|
|
|
}));
|
2018-02-23 23:36:37 +03:00
|
|
|
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, {
|
2018-03-01 22:21:00 +03:00
|
|
|
open_url: action.data.open_url,
|
2018-02-23 23:36:37 +03:00
|
|
|
pocket_id: action.data.pocket_id,
|
|
|
|
title: action.data.title,
|
2018-09-20 21:36:20 +03:00
|
|
|
type: "pocket",
|
2018-02-23 23:36:37 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return item;
|
2018-09-20 21:36:20 +03:00
|
|
|
}),
|
2018-02-23 23:36:37 +03:00
|
|
|
}));
|
2017-07-25 01:31:35 +03:00
|
|
|
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;
|
2017-09-08 17:43:37 +03:00
|
|
|
if (!newSite.type || newSite.type === "bookmark") {
|
|
|
|
newSite.type = "history";
|
|
|
|
}
|
2017-07-25 01:31:35 +03:00
|
|
|
return newSite;
|
|
|
|
}
|
|
|
|
return item;
|
2018-09-20 21:36:20 +03:00
|
|
|
}),
|
2017-07-25 01:31:35 +03:00
|
|
|
}));
|
2018-03-29 21:21:54 +03:00
|
|
|
case at.PLACES_LINK_DELETED:
|
2017-07-20 23:59:59 +03:00
|
|
|
case at.PLACES_LINK_BLOCKED:
|
2018-03-29 21:21:54 +03:00
|
|
|
if (!action.data) {
|
|
|
|
return prevState;
|
|
|
|
}
|
2017-07-20 23:59:59 +03:00
|
|
|
return prevState.map(section =>
|
|
|
|
Object.assign({}, section, {rows: section.rows.filter(site => site.url !== action.data.url)}));
|
2018-02-23 23:36:37 +03:00
|
|
|
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)}));
|
2018-09-20 21:36:20 +03:00
|
|
|
case at.SNIPPETS_PREVIEW_MODE:
|
|
|
|
return prevState.map(section => ({...section, rows: []}));
|
2017-07-20 23:59:59 +03:00
|
|
|
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);
|
2018-03-08 20:15:11 +03:00
|
|
|
case at.SNIPPET_BLOCKED:
|
|
|
|
return Object.assign({}, prevState, {blockList: prevState.blockList.concat(action.data)});
|
|
|
|
case at.SNIPPETS_BLOCKLIST_CLEARED:
|
|
|
|
return Object.assign({}, prevState, {blockList: []});
|
2017-07-20 23:59:59 +03:00
|
|
|
case at.SNIPPETS_RESET:
|
|
|
|
return INITIAL_STATE.Snippets;
|
|
|
|
default:
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-29 17:08:31 +03:00
|
|
|
function Pocket(prevState = INITIAL_STATE.Pocket, action) {
|
|
|
|
switch (action.type) {
|
|
|
|
case at.POCKET_WAITING_FOR_SPOC:
|
|
|
|
return {...prevState, waitingForSpoc: action.data};
|
2018-08-31 21:19:47 +03:00
|
|
|
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,
|
2018-09-20 21:36:20 +03:00
|
|
|
useCta: action.data.use_cta,
|
|
|
|
},
|
2018-08-31 21:19:47 +03:00
|
|
|
};
|
2018-08-29 17:08:31 +03:00
|
|
|
default:
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-03 04:23:21 +03:00
|
|
|
function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
|
2018-12-19 04:52:03 +03:00
|
|
|
switch (action.type) {
|
2019-01-03 04:23:21 +03:00
|
|
|
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:
|
2019-01-07 23:25:46 +03:00
|
|
|
return {...prevState, lastUpdated: action.data.lastUpdated || null, layout: action.data.layout || []};
|
|
|
|
case at.DISCOVERY_STREAM_LAYOUT_RESET:
|
|
|
|
return {...prevState, lastUpdated: INITIAL_STATE.DiscoveryStream.lastUpdated, layout: INITIAL_STATE.DiscoveryStream.layout};
|
2019-01-15 02:27:45 +03:00
|
|
|
case at.DISCOVERY_STREAM_FEEDS_UPDATE:
|
|
|
|
return {...prevState, feeds: action.data || prevState.feeds};
|
2019-01-16 17:56:28 +03:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return prevState;
|
2019-01-03 04:23:21 +03:00
|
|
|
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.SHOW_SEARCH:
|
2019-01-17 23:53:45 +03:00
|
|
|
return Object.assign({...prevState, hide: false});
|
2018-12-19 04:52:03 +03:00
|
|
|
default:
|
|
|
|
return prevState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-25 23:31:29 +03:00
|
|
|
this.INITIAL_STATE = INITIAL_STATE;
|
2018-02-03 01:09:17 +03:00
|
|
|
this.TOP_SITES_DEFAULT_ROWS = TOP_SITES_DEFAULT_ROWS;
|
|
|
|
this.TOP_SITES_MAX_SITES_PER_ROW = TOP_SITES_MAX_SITES_PER_ROW;
|
2017-07-20 23:59:59 +03:00
|
|
|
|
2019-01-03 04:23:21 +03:00
|
|
|
this.reducers = {
|
|
|
|
TopSites,
|
|
|
|
App,
|
|
|
|
ASRouter,
|
|
|
|
Snippets,
|
|
|
|
Prefs,
|
|
|
|
Dialog,
|
|
|
|
Sections,
|
|
|
|
Pocket,
|
|
|
|
DiscoveryStream,
|
|
|
|
Search,
|
|
|
|
};
|
2017-04-04 19:57:53 +03:00
|
|
|
|
2019-01-03 04:23:21 +03:00
|
|
|
const EXPORTED_SYMBOLS = [
|
|
|
|
"reducers",
|
|
|
|
"INITIAL_STATE",
|
|
|
|
"insertPinned",
|
|
|
|
"TOP_SITES_DEFAULT_ROWS",
|
|
|
|
"TOP_SITES_MAX_SITES_PER_ROW",
|
|
|
|
];
|