mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
325 lines
11 KiB
TypeScript
325 lines
11 KiB
TypeScript
import { useMemo } from "react";
|
|
import { FileResponse, FileType, Metadata, NavigatorCapability } from "../../../api/explorer.ts";
|
|
import { getCachedThumbExts } from "../../../redux/thunks/thumb.ts";
|
|
import { GroupPermission } from "../../../api/user.ts";
|
|
import { defaultPath } from "../../../hooks/useNavigation.tsx";
|
|
import { ContextMenuTypes } from "../../../redux/fileManagerSlice.ts";
|
|
import { Viewers, ViewersByID } from "../../../redux/siteConfigSlice.ts";
|
|
import { ExpandedViewerSetting } from "../../../redux/thunks/viewer.ts";
|
|
import SessionManager from "../../../session";
|
|
import { fileExtension } from "../../../util";
|
|
import Boolset from "../../../util/boolset.ts";
|
|
import CrUri, { Filesystem } from "../../../util/uri.ts";
|
|
import { FileManagerIndex } from "../FileManager.tsx";
|
|
|
|
const supportedArchiveTypes = ["zip", "gz", "xz", "tar", "rar", "7z", "bz2"];
|
|
|
|
export const canManageVersion = (file: FileResponse, bs: Boolset) => {
|
|
return (
|
|
file.type == FileType.file &&
|
|
(!file.metadata || !file.metadata[Metadata.share_redirect]) &&
|
|
bs.enabled(NavigatorCapability.version_control)
|
|
);
|
|
};
|
|
|
|
export const canShowInfo = (cap: Boolset) => {
|
|
return cap.enabled(NavigatorCapability.info);
|
|
};
|
|
|
|
export const canUpdate = (opt: DisplayOption) => {
|
|
return !!(
|
|
opt.allUpdatable &&
|
|
opt.hasFile &&
|
|
opt.orCapability?.enabled(NavigatorCapability.upload_file) &&
|
|
opt.allUpdatable
|
|
);
|
|
};
|
|
|
|
export interface DisplayOption {
|
|
allReadable: boolean;
|
|
allUpdatable: boolean;
|
|
|
|
hasReadable?: boolean;
|
|
hasUpdatable?: boolean;
|
|
|
|
hasTrashFile?: boolean;
|
|
hasFile?: boolean;
|
|
hasFolder?: boolean;
|
|
hasOwned?: boolean;
|
|
|
|
showEnter?: boolean;
|
|
showOpen?: boolean;
|
|
showOpenWithCascading?: () => boolean;
|
|
showOpenWith?: () => boolean;
|
|
showDownload?: boolean;
|
|
showGoToSharedLink?: boolean;
|
|
showExtractArchive?: boolean;
|
|
showTorrentRemoteDownload?: boolean;
|
|
showGoToParent?: boolean;
|
|
|
|
showDelete?: boolean;
|
|
showRestore?: boolean;
|
|
showRename?: boolean;
|
|
showPin?: boolean;
|
|
showOrganize?: boolean;
|
|
showCopy?: boolean;
|
|
showShare?: boolean;
|
|
showInfo?: boolean;
|
|
showDirectLink?: boolean;
|
|
|
|
showMove?: boolean;
|
|
showTags?: boolean;
|
|
showChangeFolderColor?: boolean;
|
|
showChangeIcon?: boolean;
|
|
showCustomProps?: boolean;
|
|
|
|
showMore?: boolean;
|
|
showVersionControl?: boolean;
|
|
showDirectLinkManagement?: boolean;
|
|
showManageShares?: boolean;
|
|
showCreateArchive?: boolean;
|
|
showResetThumb?: boolean;
|
|
|
|
andCapability?: Boolset;
|
|
orCapability?: Boolset;
|
|
|
|
showCreateFolder?: boolean;
|
|
showCreateFile?: boolean;
|
|
showRefresh?: boolean;
|
|
showNewFileFromTemplate?: boolean;
|
|
showUpload?: boolean;
|
|
showRemoteDownload?: boolean;
|
|
}
|
|
|
|
const capabilityMap: { [key: string]: Boolset } = {};
|
|
|
|
export const getActionOpt = (
|
|
targets: FileResponse[],
|
|
viewerSetting?: ExpandedViewerSetting,
|
|
type?: string,
|
|
parent?: FileResponse,
|
|
fmIndex: number = 0,
|
|
): DisplayOption => {
|
|
const currentUser = SessionManager.currentLoginOrNull();
|
|
const currentUserAnonymous = SessionManager.currentUser();
|
|
const groupBs = SessionManager.currentUserGroupPermission();
|
|
const display: DisplayOption = {
|
|
allReadable: true,
|
|
allUpdatable: true,
|
|
};
|
|
if (type == ContextMenuTypes.empty || type == ContextMenuTypes.new) {
|
|
display.showRefresh = type == ContextMenuTypes.empty;
|
|
display.showRemoteDownload = groupBs.enabled(GroupPermission.remote_download) && !!currentUser;
|
|
|
|
if (!parent || parent.type != FileType.folder) {
|
|
display.showRemoteDownload = display.showRemoteDownload && type == ContextMenuTypes.new;
|
|
return display;
|
|
}
|
|
|
|
const parentCap = new Boolset(parent.capability);
|
|
display.showCreateFolder = parentCap.enabled(NavigatorCapability.create_file) && parent.owned;
|
|
display.showCreateFile = display.showCreateFolder && fmIndex == FileManagerIndex.main;
|
|
display.showUpload = display.showCreateFile;
|
|
if (display.showCreateFile) {
|
|
const allViewers = Object.entries(ViewersByID);
|
|
for (let i = 0; i < allViewers.length; i++) {
|
|
if (allViewers[i][1] && allViewers[i][1].templates) {
|
|
display.showNewFileFromTemplate = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return display;
|
|
}
|
|
|
|
if (type == ContextMenuTypes.searchResult) {
|
|
display.showGoToParent = true;
|
|
}
|
|
|
|
const parentUrl = new CrUri(targets?.[0]?.path ?? defaultPath);
|
|
targets.forEach((target) => {
|
|
let readable = true;
|
|
let updatable = target.owned && parentUrl.fs() != Filesystem.share;
|
|
|
|
if (display.allReadable && !readable) {
|
|
display.allReadable = false;
|
|
}
|
|
if (display.allUpdatable && !updatable) {
|
|
display.allUpdatable = false;
|
|
}
|
|
|
|
if (!display.hasReadable && readable) {
|
|
display.hasReadable = true;
|
|
}
|
|
if (!display.hasUpdatable && updatable) {
|
|
display.hasUpdatable = true;
|
|
}
|
|
|
|
if (target.metadata && target.metadata[Metadata.restore_uri]) {
|
|
display.hasTrashFile = true;
|
|
}
|
|
|
|
if (target.type == FileType.file) {
|
|
display.hasFile = true;
|
|
}
|
|
|
|
if (target.type == FileType.folder) {
|
|
display.hasFolder = true;
|
|
}
|
|
|
|
if (target.owned) {
|
|
display.hasOwned = true;
|
|
}
|
|
|
|
if (target.capability) {
|
|
let bs = capabilityMap[target.capability];
|
|
if (!bs) {
|
|
bs = new Boolset(target.capability);
|
|
capabilityMap[target.capability] = bs;
|
|
}
|
|
|
|
if (!display.andCapability) {
|
|
display.andCapability = bs;
|
|
}
|
|
|
|
display.andCapability = display.andCapability.and(bs);
|
|
|
|
if (!display.orCapability) {
|
|
display.orCapability = bs;
|
|
}
|
|
display.orCapability = display.orCapability.or(bs);
|
|
}
|
|
});
|
|
|
|
const firstFileSuffix = fileExtension(targets[0]?.name ?? "");
|
|
display.showPin = !display.hasTrashFile && targets.length == 1 && display.hasFolder;
|
|
display.showDelete =
|
|
display.hasUpdatable &&
|
|
display.orCapability &&
|
|
(display.orCapability.enabled(NavigatorCapability.soft_delete) ||
|
|
display.orCapability.enabled(NavigatorCapability.delete_file));
|
|
display.showRestore = display.andCapability?.enabled(NavigatorCapability.restore);
|
|
display.showRename =
|
|
targets.length == 1 &&
|
|
display.allUpdatable &&
|
|
display.orCapability &&
|
|
display.orCapability.enabled(NavigatorCapability.rename_file);
|
|
display.showCopy = display.hasUpdatable && !!display.orCapability;
|
|
display.showShare =
|
|
targets.length == 1 &&
|
|
!!currentUser &&
|
|
groupBs.enabled(GroupPermission.share) &&
|
|
display.allUpdatable &&
|
|
(targets[0].owned || groupBs.enabled(GroupPermission.is_admin)) &&
|
|
display.orCapability &&
|
|
display.orCapability.enabled(NavigatorCapability.share) &&
|
|
(!targets[0].metadata ||
|
|
(!targets[0].metadata[Metadata.share_redirect] && !targets[0].metadata[Metadata.restore_uri]));
|
|
display.showMove = display.hasUpdatable && !!display.orCapability;
|
|
display.showTags =
|
|
display.hasUpdatable && display.orCapability && display.orCapability.enabled(NavigatorCapability.update_metadata);
|
|
display.showChangeFolderColor =
|
|
display.hasUpdatable &&
|
|
!display.hasFile &&
|
|
display.orCapability &&
|
|
display.orCapability.enabled(NavigatorCapability.update_metadata);
|
|
display.showChangeIcon =
|
|
display.hasUpdatable && display.orCapability && display.orCapability.enabled(NavigatorCapability.update_metadata);
|
|
display.showCustomProps = display.showChangeIcon;
|
|
display.showDownload =
|
|
display.hasReadable && display.orCapability && display.orCapability.enabled(NavigatorCapability.download_file);
|
|
display.showDirectLink =
|
|
(display.hasOwned || groupBs.enabled(GroupPermission.is_admin)) &&
|
|
display.orCapability &&
|
|
(currentUserAnonymous?.group?.direct_link_batch_size ?? 0) >= targets.length &&
|
|
display.orCapability.enabled(NavigatorCapability.download_file);
|
|
display.showDirectLinkManagement = display.showDirectLink && targets.length == 1 && display.hasFile;
|
|
display.showOpen =
|
|
targets.length == 1 &&
|
|
display.hasFile &&
|
|
display.showDownload &&
|
|
!!viewerSetting &&
|
|
!!firstFileSuffix &&
|
|
!!viewerSetting?.[firstFileSuffix];
|
|
display.showEnter =
|
|
targets.length == 1 &&
|
|
display.hasFolder &&
|
|
display.orCapability?.enabled(NavigatorCapability.enter_folder) &&
|
|
display.allReadable;
|
|
display.showExtractArchive =
|
|
targets.length == 1 &&
|
|
display.hasFile &&
|
|
display.showDownload &&
|
|
!!currentUser &&
|
|
groupBs.enabled(GroupPermission.archive_task) &&
|
|
supportedArchiveTypes.includes(firstFileSuffix ?? "");
|
|
display.showTorrentRemoteDownload =
|
|
targets.length == 1 &&
|
|
display.hasFile &&
|
|
display.showDownload &&
|
|
!!currentUser &&
|
|
groupBs.enabled(GroupPermission.remote_download) &&
|
|
firstFileSuffix == "torrent";
|
|
|
|
display.showOpenWithCascading = () => false;
|
|
display.showOpenWith = () => targets.length == 1 && !!display.hasFile && !!display.showDownload;
|
|
if (display.showOpen) {
|
|
display.showOpenWithCascading = () =>
|
|
!!(display.showOpen && viewerSetting && viewerSetting[firstFileSuffix ?? ""]?.length >= 1);
|
|
display.showOpenWith = () =>
|
|
!!(display.showOpen && viewerSetting && viewerSetting[firstFileSuffix ?? ""]?.length < 1);
|
|
}
|
|
display.showOrganize = display.showPin || display.showMove || display.showChangeFolderColor || display.showChangeIcon;
|
|
display.showGoToSharedLink =
|
|
targets.length == 1 && display.hasFile && targets[0].metadata && !!targets[0].metadata[Metadata.share_redirect];
|
|
display.showInfo = targets.length == 1 && display.orCapability && canShowInfo(display.orCapability);
|
|
display.showVersionControl =
|
|
targets.length == 1 &&
|
|
display.orCapability &&
|
|
display.hasReadable &&
|
|
canManageVersion(targets[0], display.orCapability);
|
|
display.showManageShares =
|
|
targets.length == 1 &&
|
|
targets[0].shared &&
|
|
display.orCapability &&
|
|
!!currentUser &&
|
|
groupBs.enabled(GroupPermission.share) &&
|
|
display.orCapability.enabled(NavigatorCapability.share);
|
|
display.showCreateArchive =
|
|
display.hasReadable &&
|
|
!!currentUser &&
|
|
groupBs.enabled(GroupPermission.archive_task) &&
|
|
display.orCapability &&
|
|
display.orCapability.enabled(NavigatorCapability.download_file);
|
|
|
|
// Reset thumbnail is available when at least one file is selected and
|
|
// current capability allows generating thumbnails
|
|
// Show only when at least one selected file has a supported extension,
|
|
// based on cached supported thumbnail extensions.
|
|
const cache = getCachedThumbExts();
|
|
const anySupported =
|
|
cache instanceof Set
|
|
? targets.some((f) => f.type == FileType.file && cache.has((fileExtension(f.name) || "").toLowerCase()))
|
|
: false;
|
|
display.showResetThumb = display.hasFile && anySupported;
|
|
|
|
display.showMore =
|
|
display.showVersionControl ||
|
|
display.showManageShares ||
|
|
display.showCreateArchive ||
|
|
display.showDirectLinkManagement ||
|
|
display.showResetThumb;
|
|
return display;
|
|
};
|
|
|
|
const useActionDisplayOpt = (targets: FileResponse[], type?: string, parent?: FileResponse, fmIndex: number = 0) => {
|
|
const opt = useMemo(() => {
|
|
return getActionOpt(targets, Viewers, type, parent, fmIndex);
|
|
}, [targets, type, parent, fmIndex]);
|
|
|
|
return opt;
|
|
};
|
|
|
|
export default useActionDisplayOpt;
|