├── .babelrc
├── .editorconfig
├── .gitattributes
├── .gitignore
├── README.md
├── app
├── _locales
│ └── en
│ │ └── messages.json
├── images
│ ├── icon-128.png
│ ├── icon-16.png
│ ├── icon-19.png
│ └── icon-38.png
├── manifest.json
├── options.html
├── popup.html
├── scripts
│ ├── background.js
│ ├── background_bundle.js
│ ├── chromereload.js
│ ├── content.js
│ └── content_bundle.js
└── styles
│ └── main.css
├── devServer.js
├── gulpfile.js
├── package.json
├── src
└── scripts
│ ├── background.js
│ ├── background
│ └── index.js
│ ├── content.js
│ ├── content
│ └── index.js
│ ├── options.js
│ ├── options
│ ├── components
│ │ └── Options.js
│ └── index.js
│ ├── popup.js
│ ├── popup
│ ├── components
│ │ └── Popup.js
│ └── index.js
│ └── shared
│ ├── actions
│ └── chromeExtension.js
│ ├── containers
│ └── createContainer.js
│ ├── helpers
│ ├── createInitState.js
│ └── getState.js
│ ├── initStorage.js
│ ├── reducers
│ └── chromeExtension.js
│ └── store
│ └── configureStore.js
├── webpack.config.dev.js
└── webpack.config.prod.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react"],
3 | "plugins": ["react-hot-loader/babel"]
4 | }
5 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 |
10 | # Change these settings to your own preference
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.json]
15 | indent_size = 2
16 |
17 | # We recommend you to keep these unchanged
18 | end_of_line = lf
19 | charset = utf-8
20 | trim_trailing_whitespace = true
21 | insert_final_newline = true
22 |
23 | [*.md]
24 | trim_trailing_whitespace = false
25 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | temp
3 | .tmp
4 | dist
5 | .sass-cache
6 | app/bower_components
7 | test/bower_components
8 | package
9 |
10 | npm-debug.log
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #Redux Chrome Extension
2 |
3 | **work in progress**
4 |
5 |
6 | A starter boilerplate for a Chrome Extension using Redux and React.js.
7 | It handles store syncing throughout the whole Extension.
8 | Uses React for Popup window UI. Console.log in every part of extensions for better debugging.
9 | Implemets Redux Counter example (https://github.com/rackt/redux/tree/master/examples/counter).
10 |
11 |
12 | https://developer.chrome.com/extensions/getstarted#unpacked
13 |
14 | ## Installation
15 |
16 | `npm i`
17 |
18 | ## Development
19 |
20 |
21 | `npm start`
22 |
23 |
24 | Browserify and Watchify are used for building scripts and it's blazing fast. For more details see: (https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md)
25 | - after running, please Reload just once manually to establish the connection for livereload
26 |
27 |
28 | 1. In Chrome open chrome://extensions/
29 | 2. Select Developer mode
30 | 3. Click on Load unpacked extension
31 | 4. Add /dist folder
32 |
33 |
34 | - You can gen more info by reading comments /src/files
35 | - There is also distinction between which code belong to example a which code is React/Redux itself
36 |
37 | ##Schema
38 |
39 | Uses (https://developer.chrome.com/extensions/messaging)
40 |
41 | **Background Page**
42 | - gets persistent data for initial state from localStorage (options, user)
43 | - passes state to Popup Window and Content Scripts and Options
44 | - receives state updates from Popup Window, Content Scripts and Options
45 | - saves changes in persistent property to localStorage
46 |
47 | **Popup Window**
48 | - gets initial state from Background Page
49 | - dispatches state updates to Background Page (and optionally to Content Scripts)
50 |
51 | **Content Script**
52 | - gets initial state from Background Page
53 | - receives state updates from Popup window
54 | - dispatches state updates to Background Page (and optionally to the rest of Content Scripts)
55 |
56 |
57 | **Options Page**
58 | - gets initial state from Background Page
59 | - dispatches state updates to Background Page
60 |
61 | *** code for functionality that is in parenthesis was commented out, see src/content.index.js and src/popup/index.js ***
62 |
63 |
64 | ## Example App
65 | - There is an example counter application
66 | - Extension's code is located in /app folder
67 | - **Do not edit files in app/scripts/* directly, it will be overwritten**
68 |
69 | ## Releasing
70 |
71 | ```bash
72 | gulp release
73 | ```
74 |
75 | You can find .zip packages in the /dist folder.
76 |
77 | ##Data passing
78 | If you understand the Schema above, you see that not every part of extension talk to each other.
79 | That's because of in certain cases it doesn't make sense to notify the part, that would otherwise load the whole state from Background Page again.
80 |
81 |
82 | It's not possible to have Content Script and Popup Window active both in the same time, since Popup Window is autoclosing when it loses focus, and after each invoking it's fetching the state from Background Page.
83 | So it doesn't make sense to send any changes from Content Script to Popup Window. Same with Popup Window and Options.
84 |
85 |
86 | On the other hand Content Script is living behind every tab all the time, so we need to propagate store changes in Popop Window to Content Scripts immediately.
87 |
88 |
89 | ##Storage
90 | All the data we need to keep stored in extension after closing Chrome or disabling Extension are being saved to localStorage.
91 |
92 |
93 | You can modify localStorage indirectly by changing `state.persistent` property, like Options page in example.
94 |
95 |
96 |
97 | ##TODO
98 |
99 | - Hot loading of Reducers
100 |
101 | - Testing
102 |
103 | - Issues and pull requests are always welcome!!
104 |
105 |
106 | Thanks to
107 |
108 | https://github.com/schovi/webpack-chrome-extension
109 |
--------------------------------------------------------------------------------
/app/_locales/en/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "appName": {
3 | "message": "Redux-chrome-extension",
4 | "description": "The name of the application"
5 | },
6 | "appDescription": {
7 | "message": "A starter boilerplate for a Chrome Extension using Redux and React.js.",
8 | "description": "The description of the application"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/images/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ladas-larry/redux-chrome-extension/b2035ed97eff27b08bd428421c78da56d24d445b/app/images/icon-128.png
--------------------------------------------------------------------------------
/app/images/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ladas-larry/redux-chrome-extension/b2035ed97eff27b08bd428421c78da56d24d445b/app/images/icon-16.png
--------------------------------------------------------------------------------
/app/images/icon-19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ladas-larry/redux-chrome-extension/b2035ed97eff27b08bd428421c78da56d24d445b/app/images/icon-19.png
--------------------------------------------------------------------------------
/app/images/icon-38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ladas-larry/redux-chrome-extension/b2035ed97eff27b08bd428421c78da56d24d445b/app/images/icon-38.png
--------------------------------------------------------------------------------
/app/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "__MSG_appName__",
3 | "version": "1.0.1",
4 | "manifest_version": 2,
5 | "description": "__MSG_appDescription__",
6 | "icons": {
7 | "16": "images/icon-16.png",
8 | "128": "images/icon-128.png"
9 | },
10 | "default_locale": "en",
11 | "background": {
12 | "scripts": [
13 | "scripts/chromereload.js",
14 | "scripts/background_bundle.js"
15 | ]
16 | },
17 | "browser_action": {
18 | "default_icon": {
19 | "19": "images/icon-19.png",
20 | "38": "images/icon-38.png"
21 | },
22 | "default_title": "Redux Chrome Extension",
23 | "default_popup": "popup.html"
24 | },
25 | "options_ui": {
26 | "page": "options.html",
27 | "chrome_style": true
28 | },
29 | "content_scripts": [
30 | {
31 | "matches": [
32 | "http://*/*",
33 | "https://*/*"
34 | ],
35 | "js": [
36 | "/scripts/content_bundle.js"
37 | ],
38 | "run_at": "document_end",
39 | "all_frames": false
40 | }
41 | ],
42 | "permissions": [
43 | "tabs",
44 | "http://*/*",
45 | "https://*/*"
46 | ],
47 | "content_security_policy": "script-src 'self' 'unsafe-eval' http://localhost:3000; object-src 'self'; "
48 | }
49 |
--------------------------------------------------------------------------------
/app/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Redux Chrome Extension Options
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Redux Chrome Extension
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/scripts/background.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) {
49 | for (var i = 1; i < arguments.length; i++) {
50 | args[i - 1] = arguments[i];
51 | }
52 | }
53 | queue.push(new Item(fun, args));
54 | if (queue.length === 1 && !draining) {
55 | setTimeout(drainQueue, 0);
56 | }
57 | };
58 |
59 | // v8 likes predictible objects
60 | function Item(fun, array) {
61 | this.fun = fun;
62 | this.array = array;
63 | }
64 | Item.prototype.run = function () {
65 | this.fun.apply(null, this.array);
66 | };
67 | process.title = 'browser';
68 | process.browser = true;
69 | process.env = {};
70 | process.argv = [];
71 | process.version = ''; // empty string to avoid regexp issues
72 | process.versions = {};
73 |
74 | function noop() {}
75 |
76 | process.on = noop;
77 | process.addListener = noop;
78 | process.once = noop;
79 | process.off = noop;
80 | process.removeListener = noop;
81 | process.removeAllListeners = noop;
82 | process.emit = noop;
83 |
84 | process.binding = function (name) {
85 | throw new Error('process.binding is not supported');
86 | };
87 |
88 | process.cwd = function () { return '/' };
89 | process.chdir = function (dir) {
90 | throw new Error('process.chdir is not supported');
91 | };
92 | process.umask = function() { return 0; };
93 |
94 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux-thunk/lib/index.js":[function(require,module,exports){
95 | 'use strict';
96 |
97 | exports.__esModule = true;
98 | exports['default'] = thunkMiddleware;
99 |
100 | function thunkMiddleware(_ref) {
101 | var dispatch = _ref.dispatch;
102 | var getState = _ref.getState;
103 |
104 | return function (next) {
105 | return function (action) {
106 | return typeof action === 'function' ? action(dispatch, getState) : next(action);
107 | };
108 | };
109 | }
110 |
111 | module.exports = exports['default'];
112 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js":[function(require,module,exports){
113 | 'use strict';
114 |
115 | exports.__esModule = true;
116 | exports['default'] = createStore;
117 |
118 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
119 |
120 | var _utilsIsPlainObject = require('./utils/isPlainObject');
121 |
122 | var _utilsIsPlainObject2 = _interopRequireDefault(_utilsIsPlainObject);
123 |
124 | /**
125 | * These are private action types reserved by Redux.
126 | * For any unknown actions, you must return the current state.
127 | * If the current state is undefined, you must return the initial state.
128 | * Do not reference these action types directly in your code.
129 | */
130 | var ActionTypes = {
131 | INIT: '@@redux/INIT'
132 | };
133 |
134 | exports.ActionTypes = ActionTypes;
135 | /**
136 | * Creates a Redux store that holds the state tree.
137 | * The only way to change the data in the store is to call `dispatch()` on it.
138 | *
139 | * There should only be a single store in your app. To specify how different
140 | * parts of the state tree respond to actions, you may combine several reducers
141 | * into a single reducer function by using `combineReducers`.
142 | *
143 | * @param {Function} reducer A function that returns the next state tree, given
144 | * the current state tree and the action to handle.
145 | *
146 | * @param {any} [initialState] The initial state. You may optionally specify it
147 | * to hydrate the state from the server in universal apps, or to restore a
148 | * previously serialized user session.
149 | * If you use `combineReducers` to produce the root reducer function, this must be
150 | * an object with the same shape as `combineReducers` keys.
151 | *
152 | * @returns {Store} A Redux store that lets you read the state, dispatch actions
153 | * and subscribe to changes.
154 | */
155 |
156 | function createStore(reducer, initialState) {
157 | if (typeof reducer !== 'function') {
158 | throw new Error('Expected the reducer to be a function.');
159 | }
160 |
161 | var currentReducer = reducer;
162 | var currentState = initialState;
163 | var listeners = [];
164 | var isDispatching = false;
165 |
166 | /**
167 | * Reads the state tree managed by the store.
168 | *
169 | * @returns {any} The current state tree of your application.
170 | */
171 | function getState() {
172 | return currentState;
173 | }
174 |
175 | /**
176 | * Adds a change listener. It will be called any time an action is dispatched,
177 | * and some part of the state tree may potentially have changed. You may then
178 | * call `getState()` to read the current state tree inside the callback.
179 | *
180 | * @param {Function} listener A callback to be invoked on every dispatch.
181 | * @returns {Function} A function to remove this change listener.
182 | */
183 | function subscribe(listener) {
184 | listeners.push(listener);
185 |
186 | return function unsubscribe() {
187 | var index = listeners.indexOf(listener);
188 | listeners.splice(index, 1);
189 | };
190 | }
191 |
192 | /**
193 | * Dispatches an action. It is the only way to trigger a state change.
194 | *
195 | * The `reducer` function, used to create the store, will be called with the
196 | * current state tree and the given `action`. Its return value will
197 | * be considered the **next** state of the tree, and the change listeners
198 | * will be notified.
199 | *
200 | * The base implementation only supports plain object actions. If you want to
201 | * dispatch a Promise, an Observable, a thunk, or something else, you need to
202 | * wrap your store creating function into the corresponding middleware. For
203 | * example, see the documentation for the `redux-thunk` package. Even the
204 | * middleware will eventually dispatch plain object actions using this method.
205 | *
206 | * @param {Object} action A plain object representing “what changed”. It is
207 | * a good idea to keep actions serializable so you can record and replay user
208 | * sessions, or use the time travelling `redux-devtools`. An action must have
209 | * a `type` property which may not be `undefined`. It is a good idea to use
210 | * string constants for action types.
211 | *
212 | * @returns {Object} For convenience, the same action object you dispatched.
213 | *
214 | * Note that, if you use a custom middleware, it may wrap `dispatch()` to
215 | * return something else (for example, a Promise you can await).
216 | */
217 | function dispatch(action) {
218 | if (!_utilsIsPlainObject2['default'](action)) {
219 | throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
220 | }
221 |
222 | if (typeof action.type === 'undefined') {
223 | throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?');
224 | }
225 |
226 | if (isDispatching) {
227 | throw new Error('Reducers may not dispatch actions.');
228 | }
229 |
230 | try {
231 | isDispatching = true;
232 | currentState = currentReducer(currentState, action);
233 | } finally {
234 | isDispatching = false;
235 | }
236 |
237 | listeners.slice().forEach(function (listener) {
238 | return listener();
239 | });
240 | return action;
241 | }
242 |
243 | /**
244 | * Replaces the reducer currently used by the store to calculate the state.
245 | *
246 | * You might need this if your app implements code splitting and you want to
247 | * load some of the reducers dynamically. You might also need this if you
248 | * implement a hot reloading mechanism for Redux.
249 | *
250 | * @param {Function} nextReducer The reducer for the store to use instead.
251 | * @returns {void}
252 | */
253 | function replaceReducer(nextReducer) {
254 | currentReducer = nextReducer;
255 | dispatch({ type: ActionTypes.INIT });
256 | }
257 |
258 | // When a store is created, an "INIT" action is dispatched so that every
259 | // reducer returns their initial state. This effectively populates
260 | // the initial state tree.
261 | dispatch({ type: ActionTypes.INIT });
262 |
263 | return {
264 | dispatch: dispatch,
265 | subscribe: subscribe,
266 | getState: getState,
267 | replaceReducer: replaceReducer
268 | };
269 | }
270 | },{"./utils/isPlainObject":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/index.js":[function(require,module,exports){
271 | 'use strict';
272 |
273 | exports.__esModule = true;
274 |
275 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
276 |
277 | var _createStore = require('./createStore');
278 |
279 | var _createStore2 = _interopRequireDefault(_createStore);
280 |
281 | var _utilsCombineReducers = require('./utils/combineReducers');
282 |
283 | var _utilsCombineReducers2 = _interopRequireDefault(_utilsCombineReducers);
284 |
285 | var _utilsBindActionCreators = require('./utils/bindActionCreators');
286 |
287 | var _utilsBindActionCreators2 = _interopRequireDefault(_utilsBindActionCreators);
288 |
289 | var _utilsApplyMiddleware = require('./utils/applyMiddleware');
290 |
291 | var _utilsApplyMiddleware2 = _interopRequireDefault(_utilsApplyMiddleware);
292 |
293 | var _utilsCompose = require('./utils/compose');
294 |
295 | var _utilsCompose2 = _interopRequireDefault(_utilsCompose);
296 |
297 | exports.createStore = _createStore2['default'];
298 | exports.combineReducers = _utilsCombineReducers2['default'];
299 | exports.bindActionCreators = _utilsBindActionCreators2['default'];
300 | exports.applyMiddleware = _utilsApplyMiddleware2['default'];
301 | exports.compose = _utilsCompose2['default'];
302 | },{"./createStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js","./utils/applyMiddleware":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/applyMiddleware.js","./utils/bindActionCreators":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/bindActionCreators.js","./utils/combineReducers":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/combineReducers.js","./utils/compose":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/applyMiddleware.js":[function(require,module,exports){
303 | 'use strict';
304 |
305 | exports.__esModule = true;
306 |
307 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
308 |
309 | exports['default'] = applyMiddleware;
310 |
311 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
312 |
313 | var _compose = require('./compose');
314 |
315 | var _compose2 = _interopRequireDefault(_compose);
316 |
317 | /**
318 | * Creates a store enhancer that applies middleware to the dispatch method
319 | * of the Redux store. This is handy for a variety of tasks, such as expressing
320 | * asynchronous actions in a concise manner, or logging every action payload.
321 | *
322 | * See `redux-thunk` package as an example of the Redux middleware.
323 | *
324 | * Because middleware is potentially asynchronous, this should be the first
325 | * store enhancer in the composition chain.
326 | *
327 | * Note that each middleware will be given the `dispatch` and `getState` functions
328 | * as named arguments.
329 | *
330 | * @param {...Function} middlewares The middleware chain to be applied.
331 | * @returns {Function} A store enhancer applying the middleware.
332 | */
333 |
334 | function applyMiddleware() {
335 | for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
336 | middlewares[_key] = arguments[_key];
337 | }
338 |
339 | return function (next) {
340 | return function (reducer, initialState) {
341 | var store = next(reducer, initialState);
342 | var _dispatch = store.dispatch;
343 | var chain = [];
344 |
345 | var middlewareAPI = {
346 | getState: store.getState,
347 | dispatch: function dispatch(action) {
348 | return _dispatch(action);
349 | }
350 | };
351 | chain = middlewares.map(function (middleware) {
352 | return middleware(middlewareAPI);
353 | });
354 | _dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch);
355 |
356 | return _extends({}, store, {
357 | dispatch: _dispatch
358 | });
359 | };
360 | };
361 | }
362 |
363 | module.exports = exports['default'];
364 | },{"./compose":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/bindActionCreators.js":[function(require,module,exports){
365 | 'use strict';
366 |
367 | exports.__esModule = true;
368 | exports['default'] = bindActionCreators;
369 |
370 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
371 |
372 | var _utilsMapValues = require('../utils/mapValues');
373 |
374 | var _utilsMapValues2 = _interopRequireDefault(_utilsMapValues);
375 |
376 | function bindActionCreator(actionCreator, dispatch) {
377 | return function () {
378 | return dispatch(actionCreator.apply(undefined, arguments));
379 | };
380 | }
381 |
382 | /**
383 | * Turns an object whose values are action creators, into an object with the
384 | * same keys, but with every function wrapped into a `dispatch` call so they
385 | * may be invoked directly. This is just a convenience method, as you can call
386 | * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
387 | *
388 | * For convenience, you can also pass a single function as the first argument,
389 | * and get a function in return.
390 | *
391 | * @param {Function|Object} actionCreators An object whose values are action
392 | * creator functions. One handy way to obtain it is to use ES6 `import * as`
393 | * syntax. You may also pass a single function.
394 | *
395 | * @param {Function} dispatch The `dispatch` function available on your Redux
396 | * store.
397 | *
398 | * @returns {Function|Object} The object mimicking the original object, but with
399 | * every action creator wrapped into the `dispatch` call. If you passed a
400 | * function as `actionCreators`, the return value will also be a single
401 | * function.
402 | */
403 |
404 | function bindActionCreators(actionCreators, dispatch) {
405 | if (typeof actionCreators === 'function') {
406 | return bindActionCreator(actionCreators, dispatch);
407 | }
408 |
409 | if (typeof actionCreators !== 'object' || actionCreators === null || actionCreators === undefined) {
410 | // eslint-disable-line no-eq-null
411 | throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');
412 | }
413 |
414 | return _utilsMapValues2['default'](actionCreators, function (actionCreator) {
415 | return bindActionCreator(actionCreator, dispatch);
416 | });
417 | }
418 |
419 | module.exports = exports['default'];
420 | },{"../utils/mapValues":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/combineReducers.js":[function(require,module,exports){
421 | (function (process){
422 | 'use strict';
423 |
424 | exports.__esModule = true;
425 | exports['default'] = combineReducers;
426 |
427 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
428 |
429 | var _createStore = require('../createStore');
430 |
431 | var _utilsIsPlainObject = require('../utils/isPlainObject');
432 |
433 | var _utilsIsPlainObject2 = _interopRequireDefault(_utilsIsPlainObject);
434 |
435 | var _utilsMapValues = require('../utils/mapValues');
436 |
437 | var _utilsMapValues2 = _interopRequireDefault(_utilsMapValues);
438 |
439 | var _utilsPick = require('../utils/pick');
440 |
441 | var _utilsPick2 = _interopRequireDefault(_utilsPick);
442 |
443 | /* eslint-disable no-console */
444 |
445 | function getUndefinedStateErrorMessage(key, action) {
446 | var actionType = action && action.type;
447 | var actionName = actionType && '"' + actionType.toString() + '"' || 'an action';
448 |
449 | return 'Reducer "' + key + '" returned undefined handling ' + actionName + '. ' + 'To ignore an action, you must explicitly return the previous state.';
450 | }
451 |
452 | function getUnexpectedStateKeyWarningMessage(inputState, outputState, action) {
453 | var reducerKeys = Object.keys(outputState);
454 | var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer';
455 |
456 | if (reducerKeys.length === 0) {
457 | return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';
458 | }
459 |
460 | if (!_utilsIsPlainObject2['default'](inputState)) {
461 | return 'The ' + argumentName + ' has unexpected type of "' + ({}).toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"');
462 | }
463 |
464 | var unexpectedKeys = Object.keys(inputState).filter(function (key) {
465 | return reducerKeys.indexOf(key) < 0;
466 | });
467 |
468 | if (unexpectedKeys.length > 0) {
469 | return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.');
470 | }
471 | }
472 |
473 | function assertReducerSanity(reducers) {
474 | Object.keys(reducers).forEach(function (key) {
475 | var reducer = reducers[key];
476 | var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT });
477 |
478 | if (typeof initialState === 'undefined') {
479 | throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');
480 | }
481 |
482 | var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
483 | if (typeof reducer(undefined, { type: type }) === 'undefined') {
484 | throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');
485 | }
486 | });
487 | }
488 |
489 | /**
490 | * Turns an object whose values are different reducer functions, into a single
491 | * reducer function. It will call every child reducer, and gather their results
492 | * into a single state object, whose keys correspond to the keys of the passed
493 | * reducer functions.
494 | *
495 | * @param {Object} reducers An object whose values correspond to different
496 | * reducer functions that need to be combined into one. One handy way to obtain
497 | * it is to use ES6 `import * as reducers` syntax. The reducers may never return
498 | * undefined for any action. Instead, they should return their initial state
499 | * if the state passed to them was undefined, and the current state for any
500 | * unrecognized action.
501 | *
502 | * @returns {Function} A reducer function that invokes every reducer inside the
503 | * passed object, and builds a state object with the same shape.
504 | */
505 |
506 | function combineReducers(reducers) {
507 | var finalReducers = _utilsPick2['default'](reducers, function (val) {
508 | return typeof val === 'function';
509 | });
510 | var sanityError;
511 |
512 | try {
513 | assertReducerSanity(finalReducers);
514 | } catch (e) {
515 | sanityError = e;
516 | }
517 |
518 | var defaultState = _utilsMapValues2['default'](finalReducers, function () {
519 | return undefined;
520 | });
521 |
522 | return function combination(state, action) {
523 | if (state === undefined) state = defaultState;
524 |
525 | if (sanityError) {
526 | throw sanityError;
527 | }
528 |
529 | var finalState = _utilsMapValues2['default'](finalReducers, function (reducer, key) {
530 | var newState = reducer(state[key], action);
531 | if (typeof newState === 'undefined') {
532 | var errorMessage = getUndefinedStateErrorMessage(key, action);
533 | throw new Error(errorMessage);
534 | }
535 | return newState;
536 | });
537 |
538 | if (process.env.NODE_ENV !== 'production') {
539 | var warningMessage = getUnexpectedStateKeyWarningMessage(state, finalState, action);
540 | if (warningMessage) {
541 | console.error(warningMessage);
542 | }
543 | }
544 |
545 | return finalState;
546 | };
547 | }
548 |
549 | module.exports = exports['default'];
550 | }).call(this,require('_process'))
551 | },{"../createStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js","../utils/isPlainObject":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js","../utils/mapValues":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js","../utils/pick":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/pick.js","_process":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/browserify/node_modules/process/browser.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js":[function(require,module,exports){
552 | /**
553 | * Composes single-argument functions from right to left.
554 | *
555 | * @param {...Function} funcs The functions to compose.
556 | * @returns {Function} A function obtained by composing functions from right to
557 | * left. For example, compose(f, g, h) is identical to arg => f(g(h(arg))).
558 | */
559 | "use strict";
560 |
561 | exports.__esModule = true;
562 | exports["default"] = compose;
563 |
564 | function compose() {
565 | for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
566 | funcs[_key] = arguments[_key];
567 | }
568 |
569 | return function (arg) {
570 | return funcs.reduceRight(function (composed, f) {
571 | return f(composed);
572 | }, arg);
573 | };
574 | }
575 |
576 | module.exports = exports["default"];
577 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js":[function(require,module,exports){
578 | 'use strict';
579 |
580 | exports.__esModule = true;
581 | exports['default'] = isPlainObject;
582 | var fnToString = function fnToString(fn) {
583 | return Function.prototype.toString.call(fn);
584 | };
585 |
586 | /**
587 | * @param {any} obj The object to inspect.
588 | * @returns {boolean} True if the argument appears to be a plain object.
589 | */
590 |
591 | function isPlainObject(obj) {
592 | if (!obj || typeof obj !== 'object') {
593 | return false;
594 | }
595 |
596 | var proto = typeof obj.constructor === 'function' ? Object.getPrototypeOf(obj) : Object.prototype;
597 |
598 | if (proto === null) {
599 | return true;
600 | }
601 |
602 | var constructor = proto.constructor;
603 |
604 | return typeof constructor === 'function' && constructor instanceof constructor && fnToString(constructor) === fnToString(Object);
605 | }
606 |
607 | module.exports = exports['default'];
608 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js":[function(require,module,exports){
609 | /**
610 | * Applies a function to every key-value pair inside an object.
611 | *
612 | * @param {Object} obj The source object.
613 | * @param {Function} fn The mapper function that receives the value and the key.
614 | * @returns {Object} A new object that contains the mapped values for the keys.
615 | */
616 | "use strict";
617 |
618 | exports.__esModule = true;
619 | exports["default"] = mapValues;
620 |
621 | function mapValues(obj, fn) {
622 | return Object.keys(obj).reduce(function (result, key) {
623 | result[key] = fn(obj[key], key);
624 | return result;
625 | }, {});
626 | }
627 |
628 | module.exports = exports["default"];
629 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/pick.js":[function(require,module,exports){
630 | /**
631 | * Picks key-value pairs from an object where values satisfy a predicate.
632 | *
633 | * @param {Object} obj The object to pick from.
634 | * @param {Function} fn The predicate the values must satisfy to be copied.
635 | * @returns {Object} The object with the values that satisfied the predicate.
636 | */
637 | "use strict";
638 |
639 | exports.__esModule = true;
640 | exports["default"] = pick;
641 |
642 | function pick(obj, fn) {
643 | return Object.keys(obj).reduce(function (result, key) {
644 | if (fn(obj[key])) {
645 | result[key] = obj[key];
646 | }
647 | return result;
648 | }, {});
649 | }
650 |
651 | module.exports = exports["default"];
652 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background.js":[function(require,module,exports){
653 | 'use strict';
654 |
655 | require('./background/index');
656 |
657 | console.log('Greetings from Backgroud Page!');
658 |
659 | },{"./background/index":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background/index.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background/index.js":[function(require,module,exports){
660 | 'use strict';
661 |
662 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
663 |
664 | var _sharedStoreConfigureStore = require('../shared/store/configureStore');
665 |
666 | var _sharedStoreConfigureStore2 = _interopRequireDefault(_sharedStoreConfigureStore);
667 |
668 | var _sharedInitStorage = require('../shared/initStorage');
669 |
670 | var _sharedInitStorage2 = _interopRequireDefault(_sharedInitStorage);
671 |
672 | var _sharedHelpersCreateInitState = require('../shared/helpers/createInitState');
673 |
674 | var _sharedHelpersCreateInitState2 = _interopRequireDefault(_sharedHelpersCreateInitState);
675 |
676 | var storage = JSON.parse(localStorage.getItem('persistent')) || _sharedInitStorage2['default'];
677 | var initialState = (0, _sharedHelpersCreateInitState2['default'])(storage);
678 |
679 | var store = (0, _sharedStoreConfigureStore2['default'])(initialState);
680 |
681 | chrome.runtime.onMessage.addListener(function (req, sender, sendResponse) {
682 | console.log(req);
683 | // Receiving updates from Popup Window and Content Scripts
684 | if (req.action === 'updateState') {
685 | store.dispatch({
686 | type: 'UPDATE_STATE',
687 | state: req.state
688 | });
689 | }
690 | // Passing initial state to Popup Window and Content Scripts
691 | if (req.action === 'getState') {
692 | sendResponse(store.getState());
693 | }
694 | });
695 |
696 | },{"../shared/helpers/createInitState":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/helpers/createInitState.js","../shared/initStorage":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/initStorage.js","../shared/store/configureStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/store/configureStore.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/actions/chromeExtension.js":[function(require,module,exports){
697 | 'use strict';
698 |
699 | Object.defineProperty(exports, '__esModule', {
700 | value: true
701 | });
702 | exports.updateState = updateState;
703 | exports.setOptions = setOptions;
704 | exports.increment = increment;
705 | exports.decrement = decrement;
706 | exports.incrementIfOdd = incrementIfOdd;
707 | exports.incrementAsync = incrementAsync;
708 | var UPDATE_STATE = 'UPDATE_STATE';
709 | exports.UPDATE_STATE = UPDATE_STATE;
710 | var SET_OPTIONS = 'SET_OPTIONS';
711 |
712 | exports.SET_OPTIONS = SET_OPTIONS;
713 |
714 | function updateState() {
715 | return {
716 | type: UPDATE_STATE
717 | };
718 | }
719 |
720 | function setOptions(options) {
721 | return {
722 | type: SET_OPTIONS,
723 | options: options
724 | };
725 | }
726 |
727 | //Counter example
728 |
729 | var INCREMENT_COUNTER = 'INCREMENT_COUNTER';
730 | exports.INCREMENT_COUNTER = INCREMENT_COUNTER;
731 | var DECREMENT_COUNTER = 'DECREMENT_COUNTER';
732 |
733 | exports.DECREMENT_COUNTER = DECREMENT_COUNTER;
734 |
735 | function increment() {
736 | return {
737 | type: INCREMENT_COUNTER
738 | };
739 | }
740 |
741 | function decrement() {
742 | return {
743 | type: DECREMENT_COUNTER
744 | };
745 | }
746 |
747 | function incrementIfOdd() {
748 | return function (dispatch, getState) {
749 | var _getState = getState();
750 |
751 | var counter = _getState.counter;
752 |
753 | if (counter % 2 === 0) {
754 | return;
755 | }
756 |
757 | dispatch(increment());
758 | };
759 | }
760 |
761 | function incrementAsync() {
762 | var delay = arguments.length <= 0 || arguments[0] === undefined ? 1000 : arguments[0];
763 |
764 | return function (dispatch) {
765 | setTimeout(function () {
766 | dispatch(increment());
767 | }, delay);
768 | };
769 | }
770 |
771 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/helpers/createInitState.js":[function(require,module,exports){
772 | "use strict";
773 |
774 | Object.defineProperty(exports, "__esModule", {
775 | value: true
776 | });
777 | exports["default"] = createInitState;
778 |
779 | function createInitState(storage) {
780 | return {
781 | persistent: storage,
782 | counter: storage.options.initCount
783 | };
784 | }
785 |
786 | module.exports = exports["default"];
787 |
788 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/initStorage.js":[function(require,module,exports){
789 | "use strict";
790 |
791 | Object.defineProperty(exports, "__esModule", {
792 | value: true
793 | });
794 | exports["default"] = {
795 | options: { initCount: 1 }
796 | };
797 | module.exports = exports["default"];
798 |
799 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/reducers/chromeExtension.js":[function(require,module,exports){
800 | 'use strict';
801 |
802 | Object.defineProperty(exports, '__esModule', {
803 | value: true
804 | });
805 | exports['default'] = chromeExtension;
806 |
807 | var _actionsChromeExtensionJs = require('../actions/chromeExtension.js');
808 |
809 | function chromeExtension(state, action) {
810 | if (state === undefined) state = { counter: 0, persistent: { options: { initCount: 1 } } };
811 |
812 | switch (action.type) {
813 | case _actionsChromeExtensionJs.UPDATE_STATE:
814 | console.log('UPDATE_STATE', action.state);
815 | var newState = Object.assign({}, state, action.state);
816 | //conditions to update localStorage only inside backround page
817 | if (location.protocol == 'chrome-extension:' && chrome.extension.getBackgroundPage() === window) {
818 | localStorage.setItem('persistent', JSON.stringify(newState.persistent));
819 | }
820 | return newState;
821 | case _actionsChromeExtensionJs.SET_OPTIONS:
822 | return Object.assign({}, state, { persistent: { options: action.options } });
823 | //Counter example
824 | case _actionsChromeExtensionJs.INCREMENT_COUNTER:
825 | return Object.assign({}, state, { counter: state.counter + 1 });
826 | case _actionsChromeExtensionJs.DECREMENT_COUNTER:
827 | return Object.assign({}, state, { counter: state.counter - 1 });
828 | default:
829 | return state;
830 | }
831 | }
832 |
833 | module.exports = exports['default'];
834 |
835 | },{"../actions/chromeExtension.js":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/actions/chromeExtension.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/store/configureStore.js":[function(require,module,exports){
836 | 'use strict';
837 |
838 | Object.defineProperty(exports, '__esModule', {
839 | value: true
840 | });
841 | exports['default'] = configureStore;
842 |
843 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
844 |
845 | var _redux = require('redux');
846 |
847 | var _reduxThunk = require('redux-thunk');
848 |
849 | var _reduxThunk2 = _interopRequireDefault(_reduxThunk);
850 |
851 | var _reducersChromeExtension = require('../reducers/chromeExtension');
852 |
853 | var _reducersChromeExtension2 = _interopRequireDefault(_reducersChromeExtension);
854 |
855 | var createStoreWithMiddleware = (0, _redux.applyMiddleware)(_reduxThunk2['default'])(_redux.createStore);
856 |
857 | function configureStore(initialState) {
858 | return createStoreWithMiddleware(_reducersChromeExtension2['default'], initialState);
859 | }
860 |
861 | module.exports = exports['default'];
862 |
863 | },{"../reducers/chromeExtension":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/reducers/chromeExtension.js","redux":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/index.js","redux-thunk":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux-thunk/lib/index.js"}]},{},["/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background.js"]);
864 |
--------------------------------------------------------------------------------
/app/scripts/background_bundle.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) {
49 | for (var i = 1; i < arguments.length; i++) {
50 | args[i - 1] = arguments[i];
51 | }
52 | }
53 | queue.push(new Item(fun, args));
54 | if (queue.length === 1 && !draining) {
55 | setTimeout(drainQueue, 0);
56 | }
57 | };
58 |
59 | // v8 likes predictible objects
60 | function Item(fun, array) {
61 | this.fun = fun;
62 | this.array = array;
63 | }
64 | Item.prototype.run = function () {
65 | this.fun.apply(null, this.array);
66 | };
67 | process.title = 'browser';
68 | process.browser = true;
69 | process.env = {};
70 | process.argv = [];
71 | process.version = ''; // empty string to avoid regexp issues
72 | process.versions = {};
73 |
74 | function noop() {}
75 |
76 | process.on = noop;
77 | process.addListener = noop;
78 | process.once = noop;
79 | process.off = noop;
80 | process.removeListener = noop;
81 | process.removeAllListeners = noop;
82 | process.emit = noop;
83 |
84 | process.binding = function (name) {
85 | throw new Error('process.binding is not supported');
86 | };
87 |
88 | process.cwd = function () { return '/' };
89 | process.chdir = function (dir) {
90 | throw new Error('process.chdir is not supported');
91 | };
92 | process.umask = function() { return 0; };
93 |
94 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux-thunk/lib/index.js":[function(require,module,exports){
95 | 'use strict';
96 |
97 | function thunkMiddleware(_ref) {
98 | var dispatch = _ref.dispatch;
99 | var getState = _ref.getState;
100 |
101 | return function (next) {
102 | return function (action) {
103 | return typeof action === 'function' ? action(dispatch, getState) : next(action);
104 | };
105 | };
106 | }
107 |
108 | module.exports = thunkMiddleware;
109 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js":[function(require,module,exports){
110 | 'use strict';
111 |
112 | exports.__esModule = true;
113 | exports['default'] = createStore;
114 |
115 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
116 |
117 | var _utilsIsPlainObject = require('./utils/isPlainObject');
118 |
119 | var _utilsIsPlainObject2 = _interopRequireDefault(_utilsIsPlainObject);
120 |
121 | /**
122 | * These are private action types reserved by Redux.
123 | * For any unknown actions, you must return the current state.
124 | * If the current state is undefined, you must return the initial state.
125 | * Do not reference these action types directly in your code.
126 | */
127 | var ActionTypes = {
128 | INIT: '@@redux/INIT'
129 | };
130 |
131 | exports.ActionTypes = ActionTypes;
132 | /**
133 | * Creates a Redux store that holds the state tree.
134 | * The only way to change the data in the store is to call `dispatch()` on it.
135 | *
136 | * There should only be a single store in your app. To specify how different
137 | * parts of the state tree respond to actions, you may combine several reducers
138 | * into a single reducer function by using `combineReducers`.
139 | *
140 | * @param {Function} reducer A function that returns the next state tree, given
141 | * the current state tree and the action to handle.
142 | *
143 | * @param {any} [initialState] The initial state. You may optionally specify it
144 | * to hydrate the state from the server in universal apps, or to restore a
145 | * previously serialized user session.
146 | * If you use `combineReducers` to produce the root reducer function, this must be
147 | * an object with the same shape as `combineReducers` keys.
148 | *
149 | * @returns {Store} A Redux store that lets you read the state, dispatch actions
150 | * and subscribe to changes.
151 | */
152 |
153 | function createStore(reducer, initialState) {
154 | if (typeof reducer !== 'function') {
155 | throw new Error('Expected the reducer to be a function.');
156 | }
157 |
158 | var currentReducer = reducer;
159 | var currentState = initialState;
160 | var listeners = [];
161 | var isDispatching = false;
162 |
163 | /**
164 | * Reads the state tree managed by the store.
165 | *
166 | * @returns {any} The current state tree of your application.
167 | */
168 | function getState() {
169 | return currentState;
170 | }
171 |
172 | /**
173 | * Adds a change listener. It will be called any time an action is dispatched,
174 | * and some part of the state tree may potentially have changed. You may then
175 | * call `getState()` to read the current state tree inside the callback.
176 | *
177 | * @param {Function} listener A callback to be invoked on every dispatch.
178 | * @returns {Function} A function to remove this change listener.
179 | */
180 | function subscribe(listener) {
181 | listeners.push(listener);
182 | var isSubscribed = true;
183 |
184 | return function unsubscribe() {
185 | if (!isSubscribed) {
186 | return;
187 | }
188 |
189 | isSubscribed = false;
190 | var index = listeners.indexOf(listener);
191 | listeners.splice(index, 1);
192 | };
193 | }
194 |
195 | /**
196 | * Dispatches an action. It is the only way to trigger a state change.
197 | *
198 | * The `reducer` function, used to create the store, will be called with the
199 | * current state tree and the given `action`. Its return value will
200 | * be considered the **next** state of the tree, and the change listeners
201 | * will be notified.
202 | *
203 | * The base implementation only supports plain object actions. If you want to
204 | * dispatch a Promise, an Observable, a thunk, or something else, you need to
205 | * wrap your store creating function into the corresponding middleware. For
206 | * example, see the documentation for the `redux-thunk` package. Even the
207 | * middleware will eventually dispatch plain object actions using this method.
208 | *
209 | * @param {Object} action A plain object representing “what changed”. It is
210 | * a good idea to keep actions serializable so you can record and replay user
211 | * sessions, or use the time travelling `redux-devtools`. An action must have
212 | * a `type` property which may not be `undefined`. It is a good idea to use
213 | * string constants for action types.
214 | *
215 | * @returns {Object} For convenience, the same action object you dispatched.
216 | *
217 | * Note that, if you use a custom middleware, it may wrap `dispatch()` to
218 | * return something else (for example, a Promise you can await).
219 | */
220 | function dispatch(action) {
221 | if (!_utilsIsPlainObject2['default'](action)) {
222 | throw new Error('Actions must be plain objects. ' + 'Use custom middleware for async actions.');
223 | }
224 |
225 | if (typeof action.type === 'undefined') {
226 | throw new Error('Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?');
227 | }
228 |
229 | if (isDispatching) {
230 | throw new Error('Reducers may not dispatch actions.');
231 | }
232 |
233 | try {
234 | isDispatching = true;
235 | currentState = currentReducer(currentState, action);
236 | } finally {
237 | isDispatching = false;
238 | }
239 |
240 | listeners.slice().forEach(function (listener) {
241 | return listener();
242 | });
243 | return action;
244 | }
245 |
246 | /**
247 | * Replaces the reducer currently used by the store to calculate the state.
248 | *
249 | * You might need this if your app implements code splitting and you want to
250 | * load some of the reducers dynamically. You might also need this if you
251 | * implement a hot reloading mechanism for Redux.
252 | *
253 | * @param {Function} nextReducer The reducer for the store to use instead.
254 | * @returns {void}
255 | */
256 | function replaceReducer(nextReducer) {
257 | currentReducer = nextReducer;
258 | dispatch({ type: ActionTypes.INIT });
259 | }
260 |
261 | // When a store is created, an "INIT" action is dispatched so that every
262 | // reducer returns their initial state. This effectively populates
263 | // the initial state tree.
264 | dispatch({ type: ActionTypes.INIT });
265 |
266 | return {
267 | dispatch: dispatch,
268 | subscribe: subscribe,
269 | getState: getState,
270 | replaceReducer: replaceReducer
271 | };
272 | }
273 | },{"./utils/isPlainObject":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/index.js":[function(require,module,exports){
274 | 'use strict';
275 |
276 | exports.__esModule = true;
277 |
278 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
279 |
280 | var _createStore = require('./createStore');
281 |
282 | var _createStore2 = _interopRequireDefault(_createStore);
283 |
284 | var _utilsCombineReducers = require('./utils/combineReducers');
285 |
286 | var _utilsCombineReducers2 = _interopRequireDefault(_utilsCombineReducers);
287 |
288 | var _utilsBindActionCreators = require('./utils/bindActionCreators');
289 |
290 | var _utilsBindActionCreators2 = _interopRequireDefault(_utilsBindActionCreators);
291 |
292 | var _utilsApplyMiddleware = require('./utils/applyMiddleware');
293 |
294 | var _utilsApplyMiddleware2 = _interopRequireDefault(_utilsApplyMiddleware);
295 |
296 | var _utilsCompose = require('./utils/compose');
297 |
298 | var _utilsCompose2 = _interopRequireDefault(_utilsCompose);
299 |
300 | exports.createStore = _createStore2['default'];
301 | exports.combineReducers = _utilsCombineReducers2['default'];
302 | exports.bindActionCreators = _utilsBindActionCreators2['default'];
303 | exports.applyMiddleware = _utilsApplyMiddleware2['default'];
304 | exports.compose = _utilsCompose2['default'];
305 | },{"./createStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js","./utils/applyMiddleware":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/applyMiddleware.js","./utils/bindActionCreators":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/bindActionCreators.js","./utils/combineReducers":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/combineReducers.js","./utils/compose":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/applyMiddleware.js":[function(require,module,exports){
306 | 'use strict';
307 |
308 | exports.__esModule = true;
309 |
310 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
311 |
312 | exports['default'] = applyMiddleware;
313 |
314 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
315 |
316 | var _compose = require('./compose');
317 |
318 | var _compose2 = _interopRequireDefault(_compose);
319 |
320 | /**
321 | * Creates a store enhancer that applies middleware to the dispatch method
322 | * of the Redux store. This is handy for a variety of tasks, such as expressing
323 | * asynchronous actions in a concise manner, or logging every action payload.
324 | *
325 | * See `redux-thunk` package as an example of the Redux middleware.
326 | *
327 | * Because middleware is potentially asynchronous, this should be the first
328 | * store enhancer in the composition chain.
329 | *
330 | * Note that each middleware will be given the `dispatch` and `getState` functions
331 | * as named arguments.
332 | *
333 | * @param {...Function} middlewares The middleware chain to be applied.
334 | * @returns {Function} A store enhancer applying the middleware.
335 | */
336 |
337 | function applyMiddleware() {
338 | for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
339 | middlewares[_key] = arguments[_key];
340 | }
341 |
342 | return function (next) {
343 | return function (reducer, initialState) {
344 | var store = next(reducer, initialState);
345 | var _dispatch = store.dispatch;
346 | var chain = [];
347 |
348 | var middlewareAPI = {
349 | getState: store.getState,
350 | dispatch: function dispatch(action) {
351 | return _dispatch(action);
352 | }
353 | };
354 | chain = middlewares.map(function (middleware) {
355 | return middleware(middlewareAPI);
356 | });
357 | _dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch);
358 |
359 | return _extends({}, store, {
360 | dispatch: _dispatch
361 | });
362 | };
363 | };
364 | }
365 |
366 | module.exports = exports['default'];
367 | },{"./compose":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/bindActionCreators.js":[function(require,module,exports){
368 | 'use strict';
369 |
370 | exports.__esModule = true;
371 | exports['default'] = bindActionCreators;
372 |
373 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
374 |
375 | var _mapValues = require('./mapValues');
376 |
377 | var _mapValues2 = _interopRequireDefault(_mapValues);
378 |
379 | function bindActionCreator(actionCreator, dispatch) {
380 | return function () {
381 | return dispatch(actionCreator.apply(undefined, arguments));
382 | };
383 | }
384 |
385 | /**
386 | * Turns an object whose values are action creators, into an object with the
387 | * same keys, but with every function wrapped into a `dispatch` call so they
388 | * may be invoked directly. This is just a convenience method, as you can call
389 | * `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
390 | *
391 | * For convenience, you can also pass a single function as the first argument,
392 | * and get a function in return.
393 | *
394 | * @param {Function|Object} actionCreators An object whose values are action
395 | * creator functions. One handy way to obtain it is to use ES6 `import * as`
396 | * syntax. You may also pass a single function.
397 | *
398 | * @param {Function} dispatch The `dispatch` function available on your Redux
399 | * store.
400 | *
401 | * @returns {Function|Object} The object mimicking the original object, but with
402 | * every action creator wrapped into the `dispatch` call. If you passed a
403 | * function as `actionCreators`, the return value will also be a single
404 | * function.
405 | */
406 |
407 | function bindActionCreators(actionCreators, dispatch) {
408 | if (typeof actionCreators === 'function') {
409 | return bindActionCreator(actionCreators, dispatch);
410 | }
411 |
412 | if (typeof actionCreators !== 'object' || actionCreators === null || actionCreators === undefined) {
413 | throw new Error('bindActionCreators expected an object or a function, instead received ' + (actionCreators === null ? 'null' : typeof actionCreators) + '. ' + 'Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');
414 | }
415 |
416 | return _mapValues2['default'](actionCreators, function (actionCreator) {
417 | return bindActionCreator(actionCreator, dispatch);
418 | });
419 | }
420 |
421 | module.exports = exports['default'];
422 | },{"./mapValues":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/combineReducers.js":[function(require,module,exports){
423 | (function (process){
424 | 'use strict';
425 |
426 | exports.__esModule = true;
427 | exports['default'] = combineReducers;
428 |
429 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
430 |
431 | var _createStore = require('../createStore');
432 |
433 | var _isPlainObject = require('./isPlainObject');
434 |
435 | var _isPlainObject2 = _interopRequireDefault(_isPlainObject);
436 |
437 | var _mapValues = require('./mapValues');
438 |
439 | var _mapValues2 = _interopRequireDefault(_mapValues);
440 |
441 | var _pick = require('./pick');
442 |
443 | var _pick2 = _interopRequireDefault(_pick);
444 |
445 | /* eslint-disable no-console */
446 |
447 | function getUndefinedStateErrorMessage(key, action) {
448 | var actionType = action && action.type;
449 | var actionName = actionType && '"' + actionType.toString() + '"' || 'an action';
450 |
451 | return 'Reducer "' + key + '" returned undefined handling ' + actionName + '. ' + 'To ignore an action, you must explicitly return the previous state.';
452 | }
453 |
454 | function getUnexpectedStateKeyWarningMessage(inputState, outputState, action) {
455 | var reducerKeys = Object.keys(outputState);
456 | var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer';
457 |
458 | if (reducerKeys.length === 0) {
459 | return 'Store does not have a valid reducer. Make sure the argument passed ' + 'to combineReducers is an object whose values are reducers.';
460 | }
461 |
462 | if (!_isPlainObject2['default'](inputState)) {
463 | return 'The ' + argumentName + ' has unexpected type of "' + ({}).toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"');
464 | }
465 |
466 | var unexpectedKeys = Object.keys(inputState).filter(function (key) {
467 | return reducerKeys.indexOf(key) < 0;
468 | });
469 |
470 | if (unexpectedKeys.length > 0) {
471 | return 'Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.');
472 | }
473 | }
474 |
475 | function assertReducerSanity(reducers) {
476 | Object.keys(reducers).forEach(function (key) {
477 | var reducer = reducers[key];
478 | var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT });
479 |
480 | if (typeof initialState === 'undefined') {
481 | throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');
482 | }
483 |
484 | var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
485 | if (typeof reducer(undefined, { type: type }) === 'undefined') {
486 | throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');
487 | }
488 | });
489 | }
490 |
491 | /**
492 | * Turns an object whose values are different reducer functions, into a single
493 | * reducer function. It will call every child reducer, and gather their results
494 | * into a single state object, whose keys correspond to the keys of the passed
495 | * reducer functions.
496 | *
497 | * @param {Object} reducers An object whose values correspond to different
498 | * reducer functions that need to be combined into one. One handy way to obtain
499 | * it is to use ES6 `import * as reducers` syntax. The reducers may never return
500 | * undefined for any action. Instead, they should return their initial state
501 | * if the state passed to them was undefined, and the current state for any
502 | * unrecognized action.
503 | *
504 | * @returns {Function} A reducer function that invokes every reducer inside the
505 | * passed object, and builds a state object with the same shape.
506 | */
507 |
508 | function combineReducers(reducers) {
509 | var finalReducers = _pick2['default'](reducers, function (val) {
510 | return typeof val === 'function';
511 | });
512 | var sanityError;
513 |
514 | try {
515 | assertReducerSanity(finalReducers);
516 | } catch (e) {
517 | sanityError = e;
518 | }
519 |
520 | var defaultState = _mapValues2['default'](finalReducers, function () {
521 | return undefined;
522 | });
523 |
524 | return function combination(state, action) {
525 | if (state === undefined) state = defaultState;
526 |
527 | if (sanityError) {
528 | throw sanityError;
529 | }
530 |
531 | var hasChanged = false;
532 | var finalState = _mapValues2['default'](finalReducers, function (reducer, key) {
533 | var previousStateForKey = state[key];
534 | var nextStateForKey = reducer(previousStateForKey, action);
535 | if (typeof nextStateForKey === 'undefined') {
536 | var errorMessage = getUndefinedStateErrorMessage(key, action);
537 | throw new Error(errorMessage);
538 | }
539 | hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
540 | return nextStateForKey;
541 | });
542 |
543 | if (process.env.NODE_ENV !== 'production') {
544 | var warningMessage = getUnexpectedStateKeyWarningMessage(state, finalState, action);
545 | if (warningMessage) {
546 | console.error(warningMessage);
547 | }
548 | }
549 |
550 | return hasChanged ? finalState : state;
551 | };
552 | }
553 |
554 | module.exports = exports['default'];
555 | }).call(this,require('_process'))
556 | },{"../createStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/createStore.js","./isPlainObject":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js","./mapValues":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js","./pick":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/pick.js","_process":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/browserify/node_modules/process/browser.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/compose.js":[function(require,module,exports){
557 | /**
558 | * Composes single-argument functions from right to left.
559 | *
560 | * @param {...Function} funcs The functions to compose.
561 | * @returns {Function} A function obtained by composing functions from right to
562 | * left. For example, compose(f, g, h) is identical to arg => f(g(h(arg))).
563 | */
564 | "use strict";
565 |
566 | exports.__esModule = true;
567 | exports["default"] = compose;
568 |
569 | function compose() {
570 | for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
571 | funcs[_key] = arguments[_key];
572 | }
573 |
574 | return function (arg) {
575 | return funcs.reduceRight(function (composed, f) {
576 | return f(composed);
577 | }, arg);
578 | };
579 | }
580 |
581 | module.exports = exports["default"];
582 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/isPlainObject.js":[function(require,module,exports){
583 | 'use strict';
584 |
585 | exports.__esModule = true;
586 | exports['default'] = isPlainObject;
587 | var fnToString = function fnToString(fn) {
588 | return Function.prototype.toString.call(fn);
589 | };
590 | var objStringValue = fnToString(Object);
591 |
592 | /**
593 | * @param {any} obj The object to inspect.
594 | * @returns {boolean} True if the argument appears to be a plain object.
595 | */
596 |
597 | function isPlainObject(obj) {
598 | if (!obj || typeof obj !== 'object') {
599 | return false;
600 | }
601 |
602 | var proto = typeof obj.constructor === 'function' ? Object.getPrototypeOf(obj) : Object.prototype;
603 |
604 | if (proto === null) {
605 | return true;
606 | }
607 |
608 | var constructor = proto.constructor;
609 |
610 | return typeof constructor === 'function' && constructor instanceof constructor && fnToString(constructor) === objStringValue;
611 | }
612 |
613 | module.exports = exports['default'];
614 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/mapValues.js":[function(require,module,exports){
615 | /**
616 | * Applies a function to every key-value pair inside an object.
617 | *
618 | * @param {Object} obj The source object.
619 | * @param {Function} fn The mapper function that receives the value and the key.
620 | * @returns {Object} A new object that contains the mapped values for the keys.
621 | */
622 | "use strict";
623 |
624 | exports.__esModule = true;
625 | exports["default"] = mapValues;
626 |
627 | function mapValues(obj, fn) {
628 | return Object.keys(obj).reduce(function (result, key) {
629 | result[key] = fn(obj[key], key);
630 | return result;
631 | }, {});
632 | }
633 |
634 | module.exports = exports["default"];
635 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/utils/pick.js":[function(require,module,exports){
636 | /**
637 | * Picks key-value pairs from an object where values satisfy a predicate.
638 | *
639 | * @param {Object} obj The object to pick from.
640 | * @param {Function} fn The predicate the values must satisfy to be copied.
641 | * @returns {Object} The object with the values that satisfied the predicate.
642 | */
643 | "use strict";
644 |
645 | exports.__esModule = true;
646 | exports["default"] = pick;
647 |
648 | function pick(obj, fn) {
649 | return Object.keys(obj).reduce(function (result, key) {
650 | if (fn(obj[key])) {
651 | result[key] = obj[key];
652 | }
653 | return result;
654 | }, {});
655 | }
656 |
657 | module.exports = exports["default"];
658 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background.js":[function(require,module,exports){
659 | 'use strict';
660 |
661 | require('./background/index');
662 |
663 | console.log('Greetings from Backgroud Page');
664 |
665 | },{"./background/index":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background/index.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background/index.js":[function(require,module,exports){
666 | 'use strict';
667 |
668 | var _configureStore = require('../shared/store/configureStore');
669 |
670 | var _configureStore2 = _interopRequireDefault(_configureStore);
671 |
672 | var _initStorage = require('../shared/initStorage');
673 |
674 | var _initStorage2 = _interopRequireDefault(_initStorage);
675 |
676 | var _createInitState = require('../shared/helpers/createInitState');
677 |
678 | var _createInitState2 = _interopRequireDefault(_createInitState);
679 |
680 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
681 |
682 | var storage = JSON.parse(localStorage.getItem('persistent')) || _initStorage2.default;
683 | var initialState = (0, _createInitState2.default)(storage);
684 |
685 | var store = (0, _configureStore2.default)(initialState);
686 |
687 | chrome.runtime.onMessage.addListener(function (req, sender, sendResponse) {
688 | console.log(req);
689 | // Receiving updates from Popup Window and Content Scripts
690 | if (req.action === 'updateState') {
691 | store.dispatch({
692 | type: 'UPDATE_STATE',
693 | state: req.state
694 | });
695 | }
696 | // Passing initial state to Popup Window and Content Scripts
697 | if (req.action === 'getState') {
698 | sendResponse(store.getState());
699 | }
700 | });
701 |
702 | },{"../shared/helpers/createInitState":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/helpers/createInitState.js","../shared/initStorage":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/initStorage.js","../shared/store/configureStore":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/store/configureStore.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/actions/chromeExtension.js":[function(require,module,exports){
703 | 'use strict';
704 |
705 | Object.defineProperty(exports, "__esModule", {
706 | value: true
707 | });
708 | exports.updateState = updateState;
709 | exports.setOptions = setOptions;
710 | exports.increment = increment;
711 | exports.decrement = decrement;
712 | exports.incrementIfOdd = incrementIfOdd;
713 | exports.incrementAsync = incrementAsync;
714 | var UPDATE_STATE = exports.UPDATE_STATE = 'UPDATE_STATE';
715 | var SET_OPTIONS = exports.SET_OPTIONS = 'SET_OPTIONS';
716 |
717 | function updateState() {
718 | return {
719 | type: UPDATE_STATE
720 | };
721 | }
722 |
723 | function setOptions(options) {
724 | return {
725 | type: SET_OPTIONS,
726 | options: options
727 | };
728 | }
729 |
730 | //Counter example
731 |
732 | var INCREMENT_COUNTER = exports.INCREMENT_COUNTER = 'INCREMENT_COUNTER';
733 | var DECREMENT_COUNTER = exports.DECREMENT_COUNTER = 'DECREMENT_COUNTER';
734 |
735 | function increment() {
736 | return {
737 | type: INCREMENT_COUNTER
738 | };
739 | }
740 |
741 | function decrement() {
742 | return {
743 | type: DECREMENT_COUNTER
744 | };
745 | }
746 |
747 | function incrementIfOdd() {
748 | return function (dispatch, getState) {
749 | var _getState = getState();
750 |
751 | var counter = _getState.counter;
752 |
753 | if (counter % 2 === 0) {
754 | return;
755 | }
756 |
757 | dispatch(increment());
758 | };
759 | }
760 |
761 | function incrementAsync() {
762 | var delay = arguments.length <= 0 || arguments[0] === undefined ? 1000 : arguments[0];
763 |
764 | return function (dispatch) {
765 | setTimeout(function () {
766 | dispatch(increment());
767 | }, delay);
768 | };
769 | }
770 |
771 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/helpers/createInitState.js":[function(require,module,exports){
772 | "use strict";
773 |
774 | Object.defineProperty(exports, "__esModule", {
775 | value: true
776 | });
777 | exports.default = createInitState;
778 | function createInitState(storage) {
779 | return {
780 | persistent: storage,
781 | counter: storage.options.initCount
782 | };
783 | }
784 |
785 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/initStorage.js":[function(require,module,exports){
786 | "use strict";
787 |
788 | Object.defineProperty(exports, "__esModule", {
789 | value: true
790 | });
791 | exports.default = {
792 | options: { initCount: 1 }
793 | };
794 |
795 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/reducers/chromeExtension.js":[function(require,module,exports){
796 | 'use strict';
797 |
798 | Object.defineProperty(exports, "__esModule", {
799 | value: true
800 | });
801 | exports.default = chromeExtension;
802 |
803 | var _chromeExtension = require('../actions/chromeExtension.js');
804 |
805 | function chromeExtension() {
806 | var state = arguments.length <= 0 || arguments[0] === undefined ? { counter: 0, persistent: { options: { initCount: 1 } } } : arguments[0];
807 | var action = arguments[1];
808 |
809 | switch (action.type) {
810 | case _chromeExtension.UPDATE_STATE:
811 | console.log('UPDATE_STATE', action.state);
812 | var newState = Object.assign({}, state, action.state);
813 | //conditions to update localStorage only inside backround page
814 | if (location.protocol == 'chrome-extension:' && chrome.extension.getBackgroundPage() === window) {
815 | localStorage.setItem('persistent', JSON.stringify(newState.persistent));
816 | }
817 | return newState;
818 | case _chromeExtension.SET_OPTIONS:
819 | return Object.assign({}, state, { persistent: { options: action.options } });
820 | //Counter example
821 | case _chromeExtension.INCREMENT_COUNTER:
822 | return Object.assign({}, state, { counter: state.counter + 1 });
823 | case _chromeExtension.DECREMENT_COUNTER:
824 | return Object.assign({}, state, { counter: state.counter - 1 });
825 | default:
826 | return state;
827 | }
828 | }
829 |
830 | },{"../actions/chromeExtension.js":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/actions/chromeExtension.js"}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/store/configureStore.js":[function(require,module,exports){
831 | 'use strict';
832 |
833 | Object.defineProperty(exports, "__esModule", {
834 | value: true
835 | });
836 | exports.default = configureStore;
837 |
838 | var _redux = require('redux');
839 |
840 | var _reduxThunk = require('redux-thunk');
841 |
842 | var _reduxThunk2 = _interopRequireDefault(_reduxThunk);
843 |
844 | var _chromeExtension = require('../reducers/chromeExtension');
845 |
846 | var _chromeExtension2 = _interopRequireDefault(_chromeExtension);
847 |
848 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
849 |
850 | var createStoreWithMiddleware = (0, _redux.applyMiddleware)(_reduxThunk2.default)(_redux.createStore);
851 |
852 | function configureStore(initialState) {
853 | return createStoreWithMiddleware(_chromeExtension2.default, initialState);
854 | }
855 |
856 | },{"../reducers/chromeExtension":"/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/shared/reducers/chromeExtension.js","redux":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux/lib/index.js","redux-thunk":"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/redux-thunk/lib/index.js"}]},{},["/Volumes/Workspace/Github/repos/redux-chrome-extension/src/scripts/background.js"]);
857 |
--------------------------------------------------------------------------------
/app/scripts/chromereload.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Reload client for Chrome Apps & Extensions.
4 | // The reload client has a compatibility with livereload.
5 | // WARNING: only supports reload command.
6 |
7 | var LIVERELOAD_HOST = 'localhost:';
8 | var LIVERELOAD_PORT = 35729;
9 | var connection = new WebSocket('ws://' + LIVERELOAD_HOST + LIVERELOAD_PORT + '/livereload');
10 |
11 | connection.onerror = function (error) {
12 | console.log('reload connection got error:', error);
13 | };
14 |
15 | connection.onmessage = function (e) {
16 | console.log('RELOAD!');
17 | console.dir(e);
18 | chrome.runtime.reload();
19 | /*if (e.data) {
20 | var data = JSON.parse(e.data);
21 | if (data && data.command === 'reload') {
22 | chrome.runtime.reload();
23 | }
24 | }*/
25 | };
26 |
--------------------------------------------------------------------------------
/app/scripts/content_bundle.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) {
49 | for (var i = 1; i < arguments.length; i++) {
50 | args[i - 1] = arguments[i];
51 | }
52 | }
53 | queue.push(new Item(fun, args));
54 | if (queue.length === 1 && !draining) {
55 | setTimeout(drainQueue, 0);
56 | }
57 | };
58 |
59 | // v8 likes predictible objects
60 | function Item(fun, array) {
61 | this.fun = fun;
62 | this.array = array;
63 | }
64 | Item.prototype.run = function () {
65 | this.fun.apply(null, this.array);
66 | };
67 | process.title = 'browser';
68 | process.browser = true;
69 | process.env = {};
70 | process.argv = [];
71 | process.version = ''; // empty string to avoid regexp issues
72 | process.versions = {};
73 |
74 | function noop() {}
75 |
76 | process.on = noop;
77 | process.addListener = noop;
78 | process.once = noop;
79 | process.off = noop;
80 | process.removeListener = noop;
81 | process.removeAllListeners = noop;
82 | process.emit = noop;
83 |
84 | process.binding = function (name) {
85 | throw new Error('process.binding is not supported');
86 | };
87 |
88 | process.cwd = function () { return '/' };
89 | process.chdir = function (dir) {
90 | throw new Error('process.chdir is not supported');
91 | };
92 | process.umask = function() { return 0; };
93 |
94 | },{}],"/Volumes/Workspace/Github/repos/redux-chrome-extension/node_modules/q/q.js":[function(require,module,exports){
95 | (function (process){
96 | // vim:ts=4:sts=4:sw=4:
97 | /*!
98 | *
99 | * Copyright 2009-2012 Kris Kowal under the terms of the MIT
100 | * license found at http://github.com/kriskowal/q/raw/master/LICENSE
101 | *
102 | * With parts by Tyler Close
103 | * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
104 | * at http://www.opensource.org/licenses/mit-license.html
105 | * Forked at ref_send.js version: 2009-05-11
106 | *
107 | * With parts by Mark Miller
108 | * Copyright (C) 2011 Google Inc.
109 | *
110 | * Licensed under the Apache License, Version 2.0 (the "License");
111 | * you may not use this file except in compliance with the License.
112 | * You may obtain a copy of the License at
113 | *
114 | * http://www.apache.org/licenses/LICENSE-2.0
115 | *
116 | * Unless required by applicable law or agreed to in writing, software
117 | * distributed under the License is distributed on an "AS IS" BASIS,
118 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119 | * See the License for the specific language governing permissions and
120 | * limitations under the License.
121 | *
122 | */
123 |
124 | (function (definition) {
125 | "use strict";
126 |
127 | // This file will function properly as a