diff --git a/src/app/theme.ts b/src/app/theme.ts index ec650a6a0..f644ee78c 100644 --- a/src/app/theme.ts +++ b/src/app/theme.ts @@ -148,6 +148,13 @@ const theme: HopeThemeConfig = { _active: { transform: "scale(.95)", transition: "0.1s" }, }, }, + Modal: { + baseStyle: { + content: { + rounded: "$lg", + }, + }, + }, }, }; diff --git a/src/components/FolderTree.tsx b/src/components/FolderTree.tsx index 0b9b272fb..a09233d98 100644 --- a/src/components/FolderTree.tsx +++ b/src/components/FolderTree.tsx @@ -155,15 +155,15 @@ export const ModalFolderChoose = (props: ModalFolderChooseProps) => { + + {t("global.cancel")} + props.onSubmit?.(value())} > {t("global.ok")} - - {t("global.cancel")} - diff --git a/src/components/ModalInput.tsx b/src/components/ModalInput.tsx index df408b246..ff224ba2e 100644 --- a/src/components/ModalInput.tsx +++ b/src/components/ModalInput.tsx @@ -43,15 +43,15 @@ export const ModalInput = (props: ModalInputProps) => { /> + + {t("global.cancel")} + props.onSubmit?.(value())} > {t("global.ok")} - - {t("global.cancel")} - diff --git a/src/hooks/useFetch.ts b/src/hooks/useFetch.ts index eb4012f48..79f0abff4 100644 --- a/src/hooks/useFetch.ts +++ b/src/hooks/useFetch.ts @@ -1,17 +1,20 @@ import { Accessor, createSignal } from "solid-js"; import { Resp } from "~/types"; -export const useLoading = ( - p: (arg?: D) => Promise, +export const useLoading = ( + p: (...arg: any[]) => Promise, fetch?: boolean, t?: boolean // initial loading true -): [Accessor, (arg?: D) => Promise] => { +): [ + Accessor, + (...arg: any[]) => Promise +] => { const [loading, setLoading] = createSignal(t ?? false); return [ loading, - async (arg?: D) => { + async (...arg: any[]) => { setLoading(true); - const data = await p(arg); + const data = await p(...arg); if (!fetch || (data as unknown as Resp<{}>).code !== 401) { // why? // because if setLoading(false) here will rerender before navigate @@ -23,27 +26,27 @@ export const useLoading = ( ]; }; -export const useFetch = ( - p: (arg?: D) => Promise>, +export const useFetch = ( + p: (...arg: any[]) => Promise>, loading?: boolean ): [ Accessor, - (arg?: D) => Promise> + (...arg: Parameters) => Promise> ] => { return useLoading(p, true, loading); }; const useListLoading = ( - p: (key: K, arg?: D) => Promise, + p: (key: K, ...arg: any[]) => Promise, fetch?: boolean, initial?: K -): [Accessor, (key: K, arg?: D) => Promise] => { +): [Accessor, (key: K, ...arg: any[]) => Promise] => { const [loading, setLoading] = createSignal(initial); return [ loading, - async (key: K, arg?: D) => { + async (key: K, ...arg: any[]) => { setLoading(() => key); - const data: unknown = await p(key, arg); + const data: unknown = await p(key, ...arg); if (!fetch || (data as Resp<{}>).code !== 401) { setLoading(undefined); } @@ -53,8 +56,8 @@ const useListLoading = ( }; export const useListFetch = ( - p: (key: K, arg?: D) => Promise>, + p: (key: K, ...arg: any[]) => Promise>, initial?: K -): [Accessor, (key: K, arg?: D) => Promise] => { +): [Accessor, (key: K, ...arg: any[]) => Promise] => { return useListLoading(p, true, initial); }; diff --git a/src/hooks/usePath.ts b/src/hooks/usePath.ts index 3d0793d35..277a67ea1 100644 --- a/src/hooks/usePath.ts +++ b/src/hooks/usePath.ts @@ -20,7 +20,7 @@ const IsDirRecord: Record = {}; export const usePath = () => { const { pathname, setSearchParams } = useRouter(); - const [, getObj] = useFetch((path?: string) => fsGet(path, password())); + const [, getObj] = useFetch((path: string) => fsGet(path, password())); const [, getObjs] = useFetch( (arg?: { path: string; index?: number; size?: number }) => { const page = { @@ -93,7 +93,7 @@ export const usePath = () => { if (append) { appendObjs(data.content); } else { - ObjStore.setObjs(data.content); + ObjStore.setObjs(data.content ?? []); } ObjStore.setReadme(data.readme); ObjStore.setWrite(data.write); diff --git a/src/lang/en/home.json b/src/lang/en/home.json index ab3560029..8b75e05d3 100644 --- a/src/lang/en/home.json +++ b/src/lang/en/home.json @@ -21,11 +21,12 @@ "toggle_checkbox": "Toggle Checkbox", "rename": "Rename", "input_new_name": "Input new name", - "only_one_tip": "Only one object can be selected to rename", + "only_one_tips": "Only one object can be selected to rename", "move": "Move", "copy": "Copy", "choose_dst_folder": "Select destination folder", "delete": "Delete", + "delete_tips": "Are you sure to delete the selected object?", "copy_url": "Copy URL", "preview_page": "Preview Page", "down_url": "Download URL", diff --git a/src/pages/home/toolbar/CopyMove.tsx b/src/pages/home/toolbar/CopyMove.tsx index eb7f9c304..5ad2421a4 100644 --- a/src/pages/home/toolbar/CopyMove.tsx +++ b/src/pages/home/toolbar/CopyMove.tsx @@ -2,24 +2,68 @@ import { createDisclosure } from "@hope-ui/solid"; import { OcFilemoved2 } from "solid-icons/oc"; import { TbCopy } from "solid-icons/tb"; import { ModalFolderChoose } from "~/components"; +import { useFetch, usePath, useRouter } from "~/hooks"; +import { selectedObjs } from "~/store"; +import { + fsCopy, + fsMove, + handleRresp, + handleRrespWithNotifySuccess, +} from "~/utils"; import { CenterIcon } from "./Icon"; export const Copy = () => { const { isOpen, onOpen, onClose } = createDisclosure(); + const [loading, ok] = useFetch(fsCopy); + const { pathname } = useRouter(); + const { refresh } = usePath(); return ( <> - + { + const resp = await ok( + pathname(), + dst, + selectedObjs().map((obj) => obj.name) + ); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} + /> > ); }; export const Move = () => { const { isOpen, onOpen, onClose } = createDisclosure(); + const [loading, ok] = useFetch(fsMove); + const { pathname } = useRouter(); + const { refresh } = usePath(); return ( <> - + { + const resp = await ok( + pathname(), + dst, + selectedObjs().map((obj) => obj.name) + ); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} + /> > // // diff --git a/src/pages/home/toolbar/CopyURL.tsx b/src/pages/home/toolbar/CopyURL.tsx index cde42a950..f4e8fbacc 100644 --- a/src/pages/home/toolbar/CopyURL.tsx +++ b/src/pages/home/toolbar/CopyURL.tsx @@ -7,13 +7,15 @@ export const CopyURL = () => { const t = useT(); const { previewPage, rawUrl } = useSelectedUrl(); const { copy } = useUtil(); + const colorScheme = "neutral"; return ( - + { copy(previewPage()); }} @@ -21,6 +23,7 @@ export const CopyURL = () => { {t("home.toolbar.preview_page")} { copy(rawUrl()); }} @@ -28,6 +31,7 @@ export const CopyURL = () => { {t("home.toolbar.down_url")} { copy(rawUrl(true)); }} diff --git a/src/pages/home/toolbar/Delete.tsx b/src/pages/home/toolbar/Delete.tsx index 325a3c5e1..47e779ef2 100644 --- a/src/pages/home/toolbar/Delete.tsx +++ b/src/pages/home/toolbar/Delete.tsx @@ -1,6 +1,65 @@ -import { RiSystemDeleteBinLine } from "solid-icons/ri"; +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalBody, + ModalFooter, + Button, + createDisclosure, +} from "@hope-ui/solid"; +import { AiOutlineDelete } from "solid-icons/ai"; +import { useFetch, usePath, useRouter, useT } from "~/hooks"; +import { selectedObjs } from "~/store"; +import { fsRemove, handleRrespWithNotifySuccess } from "~/utils"; import { CenterIcon } from "./Icon"; export const Delete = () => { - return ; -}; \ No newline at end of file + const t = useT(); + const { isOpen, onOpen, onClose } = createDisclosure(); + const [loading, ok] = useFetch(fsRemove); + const { refresh } = usePath(); + const { pathname } = useRouter(); + return ( + <> + + + + + {t("home.toolbar.delete")} + + {t("home.toolbar.delete_tips")} + + + + {t("global.cancel")} + + { + const resp = await ok( + pathname(), + selectedObjs().map((obj) => obj.name) + ); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} + > + {t("global.confirm")} + + + + + > + ); +}; diff --git a/src/pages/home/toolbar/Mkdir.tsx b/src/pages/home/toolbar/Mkdir.tsx index c9852d962..38836f07f 100644 --- a/src/pages/home/toolbar/Mkdir.tsx +++ b/src/pages/home/toolbar/Mkdir.tsx @@ -2,9 +2,14 @@ import { RightIcon } from "./Icon"; import { CgFolderAdd } from "solid-icons/cg"; import { createDisclosure } from "@hope-ui/solid"; import { ModalInput } from "~/components"; +import { useFetch, usePath, useRouter } from "~/hooks"; +import { fsMkdir, handleRrespWithNotifySuccess, pathJoin } from "~/utils"; export const Mkdir = () => { const { isOpen, onOpen, onClose } = createDisclosure(); + const [loading, ok] = useFetch(fsMkdir); + const { pathname } = useRouter(); + const { refresh } = usePath(); return ( <> @@ -12,6 +17,14 @@ export const Mkdir = () => { title="home.toolbar.input_dir_name" opened={isOpen()} onClose={onClose} + loading={loading()} + onSubmit={async (name) => { + const resp = await ok(pathJoin(pathname(), name)); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} /> > ); diff --git a/src/pages/home/toolbar/NewFile.tsx b/src/pages/home/toolbar/NewFile.tsx index ecabc5d4f..5878ca0d7 100644 --- a/src/pages/home/toolbar/NewFile.tsx +++ b/src/pages/home/toolbar/NewFile.tsx @@ -1,10 +1,15 @@ import { createDisclosure } from "@hope-ui/solid"; import { CgFileAdd } from "solid-icons/cg"; import { ModalInput } from "~/components"; +import { useFetch, usePath, useRouter } from "~/hooks"; +import { fsNewFile, handleRrespWithNotifySuccess, pathJoin } from "~/utils"; import { RightIcon } from "./Icon"; export const NewFile = () => { const { isOpen, onOpen, onClose } = createDisclosure(); + const [loading, ok] = useFetch(fsNewFile); + const { refresh } = usePath(); + const { pathname } = useRouter(); return ( <> @@ -12,6 +17,14 @@ export const NewFile = () => { title="home.toolbar.input_filename" opened={isOpen()} onClose={onClose} + loading={loading()} + onSubmit={async (name) => { + const resp = await ok(pathJoin(pathname(), name)); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} /> > ); diff --git a/src/pages/home/toolbar/Rename.tsx b/src/pages/home/toolbar/Rename.tsx index a4ff10161..cf35eb4ea 100644 --- a/src/pages/home/toolbar/Rename.tsx +++ b/src/pages/home/toolbar/Rename.tsx @@ -1,14 +1,22 @@ import { createDisclosure } from "@hope-ui/solid"; import { CgRename } from "solid-icons/cg"; import { ModalInput } from "~/components"; -import { useT } from "~/hooks"; +import { useFetch, usePath, useRouter, useT } from "~/hooks"; import { oneChecked, selectedObjs } from "~/store"; -import { notify } from "~/utils"; +import { + fsRename, + handleRrespWithNotifySuccess, + notify, + pathJoin, +} from "~/utils"; import { CenterIcon } from "./Icon"; export const Rename = () => { const { isOpen, onOpen, onClose } = createDisclosure(); const t = useT(); + const [loading, ok] = useFetch(fsRename); + const { pathname } = useRouter(); + const { refresh } = usePath(); return ( <> { as={CgRename} onClick={() => { if (!oneChecked()) { - notify.warning(t("home.toolbar.only_one_tip")); + notify.warning(t("home.toolbar.only_one_tips")); return; } onOpen(); @@ -26,7 +34,18 @@ export const Rename = () => { title="home.toolbar.input_new_name" opened={isOpen()} onClose={onClose} - defaultValue={selectedObjs()[0].name} + defaultValue={selectedObjs()[0]?.name ?? ""} + loading={loading()} + onSubmit={async (name) => { + const resp = await ok( + pathJoin(pathname(), selectedObjs()[0].name), + name + ); + handleRrespWithNotifySuccess(resp, () => { + refresh(); + onClose(); + }); + }} /> > ); diff --git a/src/pages/test/index.tsx b/src/pages/test/index.tsx index 8d486dced..8c9120149 100644 --- a/src/pages/test/index.tsx +++ b/src/pages/test/index.tsx @@ -1,6 +1,11 @@ import { Box, Button, Grid, Heading, Input } from "@hope-ui/solid"; import { useI18n } from "@solid-primitives/i18n"; +const receiveFunc = (func: Function)=>{ + +} + + const Index = () => { const [t] = useI18n(); return ( diff --git a/src/utils/api.ts b/src/utils/api.ts index e9e256679..51b613b33 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -60,7 +60,13 @@ export const fsRemove = (dir: string, names: string[]): EmptyRespPromise => { return r.post("/fs/remove", { dir, names }); }; -export const fsPut = () => {}; +export const fsNewFile = (path: string): EmptyRespPromise => { + return r.put("/fs/put", undefined, { + headers: { + "File-Path": path, + }, + }); +}; export const addAria2 = (path: string, urls: string[]) => { return r.post("/fs/add_aria2", { path, urls }); diff --git a/src/utils/notify.tsx b/src/utils/notify.tsx index c3838f69d..f521a2f60 100644 --- a/src/utils/notify.tsx +++ b/src/utils/notify.tsx @@ -9,7 +9,7 @@ import { notificationService, } from "@hope-ui/solid"; import { JSXElement } from "solid-js"; -import { alphaBgColor } from "."; +import { alphaBgColor, firstUpperCase } from "."; const notify = { render: (element: JSXElement) => { @@ -41,7 +41,7 @@ const notify = { success: (message: string) => { notificationService.show({ status: "success", - title: message, + title: firstUpperCase(message), // render: (props) => ( // // @@ -54,7 +54,7 @@ const notify = { error: (message: string) => { notificationService.show({ status: "danger", - title: message, + title: firstUpperCase(message), // render: (props) => ( // // @@ -67,7 +67,7 @@ const notify = { info: (message: string) => { notificationService.show({ status: "info", - title: message, + title: firstUpperCase(message), // render: (props) => ( // // @@ -80,7 +80,7 @@ const notify = { warning: (message: string) => { notificationService.show({ status: "warning", - title: message, + title: firstUpperCase(message), // render: (props) => ( // // diff --git a/src/utils/str.ts b/src/utils/str.ts index 80baadfa2..96e2d148f 100644 --- a/src/utils/str.ts +++ b/src/utils/str.ts @@ -1,4 +1,7 @@ export const firstUpperCase = (str: string) => { + if (str.length === 0) { + return ""; + } return str.charAt(0).toUpperCase() + str.slice(1); };
{t("home.toolbar.delete_tips")}