mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 09:21:54 +00:00
searched repos support keyboard events (#6454)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import isHotkey from 'is-hotkey';
|
import isHotkey from 'is-hotkey';
|
||||||
|
import classnames from 'classnames';
|
||||||
import MediaQuery from 'react-responsive';
|
import MediaQuery from 'react-responsive';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import searchAPI from '../../utils/search-api';
|
import searchAPI from '../../utils/search-api';
|
||||||
@@ -142,9 +143,9 @@ export default class AISearch extends Component {
|
|||||||
onUp = (e) => {
|
onUp = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
const { highlightIndex, resultItems } = this.state;
|
||||||
|
|
||||||
if (this.state.showRecent) {
|
if (this.state.showRecent) {
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex > 0) {
|
if (highlightIndex > 0) {
|
||||||
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -158,6 +159,23 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global searching, searched repos needs to support up and down keys
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
||||||
|
if (highlightSearchTypesIndex < 0) {
|
||||||
|
highlightSearchTypesIndex = resultItems.length;
|
||||||
|
}
|
||||||
|
this.setState({ highlightSearchTypesIndex }, () => {
|
||||||
|
if (this.highlightRef) {
|
||||||
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
|
if (top - height < 0) {
|
||||||
|
this.searchResultListContainerRef.current.scrollTop -= height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
||||||
if (highlightSearchTypesIndex < 0) {
|
if (highlightSearchTypesIndex < 0) {
|
||||||
@@ -167,7 +185,6 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex > 0) {
|
if (highlightIndex > 0) {
|
||||||
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -183,10 +200,10 @@ export default class AISearch extends Component {
|
|||||||
onDown = (e) => {
|
onDown = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
const { highlightIndex, resultItems } = this.state;
|
||||||
|
|
||||||
if (this.state.showRecent) {
|
if (this.state.showRecent) {
|
||||||
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex < visitedItems.length - 1) {
|
if (highlightIndex < visitedItems.length - 1) {
|
||||||
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -202,6 +219,25 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global searching, searched repos needs to support up and down keys
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
||||||
|
if (highlightSearchTypesIndex > resultItems.length) {
|
||||||
|
highlightSearchTypesIndex = 0;
|
||||||
|
}
|
||||||
|
this.setState({ highlightSearchTypesIndex }, () => {
|
||||||
|
if (this.highlightRef) {
|
||||||
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
|
const outerHeight = 300;
|
||||||
|
if (top > outerHeight) {
|
||||||
|
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
|
||||||
|
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
||||||
if (highlightSearchTypesIndex > this.state.searchTypesMax) {
|
if (highlightSearchTypesIndex > this.state.searchTypesMax) {
|
||||||
@@ -211,7 +247,6 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex, resultItems } = this.state;
|
|
||||||
if (highlightIndex < resultItems.length - 1) {
|
if (highlightIndex < resultItems.length - 1) {
|
||||||
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -241,6 +276,22 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global searching, searched repos needs to support enter
|
||||||
|
const { highlightSearchTypesIndex, resultItems } = this.state;
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
if (highlightSearchTypesIndex === 0) {
|
||||||
|
this.searchAllRepos();
|
||||||
|
} else {
|
||||||
|
let item = this.state.resultItems[highlightSearchTypesIndex - 1];
|
||||||
|
if (item) {
|
||||||
|
if (document.activeElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
this.onItemClickHandler(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightDom = document.querySelector('.search-types-highlight');
|
let highlightDom = document.querySelector('.search-types-highlight');
|
||||||
if (highlightDom) {
|
if (highlightDom) {
|
||||||
@@ -489,10 +540,10 @@ export default class AISearch extends Component {
|
|||||||
const { resultItems } = this.state;
|
const { resultItems } = this.state;
|
||||||
if (!this.props.repoID) {
|
if (!this.props.repoID) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>
|
||||||
<div className="search-types">
|
<div className="search-types">
|
||||||
<div
|
<div
|
||||||
className="search-types-repos search-types-highlight"
|
className={classnames('search-types-repos', { 'search-types-highlight': highlightIndex === 0 })}
|
||||||
onClick={this.searchAllRepos}
|
onClick={this.searchAllRepos}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
@@ -516,6 +567,8 @@ export default class AISearch extends Component {
|
|||||||
key={index}
|
key={index}
|
||||||
item={item}
|
item={item}
|
||||||
onClick={this.onItemClickHandler}
|
onClick={this.onItemClickHandler}
|
||||||
|
isHighlight={highlightIndex === index + 1}
|
||||||
|
setRef={highlightIndex === index + 1 ? (ref) => {this.highlightRef = ref;} : () => {}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@@ -6,7 +6,11 @@ import { Utils } from '../../utils/utils';
|
|||||||
function SearchResultLibrary(props) {
|
function SearchResultLibrary(props) {
|
||||||
const { item, isHighlight, onClick } = props;
|
const { item, isHighlight, onClick } = props;
|
||||||
return (
|
return (
|
||||||
<li className={classnames('search-result-item', { 'search-result-item-highlight': isHighlight })} onClick={() => onClick(item)}>
|
<li
|
||||||
|
className={classnames('search-result-item', { 'search-result-item-highlight': isHighlight })}
|
||||||
|
onClick={() => onClick(item)}
|
||||||
|
ref={ref => props.setRef(ref)}
|
||||||
|
>
|
||||||
<img className='lib-item-img' src={Utils.getDefaultLibIconUrl(true)} alt="" />
|
<img className='lib-item-img' src={Utils.getDefaultLibIconUrl(true)} alt="" />
|
||||||
<div className="item-content d-flex justify-content-between align-items-center ellipsis">{item.name}</div>
|
<div className="item-content d-flex justify-content-between align-items-center ellipsis">{item.name}</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -17,6 +21,7 @@ SearchResultLibrary.propTypes = {
|
|||||||
item: PropTypes.object.isRequired,
|
item: PropTypes.object.isRequired,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
isHighlight: PropTypes.bool,
|
isHighlight: PropTypes.bool,
|
||||||
|
setRef: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SearchResultLibrary;
|
export default SearchResultLibrary;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import isHotkey from 'is-hotkey';
|
import isHotkey from 'is-hotkey';
|
||||||
|
import classnames from 'classnames';
|
||||||
import MediaQuery from 'react-responsive';
|
import MediaQuery from 'react-responsive';
|
||||||
import { seafileAPI } from '../../utils/seafile-api';
|
import { seafileAPI } from '../../utils/seafile-api';
|
||||||
import searchAPI from '../../utils/search-api';
|
import searchAPI from '../../utils/search-api';
|
||||||
@@ -131,9 +132,9 @@ class Search extends Component {
|
|||||||
onUp = (e) => {
|
onUp = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
const { highlightIndex, resultItems } = this.state;
|
||||||
|
|
||||||
if (this.state.showRecent) {
|
if (this.state.showRecent) {
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex > 0) {
|
if (highlightIndex > 0) {
|
||||||
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -147,6 +148,23 @@ class Search extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global searching, searched repos needs to support up and down keys
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
||||||
|
if (highlightSearchTypesIndex < 0) {
|
||||||
|
highlightSearchTypesIndex = resultItems.length;
|
||||||
|
}
|
||||||
|
this.setState({ highlightSearchTypesIndex }, () => {
|
||||||
|
if (this.highlightRef) {
|
||||||
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
|
if (top - height < 0) {
|
||||||
|
this.searchResultListContainerRef.current.scrollTop -= height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1;
|
||||||
if (highlightSearchTypesIndex < 0) {
|
if (highlightSearchTypesIndex < 0) {
|
||||||
@@ -156,7 +174,6 @@ class Search extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex > 0) {
|
if (highlightIndex > 0) {
|
||||||
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -172,10 +189,10 @@ class Search extends Component {
|
|||||||
onDown = (e) => {
|
onDown = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
const { highlightIndex, resultItems } = this.state;
|
||||||
|
|
||||||
if (this.state.showRecent) {
|
if (this.state.showRecent) {
|
||||||
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
const { highlightIndex } = this.state;
|
|
||||||
if (highlightIndex < visitedItems.length - 1) {
|
if (highlightIndex < visitedItems.length - 1) {
|
||||||
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -191,6 +208,25 @@ class Search extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global searching, searched repos needs to support up and down keys
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
||||||
|
if (highlightSearchTypesIndex > resultItems.length) {
|
||||||
|
highlightSearchTypesIndex = 0;
|
||||||
|
}
|
||||||
|
this.setState({ highlightSearchTypesIndex }, () => {
|
||||||
|
if (this.highlightRef) {
|
||||||
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
|
const outerHeight = 300;
|
||||||
|
if (top > outerHeight) {
|
||||||
|
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
|
||||||
|
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1;
|
||||||
if (highlightSearchTypesIndex > this.state.searchTypesMax) {
|
if (highlightSearchTypesIndex > this.state.searchTypesMax) {
|
||||||
@@ -200,7 +236,6 @@ class Search extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex, resultItems } = this.state;
|
|
||||||
if (highlightIndex < resultItems.length - 1) {
|
if (highlightIndex < resultItems.length - 1) {
|
||||||
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
this.setState({ highlightIndex: highlightIndex + 1 }, () => {
|
||||||
if (this.highlightRef) {
|
if (this.highlightRef) {
|
||||||
@@ -228,6 +263,21 @@ class Search extends Component {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// global searching, searched repos needs to support enter
|
||||||
|
const { highlightSearchTypesIndex, resultItems } = this.state;
|
||||||
|
if (!this.props.repoID && resultItems.length > 0) {
|
||||||
|
if (highlightSearchTypesIndex === 0) {
|
||||||
|
this.searchAllRepos();
|
||||||
|
} else {
|
||||||
|
let item = this.state.resultItems[highlightSearchTypesIndex - 1];
|
||||||
|
if (item) {
|
||||||
|
if (document.activeElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
this.onItemClickHandler(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!this.state.isResultGetted) {
|
if (!this.state.isResultGetted) {
|
||||||
let highlightDom = document.querySelector('.search-types-highlight');
|
let highlightDom = document.querySelector('.search-types-highlight');
|
||||||
if (highlightDom) {
|
if (highlightDom) {
|
||||||
@@ -509,10 +559,10 @@ class Search extends Component {
|
|||||||
const { resultItems } = this.state;
|
const { resultItems } = this.state;
|
||||||
if (!this.props.repoID) {
|
if (!this.props.repoID) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>
|
||||||
<div className="search-types">
|
<div className="search-types">
|
||||||
<div
|
<div
|
||||||
className="search-types-repos search-types-highlight"
|
className={classnames('search-types-repos', { 'search-types-highlight': highlightIndex === 0 })}
|
||||||
onClick={this.searchAllRepos}
|
onClick={this.searchAllRepos}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
@@ -536,6 +586,8 @@ class Search extends Component {
|
|||||||
key={index}
|
key={index}
|
||||||
item={item}
|
item={item}
|
||||||
onClick={this.onItemClickHandler}
|
onClick={this.onItemClickHandler}
|
||||||
|
isHighlight={highlightIndex === index + 1}
|
||||||
|
setRef={highlightIndex === index + 1 ? (ref) => {this.highlightRef = ref;} : () => {}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
Reference in New Issue
Block a user