From 22db12f2a37529a560eda1839c3a23011f900fab Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 8 Oct 2017 13:58:01 +0900 Subject: move messages to shared --- src/background/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/background') diff --git a/src/background/index.js b/src/background/index.js index dbc10fb..63d13cb 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,5 +1,5 @@ import * as settingsActions from 'actions/setting'; -import messages from 'content/messages'; +import messages from 'shared/messages'; import BackgroundComponent from 'components/background'; import reducers from 'reducers'; import { createStore } from 'store'; -- cgit v1.2.3 From 58123210ab4cdd4a1f2b4720a0abbd88908baa06 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 8 Oct 2017 14:44:21 +0900 Subject: separate settings --- src/actions/setting.js | 31 -------------------------- src/background/index.js | 2 +- src/components/background.js | 2 +- src/components/setting.js | 45 -------------------------------------- src/content/index.js | 2 +- src/pages/settings.html | 18 --------------- src/pages/settings.js | 15 ------------- src/pages/settings.scss | 8 ------- src/reducers/index.js | 3 ++- src/reducers/setting.js | 17 -------------- src/settings/actions/index.js | 4 ++++ src/settings/actions/setting.js | 31 ++++++++++++++++++++++++++ src/settings/components/setting.js | 45 ++++++++++++++++++++++++++++++++++++++ src/settings/index.html | 18 +++++++++++++++ src/settings/index.js | 15 +++++++++++++ src/settings/reducers/setting.js | 17 ++++++++++++++ src/settings/site.scss | 8 +++++++ test/reducers/setting.test.js | 22 ------------------- webpack.config.js | 4 ++-- 19 files changed, 145 insertions(+), 162 deletions(-) delete mode 100644 src/actions/setting.js delete mode 100644 src/components/setting.js delete mode 100644 src/pages/settings.html delete mode 100644 src/pages/settings.js delete mode 100644 src/pages/settings.scss delete mode 100644 src/reducers/setting.js create mode 100644 src/settings/actions/index.js create mode 100644 src/settings/actions/setting.js create mode 100644 src/settings/components/setting.js create mode 100644 src/settings/index.html create mode 100644 src/settings/index.js create mode 100644 src/settings/reducers/setting.js create mode 100644 src/settings/site.scss delete mode 100644 test/reducers/setting.test.js (limited to 'src/background') diff --git a/src/actions/setting.js b/src/actions/setting.js deleted file mode 100644 index c241428..0000000 --- a/src/actions/setting.js +++ /dev/null @@ -1,31 +0,0 @@ -import actions from 'actions'; -import messages from 'shared/messages'; -import DefaultSettings from 'shared/default-settings'; - -const load = () => { - return browser.storage.local.get('settings').then((value) => { - if (value.settings) { - return set(value.settings); - } - return set(DefaultSettings); - }, console.error); -}; - -const save = (settings) => { - return browser.storage.local.set({ - settings - }).then(() => { - return browser.runtime.sendMessage({ - type: messages.SETTINGS_RELOAD - }); - }); -}; - -const set = (settings) => { - return { - type: actions.SETTING_SET_SETTINGS, - settings, - }; -}; - -export { load, save, set }; diff --git a/src/background/index.js b/src/background/index.js index 63d13cb..c51754b 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,4 +1,4 @@ -import * as settingsActions from 'actions/setting'; +import * as settingsActions from 'settings/actions/setting'; import messages from 'shared/messages'; import BackgroundComponent from 'components/background'; import reducers from 'reducers'; diff --git a/src/components/background.js b/src/components/background.js index afb90c2..200fedf 100644 --- a/src/components/background.js +++ b/src/components/background.js @@ -1,6 +1,6 @@ import messages from 'shared/messages'; import * as operationActions from 'actions/operation'; -import * as settingsActions from 'actions/setting'; +import * as settingsActions from 'settings/actions/setting'; import * as tabActions from 'actions/tab'; import * as commands from 'shared/commands'; diff --git a/src/components/setting.js b/src/components/setting.js deleted file mode 100644 index c2f99b6..0000000 --- a/src/components/setting.js +++ /dev/null @@ -1,45 +0,0 @@ -import * as settingActions from 'actions/setting'; -import { validate } from 'shared/validators/setting'; - -export default class SettingComponent { - constructor(wrapper, store) { - this.wrapper = wrapper; - this.store = store; - - let doc = wrapper.ownerDocument; - let form = doc.getElementById('vimvixen-settings-form'); - form.addEventListener('submit', this.onSubmit.bind(this)); - - let plainJson = form.elements['plain-json']; - plainJson.addEventListener('input', this.onPlainJsonChanged.bind(this)); - - store.dispatch(settingActions.load()); - } - - onSubmit(e) { - let settings = { - json: e.target.elements['plain-json'].value, - }; - this.store.dispatch(settingActions.save(settings)); - e.preventDefault(); - } - - onPlainJsonChanged(e) { - try { - let settings = JSON.parse(e.target.value); - validate(settings); - e.target.setCustomValidity(''); - } catch (err) { - e.target.setCustomValidity(err.message); - } - } - - update() { - let { settings } = this.store.getState(); - - let doc = this.wrapper.ownerDocument; - let form = doc.getElementById('vimvixen-settings-form'); - let plainJsonInput = form.elements['plain-json']; - plainJsonInput.value = settings.json; - } -} diff --git a/src/content/index.js b/src/content/index.js index 25a2e74..edca510 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -1,6 +1,6 @@ import './console-frame.scss'; import * as consoleFrames from './console-frames'; -import * as settingActions from 'actions/setting'; +import * as settingActions from 'settings/actions/setting'; import { createStore } from 'store'; import ContentInputComponent from 'components/content-input'; import KeymapperComponent from 'components/keymapper'; diff --git a/src/pages/settings.html b/src/pages/settings.html deleted file mode 100644 index 99d6c6b..0000000 --- a/src/pages/settings.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -

Configure

- -

Home page

-
- - - - -
- - - diff --git a/src/pages/settings.js b/src/pages/settings.js deleted file mode 100644 index 6e25e6f..0000000 --- a/src/pages/settings.js +++ /dev/null @@ -1,15 +0,0 @@ -import './settings.scss'; -import SettingComponent from 'components/setting'; -import settingReducer from 'reducers/setting'; -import { createStore } from 'store'; - -const store = createStore(settingReducer); -let settingComponent = null; - -store.subscribe(() => { - settingComponent.update(); -}); - -document.addEventListener('DOMContentLoaded', () => { - settingComponent = new SettingComponent(document.body, store); -}); diff --git a/src/pages/settings.scss b/src/pages/settings.scss deleted file mode 100644 index 5707c8a..0000000 --- a/src/pages/settings.scss +++ /dev/null @@ -1,8 +0,0 @@ -.vimvixen-settings-form { - textarea[name=plain-json] { - font-family: monospace; - width: 100%; - min-height: 64ex; - resize: vertical; - } -} diff --git a/src/reducers/index.js b/src/reducers/index.js index 3ebe491..9c86ebf 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,7 +1,8 @@ import inputReducer from 'reducers/input'; -import settingReducer from 'reducers/setting'; +import settingReducer from 'settings/reducers/setting'; import followReducer from 'reducers/follow'; +// Make setting reducer instead of re-use const defaultState = { input: inputReducer(undefined, {}), setting: settingReducer(undefined, {}), diff --git a/src/reducers/setting.js b/src/reducers/setting.js deleted file mode 100644 index 7326ed7..0000000 --- a/src/reducers/setting.js +++ /dev/null @@ -1,17 +0,0 @@ -import actions from 'actions'; - -const defaultState = { - settings: {} -}; - -export default function reducer(state = defaultState, action = {}) { - switch (action.type) { - case actions.SETTING_SET_SETTINGS: - return Object.assign({}, state, { - settings: action.settings, - }); - default: - return state; - } -} - diff --git a/src/settings/actions/index.js b/src/settings/actions/index.js new file mode 100644 index 0000000..8c212c2 --- /dev/null +++ b/src/settings/actions/index.js @@ -0,0 +1,4 @@ +export default { + // Settings + SETTING_SET_SETTINGS: 'setting.set.settings', +}; diff --git a/src/settings/actions/setting.js b/src/settings/actions/setting.js new file mode 100644 index 0000000..697bcf0 --- /dev/null +++ b/src/settings/actions/setting.js @@ -0,0 +1,31 @@ +import actions from 'settings/actions'; +import messages from 'shared/messages'; +import DefaultSettings from 'shared/default-settings'; + +const load = () => { + return browser.storage.local.get('settings').then((value) => { + if (value.settings) { + return set(value.settings); + } + return set(DefaultSettings); + }, console.error); +}; + +const save = (settings) => { + return browser.storage.local.set({ + settings + }).then(() => { + return browser.runtime.sendMessage({ + type: messages.SETTINGS_RELOAD + }); + }); +}; + +const set = (settings) => { + return { + type: actions.SETTING_SET_SETTINGS, + settings, + }; +}; + +export { load, save, set }; diff --git a/src/settings/components/setting.js b/src/settings/components/setting.js new file mode 100644 index 0000000..14482a3 --- /dev/null +++ b/src/settings/components/setting.js @@ -0,0 +1,45 @@ +import * as settingActions from 'settings/actions/setting'; +import { validate } from 'shared/validators/setting'; + +export default class SettingComponent { + constructor(wrapper, store) { + this.wrapper = wrapper; + this.store = store; + + let doc = wrapper.ownerDocument; + let form = doc.getElementById('vimvixen-settings-form'); + form.addEventListener('submit', this.onSubmit.bind(this)); + + let plainJson = form.elements['plain-json']; + plainJson.addEventListener('input', this.onPlainJsonChanged.bind(this)); + + store.dispatch(settingActions.load()); + } + + onSubmit(e) { + let settings = { + json: e.target.elements['plain-json'].value, + }; + this.store.dispatch(settingActions.save(settings)); + e.preventDefault(); + } + + onPlainJsonChanged(e) { + try { + let settings = JSON.parse(e.target.value); + validate(settings); + e.target.setCustomValidity(''); + } catch (err) { + e.target.setCustomValidity(err.message); + } + } + + update() { + let { settings } = this.store.getState(); + + let doc = this.wrapper.ownerDocument; + let form = doc.getElementById('vimvixen-settings-form'); + let plainJsonInput = form.elements['plain-json']; + plainJsonInput.value = settings.json; + } +} diff --git a/src/settings/index.html b/src/settings/index.html new file mode 100644 index 0000000..99d6c6b --- /dev/null +++ b/src/settings/index.html @@ -0,0 +1,18 @@ + + + + + + +

Configure

+ +

Home page

+
+ + + + +
+ + + diff --git a/src/settings/index.js b/src/settings/index.js new file mode 100644 index 0000000..8c60f80 --- /dev/null +++ b/src/settings/index.js @@ -0,0 +1,15 @@ +import './site.scss'; +import SettingComponent from 'settings/components/setting'; +import settingReducer from 'settings/reducers/setting'; +import { createStore } from 'store'; + +const store = createStore(settingReducer); +let settingComponent = null; + +store.subscribe(() => { + settingComponent.update(); +}); + +document.addEventListener('DOMContentLoaded', () => { + settingComponent = new SettingComponent(document.body, store); +}); diff --git a/src/settings/reducers/setting.js b/src/settings/reducers/setting.js new file mode 100644 index 0000000..f7d9242 --- /dev/null +++ b/src/settings/reducers/setting.js @@ -0,0 +1,17 @@ +import actions from 'settings/actions'; + +const defaultState = { + settings: {} +}; + +export default function reducer(state = defaultState, action = {}) { + switch (action.type) { + case actions.SETTING_SET_SETTINGS: + return Object.assign({}, state, { + settings: action.settings, + }); + default: + return state; + } +} + diff --git a/src/settings/site.scss b/src/settings/site.scss new file mode 100644 index 0000000..5707c8a --- /dev/null +++ b/src/settings/site.scss @@ -0,0 +1,8 @@ +.vimvixen-settings-form { + textarea[name=plain-json] { + font-family: monospace; + width: 100%; + min-height: 64ex; + resize: vertical; + } +} diff --git a/test/reducers/setting.test.js b/test/reducers/setting.test.js deleted file mode 100644 index 1af031a..0000000 --- a/test/reducers/setting.test.js +++ /dev/null @@ -1,22 +0,0 @@ -import { expect } from "chai"; -import actions from 'actions'; -import settingReducer from 'reducers/setting'; - -describe("setting reducer", () => { - it('return the initial state', () => { - let state = settingReducer(undefined, {}); - expect(state).to.have.deep.property('settings', {}); - }); - - it('return next state for SETTING_SET_SETTINGS', () => { - let action = { - type: actions.SETTING_SET_SETTINGS, - settings: { value1: 'hello', value2: 'world' }, - }; - let state = settingReducer(undefined, action); - expect(state).to.have.deep.property('settings', { - value1: 'hello', - value2: 'world', - }); - }); -}); diff --git a/webpack.config.js b/webpack.config.js index 486814a..bc3bb1c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,7 +7,7 @@ const dist = path.resolve(__dirname, 'build'); module.exports = { entry: { index: path.join(src, 'content'), - settings: path.join(src, 'pages/settings'), + settings: path.join(src, 'settings'), background: path.join(src, 'background'), console: path.join(src, 'console') }, @@ -50,7 +50,7 @@ module.exports = { inject: false }), new HtmlWebpackPlugin({ - template: path.join(src, 'pages', 'settings.html'), + template: path.join(src, 'settings', 'index.html'), filename: path.join(dist, 'settings.html'), inject: false }) -- cgit v1.2.3 From d886d7de290b6fee00c55c5487416048f3de4bf2 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 8 Oct 2017 14:57:27 +0900 Subject: move background --- src/actions/operation.js | 50 +-------------------- src/actions/tab.js | 9 ---- src/background/actions/index.js | 0 src/background/actions/operation.js | 52 ++++++++++++++++++++++ src/background/actions/tab.js | 9 ++++ src/background/components/background.js | 79 +++++++++++++++++++++++++++++++++ src/background/index.js | 4 +- src/components/background.js | 79 --------------------------------- test/settings/reducers/setting.test.js | 22 +++++++++ 9 files changed, 165 insertions(+), 139 deletions(-) delete mode 100644 src/actions/tab.js create mode 100644 src/background/actions/index.js create mode 100644 src/background/actions/operation.js create mode 100644 src/background/actions/tab.js create mode 100644 src/background/components/background.js delete mode 100644 src/components/background.js create mode 100644 test/settings/reducers/setting.test.js (limited to 'src/background') diff --git a/src/actions/operation.js b/src/actions/operation.js index 8b1590b..a27cd02 100644 --- a/src/actions/operation.js +++ b/src/actions/operation.js @@ -1,18 +1,9 @@ import operations from 'shared/operations'; import messages from 'shared/messages'; -import * as tabs from 'background/tabs'; -import * as zooms from 'background/zooms'; import * as scrolls from 'content/scrolls'; import * as navigates from 'content/navigates'; import * as followActions from 'actions/follow'; -const sendConsoleShowCommand = (tab, command) => { - return browser.tabs.sendMessage(tab.id, { - type: messages.CONSOLE_SHOW_COMMAND, - command, - }); -}; - const exec = (operation) => { switch (operation.type) { case operations.SCROLL_LINES: @@ -49,43 +40,4 @@ const exec = (operation) => { } }; -const execBackground = (operation, tab) => { - switch (operation.type) { - case operations.TAB_CLOSE: - return tabs.closeTab(tab.id); - case operations.TAB_REOPEN: - return tabs.reopenTab(); - case operations.TAB_PREV: - return tabs.selectPrevTab(tab.index, operation.count); - case operations.TAB_NEXT: - return tabs.selectNextTab(tab.index, operation.count); - case operations.TAB_RELOAD: - return tabs.reload(tab, operation.cache); - case operations.ZOOM_IN: - return zooms.zoomIn(); - case operations.ZOOM_OUT: - return zooms.zoomOut(); - case operations.ZOOM_NEUTRAL: - return zooms.neutral(); - case operations.COMMAND_SHOW: - return sendConsoleShowCommand(tab, ''); - case operations.COMMAND_SHOW_OPEN: - if (operation.alter) { - // alter url - return sendConsoleShowCommand(tab, 'open ' + tab.url); - } - return sendConsoleShowCommand(tab, 'open '); - case operations.COMMAND_SHOW_TABOPEN: - if (operation.alter) { - // alter url - return sendConsoleShowCommand(tab, 'tabopen ' + tab.url); - } - return sendConsoleShowCommand(tab, 'tabopen '); - case operations.COMMAND_SHOW_BUFFER: - return sendConsoleShowCommand(tab, 'buffer '); - default: - return Promise.resolve(); - } -}; - -export { exec, execBackground }; +export { exec }; diff --git a/src/actions/tab.js b/src/actions/tab.js deleted file mode 100644 index e512b6f..0000000 --- a/src/actions/tab.js +++ /dev/null @@ -1,9 +0,0 @@ -const openNewTab = (url) => { - return browser.tabs.create({ url: url }); -}; - -const openToTab = (url, tab) => { - return browser.tabs.update(tab.id, { url: url }); -}; - -export { openToTab, openNewTab }; diff --git a/src/background/actions/index.js b/src/background/actions/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/background/actions/operation.js b/src/background/actions/operation.js new file mode 100644 index 0000000..d736c09 --- /dev/null +++ b/src/background/actions/operation.js @@ -0,0 +1,52 @@ +import operations from 'shared/operations'; +import messages from 'shared/messages'; +import * as tabs from 'background/tabs'; +import * as zooms from 'background/zooms'; + +const sendConsoleShowCommand = (tab, command) => { + return browser.tabs.sendMessage(tab.id, { + type: messages.CONSOLE_SHOW_COMMAND, + command, + }); +}; + +const exec = (operation, tab) => { + switch (operation.type) { + case operations.TAB_CLOSE: + return tabs.closeTab(tab.id); + case operations.TAB_REOPEN: + return tabs.reopenTab(); + case operations.TAB_PREV: + return tabs.selectPrevTab(tab.index, operation.count); + case operations.TAB_NEXT: + return tabs.selectNextTab(tab.index, operation.count); + case operations.TAB_RELOAD: + return tabs.reload(tab, operation.cache); + case operations.ZOOM_IN: + return zooms.zoomIn(); + case operations.ZOOM_OUT: + return zooms.zoomOut(); + case operations.ZOOM_NEUTRAL: + return zooms.neutral(); + case operations.COMMAND_SHOW: + return sendConsoleShowCommand(tab, ''); + case operations.COMMAND_SHOW_OPEN: + if (operation.alter) { + // alter url + return sendConsoleShowCommand(tab, 'open ' + tab.url); + } + return sendConsoleShowCommand(tab, 'open '); + case operations.COMMAND_SHOW_TABOPEN: + if (operation.alter) { + // alter url + return sendConsoleShowCommand(tab, 'tabopen ' + tab.url); + } + return sendConsoleShowCommand(tab, 'tabopen '); + case operations.COMMAND_SHOW_BUFFER: + return sendConsoleShowCommand(tab, 'buffer '); + default: + return Promise.resolve(); + } +}; + +export { exec }; diff --git a/src/background/actions/tab.js b/src/background/actions/tab.js new file mode 100644 index 0000000..e512b6f --- /dev/null +++ b/src/background/actions/tab.js @@ -0,0 +1,9 @@ +const openNewTab = (url) => { + return browser.tabs.create({ url: url }); +}; + +const openToTab = (url, tab) => { + return browser.tabs.update(tab.id, { url: url }); +}; + +export { openToTab, openNewTab }; diff --git a/src/background/components/background.js b/src/background/components/background.js new file mode 100644 index 0000000..bfe1b3f --- /dev/null +++ b/src/background/components/background.js @@ -0,0 +1,79 @@ +import messages from 'shared/messages'; +import * as operationActions from 'background/actions/operation'; +import * as settingsActions from 'settings/actions/setting'; +import * as tabActions from 'background/actions/tab'; +import * as commands from 'shared/commands'; + +export default class BackgroundComponent { + constructor(store) { + this.store = store; + this.setting = {}; + + browser.runtime.onMessage.addListener((message, sender) => { + try { + return this.onMessage(message, sender); + } catch (e) { + return browser.tabs.sendMessage(sender.tab.id, { + type: messages.CONSOLE_SHOW_ERROR, + text: e.message, + }); + } + }); + } + + update() { + let state = this.store.getState(); + this.updateSettings(state); + } + + updateSettings(setting) { + if (!setting.settings.json) { + return; + } + this.settings = JSON.parse(setting.settings.json); + } + + onMessage(message, sender) { + switch (message.type) { + case messages.BACKGROUND_OPERATION: + return this.store.dispatch( + operationActions.exec(message.operation, sender.tab), + sender); + case messages.OPEN_URL: + if (message.newTab) { + return this.store.dispatch( + tabActions.openNewTab(message.url), sender); + } + return this.store.dispatch( + tabActions.openToTab(message.url, sender.tab), sender); + case messages.CONSOLE_BLURRED: + return browser.tabs.sendMessage(sender.tab.id, { + type: messages.CONSOLE_HIDE, + }); + case messages.CONSOLE_ENTERED: + return commands.exec(message.text, this.settings).catch((e) => { + return browser.tabs.sendMessage(sender.tab.id, { + type: messages.CONSOLE_SHOW_ERROR, + text: e.message, + }); + }); + case messages.SETTINGS_QUERY: + return Promise.resolve(this.store.getState().settings); + case messages.CONSOLE_QUERY_COMPLETIONS: + return commands.complete(message.text, this.settings); + case messages.SETTINGS_RELOAD: + this.store.dispatch(settingsActions.load()); + return this.broadcastSettingsChanged(); + } + } + + broadcastSettingsChanged() { + return browser.tabs.query({}).then((tabs) => { + for (let tab of tabs) { + browser.tabs.sendMessage(tab.id, { + type: messages.SETTINGS_CHANGED, + }); + } + }); + } +} diff --git a/src/background/index.js b/src/background/index.js index c51754b..587cc0b 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -1,7 +1,7 @@ import * as settingsActions from 'settings/actions/setting'; import messages from 'shared/messages'; -import BackgroundComponent from 'components/background'; -import reducers from 'reducers'; +import BackgroundComponent from 'background/components/background'; +import reducers from 'settings/reducers/setting'; import { createStore } from 'store'; const store = createStore(reducers, (e, sender) => { diff --git a/src/components/background.js b/src/components/background.js deleted file mode 100644 index 200fedf..0000000 --- a/src/components/background.js +++ /dev/null @@ -1,79 +0,0 @@ -import messages from 'shared/messages'; -import * as operationActions from 'actions/operation'; -import * as settingsActions from 'settings/actions/setting'; -import * as tabActions from 'actions/tab'; -import * as commands from 'shared/commands'; - -export default class BackgroundComponent { - constructor(store) { - this.store = store; - this.setting = {}; - - browser.runtime.onMessage.addListener((message, sender) => { - try { - return this.onMessage(message, sender); - } catch (e) { - return browser.tabs.sendMessage(sender.tab.id, { - type: messages.CONSOLE_SHOW_ERROR, - text: e.message, - }); - } - }); - } - - update() { - let state = this.store.getState(); - this.updateSettings(state.setting); - } - - updateSettings(setting) { - if (!setting.settings.json) { - return; - } - this.settings = JSON.parse(setting.settings.json); - } - - onMessage(message, sender) { - switch (message.type) { - case messages.BACKGROUND_OPERATION: - return this.store.dispatch( - operationActions.execBackground(message.operation, sender.tab), - sender); - case messages.OPEN_URL: - if (message.newTab) { - return this.store.dispatch( - tabActions.openNewTab(message.url), sender); - } - return this.store.dispatch( - tabActions.openToTab(message.url, sender.tab), sender); - case messages.CONSOLE_BLURRED: - return browser.tabs.sendMessage(sender.tab.id, { - type: messages.CONSOLE_HIDE, - }); - case messages.CONSOLE_ENTERED: - return commands.exec(message.text, this.settings).catch((e) => { - return browser.tabs.sendMessage(sender.tab.id, { - type: messages.CONSOLE_SHOW_ERROR, - text: e.message, - }); - }); - case messages.SETTINGS_QUERY: - return Promise.resolve(this.store.getState().setting.settings); - case messages.CONSOLE_QUERY_COMPLETIONS: - return commands.complete(message.text, this.settings); - case messages.SETTINGS_RELOAD: - this.store.dispatch(settingsActions.load()); - return this.broadcastSettingsChanged(); - } - } - - broadcastSettingsChanged() { - return browser.tabs.query({}).then((tabs) => { - for (let tab of tabs) { - browser.tabs.sendMessage(tab.id, { - type: messages.SETTINGS_CHANGED, - }); - } - }); - } -} diff --git a/test/settings/reducers/setting.test.js b/test/settings/reducers/setting.test.js new file mode 100644 index 0000000..0e84247 --- /dev/null +++ b/test/settings/reducers/setting.test.js @@ -0,0 +1,22 @@ +import { expect } from "chai"; +import actions from 'settings/actions'; +import settingReducer from 'settings/reducers/setting'; + +describe("setting reducer", () => { + it('return the initial state', () => { + let state = settingReducer(undefined, {}); + expect(state).to.have.deep.property('settings', {}); + }); + + it('return next state for SETTING_SET_SETTINGS', () => { + let action = { + type: actions.SETTING_SET_SETTINGS, + settings: { value1: 'hello', value2: 'world' }, + }; + let state = settingReducer(undefined, action); + expect(state).to.have.deep.property('settings', { + value1: 'hello', + value2: 'world', + }); + }); +}); -- cgit v1.2.3 From 2faf44af7443b3f858e15d63295a490afba83b4e Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 8 Oct 2017 15:11:09 +0900 Subject: move store to shared --- src/background/index.js | 2 +- src/console/index.js | 2 +- src/content/index.js | 2 +- src/settings/index.js | 2 +- src/shared/store/index.js | 53 +++++++++++++++++++ src/store/index.js | 53 ------------------- test/shared/store/index.test.js | 111 ++++++++++++++++++++++++++++++++++++++++ test/store/index.test.js | 111 ---------------------------------------- 8 files changed, 168 insertions(+), 168 deletions(-) create mode 100644 src/shared/store/index.js delete mode 100644 src/store/index.js create mode 100644 test/shared/store/index.test.js delete mode 100644 test/store/index.test.js (limited to 'src/background') diff --git a/src/background/index.js b/src/background/index.js index 587cc0b..6ba37eb 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -2,7 +2,7 @@ import * as settingsActions from 'settings/actions/setting'; import messages from 'shared/messages'; import BackgroundComponent from 'background/components/background'; import reducers from 'settings/reducers/setting'; -import { createStore } from 'store'; +import { createStore } from 'shared/store'; const store = createStore(reducers, (e, sender) => { console.error('Vim-Vixen:', e); diff --git a/src/console/index.js b/src/console/index.js index 1bcf8bc..7396a96 100644 --- a/src/console/index.js +++ b/src/console/index.js @@ -3,7 +3,7 @@ import messages from 'shared/messages'; import CompletionComponent from 'console/components/completion'; import ConsoleComponent from 'console/components/console'; import reducers from 'console/reducers'; -import { createStore } from 'store'; +import { createStore } from 'shared/store'; import * as consoleActions from 'console/actions/console'; const store = createStore(reducers); diff --git a/src/content/index.js b/src/content/index.js index 00873cc..adea871 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -1,7 +1,7 @@ import './console-frame.scss'; import * as consoleFrames from './console-frames'; import * as settingActions from 'settings/actions/setting'; -import { createStore } from 'store'; +import { createStore } from 'shared/store'; import ContentInputComponent from 'content/components/content-input'; import KeymapperComponent from 'content/components/keymapper'; import FollowComponent from 'content/components/follow'; diff --git a/src/settings/index.js b/src/settings/index.js index 8c60f80..c8d6cc4 100644 --- a/src/settings/index.js +++ b/src/settings/index.js @@ -1,7 +1,7 @@ import './site.scss'; import SettingComponent from 'settings/components/setting'; import settingReducer from 'settings/reducers/setting'; -import { createStore } from 'store'; +import { createStore } from 'shared/store'; const store = createStore(settingReducer); let settingComponent = null; diff --git a/src/shared/store/index.js b/src/shared/store/index.js new file mode 100644 index 0000000..2fafdf1 --- /dev/null +++ b/src/shared/store/index.js @@ -0,0 +1,53 @@ +class Store { + constructor(reducer, catcher) { + this.reducer = reducer; + this.catcher = catcher; + this.subscribers = []; + try { + this.state = this.reducer(undefined, {}); + } catch (e) { + catcher(e); + } + } + + dispatch(action, sender) { + if (action instanceof Promise) { + action.then((a) => { + this.transitNext(a, sender); + }).catch((e) => { + this.catcher(e, sender); + }); + } else { + try { + this.transitNext(action, sender); + } catch (e) { + this.catcher(e, sender); + } + } + return action; + } + + getState() { + return this.state; + } + + subscribe(callback) { + this.subscribers.push(callback); + } + + transitNext(action, sender) { + let newState = this.reducer(this.state, action); + if (JSON.stringify(this.state) !== JSON.stringify(newState)) { + this.state = newState; + this.subscribers.forEach(f => f(sender)); + } + } +} + +const empty = () => {}; + +const createStore = (reducer, catcher = empty) => { + return new Store(reducer, catcher); +}; + +export { createStore }; diff --git a/src/store/index.js b/src/store/index.js deleted file mode 100644 index 2fafdf1..0000000 --- a/src/store/index.js +++ /dev/null @@ -1,53 +0,0 @@ -class Store { - constructor(reducer, catcher) { - this.reducer = reducer; - this.catcher = catcher; - this.subscribers = []; - try { - this.state = this.reducer(undefined, {}); - } catch (e) { - catcher(e); - } - } - - dispatch(action, sender) { - if (action instanceof Promise) { - action.then((a) => { - this.transitNext(a, sender); - }).catch((e) => { - this.catcher(e, sender); - }); - } else { - try { - this.transitNext(action, sender); - } catch (e) { - this.catcher(e, sender); - } - } - return action; - } - - getState() { - return this.state; - } - - subscribe(callback) { - this.subscribers.push(callback); - } - - transitNext(action, sender) { - let newState = this.reducer(this.state, action); - if (JSON.stringify(this.state) !== JSON.stringify(newState)) { - this.state = newState; - this.subscribers.forEach(f => f(sender)); - } - } -} - -const empty = () => {}; - -const createStore = (reducer, catcher = empty) => { - return new Store(reducer, catcher); -}; - -export { createStore }; diff --git a/test/shared/store/index.test.js b/test/shared/store/index.test.js new file mode 100644 index 0000000..133033b --- /dev/null +++ b/test/shared/store/index.test.js @@ -0,0 +1,111 @@ +import { expect } from "chai"; +import { createStore } from 'shared/store'; + +describe("Store class", () => { + const reducer = (state, action) => { + if (state == undefined) { + return 0; + } + return state + action; + }; + + describe("#dispatch", () => { + it('transit status by immediate action', () => { + let store = createStore(reducer); + store.dispatch(10); + expect(store.getState()).to.equal(10); + + store.dispatch(-20); + expect(store.getState()).to.equal(-10); + }); + + it('returns next state by immediate action', () => { + let store = createStore(reducer); + let dispatchedAction = store.dispatch(11); + expect(dispatchedAction).to.equal(11); + }); + + it('transit status by Promise action', () => { + let store = createStore(reducer); + let p1 = Promise.resolve(10); + + return store.dispatch(p1).then(() => { + expect(store.getState()).to.equal(10); + }).then(() => { + store.dispatch(Promise.resolve(-20)); + }).then(() => { + expect(store.getState()).to.equal(-10); + }); + }); + + it('returns next state by promise action', () => { + let store = createStore(reducer); + let dispatchedAction = store.dispatch(Promise.resolve(11)); + return dispatchedAction.then((value) => { + expect(value).to.equal(11); + }); + }); + }); + + describe("#subscribe", () => { + it('invoke callback', (done) => { + let store = createStore(reducer); + store.subscribe(() => { + expect(store.getState()).to.equal(15); + done(); + }); + store.dispatch(15); + }); + + it('propagate sender object', (done) => { + let store = createStore(reducer); + store.subscribe((sender) => { + expect(sender).to.equal('sender'); + done(); + }); + store.dispatch(15, 'sender'); + }); + }) + + describe("catcher", () => { + it('catch an error in reducer on initializing by immediate action', (done) => { + let store = createStore(() => { + throw new Error(); + }, (e) => { + expect(e).to.be.an('error'); + done(); + }); + }); + + it('catch an error in reducer on initializing by immediate action', (done) => { + let store = createStore((state, action) => { + if (state === undefined) return 0; + throw new Error(); + }, (e) => { + expect(e).to.be.an('error'); + done(); + }); + store.dispatch(20); + }); + + it('catch an error in reducer on initializing by promise action', (done) => { + let store = createStore((state, action) => { + if (state === undefined) return 0; + throw new Error(); + }, (e) => { + expect(e).to.be.an('error'); + done(); + }); + store.dispatch(Promise.resolve(20)); + }); + + it('catch an error in promise action', (done) => { + let store = createStore((state, action) => 0, (e) => { + expect(e).to.be.an('error'); + done(); + }); + store.dispatch(new Promise(() => { throw new Error() })); + }); + }) +}); + diff --git a/test/store/index.test.js b/test/store/index.test.js deleted file mode 100644 index 5dce715..0000000 --- a/test/store/index.test.js +++ /dev/null @@ -1,111 +0,0 @@ -import { expect } from "chai"; -import { createStore } from 'store'; - -describe("Store class", () => { - const reducer = (state, action) => { - if (state == undefined) { - return 0; - } - return state + action; - }; - - describe("#dispatch", () => { - it('transit status by immediate action', () => { - let store = createStore(reducer); - store.dispatch(10); - expect(store.getState()).to.equal(10); - - store.dispatch(-20); - expect(store.getState()).to.equal(-10); - }); - - it('returns next state by immediate action', () => { - let store = createStore(reducer); - let dispatchedAction = store.dispatch(11); - expect(dispatchedAction).to.equal(11); - }); - - it('transit status by Promise action', () => { - let store = createStore(reducer); - let p1 = Promise.resolve(10); - - return store.dispatch(p1).then(() => { - expect(store.getState()).to.equal(10); - }).then(() => { - store.dispatch(Promise.resolve(-20)); - }).then(() => { - expect(store.getState()).to.equal(-10); - }); - }); - - it('returns next state by promise action', () => { - let store = createStore(reducer); - let dispatchedAction = store.dispatch(Promise.resolve(11)); - return dispatchedAction.then((value) => { - expect(value).to.equal(11); - }); - }); - }); - - describe("#subscribe", () => { - it('invoke callback', (done) => { - let store = createStore(reducer); - store.subscribe(() => { - expect(store.getState()).to.equal(15); - done(); - }); - store.dispatch(15); - }); - - it('propagate sender object', (done) => { - let store = createStore(reducer); - store.subscribe((sender) => { - expect(sender).to.equal('sender'); - done(); - }); - store.dispatch(15, 'sender'); - }); - }) - - describe("catcher", () => { - it('catch an error in reducer on initializing by immediate action', (done) => { - let store = createStore(() => { - throw new Error(); - }, (e) => { - expect(e).to.be.an('error'); - done(); - }); - }); - - it('catch an error in reducer on initializing by immediate action', (done) => { - let store = createStore((state, action) => { - if (state === undefined) return 0; - throw new Error(); - }, (e) => { - expect(e).to.be.an('error'); - done(); - }); - store.dispatch(20); - }); - - it('catch an error in reducer on initializing by promise action', (done) => { - let store = createStore((state, action) => { - if (state === undefined) return 0; - throw new Error(); - }, (e) => { - expect(e).to.be.an('error'); - done(); - }); - store.dispatch(Promise.resolve(20)); - }); - - it('catch an error in promise action', (done) => { - let store = createStore((state, action) => 0, (e) => { - expect(e).to.be.an('error'); - done(); - }); - store.dispatch(new Promise(() => { throw new Error() })); - }); - }) -}); - -- cgit v1.2.3