diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2018-10-13 22:15:16 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-13 22:15:16 +0900 |
commit | 8b72aac09af476e19da7e482e43769d47d1969b2 (patch) | |
tree | 7b5628784afc557e3c887e32c36e5bd49bac90d5 /src/content | |
parent | b09a4d1bae85eea537d80a5077cdd17d849cfaa5 (diff) | |
parent | 3c40b74a3e8d87ba310b46e24d6465d48766e3e8 (diff) |
Merge pull request #486 from ueokande/jump-marks
Support jump marks
Diffstat (limited to 'src/content')
-rw-r--r-- | src/content/actions/index.js | 6 | ||||
-rw-r--r-- | src/content/actions/mark.js | 46 | ||||
-rw-r--r-- | src/content/actions/operation.js | 13 | ||||
-rw-r--r-- | src/content/components/common/index.js | 7 | ||||
-rw-r--r-- | src/content/components/common/mark.js | 74 | ||||
-rw-r--r-- | src/content/components/top-content/index.js | 3 | ||||
-rw-r--r-- | src/content/reducers/index.js | 3 | ||||
-rw-r--r-- | src/content/reducers/mark.js | 25 | ||||
-rw-r--r-- | src/content/scrolls.js | 30 |
9 files changed, 191 insertions, 16 deletions
diff --git a/src/content/actions/index.js b/src/content/actions/index.js index 6976df7..0a16fdf 100644 --- a/src/content/actions/index.js +++ b/src/content/actions/index.js @@ -22,4 +22,10 @@ export default { // Find FIND_SET_KEYWORD: 'find.set.keyword', + + // Mark + MARK_START_SET: 'mark.start.set', + MARK_START_JUMP: 'mark.start.jump', + MARK_CANCEL: 'mark.cancel', + MARK_SET_LOCAL: 'mark.set.local', }; diff --git a/src/content/actions/mark.js b/src/content/actions/mark.js new file mode 100644 index 0000000..712a811 --- /dev/null +++ b/src/content/actions/mark.js @@ -0,0 +1,46 @@ +import actions from 'content/actions'; +import messages from 'shared/messages'; + +const startSet = () => { + return { type: actions.MARK_START_SET }; +}; + +const startJump = () => { + return { type: actions.MARK_START_JUMP }; +}; + +const cancel = () => { + return { type: actions.MARK_CANCEL }; +}; + +const setLocal = (key, x, y) => { + return { + type: actions.MARK_SET_LOCAL, + key, + x, + y, + }; +}; + +const setGlobal = (key, x, y) => { + browser.runtime.sendMessage({ + type: messages.MARK_SET_GLOBAL, + key, + x, + y, + }); + return { type: '' }; +}; + +const jumpGlobal = (key) => { + browser.runtime.sendMessage({ + type: messages.MARK_JUMP_GLOBAL, + key, + }); + return { type: '' }; +}; + +export { + startSet, startJump, cancel, setLocal, + setGlobal, jumpGlobal, +}; diff --git a/src/content/actions/operation.js b/src/content/actions/operation.js index 89d7fec..1aeb8be 100644 --- a/src/content/actions/operation.js +++ b/src/content/actions/operation.js @@ -6,6 +6,7 @@ import * as focuses from 'content/focuses'; import * as urls from 'content/urls'; import * as consoleFrames from 'content/console-frames'; import * as addonActions from './addon'; +import * as markActions from './mark'; import * as properties from 'shared/settings/properties'; // eslint-disable-next-line complexity, max-lines-per-function @@ -39,16 +40,16 @@ const exec = (operation, repeat, settings, addonEnabled) => { scrolls.scrollPages(operation.count, smoothscroll, repeat); break; case operations.SCROLL_TOP: - scrolls.scrollTop(smoothscroll, repeat); + scrolls.scrollToTop(smoothscroll); break; case operations.SCROLL_BOTTOM: - scrolls.scrollBottom(smoothscroll, repeat); + scrolls.scrollToBottom(smoothscroll); break; case operations.SCROLL_HOME: - scrolls.scrollHome(smoothscroll, repeat); + scrolls.scrollToHome(smoothscroll); break; case operations.SCROLL_END: - scrolls.scrollEnd(smoothscroll, repeat); + scrolls.scrollToEnd(smoothscroll); break; case operations.FOLLOW_START: window.top.postMessage(JSON.stringify({ @@ -57,6 +58,10 @@ const exec = (operation, repeat, settings, addonEnabled) => { background: operation.background, }), '*'); break; + case operations.MARK_SET_PREFIX: + return markActions.startSet(); + case operations.MARK_JUMP_PREFIX: + return markActions.startJump(); case operations.NAVIGATE_HISTORY_PREV: navigates.historyPrev(window); break; diff --git a/src/content/components/common/index.js b/src/content/components/common/index.js index a1e71a1..bcab4fa 100644 --- a/src/content/components/common/index.js +++ b/src/content/components/common/index.js @@ -1,6 +1,7 @@ import InputComponent from './input'; -import KeymapperComponent from './keymapper'; import FollowComponent from './follow'; +import MarkComponent from './mark'; +import KeymapperComponent from './keymapper'; import * as settingActions from 'content/actions/setting'; import messages from 'shared/messages'; import * as addonActions from '../../actions/addon'; @@ -8,11 +9,13 @@ import * as blacklists from 'shared/blacklists'; export default class Common { constructor(win, store) { - const follow = new FollowComponent(win, store); const input = new InputComponent(win.document.body, store); + const follow = new FollowComponent(win, store); + const mark = new MarkComponent(win.document.body, store); const keymapper = new KeymapperComponent(store); input.onKey(key => follow.key(key)); + input.onKey(key => mark.key(key)); input.onKey(key => keymapper.key(key)); this.win = win; diff --git a/src/content/components/common/mark.js b/src/content/components/common/mark.js new file mode 100644 index 0000000..1ed636b --- /dev/null +++ b/src/content/components/common/mark.js @@ -0,0 +1,74 @@ +import * as markActions from 'content/actions/mark'; +import * as scrolls from 'content/scrolls'; +import * as consoleFrames from 'content/console-frames'; +import * as properties from 'shared/settings/properties'; + +const cancelKey = (key) => { + return key.key === 'Esc' || key.key === '[' && key.ctrlKey; +}; + +const globalKey = (key) => { + return (/^[A-Z0-9]$/).test(key); +}; + +export default class MarkComponent { + constructor(body, store) { + this.body = body; + this.store = store; + } + + // eslint-disable-next-line max-statements + key(key) { + let { mark: markStage, setting } = this.store.getState(); + let smoothscroll = setting.properties.smoothscroll || + properties.defaults.smoothscroll; + + if (!markStage.setMode && !markStage.jumpMode) { + return false; + } + + if (cancelKey(key)) { + this.store.dispatch(markActions.cancel()); + return true; + } + + if (key.ctrlKey || key.metaKey || key.altKey) { + consoleFrames.postError(window.document, 'Unknown mark'); + } else if (globalKey(key.key) && markStage.setMode) { + this.doSetGlobal(key); + } else if (globalKey(key.key) && markStage.jumpMode) { + this.doJumpGlobal(key); + } else if (markStage.setMode) { + this.doSet(key); + } else if (markStage.jumpMode) { + this.doJump(markStage.marks, key, smoothscroll); + } + + this.store.dispatch(markActions.cancel()); + return true; + } + + doSet(key) { + let { x, y } = scrolls.getScroll(); + this.store.dispatch(markActions.setLocal(key.key, x, y)); + } + + doJump(marks, key, smoothscroll) { + if (!marks[key.key]) { + consoleFrames.postError(window.document, 'Mark is not set'); + return; + } + + let { x, y } = marks[key.key]; + scrolls.scrollTo(x, y, smoothscroll); + } + + doSetGlobal(key) { + let { x, y } = scrolls.getScroll(); + this.store.dispatch(markActions.setGlobal(key.key, x, y)); + } + + doJumpGlobal(key) { + this.store.dispatch(markActions.jumpGlobal(key.key)); + } +} diff --git a/src/content/components/top-content/index.js b/src/content/components/top-content/index.js index e22e957..1aaef1b 100644 --- a/src/content/components/top-content/index.js +++ b/src/content/components/top-content/index.js @@ -3,6 +3,7 @@ import FollowController from './follow-controller'; import FindComponent from './find'; import * as consoleFrames from '../../console-frames'; import messages from 'shared/messages'; +import * as scrolls from 'content/scrolls'; export default class TopContent { @@ -33,6 +34,8 @@ export default class TopContent { type: messages.ADDON_ENABLED_RESPONSE, enabled: addonState.enabled, }); + case messages.TAB_SCROLL_TO: + return scrolls.scrollTo(message.x, message.y, false); } } } diff --git a/src/content/reducers/index.js b/src/content/reducers/index.js index 6e6a147..bf612a3 100644 --- a/src/content/reducers/index.js +++ b/src/content/reducers/index.js @@ -4,7 +4,8 @@ import find from './find'; import setting from './setting'; import input from './input'; import followController from './follow-controller'; +import mark from './mark'; export default combineReducers({ - addon, find, setting, input, followController, + addon, find, setting, input, followController, mark, }); diff --git a/src/content/reducers/mark.js b/src/content/reducers/mark.js new file mode 100644 index 0000000..2c96cc5 --- /dev/null +++ b/src/content/reducers/mark.js @@ -0,0 +1,25 @@ +import actions from 'content/actions'; + +const defaultState = { + setMode: false, + jumpMode: false, + marks: {}, +}; + +export default function reducer(state = defaultState, action = {}) { + switch (action.type) { + case actions.MARK_START_SET: + return { ...state, setMode: true }; + case actions.MARK_START_JUMP: + return { ...state, jumpMode: true }; + case actions.MARK_CANCEL: + return { ...state, setMode: false, jumpMode: false }; + case actions.MARK_SET_LOCAL: { + let marks = { ...state.marks }; + marks[action.key] = { x: action.x, y: action.y }; + return { ...state, setMode: false, marks }; + } + default: + return state; + } +} diff --git a/src/content/scrolls.js b/src/content/scrolls.js index 0d1f7c8..b9a4bc3 100644 --- a/src/content/scrolls.js +++ b/src/content/scrolls.js @@ -130,6 +130,11 @@ const scroller = (element, smooth, repeat) => { return new RoughtScroller(element); }; +const getScroll = () => { + let target = scrollTarget(); + return { x: target.scrollLeft, y: target.scrollTop }; +}; + const scrollVertically = (count, smooth, repeat) => { let target = scrollTarget(); let x = target.scrollLeft; @@ -158,35 +163,42 @@ const scrollPages = (count, smooth, repeat) => { scroller(target, smooth, repeat).scroll(x, y); }; -const scrollTop = (smooth, repeat) => { +const scrollTo = (x, y, smooth) => { + let target = scrollTarget(); + scroller(target, smooth, false).scroll(x, y); +}; + +const scrollToTop = (smooth) => { let target = scrollTarget(); let x = target.scrollLeft; let y = 0; - scroller(target, smooth, repeat).scroll(x, y); + scroller(target, smooth, false).scroll(x, y); }; -const scrollBottom = (smooth, repeat) => { +const scrollToBottom = (smooth) => { let target = scrollTarget(); let x = target.scrollLeft; let y = target.scrollHeight; - scroller(target, smooth, repeat).scroll(x, y); + scroller(target, smooth, false).scroll(x, y); }; -const scrollHome = (smooth, repeat) => { +const scrollToHome = (smooth) => { let target = scrollTarget(); let x = 0; let y = target.scrollTop; - scroller(target, smooth, repeat).scroll(x, y); + scroller(target, smooth, false).scroll(x, y); }; -const scrollEnd = (smooth, repeat) => { +const scrollToEnd = (smooth) => { let target = scrollTarget(); let x = target.scrollWidth; let y = target.scrollTop; - scroller(target, smooth, repeat).scroll(x, y); + scroller(target, smooth, false).scroll(x, y); }; export { + getScroll, scrollVertically, scrollHorizonally, scrollPages, - scrollTop, scrollBottom, scrollHome, scrollEnd + scrollTo, + scrollToTop, scrollToBottom, scrollToHome, scrollToEnd }; |