diff --git a/src/components/FolderTree.tsx b/src/components/FolderTree.tsx index 4f8cdd386..ef1a31680 100644 --- a/src/components/FolderTree.tsx +++ b/src/components/FolderTree.tsx @@ -226,17 +226,27 @@ export const ModalFolderChoose = (props: ModalFolderChooseProps) => { autoOpen /> - - {props.footerSlot} - - + + + {props.footerSlot} + + + + + diff --git a/src/lang/en/home.json b/src/lang/en/home.json index caa04855d..0922f1251 100644 --- a/src/lang/en/home.json +++ b/src/lang/en/home.json @@ -215,6 +215,7 @@ "conflict_policy": { "cancel_if_exists": "Cancel if file exists", "overwrite_existing": "Overwrite existing files", - "skip_existing": "Skip existing files" + "skip_existing": "Skip existing files", + "merge": "Only Copy new files and subdirectories" } } diff --git a/src/pages/home/toolbar/CopyMove.tsx b/src/pages/home/toolbar/CopyMove.tsx index 4d10b3151..9f43a7a94 100644 --- a/src/pages/home/toolbar/CopyMove.tsx +++ b/src/pages/home/toolbar/CopyMove.tsx @@ -1,4 +1,4 @@ -import { Checkbox, createDisclosure } from "@hope-ui/solid" +import { Checkbox, createDisclosure, VStack } from "@hope-ui/solid" import { createSignal, onCleanup } from "solid-js" import { ModalFolderChoose } from "~/components" import { useFetch, usePath, useRouter, useT } from "~/hooks" @@ -12,6 +12,8 @@ export const Copy = () => { const { pathname } = useRouter() const { refresh } = usePath() const [overwrite, setOverwrite] = createSignal(false) + const [skipExisting, setSkipExisting] = createSignal(false) + const [merge, setMerge] = createSignal(false) const handler = (name: string) => { if (name === "copy") { onOpen() @@ -29,15 +31,42 @@ export const Copy = () => { onClose={onClose} loading={loading()} footerSlot={ - { - setOverwrite(!overwrite()) - }} - > - {t("home.conflict_policy.overwrite_existing")} - + + { + const curOverwrite = !overwrite() + if (curOverwrite) { + setSkipExisting(false) + setMerge(false) + } + setOverwrite(curOverwrite) + }} + > + {t("home.conflict_policy.overwrite_existing")} + + { + setSkipExisting(!skipExisting()) + }} + disabled={overwrite() || merge()} + > + {t("home.conflict_policy.skip_existing")} + + { + setMerge(!merge()) + }} + disabled={overwrite() || skipExisting()} + > + {t("home.conflict_policy.merge")} + + } onSubmit={async (dst) => { const resp = await ok( @@ -45,6 +74,8 @@ export const Copy = () => { dst, selectedObjs().map((obj) => obj.name), overwrite(), + skipExisting(), + merge(), ) handleRespWithNotifySuccess(resp, () => { refresh() @@ -62,6 +93,7 @@ export const Move = () => { const { pathname } = useRouter() const { refresh } = usePath() const [overwrite, setOverwrite] = createSignal(false) + const [skipExisting, setSkipExisting] = createSignal(false) const handler = (name: string) => { if (name === "move") { onOpen() @@ -79,15 +111,31 @@ export const Move = () => { onClose={onClose} loading={loading()} footerSlot={ - { - setOverwrite(!overwrite()) - }} - > - {t("home.conflict_policy.overwrite_existing")} - + + { + const curOverwrite = !overwrite() + if (curOverwrite) { + setSkipExisting(false) + } + setOverwrite(curOverwrite) + }} + > + {t("home.conflict_policy.overwrite_existing")} + + { + setSkipExisting(!skipExisting()) + }} + disabled={overwrite()} + > + {t("home.conflict_policy.skip_existing")} + + } onSubmit={async (dst) => { const resp = await ok( @@ -95,6 +143,7 @@ export const Move = () => { dst, selectedObjs().map((obj) => obj.name), overwrite(), + skipExisting(), ) handleRespWithNotifySuccess(resp, () => { refresh() diff --git a/src/pages/manage/tasks/Copy.tsx b/src/pages/manage/tasks/Copy.tsx index 04ca403ea..f5973d5d1 100644 --- a/src/pages/manage/tasks/Copy.tsx +++ b/src/pages/manage/tasks/Copy.tsx @@ -10,7 +10,8 @@ const Copy = () => { type="copy" canRetry nameAnalyzer={{ - regex: /^copy \[(.*\/([^\/]*))]\((.*\/([^\/]*))\) to \[(.+)]\((.+)\)$/, + regex: + /^(?:copy|merge) \[(.*\/([^\/]*))]\((.*\/([^\/]*))\) to \[(.+)]\((.+)\)$/, title: (matches) => { if (matches[4] !== "") return matches[4] return matches[2] === "" ? "/" : matches[2] diff --git a/src/utils/api.ts b/src/utils/api.ts index f22415076..e570dfda6 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -83,8 +83,15 @@ export const fsMove = ( dst_dir: string, names: string[], overwrite: boolean, + skip_existing: boolean, ): PEmptyResp => { - return r.post("/fs/move", { src_dir, dst_dir, names, overwrite }) + return r.post("/fs/move", { + src_dir, + dst_dir, + names, + overwrite, + skip_existing, + }) } export const fsRecursiveMove = ( @@ -100,8 +107,17 @@ export const fsCopy = ( dst_dir: string, names: string[], overwrite: boolean, + skip_existing: boolean, + merge: boolean, ): PEmptyResp => { - return r.post("/fs/copy", { src_dir, dst_dir, names, overwrite }) + return r.post("/fs/copy", { + src_dir, + dst_dir, + names, + overwrite, + skip_existing, + merge, + }) } export const fsRemove = (dir: string, names: string[]): PEmptyResp => {