mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-31 10:02:45 +00:00
542 lines
19 KiB
JavaScript
542 lines
19 KiB
JavaScript
import React, { Component } from "react";
|
|
import PropTypes from "prop-types";
|
|
import { connect } from "react-redux";
|
|
import { withRouter } from "react-router-dom";
|
|
import RightIcon from "@material-ui/icons/KeyboardArrowRight";
|
|
import ViewListIcon from "@material-ui/icons/ViewList";
|
|
import ViewModuleIcon from "@material-ui/icons/ViewModule";
|
|
import ViewSmallIcon from "@material-ui/icons/ViewComfy";
|
|
import TextTotateVerticalIcon from "@material-ui/icons/TextRotateVertical";
|
|
import ShareIcon from "@material-ui/icons/Share";
|
|
import NewFolderIcon from "@material-ui/icons/CreateNewFolder";
|
|
import RefreshIcon from "@material-ui/icons/Refresh";
|
|
import {
|
|
navitateTo,
|
|
navitateUp,
|
|
changeViewMethod,
|
|
changeSortMethod,
|
|
setNavigatorError,
|
|
updateFileList,
|
|
setNavigatorLoadingStatus,
|
|
refreshFileList,
|
|
setSelectedTarget,
|
|
openCreateFolderDialog,
|
|
openShareDialog,
|
|
drawerToggleAction
|
|
} from "../../../actions/index";
|
|
import API from "../../../middleware/Api";
|
|
import { setCookie, setGetParameter, fixUrlHash } from "../../../untils/index";
|
|
import {
|
|
withStyles,
|
|
Divider,
|
|
Menu,
|
|
MenuItem,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
IconButton
|
|
} from "@material-ui/core";
|
|
import PathButton from "./PathButton";
|
|
import DropDown from "./DropDown";
|
|
import pathHelper from "../../../untils/page"
|
|
|
|
const mapStateToProps = state => {
|
|
return {
|
|
path: state.navigator.path,
|
|
refresh: state.navigator.refresh,
|
|
drawerDesktopOpen: state.viewUpdate.open,
|
|
viewMethod: state.viewUpdate.explorerViewMethod,
|
|
keywords: state.explorer.keywords,
|
|
sortMethod: state.viewUpdate.sortMethod
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = dispatch => {
|
|
return {
|
|
navigateToPath: path => {
|
|
dispatch(navitateTo(path));
|
|
},
|
|
navitateUp: () => {
|
|
dispatch(navitateUp());
|
|
},
|
|
changeView: method => {
|
|
dispatch(changeViewMethod(method));
|
|
},
|
|
changeSort: method => {
|
|
dispatch(changeSortMethod(method));
|
|
},
|
|
setNavigatorError: (status, msg) => {
|
|
dispatch(setNavigatorError(status, msg));
|
|
},
|
|
updateFileList: list => {
|
|
dispatch(updateFileList(list));
|
|
},
|
|
setNavigatorLoadingStatus: status => {
|
|
dispatch(setNavigatorLoadingStatus(status));
|
|
},
|
|
refreshFileList: () => {
|
|
dispatch(refreshFileList());
|
|
},
|
|
setSelectedTarget: target => {
|
|
dispatch(setSelectedTarget(target));
|
|
},
|
|
openCreateFolderDialog: () => {
|
|
dispatch(openCreateFolderDialog());
|
|
},
|
|
openShareDialog: () => {
|
|
dispatch(openShareDialog());
|
|
},
|
|
handleDesktopToggle: open => {
|
|
dispatch(drawerToggleAction(open));
|
|
}
|
|
};
|
|
};
|
|
|
|
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
const sortOptions = [
|
|
"文件名称正序",
|
|
"文件名称倒序",
|
|
"上传时间正序",
|
|
"上传时间到序",
|
|
"文件大小正序",
|
|
"文件大小倒序"
|
|
];
|
|
|
|
const styles = theme => ({
|
|
container: {
|
|
[theme.breakpoints.down("xs")]: {
|
|
display: "none"
|
|
},
|
|
height: "48px",
|
|
overflow: "hidden",
|
|
backgroundColor: theme.palette.background.paper
|
|
},
|
|
navigatorContainer: {
|
|
display: "flex",
|
|
justifyContent: "space-between"
|
|
},
|
|
nav: {
|
|
height: "47px",
|
|
padding: "5px 15px",
|
|
display: "flex"
|
|
},
|
|
optionContainer: {
|
|
paddingTop: "6px",
|
|
marginRight: "10px"
|
|
},
|
|
rightIcon: {
|
|
marginTop: "6px",
|
|
verticalAlign: "top",
|
|
color: "#868686"
|
|
},
|
|
expandMore: {
|
|
color: "#8d8d8d"
|
|
},
|
|
sideButton: {
|
|
padding: "8px",
|
|
marginRight: "5px"
|
|
}
|
|
});
|
|
|
|
class NavigatorCompoment extends Component {
|
|
keywords = null;
|
|
|
|
state = {
|
|
hidden: false,
|
|
hiddenFolders: [],
|
|
folders: [],
|
|
anchorEl: null,
|
|
hiddenMode: false,
|
|
anchorHidden: null,
|
|
anchorSort: null,
|
|
selectedIndex: 0
|
|
};
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.element = React.createRef();
|
|
}
|
|
|
|
componentDidMount = () => {
|
|
this.renderPath();
|
|
// 如果是在个人文件管理页,首次加载时打开侧边栏
|
|
this.props.handleDesktopToggle(true);
|
|
// 后退操作时重新导航
|
|
window.onpopstate = event => {
|
|
var url = new URL(fixUrlHash(window.location.href));
|
|
var c = url.searchParams.get("path");
|
|
if (c !== null && c !== this.props.path) {
|
|
this.props.navigateToPath(c);
|
|
}
|
|
};
|
|
};
|
|
|
|
renderPath = (path = null) => {
|
|
this.props.setNavigatorError(false, null);
|
|
this.setState({
|
|
folders:
|
|
path !== null
|
|
? path.substr(1).split("/")
|
|
: this.props.path.substr(1).split("/")
|
|
});
|
|
var newPath = path !== null ? path : this.props.path;
|
|
var apiURL = this.keywords === null ? "/directory" : "/File/SearchFile";
|
|
newPath = this.keywords === null ? newPath : this.keywords;
|
|
API.get(apiURL + newPath)
|
|
.then(response => {
|
|
this.props.updateFileList(response.data);
|
|
this.props.setNavigatorLoadingStatus(false);
|
|
let pathTemp = (path !== null
|
|
? path.substr(1).split("/")
|
|
: this.props.path.substr(1).split("/")
|
|
).join(",");
|
|
setCookie("path_tmp", encodeURIComponent(pathTemp), 1);
|
|
if (this.keywords === null) {
|
|
setGetParameter("path", encodeURIComponent(newPath));
|
|
}
|
|
})
|
|
.catch(error => {
|
|
this.props.setNavigatorError(true, error);
|
|
});
|
|
this.checkOverFlow(true);
|
|
};
|
|
|
|
redresh = path => {
|
|
this.props.setNavigatorLoadingStatus(true);
|
|
this.props.setNavigatorError(false, "error");
|
|
this.renderPath(path);
|
|
};
|
|
|
|
componentWillReceiveProps = nextProps => {
|
|
if (this.props.keywords !== nextProps.keywords) {
|
|
this.keywords = nextProps.keywords;
|
|
}
|
|
if (this.props.path !== nextProps.path) {
|
|
this.renderPath(nextProps.path);
|
|
}
|
|
if (this.props.refresh !== nextProps.refresh) {
|
|
this.redresh(nextProps.path);
|
|
}
|
|
};
|
|
|
|
componentDidUpdate = (prevProps, prevStates) => {
|
|
if (this.state.folders !== prevStates.folders) {
|
|
this.checkOverFlow(true);
|
|
}
|
|
if (this.props.drawerDesktopOpen !== prevProps.drawerDesktopOpen) {
|
|
delay(500).then(() => this.checkOverFlow());
|
|
}
|
|
};
|
|
|
|
checkOverFlow = force => {
|
|
if (this.overflowInitLock && !force) {
|
|
return;
|
|
}
|
|
if (this.element.current !== null) {
|
|
const hasOverflowingChildren =
|
|
this.element.current.offsetHeight <
|
|
this.element.current.scrollHeight ||
|
|
this.element.current.offsetWidth <
|
|
this.element.current.scrollWidth;
|
|
if (hasOverflowingChildren) {
|
|
this.overflowInitLock = true;
|
|
this.setState({ hiddenMode: true });
|
|
}
|
|
if (!hasOverflowingChildren && this.state.hiddenMode) {
|
|
this.setState({ hiddenMode: false });
|
|
}
|
|
}
|
|
};
|
|
|
|
navigateTo = (event, id) => {
|
|
if (id === this.state.folders.length - 1) {
|
|
//最后一个路径
|
|
this.setState({ anchorEl: event.currentTarget });
|
|
return;
|
|
} else if (
|
|
id === -1 &&
|
|
this.state.folders.length === 1 &&
|
|
this.state.folders[0] === ""
|
|
) {
|
|
this.props.refreshFileList();
|
|
this.handleClose();
|
|
return;
|
|
} else if (id === -1) {
|
|
this.props.navigateToPath("/");
|
|
this.handleClose();
|
|
return;
|
|
} else {
|
|
this.props.navigateToPath(
|
|
"/" + this.state.folders.slice(0, id + 1).join("/")
|
|
);
|
|
this.handleClose();
|
|
}
|
|
};
|
|
|
|
handleClose = () => {
|
|
this.setState({ anchorEl: null, anchorHidden: null, anchorSort: null });
|
|
};
|
|
|
|
showHiddenPath = e => {
|
|
this.setState({ anchorHidden: e.currentTarget });
|
|
};
|
|
|
|
showSortOptions = e => {
|
|
this.setState({ anchorSort: e.currentTarget });
|
|
};
|
|
|
|
performAction = e => {
|
|
this.handleClose();
|
|
if (e === "refresh") {
|
|
this.redresh();
|
|
return;
|
|
}
|
|
let presentPath = this.props.path.split("/");
|
|
let newTarget = [
|
|
{
|
|
type: "dir",
|
|
name: presentPath.pop(),
|
|
path: presentPath.length === 1 ? "/" : presentPath.join("/")
|
|
}
|
|
];
|
|
//this.props.navitateUp();
|
|
switch (e) {
|
|
case "share":
|
|
this.props.setSelectedTarget(newTarget);
|
|
this.props.openShareDialog();
|
|
break;
|
|
case "newfolder":
|
|
this.props.openCreateFolderDialog();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
|
|
toggleViewMethod = () => {
|
|
this.props.changeView(
|
|
this.props.viewMethod === "icon"
|
|
? "list"
|
|
: this.props.viewMethod === "list"
|
|
? "smallIcon"
|
|
: "icon"
|
|
);
|
|
};
|
|
|
|
handleMenuItemClick = (e, index) => {
|
|
this.setState({ selectedIndex: index, anchorEl: null });
|
|
let optionsTable = {
|
|
0: "namePos",
|
|
1: "nameRev",
|
|
2: "timePos",
|
|
3: "timeRev",
|
|
4: "sizePos",
|
|
5: "sizeRes"
|
|
};
|
|
this.props.changeSort(optionsTable[index]);
|
|
this.handleClose();
|
|
this.props.refreshFileList();
|
|
};
|
|
|
|
render() {
|
|
const { classes } = this.props;
|
|
|
|
let presentFolderMenu = (
|
|
<Menu
|
|
id="presentFolderMenu"
|
|
anchorEl={this.state.anchorEl}
|
|
open={Boolean(this.state.anchorEl)}
|
|
onClose={this.handleClose}
|
|
disableAutoFocusItem={true}
|
|
>
|
|
<MenuItem onClick={() => this.performAction("refresh")}>
|
|
<ListItemIcon>
|
|
<RefreshIcon />
|
|
</ListItemIcon>
|
|
刷新
|
|
</MenuItem>
|
|
{this.props.keywords === null && pathHelper.isHomePage(this.props.location.pathname) && (
|
|
<div>
|
|
<Divider />
|
|
<MenuItem onClick={() => this.performAction("share")}>
|
|
<ListItemIcon>
|
|
<ShareIcon />
|
|
</ListItemIcon>
|
|
分享
|
|
</MenuItem>
|
|
|
|
<MenuItem
|
|
onClick={() => this.performAction("newfolder")}
|
|
>
|
|
<ListItemIcon>
|
|
<NewFolderIcon />
|
|
</ListItemIcon>
|
|
创建文件夹
|
|
</MenuItem>
|
|
</div>
|
|
)}
|
|
</Menu>
|
|
);
|
|
|
|
return (
|
|
<div className={classes.container}>
|
|
<div className={classes.navigatorContainer}>
|
|
<div className={classes.nav} ref={this.element}>
|
|
<span>
|
|
<PathButton
|
|
folder="/"
|
|
path="/"
|
|
onClick={e => this.navigateTo(e, -1)}
|
|
/>
|
|
<RightIcon className={classes.rightIcon} />
|
|
</span>
|
|
{this.state.hiddenMode && (
|
|
<span>
|
|
<PathButton
|
|
more
|
|
title="显示路径"
|
|
onClick={this.showHiddenPath}
|
|
/>
|
|
<Menu
|
|
id="hiddenPathMenu"
|
|
anchorEl={this.state.anchorHidden}
|
|
open={Boolean(this.state.anchorHidden)}
|
|
onClose={this.handleClose}
|
|
disableAutoFocusItem={true}
|
|
>
|
|
<DropDown onClose={this.handleClose} folders={this.state.folders.slice(0, -1)} navigateTo = {this.navigateTo}/>
|
|
|
|
</Menu>
|
|
<RightIcon className={classes.rightIcon} />
|
|
{/* <Button component="span" onClick={(e)=>this.navigateTo(e,this.state.folders.length-1)}>
|
|
{this.state.folders.slice(-1)}
|
|
<ExpandMore className={classes.expandMore}/>
|
|
</Button> */}
|
|
<PathButton
|
|
folder={this.state.folders.slice(-1)}
|
|
path={
|
|
"/" +
|
|
this.state.folders
|
|
.slice(0, -1)
|
|
.join("/")
|
|
}
|
|
last={true}
|
|
onClick={e =>
|
|
this.navigateTo(
|
|
e,
|
|
this.state.folders.length - 1
|
|
)
|
|
}
|
|
/>
|
|
{presentFolderMenu}
|
|
</span>
|
|
)}
|
|
{!this.state.hiddenMode &&
|
|
this.state.folders.map((folder, id, folders) => (
|
|
<span key={id}>
|
|
{folder !== "" && (
|
|
<span>
|
|
<PathButton
|
|
folder={folder}
|
|
path={
|
|
"/" +
|
|
folders
|
|
.slice(0, id)
|
|
.join("/")
|
|
}
|
|
last={id === folders.length - 1}
|
|
onClick={e =>
|
|
this.navigateTo(e, id)
|
|
}
|
|
/>
|
|
{id === folders.length - 1 &&
|
|
presentFolderMenu}
|
|
{id !== folders.length - 1 && (
|
|
<RightIcon
|
|
className={
|
|
classes.rightIcon
|
|
}
|
|
/>
|
|
)}
|
|
</span>
|
|
)}
|
|
</span>
|
|
))}
|
|
</div>
|
|
<div className={classes.optionContainer}>
|
|
{this.props.viewMethod === "icon" && (
|
|
<IconButton
|
|
title="列表展示"
|
|
className={classes.sideButton}
|
|
onClick={this.toggleViewMethod}
|
|
>
|
|
<ViewListIcon fontSize="small" />
|
|
</IconButton>
|
|
)}
|
|
{this.props.viewMethod === "list" && (
|
|
<IconButton
|
|
title="小图标展示"
|
|
className={classes.sideButton}
|
|
onClick={this.toggleViewMethod}
|
|
>
|
|
<ViewSmallIcon fontSize="small" />
|
|
</IconButton>
|
|
)}
|
|
|
|
{this.props.viewMethod === "smallIcon" && (
|
|
<IconButton
|
|
title="大图标展示"
|
|
className={classes.sideButton}
|
|
onClick={this.toggleViewMethod}
|
|
>
|
|
<ViewModuleIcon fontSize="small" />
|
|
</IconButton>
|
|
)}
|
|
|
|
<IconButton
|
|
title="排序方式"
|
|
className={classes.sideButton}
|
|
onClick={this.showSortOptions}
|
|
>
|
|
<TextTotateVerticalIcon fontSize="small" />
|
|
</IconButton>
|
|
<Menu
|
|
id="sort-menu"
|
|
anchorEl={this.state.anchorSort}
|
|
open={Boolean(this.state.anchorSort)}
|
|
onClose={this.handleClose}
|
|
>
|
|
{sortOptions.map((option, index) => (
|
|
<MenuItem
|
|
key={option}
|
|
selected={
|
|
index === this.state.selectedIndex
|
|
}
|
|
onClick={event =>
|
|
this.handleMenuItemClick(event, index)
|
|
}
|
|
>
|
|
{option}
|
|
</MenuItem>
|
|
))}
|
|
</Menu>
|
|
</div>
|
|
</div>
|
|
<Divider />
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
NavigatorCompoment.propTypes = {
|
|
classes: PropTypes.object.isRequired,
|
|
path: PropTypes.string.isRequired
|
|
};
|
|
|
|
const Navigator = connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(withStyles(styles)(withRouter(NavigatorCompoment)));
|
|
|
|
export default Navigator;
|