From e8056d2a709df9c9c182382fc7a31795e4dc1c0f Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 9 Sep 2017 22:07:27 +0900 Subject: [PATCH] console state as action/reducer in redux --- src/actions/console.js | 28 +++++++++ src/actions/index.js | 6 ++ src/console/console-frame.js | 21 ++----- src/console/console.js | 106 +++++++++++++++-------------------- src/content/index.js | 1 - src/reducers/console.js | 39 +++++++++++++ 6 files changed, 123 insertions(+), 78 deletions(-) create mode 100644 src/actions/console.js create mode 100644 src/actions/index.js create mode 100644 src/reducers/console.js diff --git a/src/actions/console.js b/src/actions/console.js new file mode 100644 index 0000000..99a46e8 --- /dev/null +++ b/src/actions/console.js @@ -0,0 +1,28 @@ +import actions from '../actions'; + +export function showCommand(text) { + return { + type: actions.CONSOLE_SHOW_COMMAND, + text: text + }; +} + +export function setCompletions(completions) { + return { + type: actions.CONSOLE_SET_COMPLETIONS, + completions: completions + }; +} + +export function showError(text) { + return { + type: actions.CONSOLE_SHOW_ERROR, + text: text + }; +} + +export function hide() { + return { + type: actions.CONSOLE_HIDE + }; +} diff --git a/src/actions/index.js b/src/actions/index.js new file mode 100644 index 0000000..38ced9d --- /dev/null +++ b/src/actions/index.js @@ -0,0 +1,6 @@ +export default { + CONSOLE_SHOW_COMMAND: 'vimvixen.console.show.command', + CONSOLE_SET_COMPLETIONS: 'vimvixen.console.set.completions', + CONSOLE_SHOW_ERROR: 'vimvixen.console.show.error', + CONSOLE_HIDE: 'vimvixen.console.hide' +}; diff --git a/src/console/console-frame.js b/src/console/console-frame.js index f07d8ab..8b4c17a 100644 --- a/src/console/console-frame.js +++ b/src/console/console-frame.js @@ -1,4 +1,5 @@ import './console-frame.scss'; +import * as consoleActions from '../actions/console'; export default class ConsoleFrame { constructor(win) { @@ -16,26 +17,17 @@ export default class ConsoleFrame { showCommand(text) { this.showFrame(); - - let message = { - type: 'vimvixen.console.show.command', - text: text - }; this.errorShown = false; - return browser.runtime.sendMessage(message); + return browser.runtime.sendMessage(consoleActions.showCommand(text)); } showError(text) { this.showFrame(); - let message = { - type: 'vimvixen.console.show.error', - text: text - }; this.errorShown = true; this.element.blur(); - return browser.runtime.sendMessage(message); + return browser.runtime.sendMessage(consoleActions.showError(text)); } showFrame() { @@ -46,6 +38,8 @@ export default class ConsoleFrame { this.element.style.display = 'none'; this.element.blur(); this.errorShown = false; + + return browser.runtime.sendMessage(consoleActions.hide()); } isErrorShown() { @@ -53,9 +47,6 @@ export default class ConsoleFrame { } setCompletions(completions) { - return browser.runtime.sendMessage({ - type: 'vimvixen.console.set.completions', - completions: completions - }); + return browser.runtime.sendMessage(consoleActions.setCompletions(completions)); } } diff --git a/src/console/console.js b/src/console/console.js index 006f640..044aa5f 100644 --- a/src/console/console.js +++ b/src/console/console.js @@ -1,10 +1,12 @@ import './console.scss'; import Completion from './completion'; +import consoleReducer, { defaultState } from '../reducers/console'; // TODO consider object-oriented var prevValue = ""; var completion = null; var completionOrigin = ""; +let state = defaultState; const blurMessage = () => { return { @@ -96,38 +98,6 @@ window.addEventListener('load', () => { input.addEventListener('keyup', handleKeyup); }); -const showCommand = (text) => { - let command = window.document.querySelector('#vimvixen-console-command'); - command.style.display = 'block'; - - let error = window.document.querySelector('#vimvixen-console-error'); - error.style.display = 'none'; - - let input = window.document.querySelector('#vimvixen-console-command-input'); - input.value = text; - input.focus(); - - completion = null; - let container = window.document.querySelector('#vimvixen-console-completion'); - container.innerHTML = ''; - - return browser.runtime.sendMessage(keyupMessage(input)); -} - -const showError = (text) => { - let error = window.document.querySelector('#vimvixen-console-error'); - error.textContent = text; - error.style.display = 'block'; - - let command = window.document.querySelector('#vimvixen-console-command'); - command.style.display = 'none'; - - let completion = window.document.querySelector('#vimvixen-console-completion'); - completion.style.display = 'none'; - - return Promise.resolve(); -} - const createCompletionTitle = (text) => { let li = document.createElement('li'); li.className = 'vimvixen-console-completion-title'; @@ -152,56 +122,68 @@ const createCompletionItem = (icon, caption, url) => { return li; } -const setCompletions = (completions) => { +const selectCompletion = (target) => { let container = window.document.querySelector('#vimvixen-console-completion'); - container.style.display = 'block'; - container.innerHTML = ''; + Array.prototype.forEach.call(container.children, (ele) => { + if (!ele.classList.contains('vimvixen-console-completion-item')) { + return; + } + if (ele === target) { + ele.classList.add('vimvixen-completion-selected'); + } else { + ele.classList.remove('vimvixen-completion-selected'); + } + }); +}; + +const updateCompletions = (completions) => { + let completionsContainer = window.document.querySelector('#vimvixen-console-completion'); + let input = window.document.querySelector('#vimvixen-console-command-input'); + + completionsContainer.innerHTML = ''; let pairs = []; for (let group of completions) { let title = createCompletionTitle(group.name); - container.append(title); + completionsContainer.append(title); for (let item of group.items) { let li = createCompletionItem(item.icon, item.caption, item.url); - container.append(li); + completionsContainer.append(li); pairs.push([item, li]); } } completion = new Completion(pairs); + completionOrigin = input.value.split(' ')[0]; +} +const update = (prevState, state) => { + let error = window.document.querySelector('#vimvixen-console-error'); + let command = window.document.querySelector('#vimvixen-console-command'); let input = window.document.querySelector('#vimvixen-console-command-input'); - completionOrigin = input.value.split(' ')[0]; - return Promise.resolve(); -} + error.style.display = state.errorShown ? 'block' : 'none'; + error.textContent = state.errorText; -const selectCompletion = (target) => { - let container = window.document.querySelector('#vimvixen-console-completion'); - Array.prototype.forEach.call(container.children, (ele) => { - if (!ele.classList.contains('vimvixen-console-completion-item')) { - return; - } - if (ele === target) { - ele.classList.add('vimvixen-completion-selected'); - } else { - ele.classList.remove('vimvixen-completion-selected'); - } - }); -}; + command.style.display = state.commandShown ? 'block' : 'none'; + if (!prevState.commandShown && state.commandShown) { + // setup input on firstly shown + input.value = state.commandText; + input.focus(); + } + + if (JSON.stringify(state.completions) !== JSON.stringify(prevState.completions)) { + updateCompletions(state.completions); + } +} browser.runtime.onMessage.addListener((action) => { - switch (action.type) { - case 'vimvixen.console.show.error': - return showError(action.text); - case 'vimvixen.console.set.completions': - return setCompletions(action.completions); - case 'vimvixen.console.show.command': - return showCommand(action.text); - default: - return Promise.resolve(); + let nextState = consoleReducer(state, action); + if (JSON.stringify(nextState) !== JSON.stringify(state)) { + update(state, nextState); + state = nextState; } }); diff --git a/src/content/index.js b/src/content/index.js index bf90363..deb3506 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -6,7 +6,6 @@ import Follow from './follow'; let vvConsole = new ConsoleFrame(window); - browser.runtime.onMessage.addListener((action) => { switch (action.type) { case actions.CMD_OPEN: diff --git a/src/reducers/console.js b/src/reducers/console.js new file mode 100644 index 0000000..62fc951 --- /dev/null +++ b/src/reducers/console.js @@ -0,0 +1,39 @@ +import actions from '../actions'; + +export const defaultState = { + errorText: '', + errorShown: false, + commandText: '', + commandShown: false, + completions: [], +}; + +export default function reducer(state = defaultState, action = {}) { + switch (action.type) { + case actions.CONSOLE_SHOW_COMMAND: + return Object.assign({}, state, { + commandShown: true, + commandText: action.text, + errorShow: false, + completions: [] + }); + case actions.CONSOLE_SET_COMPLETIONS: + return Object.assign({}, state, { + completions: action.completions + }); + case actions.CONSOLE_SHOW_ERROR: + return Object.assign({}, state, { + errorText: action.message, + errorShow: true, + commandShown: false, + }); + case actions.CONSOLE_HIDE: + return Object.assign({}, state, { + errorShown: false, + commandShown: false + + }); + default: + return state; + } +}