From eff8d9a83edf63bab09df4bd7f6e20e85fba3899 Mon Sep 17 00:00:00 2001 From: Shin'ya UEOKA Date: Tue, 3 Oct 2017 02:54:38 +0000 Subject: [PATCH 1/3] comtent input as compoents --- src/components/content-input.js | 31 +++++++++++++++++++++++++++++++ src/content/index.js | 18 ++---------------- 2 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 src/components/content-input.js diff --git a/src/components/content-input.js b/src/components/content-input.js new file mode 100644 index 0000000..81f2e6b --- /dev/null +++ b/src/components/content-input.js @@ -0,0 +1,31 @@ +import messages from '../content/messages'; + +export default class ContentInputComponent { + constructor(target) { + target.addEventListener('keypress', this.onKeyPress.bind(this)); + target.addEventListener('keydown', this.onKeyDown.bind(this)); + target.addEventListener('keyup', this.onKeyUp.bind(this)); + } + + onKeyPress(e) { + if (e.target instanceof HTMLInputElement || + e.target instanceof HTMLTextAreaElement || + e.target instanceof HTMLSelectElement) { + if (e.key === 'Escape' && e.target.blur) { + e.target.blur(); + } + return; + } + browser.runtime.sendMessage({ + type: messages.KEYDOWN, + code: e.which, + ctrl: e.ctrlKey + }); + } + + onKeyDown() { + } + + onKeyUp() { + } +} diff --git a/src/content/index.js b/src/content/index.js index 0dbc8c1..e5a2965 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -4,6 +4,7 @@ import * as scrolls from '../content/scrolls'; import * as navigates from '../content/navigates'; import * as followActions from '../actions/follow'; import * as store from '../store'; +import ContentInputComponent from '../components/content-input'; import FollowComponent from '../components/follow'; import followReducer from '../reducers/follow'; import operations from '../operations'; @@ -18,25 +19,10 @@ followStore.subscribe(() => { console.error(e); } }); +const contentInputComponent = new ContentInputComponent(window); consoleFrames.initialize(window.document); -window.addEventListener('keypress', (e) => { - if (e.target instanceof HTMLInputElement || - e.target instanceof HTMLTextAreaElement || - e.target instanceof HTMLSelectElement) { - if (e.key === 'Escape' && e.target.blur) { - e.target.blur(); - } - return; - } - browser.runtime.sendMessage({ - type: messages.KEYDOWN, - code: e.which, - ctrl: e.ctrlKey - }); -}); - const execOperation = (operation) => { switch (operation.type) { case operations.SCROLL_LINES: From 5ac1f60ece0a112a55f329ed34b455dcc776b22c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 3 Oct 2017 20:58:50 +0900 Subject: [PATCH 2/3] remove deprecated property in KeyboardEvent --- src/actions/input.js | 12 +++++++++--- src/components/background-input.js | 6 ++---- src/components/background.js | 2 +- src/components/content-input.js | 2 +- src/content/index.js | 1 + src/reducers/input.js | 11 +++-------- src/shared/keys.js | 21 -------------------- test/actions/input.test.js | 11 ++++++++--- test/reducers/input.test.js | 22 +++++++-------------- test/shared/keys.test.js | 31 ------------------------------ 10 files changed, 32 insertions(+), 87 deletions(-) delete mode 100644 src/shared/keys.js delete mode 100644 test/shared/keys.test.js diff --git a/src/actions/input.js b/src/actions/input.js index 07948a1..67788dd 100644 --- a/src/actions/input.js +++ b/src/actions/input.js @@ -1,10 +1,16 @@ import actions from '../actions'; -const keyPress = (code, ctrl) => { +const asKeymapChars = (key, ctrl) => { + if (ctrl) { + return ''; + } + return key; +}; + +const keyPress = (key, ctrl) => { return { type: actions.INPUT_KEY_PRESS, - code, - ctrl + key: asKeymapChars(key, ctrl), }; }; diff --git a/src/components/background-input.js b/src/components/background-input.js index 9c6ef1c..4735d5a 100644 --- a/src/components/background-input.js +++ b/src/components/background-input.js @@ -1,5 +1,4 @@ import * as inputActions from '../actions/input'; -import * as keys from '../shared/keys'; import * as operationActions from '../actions/operation'; export default class BackgroundInputComponent { @@ -37,15 +36,14 @@ export default class BackgroundInputComponent { } handleKeysChanged(sender, input) { - let prefix = keys.asKeymapChars(input.keys); let matched = Object.keys(this.keymaps).filter((keyStr) => { - return keyStr.startsWith(prefix); + return keyStr.startsWith(input.keys); }); if (matched.length === 0) { this.store.dispatch(inputActions.clearKeys(), sender); return Promise.resolve(); } else if (matched.length > 1 || - matched.length === 1 && prefix !== matched[0]) { + matched.length === 1 && input.keys !== matched[0]) { return Promise.resolve(); } let operation = this.keymaps[matched]; diff --git a/src/components/background.js b/src/components/background.js index 4c5bb19..0585a04 100644 --- a/src/components/background.js +++ b/src/components/background.js @@ -35,7 +35,7 @@ export default class BackgroundComponent { switch (message.type) { case messages.KEYDOWN: return this.store.dispatch( - inputActions.keyPress(message.code, message.ctrl), sender); + inputActions.keyPress(message.key, message.ctrl), sender); case messages.OPEN_URL: if (message.newTab) { return this.store.dispatch( diff --git a/src/components/content-input.js b/src/components/content-input.js index 81f2e6b..53a2f7d 100644 --- a/src/components/content-input.js +++ b/src/components/content-input.js @@ -18,7 +18,7 @@ export default class ContentInputComponent { } browser.runtime.sendMessage({ type: messages.KEYDOWN, - code: e.which, + key: e.key, ctrl: e.ctrlKey }); } diff --git a/src/content/index.js b/src/content/index.js index e5a2965..655bea4 100644 --- a/src/content/index.js +++ b/src/content/index.js @@ -19,6 +19,7 @@ followStore.subscribe(() => { console.error(e); } }); +// eslint-disable-next-line no-unused-vars const contentInputComponent = new ContentInputComponent(window); consoleFrames.initialize(window.document); diff --git a/src/reducers/input.js b/src/reducers/input.js index eb7ff24..8be701e 100644 --- a/src/reducers/input.js +++ b/src/reducers/input.js @@ -1,23 +1,18 @@ import actions from '../actions'; const defaultState = { - keys: [], + keys: '', }; export default function reducer(state = defaultState, action = {}) { switch (action.type) { case actions.INPUT_KEY_PRESS: return Object.assign({}, state, { - keys: state.keys.concat([ - { - code: action.code, - ctrl: action.ctrl - } - ]) + keys: state.keys + action.key }); case actions.INPUT_CLEAR_KEYS: return Object.assign({}, state, { - keys: [], + keys: '', }); default: return state; diff --git a/src/shared/keys.js b/src/shared/keys.js deleted file mode 100644 index aca050e..0000000 --- a/src/shared/keys.js +++ /dev/null @@ -1,21 +0,0 @@ -const asKeymapChars = (keys) => { - return keys.map((k) => { - let c = String.fromCharCode(k.code); - if (k.ctrl) { - return ''; - } - return c; - }).join(''); -}; - -const asCaretChars = (keys) => { - return keys.map((k) => { - let c = String.fromCharCode(k.code); - if (k.ctrl) { - return '^' + c.toUpperCase(); - } - return c; - }).join(''); -}; - -export { asKeymapChars, asCaretChars }; diff --git a/test/actions/input.test.js b/test/actions/input.test.js index 9ec6de4..904d3e7 100644 --- a/test/actions/input.test.js +++ b/test/actions/input.test.js @@ -5,10 +5,15 @@ import * as inputActions from '../../src/actions/input'; describe("input actions", () => { describe("keyPress", () => { it('create INPUT_KEY_PRESS action', () => { - let action = inputActions.keyPress(123, true); + let action = inputActions.keyPress('a', false); expect(action.type).to.equal(actions.INPUT_KEY_PRESS); - expect(action.code).to.equal(123); - expect(action.ctrl).to.be.true; + expect(action.key).to.equal('a'); + }); + + it('create INPUT_KEY_PRESS action from key with ctrl', () => { + let action = inputActions.keyPress('b', true); + expect(action.type).to.equal(actions.INPUT_KEY_PRESS); + expect(action.key).to.equal(''); }); }); diff --git a/test/reducers/input.test.js b/test/reducers/input.test.js index d7a0855..3c3bf39 100644 --- a/test/reducers/input.test.js +++ b/test/reducers/input.test.js @@ -5,30 +5,22 @@ import inputReducer from '../../src/reducers/input'; describe("input reducer", () => { it('return the initial state', () => { let state = inputReducer(undefined, {}); - expect(state).to.have.deep.property('keys', []); + expect(state).to.have.deep.property('keys', ''); }); it('return next state for INPUT_KEY_PRESS', () => { - let action = { type: actions.INPUT_KEY_PRESS, code: 123, ctrl: true }; + let action = { type: actions.INPUT_KEY_PRESS, key: 'a' }; let state = inputReducer(undefined, action); - expect(state).to.have.deep.property('keys', [{ code: 123, ctrl: true }]); + expect(state).to.have.deep.property('keys', 'a'); - action = { type: actions.INPUT_KEY_PRESS, code: 456, ctrl: false }; + action = { type: actions.INPUT_KEY_PRESS, key: '' }; state = inputReducer(state, action); - expect(state).to.have.deep.property('keys', [ - { code: 123, ctrl: true }, - { code: 456, ctrl: false } - ]); + expect(state).to.have.deep.property('keys', 'a'); }); it('return next state for INPUT_CLEAR_KEYS', () => { let action = { type: actions.INPUT_CLEAR_KEYS }; - let state = inputReducer({ - keys: [ - { code: 123, ctrl: true }, - { code: 456, ctrl: false } - ] - }, action); - expect(state).to.have.deep.property('keys', []); + let state = inputReducer({ keys: 'abc' }, action); + expect(state).to.have.deep.property('keys', ''); }); }); diff --git a/test/shared/keys.test.js b/test/shared/keys.test.js deleted file mode 100644 index 53c953d..0000000 --- a/test/shared/keys.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { expect } from "chai"; -import * as keys from '../../src/shared/keys'; - -describe("keys", () => { - const KEYMAP = { - 'gGG': [], - 'gg': { type: 'scroll.top' }, - }; - - const g = 'g'.charCodeAt(0); - const G = 'G'.charCodeAt(0); - const x = 'x'.charCodeAt(0); - - describe('#asKeymapChars', () => { - let keySequence = [ - { code: g }, - { code: x, ctrl: true }, - { code: G } - ]; - expect(keys.asKeymapChars(keySequence)).to.equal('gG'); - }); - - describe('#asCaretChars', () => { - let keySequence = [ - { code: g }, - { code: x, ctrl: true }, - { code: G } - ]; - expect(keys.asCaretChars(keySequence)).to.equal('g^XG'); - }); -}); From 4b5616b5244f14a8e6b1edf59e944edb7d8ae2d4 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 3 Oct 2017 21:07:11 +0900 Subject: [PATCH 3/3] capture keys on both keypress and keydown --- src/components/content-input.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/components/content-input.js b/src/components/content-input.js index 53a2f7d..6437128 100644 --- a/src/components/content-input.js +++ b/src/components/content-input.js @@ -2,12 +2,31 @@ import messages from '../content/messages'; export default class ContentInputComponent { constructor(target) { + this.pressed = {}; + target.addEventListener('keypress', this.onKeyPress.bind(this)); target.addEventListener('keydown', this.onKeyDown.bind(this)); target.addEventListener('keyup', this.onKeyUp.bind(this)); } onKeyPress(e) { + this.capture(e); + } + + onKeyDown(e) { + this.capture(e); + } + + onKeyUp(e) { + this.pressed[e.key] = false; + } + + capture(e) { + if (this.pressed[e.key]) { + return; + } + this.pressed[e.key] = true; + if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLSelectElement) { @@ -22,10 +41,4 @@ export default class ContentInputComponent { ctrl: e.ctrlKey }); } - - onKeyDown() { - } - - onKeyUp() { - } }