diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2019-02-25 22:04:12 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-25 22:04:12 +0900 |
commit | 124e221999e914d63326a91602517d1e5e1bea73 (patch) | |
tree | 99184620375b5608c31b58f14d74cb450f7f4224 /src | |
parent | cebd64a69f705482957a5e6a3f23054ca7985aa4 (diff) | |
parent | 9868da1ac479ee75a4abe8142a9b406a18b5ac52 (diff) |
Merge pull request #538 from ueokande/scroll-console
Scroll console
Diffstat (limited to 'src')
-rw-r--r-- | src/console/components/console.jsx | 8 | ||||
-rw-r--r-- | src/console/components/console/completion.jsx | 55 | ||||
-rw-r--r-- | src/console/reducers/index.js | 70 |
3 files changed, 79 insertions, 54 deletions
diff --git a/src/console/components/console.jsx b/src/console/components/console.jsx index 23c93e3..7994f78 100644 --- a/src/console/components/console.jsx +++ b/src/console/components/console.jsx @@ -6,6 +6,8 @@ import Completion from './console/completion'; import Message from './console/message'; import * as consoleActions from '../../console/actions/console'; +const COMPLETION_MAX_ITEMS = 33; + class ConsoleComponent extends Component { onBlur() { if (this.props.mode === 'command' || this.props.mode === 'find') { @@ -105,7 +107,11 @@ class ConsoleComponent extends Component { case 'command': case 'find': return <div className='vimvixen-console-command-wrapper'> - <Completion /> + <Completion + size={COMPLETION_MAX_ITEMS} + completions={this.props.completions} + select={this.props.select} + /> <Input ref={(c) => { this.input = c; }} mode={this.props.mode} diff --git a/src/console/components/console/completion.jsx b/src/console/components/console/completion.jsx index c60543b..d836cec 100644 --- a/src/console/components/console/completion.jsx +++ b/src/console/components/console/completion.jsx @@ -1,5 +1,4 @@ import { Component, h } from 'preact'; -import { connect } from 'preact-redux'; const CompletionTitle = (props) => { return <li className='vimvixen-console-completion-title' >{props.title}</li>; @@ -25,25 +24,60 @@ const CompletionItem = (props) => { class CompletionComponent extends Component { + constructor() { + super(); + this.state = { viewOffset: 0, select: -1 }; + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (prevState.select === nextProps.select) { + return null; + } + + let viewSelect = (() => { + let index = 0; + for (let i = 0; i < nextProps.completions.length; ++i) { + ++index; + let g = nextProps.completions[i]; + if (nextProps.select + i + 1 < index + g.items.length) { + return nextProps.select + i + 1; + } + index += g.items.length; + } + })(); + + let viewOffset = 0; + if (nextProps.select < 0) { + viewOffset = 0; + } else if (prevState.select < nextProps.select) { + viewOffset = Math.max(prevState.viewOffset, + viewSelect - nextProps.size + 1); + } else if (prevState.select > nextProps.select) { + viewOffset = Math.min(prevState.viewOffset, viewSelect); + } + return { viewOffset, select: nextProps.select }; + } + render() { let eles = []; - for (let i = 0; i < this.props.completions.length; ++i) { - let group = this.props.completions[i]; + let index = 0; + + for (let group of this.props.completions) { eles.push(<CompletionTitle title={ group.name }/>); - for (let j = 0; j < group.items.length; ++j) { - let item = group.items[j]; - let selected = - i === this.props.groupSelection && - j === this.props.itemSelection; + for (let item of group.items) { eles.push(<CompletionItem icon={item.icon} caption={item.caption} url={item.url} - highlight={selected} + highlight={index === this.props.select} / >); + ++index; } } + let viewOffset = this.state.viewOffset; + eles = eles.slice(viewOffset, viewOffset + this.props.size); + return ( <ul className='vimvixen-console-completion'> { eles } @@ -52,5 +86,4 @@ class CompletionComponent extends Component { } } -const mapStateToProps = state => state; -export default connect(mapStateToProps)(CompletionComponent); +export default CompletionComponent; diff --git a/src/console/reducers/index.js b/src/console/reducers/index.js index 7dcad17..614a72f 100644 --- a/src/console/reducers/index.js +++ b/src/console/reducers/index.js @@ -6,52 +6,43 @@ const defaultState = { consoleText: '', completionSource: '', completions: [], - groupSelection: -1, - itemSelection: -1, + select: -1, + viewIndex: 0, }; const nextSelection = (state) => { if (state.completions.length === 0) { - return [-1, -1]; + return -1; } - if (state.groupSelection < 0) { - return [0, 0]; + if (state.select < 0) { + return 0; } - let group = state.completions[state.groupSelection]; - if (state.groupSelection + 1 >= state.completions.length && - state.itemSelection + 1 >= group.items.length) { - return [-1, -1]; + let length = state.completions + .map(g => g.items.length) + .reduce((x, y) => x + y); + if (state.select + 1 < length) { + return state.select + 1; } - if (state.itemSelection + 1 >= group.items.length) { - return [state.groupSelection + 1, 0]; - } - return [state.groupSelection, state.itemSelection + 1]; + return -1; }; const prevSelection = (state) => { - if (state.groupSelection < 0) { - return [ - state.completions.length - 1, - state.completions[state.completions.length - 1].items.length - 1 - ]; - } - if (state.groupSelection === 0 && state.itemSelection === 0) { - return [-1, -1]; - } else if (state.itemSelection === 0) { - return [ - state.groupSelection - 1, - state.completions[state.groupSelection - 1].items.length - 1 - ]; + let length = state.completions + .map(g => g.items.length) + .reduce((x, y) => x + y); + if (state.select < 0) { + return length - 1; } - return [state.groupSelection, state.itemSelection - 1]; + return state.select - 1; }; -const nextConsoleText = (completions, group, item, defaults) => { - if (group < 0 || item < 0) { +const nextConsoleText = (completions, select, defaults) => { + if (select < 0) { return defaults; } - return completions[group].items[item].content; + let items = completions.map(g => g.items).reduce((g1, g2) => g1.concat(g2)); + return items[select].content; }; // eslint-disable-next-line max-lines-per-function @@ -90,25 +81,20 @@ export default function reducer(state = defaultState, action = {}) { return { ...state, completions: action.completions, completionSource: action.completionSource, - groupSelection: -1, - itemSelection: -1, }; + select: -1 }; case actions.CONSOLE_COMPLETION_NEXT: { - let next = nextSelection(state); + let select = nextSelection(state); return { ...state, - groupSelection: next[0], - itemSelection: next[1], + select: select, consoleText: nextConsoleText( - state.completions, next[0], next[1], - state.completionSource), }; + state.completions, select, state.completionSource) }; } case actions.CONSOLE_COMPLETION_PREV: { - let next = prevSelection(state); + let select = prevSelection(state); return { ...state, - groupSelection: next[0], - itemSelection: next[1], + select: select, consoleText: nextConsoleText( - state.completions, next[0], next[1], - state.completionSource), }; + state.completions, select, state.completionSource) }; } default: return state; |