From 6127fdc285bc430b48259bd6e90b69623b4e76cc Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Thu, 14 Sep 2017 21:40:28 +0900 Subject: [PATCH] use input as store/reducer --- src/actions/operation.js | 12 +++++----- src/background/index.js | 45 ++++++++++++++++++++------------------ src/reducers/background.js | 8 +++---- src/reducers/command.js | 10 ++++----- src/reducers/index.js | 6 ++++- 5 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/actions/operation.js b/src/actions/operation.js index 352bfac..8ca0f4b 100644 --- a/src/actions/operation.js +++ b/src/actions/operation.js @@ -2,18 +2,18 @@ import operations from '../operations'; import * as tabs from '../background/tabs'; import * as zooms from '../background/zooms'; -export function exec(operation, sender) { +export function exec(operation, tab) { switch (operation.type) { case operations.TABS_CLOSE: - return tabs.closeTab(sender.tab.id); + return tabs.closeTab(tab.id); case operations.TABS_REOPEN: return tabs.reopenTab(); case operations.TABS_PREV: - return tabs.selectPrevTab(sender.tab.index, operation.count); + return tabs.selectPrevTab(tab.index, operation.count); case operations.TABS_NEXT: - return tabs.selectNextTab(sender.tab.index, operation.count); + return tabs.selectNextTab(tab.index, operation.count); case operations.TABS_RELOAD: - return tabs.reload(sender.tab, operation.cache); + return tabs.reload(tab, operation.cache); case operations.ZOOM_IN: return zooms.zoomIn(); case operations.ZOOM_OUT: @@ -21,7 +21,7 @@ export function exec(operation, sender) { case operations.ZOOM_NEUTRAL: return zooms.neutral(); default: - return browser.tabs.sendMessage(sender.tab.id, { + return browser.tabs.sendMessage(tab.id, { type: 'require.content.operation', operation }); diff --git a/src/background/index.js b/src/background/index.js index e9757b9..d56fab8 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -4,49 +4,52 @@ import * as operationActions from '../actions/operation'; import backgroundReducers from '../reducers/background'; import reducers from '../reducers'; import commandReducer from '../reducers/command'; -import inputReducers from '../reducers/input'; import * as store from '../store' const backgroundStore = store.createStore(reducers, (e) => { console.error('Vim-Vixen:', e); }); -let inputState = inputReducers(undefined, {}); +backgroundStore.subscribe(() => { + browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { + if (tabs.length > 0) { + return keyQueueChanged(tabs[0], backgroundStore.getState()); + } + }); +}); -const keyQueueChanged = (sender, prevState, state) => { - if (state.keys.length === 0) { +const keyQueueChanged = (sendToTab, state) => { + if (state.input.keys.length === 0) { return Promise.resolve(); } - let prefix = keys.asKeymapChars(state.keys); + let prefix = keys.asKeymapChars(state.input.keys); let matched = Object.keys(keys.defaultKeymap).filter((keys) => { return keys.startsWith(prefix); }); if (matched.length == 0) { - return handleMessage(inputActions.clearKeys(), sender); + return handleMessage(inputActions.clearKeys(), sendToTab); } else if (matched.length > 1 || matched.length === 1 && prefix !== matched[0]) { return Promise.resolve(); } let action = keys.defaultKeymap[matched]; - backgroundStore.dispatch(operationActions.exec(action, sender)); - return handleMessage(inputActions.clearKeys(), sender).then(() => { - return backgroundReducers(undefined, action, sender).then(() => { - return browser.tabs.sendMessage(sender.tab.id, action); + backgroundStore.dispatch(operationActions.exec(action, sendToTab)); + return handleMessage(inputActions.clearKeys(), sendToTab).then(() => { + return backgroundReducers(undefined, action, sendToTab).then(() => { + return browser.tabs.sendMessage(sendToTab.id, action); }); }); }; -const handleMessage = (action, sender) => { - let nextInputState = inputReducers(inputState, action); - if (JSON.stringify(nextInputState) !== JSON.stringify(inputState)) { - let prevState = inputState; - inputState = nextInputState; - return keyQueueChanged(sender, prevState, inputState); - } - return backgroundReducers(undefined, action, sender).then(() => { - return commandReducer(undefined, action, sender).then(() => { - return browser.tabs.sendMessage(sender.tab.id, action); +const handleMessage = (action, sendToTab) => { + backgroundStore.dispatch(action); + + return backgroundReducers(undefined, action, sendToTab).then(() => { + return commandReducer(undefined, action, sendToTab).then(() => { + return browser.tabs.sendMessage(sendToTab.id, action); }); }); }; -browser.runtime.onMessage.addListener(handleMessage); +browser.runtime.onMessage.addListener((action, sender) => { + handleMessage(action, sender.tab); +}); diff --git a/src/reducers/background.js b/src/reducers/background.js index 7a279c9..ba934fd 100644 --- a/src/reducers/background.js +++ b/src/reducers/background.js @@ -2,7 +2,7 @@ import * as tabs from '../background/tabs'; import * as consoleActions from '../actions/console'; import actions from '../actions'; -const doCompletion = (command, keywords, sender) => { +const doCompletion = (command, keywords, tabId) => { if (command === 'buffer') { return tabs.getCompletions(keywords).then((tabs) => { let items = tabs.map((tab) => { @@ -18,18 +18,18 @@ const doCompletion = (command, keywords, sender) => { items: items }; return browser.tabs.sendMessage( - sender, + tabId, consoleActions.setCompletions([completions])); }); } return Promise.resolve(); }; -export default function reducer(state, action = {}, sender) { +export default function reducer(state, action = {}, sendToTab) { // TODO hide sender object switch (action.type) { case actions.BACKGROUND_REQUEST_COMPLETIONS: - return doCompletion(action.command, action.keywords, sender.tab.id); + return doCompletion(action.command, action.keywords, sendToTab.id); default: return Promise.resolve(); } diff --git a/src/reducers/command.js b/src/reducers/command.js index 7e03593..b645e29 100644 --- a/src/reducers/command.js +++ b/src/reducers/command.js @@ -1,23 +1,23 @@ import * as tabs from '../background/tabs'; import actions from '../actions'; -const cmdBuffer = (sender, arg) => { +const cmdBuffer = (tab, arg) => { if (isNaN(arg)) { - return tabs.selectByKeyword(sender.tab, arg); + return tabs.selectByKeyword(tab, arg); } else { let index = parseInt(arg, 10) - 1; return tabs.selectAt(index); } } -export default function reducer(state, action, sender) { +export default function reducer(state, action, sendToTab) { switch (action.type) { case actions.COMMAND_OPEN_URL: - return browser.tabs.update(sender.tab.id, { url: action.url }); + return browser.tabs.update(sendToTab.id, { url: action.url }); case actions.COMMAND_TABOPEN_URL: return browser.tabs.create({ url: action.url }); case actions.COMMAND_BUFFER: - return cmdBuffer(sender, action.keywords); + return cmdBuffer(sendToTab, action.keywords); default: return Promise.resolve(); } diff --git a/src/reducers/index.js b/src/reducers/index.js index d49af7d..6cc1a31 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,7 +1,11 @@ +import inputReducer from '../reducers/input'; + const defaultState = { + input: inputReducer(undefined, {}) }; -export default function reducer(state = defaultState/*, action = {}*/) { +export default function reducer(state = defaultState, action = {}) { return Object.assign({}, state, { + input: inputReducer(state.input, action) }); }