mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 01:12:03 +00:00
change recent search items support keyboard (#6283)
This commit is contained in:
@@ -73,6 +73,13 @@ export default class AISearch extends Component {
|
|||||||
this.isRepoOwner = false;
|
this.isRepoOwner = false;
|
||||||
this.isAdmin = false;
|
this.isAdmin = false;
|
||||||
}
|
}
|
||||||
|
this.searchResultListContainerRef = React.createRef();
|
||||||
|
const { repoID } = props;
|
||||||
|
let storeKey = 'sfVisitedAISearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
this.storeKey = storeKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -150,6 +157,22 @@ export default class AISearch extends Component {
|
|||||||
onUp = (e) => {
|
onUp = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (this.state.showRecent) {
|
||||||
|
const { highlightIndex } = this.state;
|
||||||
|
if (highlightIndex > 0) {
|
||||||
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
|
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) {
|
||||||
@@ -158,13 +181,14 @@ export default class AISearch extends Component {
|
|||||||
this.setState({ highlightSearchTypesIndex });
|
this.setState({ highlightSearchTypesIndex });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex } = this.state;
|
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) {
|
||||||
const { top, height } = this.highlightRef.getBoundingClientRect();
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
if (top - height < 0) {
|
if (top - height < 0) {
|
||||||
this.searchContainer.current.scrollTop -= height;
|
this.searchResultListContainerRef.current.scrollTop -= height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -174,6 +198,25 @@ export default class AISearch extends Component {
|
|||||||
onDown = (e) => {
|
onDown = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
@@ -182,6 +225,7 @@ export default class AISearch extends Component {
|
|||||||
this.setState({ highlightSearchTypesIndex });
|
this.setState({ highlightSearchTypesIndex });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex, resultItems } = this.state;
|
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 }, () => {
|
||||||
@@ -189,7 +233,8 @@ export default class AISearch extends Component {
|
|||||||
const { top, height } = this.highlightRef.getBoundingClientRect();
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
const outerHeight = 300;
|
const outerHeight = 300;
|
||||||
if (top > outerHeight) {
|
if (top > outerHeight) {
|
||||||
this.searchContainer.current.scrollTop += height;
|
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
|
||||||
|
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -198,6 +243,19 @@ export default class AISearch extends Component {
|
|||||||
|
|
||||||
onEnter = (e) => {
|
onEnter = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (this.state.showRecent) {
|
||||||
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
|
const item = visitedItems[this.state.highlightIndex];
|
||||||
|
if (item) {
|
||||||
|
if (document.activeElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
this.onItemClickHandler(item);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -213,6 +271,7 @@ export default class AISearch extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = this.state.resultItems[this.state.highlightIndex];
|
let item = this.state.resultItems[this.state.highlightIndex];
|
||||||
if (item) {
|
if (item) {
|
||||||
if (document.activeElement) {
|
if (document.activeElement) {
|
||||||
@@ -244,13 +303,8 @@ export default class AISearch extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
keepVisitedItem = (targetItem) => {
|
keepVisitedItem = (targetItem) => {
|
||||||
const { repoID } = this.props;
|
|
||||||
let targetIndex;
|
let targetIndex;
|
||||||
let storeKey = 'sfVisitedAISearchItems';
|
const items = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
if (repoID) {
|
|
||||||
storeKey += repoID;
|
|
||||||
}
|
|
||||||
const items = JSON.parse(localStorage.getItem(storeKey)) || [];
|
|
||||||
for (let i = 0, len = items.length; i < len; i++) {
|
for (let i = 0, len = items.length; i < len; i++) {
|
||||||
const { repo_id, path } = items[i];
|
const { repo_id, path } = items[i];
|
||||||
const { repo_id: targetRepoID, path: targetPath } = targetItem;
|
const { repo_id: targetRepoID, path: targetPath } = targetItem;
|
||||||
@@ -266,7 +320,7 @@ export default class AISearch extends Component {
|
|||||||
if (items.length > 50) { // keep 50 items at most
|
if (items.length > 50) { // keep 50 items at most
|
||||||
items.pop();
|
items.pop();
|
||||||
}
|
}
|
||||||
localStorage.setItem(storeKey, JSON.stringify(items));
|
localStorage.setItem(this.storeKey, JSON.stringify(items));
|
||||||
};
|
};
|
||||||
|
|
||||||
onChangeHandler = (event) => {
|
onChangeHandler = (event) => {
|
||||||
@@ -436,7 +490,7 @@ export default class AISearch extends Component {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MediaQuery query="(min-width: 768px)">
|
<MediaQuery query="(min-width: 768px)">
|
||||||
<div className="search-result-list-container">{results}</div>
|
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>{results}</div>
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
<MediaQuery query="(max-width: 767.8px)">
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
{results}
|
{results}
|
||||||
@@ -567,12 +621,7 @@ export default class AISearch extends Component {
|
|||||||
if (!width || width === 'default') return null;
|
if (!width || width === 'default') return null;
|
||||||
|
|
||||||
if (this.state.showRecent) {
|
if (this.state.showRecent) {
|
||||||
const { repoID } = this.props;
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
let storeKey = 'sfVisitedAISearchItems';
|
|
||||||
if (repoID) {
|
|
||||||
storeKey += repoID;
|
|
||||||
}
|
|
||||||
const visitedItems = JSON.parse(localStorage.getItem(storeKey)) || [];
|
|
||||||
if (visitedItems.length) {
|
if (visitedItems.length) {
|
||||||
return this.renderVisitedItems(visitedItems);
|
return this.renderVisitedItems(visitedItems);
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,13 @@ class Search extends Component {
|
|||||||
this.searchContainer = React.createRef();
|
this.searchContainer = React.createRef();
|
||||||
this.searchResultListRef = React.createRef();
|
this.searchResultListRef = React.createRef();
|
||||||
this.isChineseInput = false;
|
this.isChineseInput = false;
|
||||||
|
this.searchResultListContainerRef = React.createRef();
|
||||||
|
const { repoID } = props;
|
||||||
|
let storeKey = 'sfVisitedSearchItems';
|
||||||
|
if (repoID) {
|
||||||
|
storeKey += repoID;
|
||||||
|
}
|
||||||
|
this.storeKey = storeKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -112,6 +119,22 @@ class Search extends Component {
|
|||||||
onUp = (e) => {
|
onUp = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (this.state.showRecent) {
|
||||||
|
const { highlightIndex } = this.state;
|
||||||
|
if (highlightIndex > 0) {
|
||||||
|
this.setState({ highlightIndex: highlightIndex - 1 }, () => {
|
||||||
|
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) {
|
||||||
@@ -120,13 +143,14 @@ class Search extends Component {
|
|||||||
this.setState({ highlightSearchTypesIndex });
|
this.setState({ highlightSearchTypesIndex });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex } = this.state;
|
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) {
|
||||||
const { top, height } = this.highlightRef.getBoundingClientRect();
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
if (top - height < 0) {
|
if (top - height < 0) {
|
||||||
this.searchContainer.current.scrollTop -= height;
|
this.searchResultListContainerRef.current.scrollTop -= height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -136,6 +160,25 @@ class Search extends Component {
|
|||||||
onDown = (e) => {
|
onDown = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
@@ -144,6 +187,7 @@ class Search extends Component {
|
|||||||
this.setState({ highlightSearchTypesIndex });
|
this.setState({ highlightSearchTypesIndex });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { highlightIndex, resultItems } = this.state;
|
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 }, () => {
|
||||||
@@ -151,7 +195,8 @@ class Search extends Component {
|
|||||||
const { top, height } = this.highlightRef.getBoundingClientRect();
|
const { top, height } = this.highlightRef.getBoundingClientRect();
|
||||||
const outerHeight = 300;
|
const outerHeight = 300;
|
||||||
if (top > outerHeight) {
|
if (top > outerHeight) {
|
||||||
this.searchContainer.current.scrollTop += height;
|
const newScrollTop = this.searchResultListContainerRef.current.scrollTop + height;
|
||||||
|
this.searchResultListContainerRef.current.scrollTop = newScrollTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -160,6 +205,17 @@ class Search extends Component {
|
|||||||
|
|
||||||
onEnter = (e) => {
|
onEnter = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (this.state.showRecent) {
|
||||||
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
|
const item = visitedItems[this.state.highlightIndex];
|
||||||
|
if (item) {
|
||||||
|
if (document.activeElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
this.onItemClickHandler(item);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
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) {
|
||||||
@@ -206,12 +262,8 @@ class Search extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
keepVisitedItem = (targetItem) => {
|
keepVisitedItem = (targetItem) => {
|
||||||
const { repoID } = this.props;
|
|
||||||
let targetIndex;
|
let targetIndex;
|
||||||
let storeKey = 'sfVisitedSearchItems';
|
const storeKey = this.storeKey;
|
||||||
if (repoID) {
|
|
||||||
storeKey += repoID;
|
|
||||||
}
|
|
||||||
const items = JSON.parse(localStorage.getItem(storeKey)) || [];
|
const items = JSON.parse(localStorage.getItem(storeKey)) || [];
|
||||||
for (let i = 0, len = items.length; i < len; i++) {
|
for (let i = 0, len = items.length; i < len; i++) {
|
||||||
const { repo_id, path } = items[i];
|
const { repo_id, path } = items[i];
|
||||||
@@ -416,12 +468,7 @@ class Search extends Component {
|
|||||||
if (!width || width === 'default') return null;
|
if (!width || width === 'default') return null;
|
||||||
|
|
||||||
if (showRecent) {
|
if (showRecent) {
|
||||||
const { repoID } = this.props;
|
const visitedItems = JSON.parse(localStorage.getItem(this.storeKey)) || [];
|
||||||
let storeKey = 'sfVisitedSearchItems';
|
|
||||||
if (repoID) {
|
|
||||||
storeKey += repoID;
|
|
||||||
}
|
|
||||||
const visitedItems = JSON.parse(localStorage.getItem(storeKey)) || [];
|
|
||||||
if (visitedItems.length > 0) {
|
if (visitedItems.length > 0) {
|
||||||
return this.renderResults(visitedItems, true);
|
return this.renderResults(visitedItems, true);
|
||||||
}
|
}
|
||||||
@@ -586,7 +633,7 @@ class Search extends Component {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MediaQuery query="(min-width: 768px)">
|
<MediaQuery query="(min-width: 768px)">
|
||||||
<div className="search-result-list-container">{results}</div>
|
<div className="search-result-list-container" ref={this.searchResultListContainerRef}>{results}</div>
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
<MediaQuery query="(max-width: 767.8px)">
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
{results}
|
{results}
|
||||||
|
Reference in New Issue
Block a user