Skip to content

Commit

Permalink
feat: toolbar operations
Browse files Browse the repository at this point in the history
  • Loading branch information
xhofe committed Aug 19, 2022
1 parent abf9174 commit 7093356
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 39 deletions.
7 changes: 7 additions & 0 deletions src/app/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ const theme: HopeThemeConfig = {
_active: { transform: "scale(.95)", transition: "0.1s" },
},
},
Modal: {
baseStyle: {
content: {
rounded: "$lg",
},
},
},
},
};

Expand Down
6 changes: 3 additions & 3 deletions src/components/FolderTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ export const ModalFolderChoose = (props: ModalFolderChooseProps) => {
<FolderTree onChange={setValue} />
</ModalBody>
<ModalFooter display="flex" gap="$2">
<Button onClick={props.onClose} colorScheme="neutral">
{t("global.cancel")}
</Button>
<Button
loading={props.loading}
onClick={() => props.onSubmit?.(value())}
>
{t("global.ok")}
</Button>
<Button onClick={props.onClose} colorScheme="neutral">
{t("global.cancel")}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
Expand Down
6 changes: 3 additions & 3 deletions src/components/ModalInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ export const ModalInput = (props: ModalInputProps) => {
/>
</ModalBody>
<ModalFooter display="flex" gap="$2">
<Button onClick={props.onClose} colorScheme="neutral">
{t("global.cancel")}
</Button>
<Button
loading={props.loading}
onClick={() => props.onSubmit?.(value())}
>
{t("global.ok")}
</Button>
<Button onClick={props.onClose} colorScheme="neutral">
{t("global.cancel")}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
Expand Down
31 changes: 17 additions & 14 deletions src/hooks/useFetch.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { Accessor, createSignal } from "solid-js";
import { Resp } from "~/types";

export const useLoading = <T, D>(
p: (arg?: D) => Promise<T>,
export const useLoading = <T>(
p: (...arg: any[]) => Promise<T>,
fetch?: boolean,
t?: boolean // initial loading true
): [Accessor<boolean>, (arg?: D) => Promise<unknown extends T ? any : T>] => {
): [
Accessor<boolean>,
(...arg: any[]) => Promise<unknown extends T ? any : T>
] => {
const [loading, setLoading] = createSignal<boolean>(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
Expand All @@ -23,27 +26,27 @@ export const useLoading = <T, D>(
];
};

export const useFetch = <T, D>(
p: (arg?: D) => Promise<Resp<T>>,
export const useFetch = <T>(
p: (...arg: any[]) => Promise<Resp<T>>,
loading?: boolean
): [
Accessor<boolean>,
(arg?: D) => Promise<Resp<unknown extends T ? any : T>>
(...arg: Parameters<typeof p>) => Promise<Resp<unknown extends T ? any : T>>
] => {
return useLoading(p, true, loading);
};

const useListLoading = <T, K, D>(
p: (key: K, arg?: D) => Promise<T>,
p: (key: K, ...arg: any[]) => Promise<T>,
fetch?: boolean,
initial?: K
): [Accessor<K | undefined>, (key: K, arg?: D) => Promise<any>] => {
): [Accessor<K | undefined>, (key: K, ...arg: any[]) => Promise<any>] => {
const [loading, setLoading] = createSignal<K | undefined>(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);
}
Expand All @@ -53,8 +56,8 @@ const useListLoading = <T, K, D>(
};

export const useListFetch = <T, K, D>(
p: (key: K, arg?: D) => Promise<Resp<T>>,
p: (key: K, ...arg: any[]) => Promise<Resp<T>>,
initial?: K
): [Accessor<K | undefined>, (key: K, arg?: D) => Promise<any>] => {
): [Accessor<K | undefined>, (key: K, ...arg: any[]) => Promise<any>] => {
return useListLoading(p, true, initial);
};
4 changes: 2 additions & 2 deletions src/hooks/usePath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const IsDirRecord: Record<string, boolean> = {};

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 = {
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/lang/en/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
48 changes: 46 additions & 2 deletions src/pages/home/toolbar/CopyMove.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
<CenterIcon tip="copy" as={TbCopy} onClick={onOpen} />
<ModalFolderChoose opened={isOpen()} onClose={onClose} />
<ModalFolderChoose
opened={isOpen()}
onClose={onClose}
loading={loading()}
onSubmit={async (dst) => {
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 (
<>
<CenterIcon tip="move" p="$1_5" as={OcFilemoved2} onClick={onOpen} />
<ModalFolderChoose opened={isOpen()} onClose={onClose} />
<ModalFolderChoose
opened={isOpen()}
onClose={onClose}
loading={loading()}
onSubmit={async (dst) => {
const resp = await ok(
pathname(),
dst,
selectedObjs().map((obj) => obj.name)
);
handleRrespWithNotifySuccess(resp, () => {
refresh();
onClose();
});
}}
/>
</>
// <CenterIcon tip="move" viewBox="0 0 1024 1024" fill="currentColor">
// <path d="M840.704 256h-36.992c-82.624 0-82.496-128-140.864-128H311.232C245.44 128 192 181.44 192 247.296V384h64V247.296C256 216.832 280.832 192 311.232 192h339.456c3.968 6.144 9.024 15.36 12.672 22.208C684.8 253.76 720.704 320 803.712 320h36.992C869.12 320 896 351.104 896 384v392.768c0 30.4-24.832 55.232-55.296 55.232H311.232c-30.4 0-55.232-24.832-55.232-55.232V704h-64v72.768C192 842.624 245.44 896 311.232 896H840.64C906.56 896 960 842.624 960 776.768V384c0-65.856-53.44-128-119.296-128z"></path>
Expand Down
6 changes: 5 additions & 1 deletion src/pages/home/toolbar/CopyURL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ export const CopyURL = () => {
const t = useT();
const { previewPage, rawUrl } = useSelectedUrl();
const { copy } = useUtil();
const colorScheme = "neutral";
return (
<Menu>
<Menu placement="top" offset={10}>
<MenuTrigger as="span">
<CenterIcon tip="copy_url" as={TbCopy} />
</MenuTrigger>
<MenuContent>
<MenuItem
colorScheme={colorScheme}
onSelect={() => {
copy(previewPage());
}}
>
{t("home.toolbar.preview_page")}
</MenuItem>
<MenuItem
colorScheme={colorScheme}
onSelect={() => {
copy(rawUrl());
}}
>
{t("home.toolbar.down_url")}
</MenuItem>
<MenuItem
colorScheme={colorScheme}
onSelect={() => {
copy(rawUrl(true));
}}
Expand Down
65 changes: 62 additions & 3 deletions src/pages/home/toolbar/Delete.tsx
Original file line number Diff line number Diff line change
@@ -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 <CenterIcon tip="delete" as={RiSystemDeleteBinLine} />;
};
const t = useT();
const { isOpen, onOpen, onClose } = createDisclosure();
const [loading, ok] = useFetch(fsRemove);
const { refresh } = usePath();
const { pathname } = useRouter();
return (
<>
<CenterIcon tip="delete" as={AiOutlineDelete} onClick={onOpen} />
<Modal
opened={isOpen()}
onClose={onClose}
size={{
"@initial": "xs",
"@md": "md",
}}
>
<ModalOverlay />
<ModalContent>
<ModalHeader>{t("home.toolbar.delete")}</ModalHeader>
<ModalBody>
<p>{t("home.toolbar.delete_tips")}</p>
</ModalBody>
<ModalFooter display="flex" gap="$2">
<Button onClick={onClose} colorScheme="neutral">
{t("global.cancel")}
</Button>
<Button
colorScheme="danger"
loading={loading()}
onClick={async () => {
const resp = await ok(
pathname(),
selectedObjs().map((obj) => obj.name)
);
handleRrespWithNotifySuccess(resp, () => {
refresh();
onClose();
});
}}
>
{t("global.confirm")}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
};
13 changes: 13 additions & 0 deletions src/pages/home/toolbar/Mkdir.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@ 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 (
<>
<RightIcon as={CgFolderAdd} p="$1_5" tip="mkdir" onClick={onOpen} />
<ModalInput
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();
});
}}
/>
</>
);
Expand Down
13 changes: 13 additions & 0 deletions src/pages/home/toolbar/NewFile.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
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 (
<>
<RightIcon as={CgFileAdd} tip="new_file" onClick={onOpen} />
<ModalInput
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();
});
}}
/>
</>
);
Expand Down
Loading

0 comments on commit 7093356

Please sign in to comment.