1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-09 19:01:42 +00:00

Feature/improve interactivity of searched list in move dialog (#6597)

* improve interactivity of search result

* clean up redundant code

* clean up redundant code
This commit is contained in:
Aries
2024-08-21 11:35:50 +08:00
committed by GitHub
parent a8b61af868
commit c08abe8fc1
6 changed files with 137 additions and 24 deletions

View File

@@ -57,6 +57,8 @@ class FileChooser extends React.Component {
searchInfo: '',
searchResults: [],
selectedItemInfo: {},
isBrowsing: false,
browsingPath: '',
};
this.inputValue = '';
this.timer = null;
@@ -115,6 +117,8 @@ class FileChooser extends React.Component {
this.setState({
isSearching: false,
isResultGot: false,
isBrowsing: false,
browsingPath: '',
searchInfo: '',
searchResults: [],
});
@@ -182,8 +186,12 @@ class FileChooser extends React.Component {
this.setState({
isSearching: false,
isResultGot: false,
isBrowsing: false,
browsingPath: '',
searchInfo: '',
searchResults: [],
selectedPath: this.props.currentPath,
selectedItemInfo: {},
});
this.inputValue = '';
this.timer = null;
@@ -204,7 +212,7 @@ class FileChooser extends React.Component {
}
this.inputValue = searchInfo;
if (this.inputValue === '' || this.getValueLength(this.inputValue) < 3) {
if (this.inputValue === '') {
this.setState({
isResultGot: false,
});
@@ -242,18 +250,27 @@ class FileChooser extends React.Component {
};
sendRequest = (queryData, cancelToken) => {
const filterCurrentRepo = (results) => {
if (this.props.mode === 'only_other_libraries') {
return results.filter(item => item.repo_id !== this.state.currentRepoInfo.repo_id);
}
return results;
};
if (isPro && enableSeasearch && !enableElasticsearch) {
seafileAPI.aiSearchFiles(queryData, cancelToken).then(res => {
const filteredResults = filterCurrentRepo(res.data.results.filter(item => item.is_dir));
this.setState({
searchResults: res.data.results.length > 0 ? this.formatResultItems(res.data.results.filter(item => item.is_dir)) : [],
searchResults: filteredResults.length > 0 ? this.formatResultItems(filteredResults) : [],
isResultGot: true
});
this.source = null;
});
} else {
seafileAPI.searchFiles(queryData, cancelToken).then(res => {
const filteredResults = filterCurrentRepo(res.data.results);
this.setState({
searchResults: res.data.total ? this.formatResultItems(res.data.results) : [],
searchResults: res.data.total ? this.formatResultItems(filteredResults) : [],
isResultGot: true
});
this.source = null;
@@ -306,10 +323,6 @@ class FileChooser extends React.Component {
};
renderSearchedView = () => {
if (this.getValueLength(this.inputValue) < 3) {
return '';
}
if (!this.state.isResultGot) {
return (<Loading />);
}
@@ -409,7 +422,16 @@ class FileChooser extends React.Component {
}
}
this.onCloseSearching();
this.setState({
isSearching: false,
isResultGot: false,
searchResults: [],
isBrowsing: true,
browsingPath: item.path.substring(0, item.path.length - 1),
});
this.inputValue = '';
this.timer = null;
this.source = null;
};
onScroll = (event) => {
event.stopPropagation();
@@ -481,6 +503,8 @@ class FileChooser extends React.Component {
isShowFile={isShowFile}
fileSuffixes={fileSuffixes}
selectedItemInfo={selectedItemInfo}
isBrowsing={this.state.isBrowsing}
browsingPath={this.state.browsingPath}
/>
</div>
)}
@@ -517,6 +541,8 @@ class FileChooser extends React.Component {
isShowFile={isShowFile}
fileSuffixes={fileSuffixes}
selectedItemInfo={selectedItemInfo}
isBrowsing={this.state.isBrowsing}
browsingPath={this.state.browsingPath}
/>
</div>
)}
@@ -534,7 +560,7 @@ class FileChooser extends React.Component {
};
render() {
const { repoID } = this.props;
const { repoID, mode } = this.props;
const { selectedRepo, searchInfo, isSearching } = this.state;
if (!selectedRepo && repoID) {
@@ -543,7 +569,7 @@ class FileChooser extends React.Component {
return (
<Fragment>
{isPro && this.props.mode !== 'recently_used' && (
{isPro && mode !== 'recently_used' && (
<div className="file-chooser-search-input">
<Input className="search-input" placeholder={gettext('Search')} type='text' value={searchInfo} onChange={this.onSearchInfoChanged}></Input>
{searchInfo.length !== 0 && (

View File

@@ -21,6 +21,8 @@ const propTypes = {
fileSuffixes: PropTypes.array,
selectedItemInfo: PropTypes.object,
hideLibraryName: PropTypes.bool,
isBrowsing: PropTypes.bool,
browsingPath: PropTypes.string,
};
class RepoListItem extends React.Component {
@@ -63,6 +65,30 @@ class RepoListItem extends React.Component {
}
}
componentDidUpdate(prevProps) {
if (prevProps.isBrowsing && !this.props.isBrowsing) {
this.setState({
treeData: treeHelper.buildTree(),
isShowChildren: this.props.initToShowChildren,
});
const { isCurrentRepo, currentPath, repo, selectedItemInfo } = this.props;
const { repoID } = selectedItemInfo || {};
if (isCurrentRepo && !repoID) {
this.loadRepoDirentList(repo);
setTimeout(() => {
const repoID = repo.repo_id;
if (isCurrentRepo && currentPath && currentPath != '/') {
const expandNode = true;
this.loadNodeAndParentsByPath(repoID, currentPath, expandNode);
}
}, 0);
}
}
}
componentWillUnmount() {
this.setState({ isMounted: false });
}
@@ -205,7 +231,7 @@ class RepoListItem extends React.Component {
return (
<li>
{!this.props.hideLibraryName &&
{!this.props.hideLibraryName && !this.props.isBrowsing &&
<div className={`${repoActive ? 'item-active' : ''} item-info`} onClick={this.onRepoItemClick}>
<div className="item-left-icon">
<span className={`item-toggle icon sf3-font ${this.state.isShowChildren ? 'sf3-font-down' : 'sf3-font-down rotate-270 d-inline-block'}`} onClick={this.onToggleClick}></span>
@@ -228,6 +254,8 @@ class RepoListItem extends React.Component {
treeData={this.state.treeData}
onNodeCollapse={this.onNodeCollapse}
onNodeExpanded={this.onNodeExpanded}
isBrowsing={this.props.isBrowsing}
browsingPath={this.props.browsingPath}
/>
)}
</li>

View File

@@ -15,6 +15,8 @@ const propTypes = {
fileSuffixes: PropTypes.array,
selectedItemInfo: PropTypes.object,
currentPath: PropTypes.string,
isBrowsing: PropTypes.bool,
browsingPath: PropTypes.string,
};
class RepoListView extends React.Component {
@@ -43,6 +45,8 @@ class RepoListView extends React.Component {
isShowFile={this.props.isShowFile}
fileSuffixes={this.props.fileSuffixes}
selectedItemInfo={this.props.selectedItemInfo}
isBrowsing={this.props.isBrowsing}
browsingPath={this.props.browsingPath}
/>
);
})}

View File

@@ -13,12 +13,44 @@ class SearchedListView extends React.Component {
constructor(props) {
super(props);
this.state = {
currentItem: null,
currentItem: props.searchResults.length > 0 ? props.searchResults[0] : null,
currentIndex: props.searchResults.length > 0 ? 0 : -1,
};
this.itemRef = React.createRef();
}
onItemClick = (item) => {
this.setState({ currentItem: item });
componentDidMount() {
document.addEventListener('keydown', this.handleKeyDown);
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleKeyDown);
}
handleKeyDown = (event) => {
const { searchResults } = this.props;
const { currentIndex } = this.state;
if (event.key === 'ArrowDown') {
const nextIndex = (currentIndex + 1) % searchResults.length;
this.setState({
currentItem: searchResults[nextIndex],
currentIndex: nextIndex,
});
} else if (event.key === 'ArrowUp') {
const prevIndex = (currentIndex - 1 + searchResults.length) % searchResults.length;
this.setState({
currentItem: searchResults[prevIndex],
currentIndex: prevIndex,
});
} else if (event.key === 'Enter') {
this.onItemClick(searchResults[currentIndex], currentIndex);
this.props.onSearchedItemDoubleClick(searchResults[currentIndex]);
}
};
onItemClick = (item, index) => {
this.setState({ currentItem: item, currentIndex: index });
this.props.onItemClick(item);
};
@@ -36,9 +68,10 @@ class SearchedListView extends React.Component {
return (
<SearchedListItem
key={index}
ref={this.itemRef}
item={item}
currentItem={this.state.currentItem}
onItemClick={this.onItemClick}
onItemClick={() => this.onItemClick(item, index)}
onSearchedItemDoubleClick={this.props.onSearchedItemDoubleClick}
/>
);

View File

@@ -12,6 +12,7 @@ const propTypes = {
filePath: PropTypes.string,
fileSuffixes: PropTypes.array,
level: PropTypes.number,
isBrowsing: PropTypes.bool,
};
class TreeViewItem extends React.Component {
@@ -96,7 +97,7 @@ class TreeViewItem extends React.Component {
if (this.props.selectedRepo) {
isCurrentRepo = this.props.selectedRepo.repo_id === this.props.repo.repo_id;
}
let isCurrentPath = this.props.selectedPath === this.state.filePath;
let isCurrentPath = this.props.selectedPath === this.state.filePath || this.props.selectedPath === node.path;
const fileName = node.object.name;
if (this.props.fileSuffixes && fileName && node.object.type === 'file') {

View File

@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import TreeListItem from './tree-list-item';
import treeHelper from '../tree-view/tree-helper';
const propTypes = {
selectedPath: PropTypes.string,
@@ -11,22 +12,42 @@ const propTypes = {
onNodeCollapse: PropTypes.func.isRequired,
onNodeExpanded: PropTypes.func.isRequired,
fileSuffixes: PropTypes.array,
isBrowsing: PropTypes.bool,
browsingPath: PropTypes.string,
};
class TreeListView extends React.Component {
render() {
const {
isBrowsing,
browsingPath,
treeData,
selectedPath,
onNodeCollapse,
onNodeExpanded,
repo,
onDirentItemClick,
selectedRepo,
fileSuffixes
} = this.props;
const browsingNode = treeHelper.findNodeByPath(treeData, browsingPath);
if (isBrowsing && !browsingNode) return null;
const node = isBrowsing ? browsingNode : treeData.root;
return (
<div className="list-view-content">
<TreeListItem
node={this.props.treeData.root}
onNodeCollapse={this.props.onNodeCollapse}
onNodeExpanded={this.props.onNodeExpanded}
repo={this.props.repo}
onDirentItemClick={this.props.onDirentItemClick}
selectedRepo={this.props.selectedRepo}
selectedPath={this.props.selectedPath}
fileSuffixes={this.props.fileSuffixes}
node={node}
onNodeCollapse={onNodeCollapse}
onNodeExpanded={onNodeExpanded}
repo={repo}
onDirentItemClick={onDirentItemClick}
selectedRepo={selectedRepo}
selectedPath={selectedPath}
fileSuffixes={fileSuffixes}
level={0}
/>
</div>