570 lines
15 KiB
JavaScript
570 lines
15 KiB
JavaScript
/******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId])
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // identity function for calling harmony imports with the correct context
|
|
/******/ __webpack_require__.i = function(value) { return value; };
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, {
|
|
/******/ configurable: false,
|
|
/******/ enumerable: true,
|
|
/******/ get: getter
|
|
/******/ });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(__webpack_require__.s = 10);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = React;
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = ReactRedux;
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/* 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/. */
|
|
|
|
|
|
const MAIN_MESSAGE_TYPE = "ActivityStream:Main";
|
|
const CONTENT_MESSAGE_TYPE = "ActivityStream:Content";
|
|
|
|
const actionTypes = ["INIT", "UNINIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_UNLOAD", "PERFORM_SEARCH", "SCREENSHOT_UPDATED", "SEARCH_STATE_UPDATED", "TOP_SITES_UPDATED"
|
|
// The line below creates an object like this:
|
|
// {
|
|
// INIT: "INIT",
|
|
// UNINIT: "UNINIT"
|
|
// }
|
|
// It prevents accidentally adding a different key/value name.
|
|
].reduce((obj, type) => {
|
|
obj[type] = type;return obj;
|
|
}, {});
|
|
|
|
// Helper function for creating routed actions between content and main
|
|
// Not intended to be used by consumers
|
|
function _RouteMessage(action, options) {
|
|
const meta = action.meta ? Object.assign({}, action.meta) : {};
|
|
if (!options || !options.from || !options.to) {
|
|
throw new Error("Routed Messages must have options as the second parameter, and must at least include a .from and .to property.");
|
|
}
|
|
// For each of these fields, if they are passed as an option,
|
|
// add them to the action. If they are not defined, remove them.
|
|
["from", "to", "toTarget", "fromTarget", "skipOrigin"].forEach(o => {
|
|
if (typeof options[o] !== "undefined") {
|
|
meta[o] = options[o];
|
|
} else if (meta[o]) {
|
|
delete meta[o];
|
|
}
|
|
});
|
|
return Object.assign({}, action, { meta });
|
|
}
|
|
|
|
/**
|
|
* SendToMain - Creates a message that will be sent to the Main process.
|
|
*
|
|
* @param {object} action Any redux action (required)
|
|
* @param {object} options
|
|
* @param {string} options.fromTarget The id of the content port from which the action originated. (optional)
|
|
* @return {object} An action with added .meta properties
|
|
*/
|
|
function SendToMain(action) {
|
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
return _RouteMessage(action, {
|
|
from: CONTENT_MESSAGE_TYPE,
|
|
to: MAIN_MESSAGE_TYPE,
|
|
fromTarget: options.fromTarget
|
|
});
|
|
}
|
|
|
|
/**
|
|
* BroadcastToContent - Creates a message that will be sent to ALL content processes.
|
|
*
|
|
* @param {object} action Any redux action (required)
|
|
* @return {object} An action with added .meta properties
|
|
*/
|
|
function BroadcastToContent(action) {
|
|
return _RouteMessage(action, {
|
|
from: MAIN_MESSAGE_TYPE,
|
|
to: CONTENT_MESSAGE_TYPE
|
|
});
|
|
}
|
|
|
|
/**
|
|
* SendToContent - Creates a message that will be sent to a particular Content process.
|
|
*
|
|
* @param {object} action Any redux action (required)
|
|
* @param {string} target The id of a content port
|
|
* @return {object} An action with added .meta properties
|
|
*/
|
|
function SendToContent(action, target) {
|
|
if (!target) {
|
|
throw new Error("You must provide a target ID as the second parameter of SendToContent. If you want to send to all content processes, use BroadcastToContent");
|
|
}
|
|
return _RouteMessage(action, {
|
|
from: MAIN_MESSAGE_TYPE,
|
|
to: CONTENT_MESSAGE_TYPE,
|
|
toTarget: target
|
|
});
|
|
}
|
|
|
|
var actionCreators = {
|
|
SendToMain,
|
|
SendToContent,
|
|
BroadcastToContent
|
|
};
|
|
|
|
// These are helpers to test for certain kinds of actions
|
|
|
|
var actionUtils = {
|
|
isSendToMain(action) {
|
|
if (!action.meta) {
|
|
return false;
|
|
}
|
|
return action.meta.to === MAIN_MESSAGE_TYPE && action.meta.from === CONTENT_MESSAGE_TYPE;
|
|
},
|
|
isBroadcastToContent(action) {
|
|
if (!action.meta) {
|
|
return false;
|
|
}
|
|
if (action.meta.to === CONTENT_MESSAGE_TYPE && !action.meta.toTarget) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
isSendToContent(action) {
|
|
if (!action.meta) {
|
|
return false;
|
|
}
|
|
if (action.meta.to === CONTENT_MESSAGE_TYPE && action.meta.toTarget) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
_RouteMessage
|
|
};
|
|
module.exports = {
|
|
actionTypes,
|
|
actionCreators,
|
|
actionUtils,
|
|
MAIN_MESSAGE_TYPE,
|
|
CONTENT_MESSAGE_TYPE
|
|
};
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const React = __webpack_require__(0);
|
|
const TopSites = __webpack_require__(8);
|
|
const Search = __webpack_require__(7);
|
|
|
|
const Base = () => React.createElement(
|
|
"div",
|
|
{ className: "outer-wrapper" },
|
|
React.createElement(
|
|
"main",
|
|
null,
|
|
React.createElement(Search, null),
|
|
React.createElement(TopSites, null)
|
|
)
|
|
);
|
|
|
|
module.exports = Base;
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* globals sendAsyncMessage, addMessageListener */
|
|
|
|
var _require = __webpack_require__(9);
|
|
|
|
const createStore = _require.createStore,
|
|
combineReducers = _require.combineReducers,
|
|
applyMiddleware = _require.applyMiddleware;
|
|
|
|
var _require2 = __webpack_require__(2);
|
|
|
|
const au = _require2.actionUtils;
|
|
|
|
|
|
const MERGE_STORE_ACTION = "NEW_TAB_INITIAL_STATE";
|
|
const OUTGOING_MESSAGE_NAME = "ActivityStream:ContentToMain";
|
|
const INCOMING_MESSAGE_NAME = "ActivityStream:MainToContent";
|
|
|
|
/**
|
|
* A higher-order function which returns a reducer that, on MERGE_STORE action,
|
|
* will return the action.data object merged into the previous state.
|
|
*
|
|
* For all other actions, it merely calls mainReducer.
|
|
*
|
|
* Because we want this to merge the entire state object, it's written as a
|
|
* higher order function which takes the main reducer (itself often a call to
|
|
* combineReducers) as a parameter.
|
|
*
|
|
* @param {function} mainReducer reducer to call if action != MERGE_STORE_ACTION
|
|
* @return {function} a reducer that, on MERGE_STORE_ACTION action,
|
|
* will return the action.data object merged
|
|
* into the previous state, and the result
|
|
* of calling mainReducer otherwise.
|
|
*/
|
|
function mergeStateReducer(mainReducer) {
|
|
return (prevState, action) => {
|
|
if (action.type === MERGE_STORE_ACTION) {
|
|
return Object.assign({}, prevState, action.data);
|
|
}
|
|
|
|
return mainReducer(prevState, action);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* messageMiddleware - Middleware that looks for SentToMain type actions, and sends them if necessary
|
|
*/
|
|
const messageMiddleware = store => next => action => {
|
|
if (au.isSendToMain(action)) {
|
|
sendAsyncMessage(OUTGOING_MESSAGE_NAME, action);
|
|
}
|
|
next(action);
|
|
};
|
|
|
|
/**
|
|
* initStore - Create a store and listen for incoming actions
|
|
*
|
|
* @param {object} reducers An object containing Redux reducers
|
|
* @return {object} A redux store
|
|
*/
|
|
module.exports = function initStore(reducers) {
|
|
const store = createStore(mergeStateReducer(combineReducers(reducers)), applyMiddleware(messageMiddleware));
|
|
|
|
addMessageListener(INCOMING_MESSAGE_NAME, msg => {
|
|
store.dispatch(msg.data);
|
|
});
|
|
|
|
return store;
|
|
};
|
|
|
|
module.exports.MERGE_STORE_ACTION = MERGE_STORE_ACTION;
|
|
module.exports.OUTGOING_MESSAGE_NAME = OUTGOING_MESSAGE_NAME;
|
|
module.exports.INCOMING_MESSAGE_NAME = INCOMING_MESSAGE_NAME;
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/* 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/. */
|
|
|
|
|
|
var _require = __webpack_require__(2);
|
|
|
|
const at = _require.actionTypes;
|
|
|
|
|
|
const INITIAL_STATE = {
|
|
TopSites: {
|
|
init: false,
|
|
rows: []
|
|
},
|
|
Search: {
|
|
currentEngine: {
|
|
name: "",
|
|
icon: ""
|
|
},
|
|
engines: []
|
|
}
|
|
};
|
|
|
|
// TODO: Handle some real actions here, once we have a TopSites feed working
|
|
function TopSites() {
|
|
let prevState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : INITIAL_STATE.TopSites;
|
|
let action = arguments[1];
|
|
|
|
let hasMatch;
|
|
let newRows;
|
|
switch (action.type) {
|
|
case at.TOP_SITES_UPDATED:
|
|
if (!action.data) {
|
|
return prevState;
|
|
}
|
|
return Object.assign({}, prevState, { init: true, rows: action.data });
|
|
case at.SCREENSHOT_UPDATED:
|
|
newRows = prevState.rows.map(row => {
|
|
if (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;
|
|
default:
|
|
return prevState;
|
|
}
|
|
}
|
|
|
|
function Search() {
|
|
let prevState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : INITIAL_STATE.Search;
|
|
let action = arguments[1];
|
|
|
|
switch (action.type) {
|
|
case at.SEARCH_STATE_UPDATED:
|
|
{
|
|
if (!action.data) {
|
|
return prevState;
|
|
}
|
|
var _action$data = action.data;
|
|
let currentEngine = _action$data.currentEngine,
|
|
engines = _action$data.engines;
|
|
|
|
return Object.assign({}, prevState, {
|
|
currentEngine,
|
|
engines
|
|
});
|
|
}
|
|
default:
|
|
return prevState;
|
|
}
|
|
}
|
|
var reducers = { TopSites, Search };
|
|
module.exports = {
|
|
reducers,
|
|
INITIAL_STATE
|
|
};
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = ReactDOM;
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const React = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(1);
|
|
|
|
const connect = _require.connect;
|
|
|
|
var _require2 = __webpack_require__(2);
|
|
|
|
const actionTypes = _require2.actionTypes,
|
|
actionCreators = _require2.actionCreators;
|
|
|
|
|
|
const Search = React.createClass({
|
|
displayName: "Search",
|
|
|
|
getInitialState() {
|
|
return { searchString: "" };
|
|
},
|
|
performSearch(options) {
|
|
let searchData = {
|
|
engineName: options.engineName,
|
|
searchString: options.searchString,
|
|
searchPurpose: "newtab",
|
|
healthReportKey: "newtab"
|
|
};
|
|
this.props.dispatch(actionCreators.SendToMain({ type: actionTypes.PERFORM_SEARCH, data: searchData }));
|
|
},
|
|
onClick(event) {
|
|
const currentEngine = this.props.Search.currentEngine;
|
|
|
|
event.preventDefault();
|
|
this.performSearch({ engineName: currentEngine.name, searchString: this.state.searchString });
|
|
},
|
|
onChange(event) {
|
|
this.setState({ searchString: event.target.value });
|
|
},
|
|
render() {
|
|
return React.createElement(
|
|
"form",
|
|
{ className: "search-wrapper" },
|
|
React.createElement("span", { className: "search-label" }),
|
|
React.createElement("input", { value: this.state.searchString, type: "search",
|
|
onChange: this.onChange,
|
|
maxLength: "256", title: "Submit search",
|
|
placeholder: "Search the Web" }),
|
|
React.createElement("button", { onClick: this.onClick })
|
|
);
|
|
}
|
|
});
|
|
|
|
module.exports = connect(state => ({ Search: state.Search }))(Search);
|
|
|
|
/***/ }),
|
|
/* 8 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
const React = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(1);
|
|
|
|
const connect = _require.connect;
|
|
|
|
|
|
function displayURL(url) {
|
|
return new URL(url).hostname.replace(/^www./, "");
|
|
}
|
|
|
|
const TopSites = props => React.createElement(
|
|
"section",
|
|
null,
|
|
React.createElement(
|
|
"h3",
|
|
{ className: "section-title" },
|
|
"Top Sites"
|
|
),
|
|
React.createElement(
|
|
"ul",
|
|
{ className: "top-sites-list" },
|
|
props.TopSites.rows.map(link => {
|
|
const title = displayURL(link.url);
|
|
const className = `screenshot${link.screenshot ? " active" : ""}`;
|
|
const style = { backgroundImage: link.screenshot ? `url(${link.screenshot})` : "none" };
|
|
return React.createElement(
|
|
"li",
|
|
{ key: link.url },
|
|
React.createElement(
|
|
"a",
|
|
{ href: link.url },
|
|
React.createElement(
|
|
"div",
|
|
{ className: "tile" },
|
|
React.createElement(
|
|
"span",
|
|
{ className: "letter-fallback", ariaHidden: true },
|
|
title[0]
|
|
),
|
|
React.createElement("div", { className: className, style: style })
|
|
),
|
|
React.createElement(
|
|
"div",
|
|
{ className: "title" },
|
|
title
|
|
)
|
|
)
|
|
);
|
|
})
|
|
)
|
|
);
|
|
|
|
module.exports = connect(state => ({ TopSites: state.TopSites }))(TopSites);
|
|
|
|
/***/ }),
|
|
/* 9 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = Redux;
|
|
|
|
/***/ }),
|
|
/* 10 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* globals addMessageListener, removeMessageListener */
|
|
const React = __webpack_require__(0);
|
|
const ReactDOM = __webpack_require__(6);
|
|
const Base = __webpack_require__(3);
|
|
|
|
var _require = __webpack_require__(1);
|
|
|
|
const Provider = _require.Provider;
|
|
|
|
const initStore = __webpack_require__(4);
|
|
|
|
var _require2 = __webpack_require__(5);
|
|
|
|
const reducers = _require2.reducers;
|
|
|
|
|
|
const store = initStore(reducers);
|
|
|
|
ReactDOM.render(React.createElement(
|
|
Provider,
|
|
{ store: store },
|
|
React.createElement(Base, null)
|
|
), document.getElementById("root"));
|
|
|
|
/***/ })
|
|
/******/ ]); |