diff --git a/frontend/src/components/search/ai-search.js b/frontend/src/components/search/ai-search.js index 4e79eee904..990728319c 100644 --- a/frontend/src/components/search/ai-search.js +++ b/frontend/src/components/search/ai-search.js @@ -1,6 +1,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import isHotkey from 'is-hotkey'; +import classnames from 'classnames'; import MediaQuery from 'react-responsive'; import { seafileAPI } from '../../utils/seafile-api'; import searchAPI from '../../utils/search-api'; @@ -142,9 +143,9 @@ export default class AISearch extends Component { onUp = (e) => { e.preventDefault(); e.stopPropagation(); + const { highlightIndex, resultItems } = this.state; if (this.state.showRecent) { - const { highlightIndex } = this.state; if (highlightIndex > 0) { this.setState({ highlightIndex: highlightIndex - 1 }, () => { if (this.highlightRef) { @@ -158,6 +159,23 @@ export default class AISearch extends Component { 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) { let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1; if (highlightSearchTypesIndex < 0) { @@ -167,7 +185,6 @@ export default class AISearch extends Component { return; } - const { highlightIndex } = this.state; if (highlightIndex > 0) { this.setState({ highlightIndex: highlightIndex - 1 }, () => { if (this.highlightRef) { @@ -183,10 +200,10 @@ export default class AISearch extends Component { onDown = (e) => { e.preventDefault(); e.stopPropagation(); + const { highlightIndex, resultItems } = this.state; if (this.state.showRecent) { const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || []; - const { highlightIndex } = this.state; if (highlightIndex < visitedItems.length - 1) { this.setState({ highlightIndex: highlightIndex + 1 }, () => { if (this.highlightRef) { @@ -202,6 +219,25 @@ export default class AISearch extends Component { 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) { let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1; if (highlightSearchTypesIndex > this.state.searchTypesMax) { @@ -211,7 +247,6 @@ export default class AISearch extends Component { return; } - const { highlightIndex, resultItems } = this.state; if (highlightIndex < resultItems.length - 1) { this.setState({ highlightIndex: highlightIndex + 1 }, () => { if (this.highlightRef) { @@ -241,6 +276,22 @@ export default class AISearch extends Component { 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) { let highlightDom = document.querySelector('.search-types-highlight'); if (highlightDom) { @@ -489,10 +540,10 @@ export default class AISearch extends Component { const { resultItems } = this.state; if (!this.props.repoID) { return ( -
+
@@ -516,6 +567,8 @@ export default class AISearch extends Component { key={index} item={item} onClick={this.onItemClickHandler} + isHighlight={highlightIndex === index + 1} + setRef={highlightIndex === index + 1 ? (ref) => {this.highlightRef = ref;} : () => {}} /> ); })} diff --git a/frontend/src/components/search/search-result-library.js b/frontend/src/components/search/search-result-library.js index 174638cc64..8d05e843d6 100644 --- a/frontend/src/components/search/search-result-library.js +++ b/frontend/src/components/search/search-result-library.js @@ -6,7 +6,11 @@ import { Utils } from '../../utils/utils'; function SearchResultLibrary(props) { const { item, isHighlight, onClick } = props; return ( -
  • onClick(item)}> +
  • onClick(item)} + ref={ref => props.setRef(ref)} + >
    {item.name}
  • @@ -17,6 +21,7 @@ SearchResultLibrary.propTypes = { item: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, isHighlight: PropTypes.bool, + setRef: PropTypes.func, }; export default SearchResultLibrary; diff --git a/frontend/src/components/search/search.js b/frontend/src/components/search/search.js index 871086cf8f..66eac85979 100644 --- a/frontend/src/components/search/search.js +++ b/frontend/src/components/search/search.js @@ -1,6 +1,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import isHotkey from 'is-hotkey'; +import classnames from 'classnames'; import MediaQuery from 'react-responsive'; import { seafileAPI } from '../../utils/seafile-api'; import searchAPI from '../../utils/search-api'; @@ -131,9 +132,9 @@ class Search extends Component { onUp = (e) => { e.preventDefault(); e.stopPropagation(); + const { highlightIndex, resultItems } = this.state; if (this.state.showRecent) { - const { highlightIndex } = this.state; if (highlightIndex > 0) { this.setState({ highlightIndex: highlightIndex - 1 }, () => { if (this.highlightRef) { @@ -147,6 +148,23 @@ class Search extends Component { 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) { let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex - 1; if (highlightSearchTypesIndex < 0) { @@ -156,7 +174,6 @@ class Search extends Component { return; } - const { highlightIndex } = this.state; if (highlightIndex > 0) { this.setState({ highlightIndex: highlightIndex - 1 }, () => { if (this.highlightRef) { @@ -172,10 +189,10 @@ class Search extends Component { onDown = (e) => { e.preventDefault(); e.stopPropagation(); + const { highlightIndex, resultItems } = this.state; if (this.state.showRecent) { const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || []; - const { highlightIndex } = this.state; if (highlightIndex < visitedItems.length - 1) { this.setState({ highlightIndex: highlightIndex + 1 }, () => { if (this.highlightRef) { @@ -191,6 +208,25 @@ class Search extends Component { 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) { let highlightSearchTypesIndex = this.state.highlightSearchTypesIndex + 1; if (highlightSearchTypesIndex > this.state.searchTypesMax) { @@ -200,7 +236,6 @@ class Search extends Component { return; } - const { highlightIndex, resultItems } = this.state; if (highlightIndex < resultItems.length - 1) { this.setState({ highlightIndex: highlightIndex + 1 }, () => { if (this.highlightRef) { @@ -228,6 +263,21 @@ class Search extends Component { } 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) { let highlightDom = document.querySelector('.search-types-highlight'); if (highlightDom) { @@ -509,10 +559,10 @@ class Search extends Component { const { resultItems } = this.state; if (!this.props.repoID) { return ( -
    +
    @@ -536,6 +586,8 @@ class Search extends Component { key={index} item={item} onClick={this.onItemClickHandler} + isHighlight={highlightIndex === index + 1} + setRef={highlightIndex === index + 1 ? (ref) => {this.highlightRef = ref;} : () => {}} /> ); })}