mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-29 23:22:46 +00:00
244 lines
7.3 KiB
JavaScript
244 lines
7.3 KiB
JavaScript
import React, { useCallback, useEffect } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import statusHelper from "../../utils/page";
|
|
import FileIcon from "./FileIcon";
|
|
import SmallIcon from "./SmallIcon";
|
|
import TableItem from "./TableRow";
|
|
import classNames from "classnames";
|
|
import { makeStyles } from "@material-ui/core";
|
|
import { useDrag } from "react-dnd";
|
|
import { getEmptyImage } from "react-dnd-html5-backend";
|
|
import DropWarpper from "./DnD/DropWarpper";
|
|
import { useLocation } from "react-router-dom";
|
|
import { pathBack } from "../../utils";
|
|
import {
|
|
changeContextMenu,
|
|
dragAndDrop,
|
|
navigateTo,
|
|
openLoadingDialog,
|
|
openPreview,
|
|
selectFile,
|
|
setSelectedTarget,
|
|
toggleSnackbar,
|
|
} from "../../redux/explorer";
|
|
|
|
const useStyles = makeStyles(() => ({
|
|
container: {
|
|
padding: "7px",
|
|
},
|
|
fixFlex: {
|
|
minWidth: 0,
|
|
},
|
|
dragging: {
|
|
opacity: 0.4,
|
|
},
|
|
}));
|
|
|
|
export default function ObjectIcon(props) {
|
|
const path = useSelector((state) => state.navigator.path);
|
|
const selected = useSelector((state) => state.explorer.selected);
|
|
const viewMethod = useSelector(
|
|
(state) => state.viewUpdate.explorerViewMethod
|
|
);
|
|
const navigatorPath = useSelector((state) => state.navigator.path);
|
|
const location = useLocation();
|
|
|
|
const dispatch = useDispatch();
|
|
const ContextMenu = useCallback(
|
|
(type, open) => dispatch(changeContextMenu(type, open)),
|
|
[dispatch]
|
|
);
|
|
const SetSelectedTarget = useCallback(
|
|
(targets) => dispatch(setSelectedTarget(targets)),
|
|
[dispatch]
|
|
);
|
|
|
|
const NavitateTo = useCallback((targets) => dispatch(navigateTo(targets)), [
|
|
dispatch,
|
|
]);
|
|
const ToggleSnackbar = useCallback(
|
|
(vertical, horizontal, msg, color) =>
|
|
dispatch(toggleSnackbar(vertical, horizontal, msg, color)),
|
|
[dispatch]
|
|
);
|
|
const DragAndDrop = useCallback(
|
|
(source, target) => dispatch(dragAndDrop(source, target)),
|
|
[dispatch]
|
|
);
|
|
const OpenLoadingDialog = useCallback(
|
|
(text) => dispatch(openLoadingDialog(text)),
|
|
[dispatch]
|
|
);
|
|
const OpenPreview = useCallback((share) => dispatch(openPreview(share)), [
|
|
dispatch,
|
|
]);
|
|
const StartDownload = useCallback(
|
|
(share, file) => dispatch(StartDownload(share, file)),
|
|
[dispatch]
|
|
);
|
|
|
|
const classes = useStyles();
|
|
|
|
const contextMenu = (e) => {
|
|
if (props.file.type === "up") {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
if (
|
|
selected.findIndex((value) => {
|
|
return value === props.file;
|
|
}) === -1
|
|
) {
|
|
SetSelectedTarget([props.file]);
|
|
}
|
|
ContextMenu("file", true);
|
|
};
|
|
|
|
const SelectFile = (e) => {
|
|
dispatch(selectFile(props.file, e, props.index));
|
|
};
|
|
const enterFolder = () => {
|
|
NavitateTo(
|
|
path === "/" ? path + props.file.name : path + "/" + props.file.name
|
|
);
|
|
};
|
|
const handleClick = (e) => {
|
|
if (props.file.type === "up") {
|
|
NavitateTo(pathBack(navigatorPath));
|
|
return;
|
|
}
|
|
|
|
SelectFile(e);
|
|
if (props.file.type === "dir" && (!e.ctrlKey && !e.metaKey && !e.shiftKey)) {
|
|
enterFolder();
|
|
}
|
|
};
|
|
|
|
const handleDoubleClick = () => {
|
|
if (props.file.type === "up") {
|
|
return;
|
|
}
|
|
if (props.file.type === "dir") {
|
|
enterFolder();
|
|
return;
|
|
}
|
|
|
|
OpenPreview(window.shareInfo);
|
|
};
|
|
|
|
const handleIconClick = (e) => {
|
|
e.stopPropagation();
|
|
e.ctrlKey = true;
|
|
SelectFile(e);
|
|
return false;
|
|
};
|
|
|
|
const [{ isDragging }, drag, preview] = useDrag({
|
|
item: {
|
|
object: props.file,
|
|
type: "object",
|
|
selected: [...selected],
|
|
viewMethod: viewMethod,
|
|
},
|
|
end: (item, monitor) => {
|
|
const dropResult = monitor.getDropResult();
|
|
if (item && dropResult) {
|
|
if (dropResult.folder) {
|
|
if (
|
|
item.object.id !== dropResult.folder.id ||
|
|
item.object.type !== dropResult.folder.type
|
|
) {
|
|
DragAndDrop(item.object, dropResult.folder);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
canDrag: () => {
|
|
return (
|
|
!statusHelper.isMobile() &&
|
|
statusHelper.isHomePage(location.pathname)
|
|
);
|
|
},
|
|
collect: (monitor) => ({
|
|
isDragging: monitor.isDragging(),
|
|
}),
|
|
});
|
|
|
|
useEffect(() => {
|
|
preview(getEmptyImage(), { captureDraggingState: true });
|
|
// eslint-disable-next-line
|
|
}, []);
|
|
|
|
if (viewMethod === "list") {
|
|
return (
|
|
<>
|
|
{props.file.type === "dir" && (
|
|
<DropWarpper
|
|
isListView={true}
|
|
pref={drag}
|
|
className={classNames(classes.container, {
|
|
[classes.dragging]: isDragging,
|
|
})}
|
|
onIconClick={handleIconClick}
|
|
contextMenu={contextMenu}
|
|
handleClick={handleClick}
|
|
handleDoubleClick={handleDoubleClick.bind(this)}
|
|
folder={props.file}
|
|
/>
|
|
)}
|
|
{props.file.type !== "dir" && (
|
|
<TableItem
|
|
pref={drag}
|
|
className={classNames(classes.container, {
|
|
[classes.dragging]: isDragging,
|
|
})}
|
|
onIconClick={handleIconClick}
|
|
contextMenu={contextMenu}
|
|
handleClick={handleClick}
|
|
handleDoubleClick={handleDoubleClick.bind(this)}
|
|
file={props.file}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
ref={drag}
|
|
className={classNames({
|
|
[classes.container]: viewMethod !== "list",
|
|
[classes.dragging]: isDragging,
|
|
})}
|
|
>
|
|
<div
|
|
className={classes.fixFlex}
|
|
onContextMenu={contextMenu}
|
|
onClick={handleClick}
|
|
onDoubleClick={handleDoubleClick.bind(this)}
|
|
>
|
|
{props.file.type === "dir" && viewMethod !== "list" && (
|
|
<DropWarpper
|
|
isListView={false}
|
|
onIconClick={handleIconClick}
|
|
folder={props.file}
|
|
/>
|
|
)}
|
|
{props.file.type === "file" && viewMethod === "icon" && (
|
|
<FileIcon
|
|
onIconClick={handleIconClick}
|
|
ref={drag}
|
|
file={props.file}
|
|
/>
|
|
)}
|
|
{props.file.type === "file" && viewMethod === "smallIcon" && (
|
|
<SmallIcon
|
|
onIconClick={handleIconClick}
|
|
file={props.file}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|