From e010df8bc9c03684383aef3cb6e2765bf06e6d31 Mon Sep 17 00:00:00 2001 From: Xhofe Date: Tue, 5 Apr 2022 20:16:44 +0800 Subject: [PATCH 01/11] feat: global and meta readme --- src/pages/list/context.tsx | 4 ++- src/pages/list/layout/index.tsx | 49 ++++++++++++++++----------------- src/pages/manage/metas.tsx | 7 +++++ 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/pages/list/context.tsx b/src/pages/list/context.tsx index 9917adc..94b1b60 100644 --- a/src/pages/list/context.tsx +++ b/src/pages/list/context.tsx @@ -36,6 +36,7 @@ export interface Meta { driver: string; upload: boolean; total: number; + readme: string; } export interface PathResp { @@ -132,7 +133,7 @@ export const IContext = createContext({ selectFiles: [], setSelectFiles: () => {}, setType: () => {}, - meta: { driver: "", upload: false, total: 0 }, + meta: { driver: "", upload: false, total: 0, readme: "" }, setMeta: () => {}, loggedIn: false, page: { page_num: 1, page_size: 30 }, @@ -263,6 +264,7 @@ const IContextProvider = (props: any) => { driver: "", upload: false, total: 0, + readme: "", }); const [loggedIn, setLoggedIn] = React.useState(false); if (!settingLoaded) { diff --git a/src/pages/list/layout/index.tsx b/src/pages/list/layout/index.tsx index 2d55915..f8b84d0 100644 --- a/src/pages/list/layout/index.tsx +++ b/src/pages/list/layout/index.tsx @@ -1,14 +1,7 @@ -import React, { - lazy, - Suspense, - useContext, - useEffect, - useMemo, -} from "react"; +import React, { lazy, Suspense, useContext, useEffect, useMemo } from "react"; import { Box, useColorModeValue, - Spinner, Center, VStack, @@ -21,7 +14,7 @@ import Nav from "./nav"; import Error from "./error"; import Markdown from "../preview/markdown"; import Overlay from "../../../components/overlay"; -import { IContext,File as File_ } from "../context"; +import { IContext, File as File_ } from "../context"; const Files = lazy(() => import("./files")); const File = lazy(() => import("./file")); @@ -29,7 +22,7 @@ const File = lazy(() => import("./file")); const KuttyHero = () => { // console.log("KuttyHero"); const bgColor = useColorModeValue("white", "gray.700"); - + const { t } = useTranslation(); const { getSetting, @@ -39,30 +32,34 @@ const KuttyHero = () => { type, msg, files, + meta, } = useContext(IContext); const readme = useMemo(() => { if (type === "file") { return undefined; } + const readmeFile: File_ = { + name: "README.md", + size: 0, + type: -1, + driver: "local", + updated_at: "", + thumbnail: "", + url: meta.readme, + }; + if (meta.readme) { + return readmeFile; + } const file = files.find((file) => file.name.toLowerCase() === "readme.md"); - if ( - file === undefined && - location.pathname === "/" && - getSetting("home readme url") - ) { - const homeReadmeFile: File_ = { - name: "README.md", - size: 0, - type: -1, - driver: "local", - updated_at: "", - thumbnail: "", - url: getSetting("home readme url"), - }; - return homeReadmeFile; + if (file) { + return file; + } + if (getSetting("global readme url")) { + readmeFile.url = getSetting("global readme url"); + return readmeFile; } - return file; + return undefined; }, [files, type, settingLoaded]); return ( diff --git a/src/pages/manage/metas.tsx b/src/pages/manage/metas.tsx index ce6f7e8..01d1581 100644 --- a/src/pages/manage/metas.tsx +++ b/src/pages/manage/metas.tsx @@ -39,6 +39,7 @@ export interface Meta { hide: string; upload: boolean; only_shows: string; + readme: string; } const EmptyMeta = { @@ -48,6 +49,7 @@ const EmptyMeta = { hide: "", upload: false, only_shows: "", + readme: "", }; const Metas = () => { @@ -213,6 +215,11 @@ const Metas = () => { description: "Allow visitors to upload", type: "bool", }, + { + name: "readme", + description: "Readme url", + type: "string", + } ].map((item) => { return ( Date: Fri, 8 Apr 2022 19:57:35 +0800 Subject: [PATCH 02/11] feat: add search button --- src/pages/list/layout/header.tsx | 200 +++++++++++++++---------------- src/pages/list/layout/search.tsx | 88 ++++++++++++++ 2 files changed, 188 insertions(+), 100 deletions(-) create mode 100644 src/pages/list/layout/search.tsx diff --git a/src/pages/list/layout/header.tsx b/src/pages/list/layout/header.tsx index de55872..67f9c17 100644 --- a/src/pages/list/layout/header.tsx +++ b/src/pages/list/layout/header.tsx @@ -9,8 +9,9 @@ import { Tooltip, useColorModeValue, Box, + SlideFade, } from "@chakra-ui/react"; -import React, { useContext, useRef } from "react"; +import React, { useContext, useRef, useState } from "react"; import { IContext } from "../context"; import { FaListUl } from "react-icons/fa"; // import { AiTwotoneCopy } from "react-icons/ai"; @@ -25,6 +26,7 @@ import { Link, useLocation } from "react-router-dom"; import { copyToClip } from "../../../utils/copy-clip"; import useFileUrl from "../../../hooks/useFileUrl"; import Uploader, { UploaderHandle } from "./uploader"; +import Search from "./search"; const Header = () => { const { t } = useTranslation(); @@ -46,16 +48,14 @@ const Header = () => { logos.split(",").shift(), logos.split(",").pop() ) as string; - const { pathname } = useLocation(); const uploadRef = useRef(null); + const [isSearch, setIsSearch] = useState(false); return ( {logo.includes("http") ? ( - } + fallback={} rounded="lg" h="44px" w="auto" @@ -66,113 +66,113 @@ const Header = () => { )} - {type === "file" && ( - - { - if (type === "file") { - let url = fileUrl(); - window.open(url, "_blank"); - return; - } - // if (multiSelect) { - // downPack(selectFiles); - // return; - // } - // if (type === "folder") { - // downPack(files); - // return; - // } - }} - /> - - )} - {type === "folder" && - !getSetting("no upload").split(",").includes(meta.driver) && - (meta.upload || loggedIn) && ( - + {type === "folder" && } + {!isSearch&& + + {type === "file" && ( { - uploadRef.current!.upload(); + if (type === "file") { + let url = fileUrl(); + window.open(url, "_blank"); + return; + } }} /> - - - )} - {type !== "error" && ( - - { - let content = ""; - if (type === "file") { - content = fileUrl(); - } else { - let files_ = files; - if (multiSelect) { - files_ = selectFiles; - } - content = files_ - .filter((file) => file.type !== 1) - .map((file) => { - return fileUrl(file); - }) - .join("\n"); - } - copyToClip(content); - toast({ - title: t("Copied"), - status: "success", - duration: 3000, - isClosable: true, - }); - }} - /> - - )} - - { - setShow!(show === "list" ? "grid" : "list"); - localStorage.setItem("show", show === "list" ? "grid" : "list"); - }} - as={show === "list" ? BsFillGridFill : FaListUl} - /> - + )} + {type === "folder" && + !getSetting("no upload").split(",").includes(meta.driver) && + (meta.upload || loggedIn) && ( + + + { + uploadRef.current!.upload(); + }} + /> + + + + )} + {type !== "error" && ( + + { + let content = ""; + if (type === "file") { + content = fileUrl(); + } else { + let files_ = files; + if (multiSelect) { + files_ = selectFiles; + } + content = files_ + .filter((file) => file.type !== 1) + .map((file) => { + return fileUrl(file); + }) + .join("\n"); + } + copyToClip(content); + toast({ + title: t("Copied"), + status: "success", + duration: 3000, + isClosable: true, + }); + }} + /> + + )} + + { + setShow!(show === "list" ? "grid" : "list"); + localStorage.setItem( + "show", + show === "list" ? "grid" : "list" + ); + }} + as={show === "list" ? BsFillGridFill : FaListUl} + /> + + + } ); diff --git a/src/pages/list/layout/search.tsx b/src/pages/list/layout/search.tsx new file mode 100644 index 0000000..135bd47 --- /dev/null +++ b/src/pages/list/layout/search.tsx @@ -0,0 +1,88 @@ +import { Box, HStack, Icon, Input, Tooltip } from "@chakra-ui/react"; +import React, { useContext, useEffect, useRef, useState } from "react"; +import { IContext } from "../context"; +import { FcSearch } from "react-icons/fc"; +import { useTranslation } from "react-i18next"; +import { useHistory } from "react-router-dom"; + +interface SearchProps { + isSearch: boolean; + setIsSearch: (isSearch: boolean) => void; +} + +const Search = (props: SearchProps) => { + const inputRef = useRef(null); + const { t } = useTranslation(); + const { getSetting } = useContext(IContext); + const [keyword, setKeyword] = useState(""); + const search = () => { + // console.log(keyword); + history.push(`?search=${keyword}`); + }; + const history = useHistory(); + // if (!getSetting("search")) return null; + useEffect(() => { + if (props.isSearch) { + inputRef.current?.focus(); + } + const switchSearch = (e: KeyboardEvent) => { + if (["f", "F"].includes(e.key) && e.ctrlKey) { + props.setIsSearch(!props.isSearch); + e.preventDefault(); + } + }; + document.addEventListener("keydown", switchSearch); + const cancelSearch = (e: MouseEvent) => { + props.setIsSearch(false); + }; + document.addEventListener("click", cancelSearch); + return () => { + document.removeEventListener("keydown", switchSearch); + document.removeEventListener("click", cancelSearch); + }; + }, [props.isSearch]); + return ( + { + e.stopPropagation(); + }} + > + { + if (e.key === "Enter") { + search(); + } + }} + onChange={(e) => { + setKeyword(e.target.value); + }} + ref={inputRef} + /> + + + { + if (!props.isSearch) { + props.setIsSearch(true); + } else { + search(); + } + }} + as={FcSearch} + /> + + + ); +}; + +export default Search; From 13d7b5fc8eff9c23ea29f0481bbe8777ed7e93ec Mon Sep 17 00:00:00 2001 From: Xhofe Date: Fri, 8 Apr 2022 20:11:27 +0800 Subject: [PATCH 03/11] feat: add search route --- src/pages/list/context.tsx | 3 +- src/pages/list/index.tsx | 17 ++- src/pages/list/layout/header.tsx | 194 ++++++++++++------------ src/pages/list/layout/index.tsx | 3 + src/pages/list/layout/results/index.tsx | 11 ++ 5 files changed, 131 insertions(+), 97 deletions(-) create mode 100644 src/pages/list/layout/results/index.tsx diff --git a/src/pages/list/context.tsx b/src/pages/list/context.tsx index 94b1b60..94156ba 100644 --- a/src/pages/list/context.tsx +++ b/src/pages/list/context.tsx @@ -69,7 +69,8 @@ type TypeType = | "error" | "loading" | "unauthorized" - | "nexting"; + | "nexting" + | "search"; interface Sort { orderBy?: "name" | "updated_at" | "size"; diff --git a/src/pages/list/index.tsx b/src/pages/list/index.tsx index efd7de7..f4b21dc 100644 --- a/src/pages/list/index.tsx +++ b/src/pages/list/index.tsx @@ -47,11 +47,14 @@ const Do = (props: any) => { const history = useHistory(); const location = useLocation(); const toast = useToast(); - const { path,cancelPath } = useApi(); + const { path, cancelPath } = useApi(); const refresh = useSyncCallback(() => { if (!settingLoaded) { return; } + if (switchToSearch()) { + return; + } cancelPath(); console.log("refresh"); console.log(page); @@ -159,6 +162,18 @@ const Do = (props: any) => { useChangeEffect(() => { nextPage(); }, [page]); + const switchToSearch = () => { + const query = new URLSearchParams(location.search); + const search = query.get("search"); + if (search) { + setType("search"); + return true; + } + return false; + }; + useEffect(() => { + switchToSearch(); + }, [location.search]); const { isOpen, onClose, onOpen } = useDisclosure(); const initialRef = React.useRef(); useEffect(() => { diff --git a/src/pages/list/layout/header.tsx b/src/pages/list/layout/header.tsx index 67f9c17..7791570 100644 --- a/src/pages/list/layout/header.tsx +++ b/src/pages/list/layout/header.tsx @@ -66,113 +66,117 @@ const Header = () => { )} - {type === "folder" && } - {!isSearch&& - - {type === "file" && ( - - { - if (type === "file") { - let url = fileUrl(); - window.open(url, "_blank"); - return; - } - }} - /> - - )} - {type === "folder" && - !getSetting("no upload").split(",").includes(meta.driver) && - (meta.upload || loggedIn) && ( - - - { - uploadRef.current!.upload(); - }} - /> - - - + {["folder", "search"].includes(type) && ( + + )} + {!isSearch && ( + + + {type === "file" && ( + + { + if (type === "file") { + let url = fileUrl(); + window.open(url, "_blank"); + return; + } + }} + /> + + )} + {type === "folder" && + !getSetting("no upload").split(",").includes(meta.driver) && + (meta.upload || loggedIn) && ( + + + { + uploadRef.current!.upload(); + }} + /> + + + + )} + {type !== "error" && ( + + { + let content = ""; + if (type === "file") { + content = fileUrl(); + } else { + let files_ = files; + if (multiSelect) { + files_ = selectFiles; + } + content = files_ + .filter((file) => file.type !== 1) + .map((file) => { + return fileUrl(file); + }) + .join("\n"); + } + copyToClip(content); + toast({ + title: t("Copied"), + status: "success", + duration: 3000, + isClosable: true, + }); + }} + /> + )} - {type !== "error" && ( { - let content = ""; - if (type === "file") { - content = fileUrl(); - } else { - let files_ = files; - if (multiSelect) { - files_ = selectFiles; - } - content = files_ - .filter((file) => file.type !== 1) - .map((file) => { - return fileUrl(file); - }) - .join("\n"); - } - copyToClip(content); - toast({ - title: t("Copied"), - status: "success", - duration: 3000, - isClosable: true, - }); + setShow!(show === "list" ? "grid" : "list"); + localStorage.setItem( + "show", + show === "list" ? "grid" : "list" + ); }} + as={show === "list" ? BsFillGridFill : FaListUl} /> - )} - - { - setShow!(show === "list" ? "grid" : "list"); - localStorage.setItem( - "show", - show === "list" ? "grid" : "list" - ); - }} - as={show === "list" ? BsFillGridFill : FaListUl} - /> - - - } + + + )} ); diff --git a/src/pages/list/layout/index.tsx b/src/pages/list/layout/index.tsx index f8b84d0..a7cf03f 100644 --- a/src/pages/list/layout/index.tsx +++ b/src/pages/list/layout/index.tsx @@ -15,6 +15,7 @@ import Error from "./error"; import Markdown from "../preview/markdown"; import Overlay from "../../../components/overlay"; import { IContext, File as File_ } from "../context"; +import Results from "./results"; const Files = lazy(() => import("./files")); const File = lazy(() => import("./file")); @@ -98,6 +99,8 @@ const KuttyHero = () => { ) : type === "file" ? ( + ) : type === "search" ? ( + ) : ( )} diff --git a/src/pages/list/layout/results/index.tsx b/src/pages/list/layout/results/index.tsx new file mode 100644 index 0000000..3646d77 --- /dev/null +++ b/src/pages/list/layout/results/index.tsx @@ -0,0 +1,11 @@ +import React from "react"; + +const Results = ()=>{ + return ( +
+

Results

+
+ ) +} + +export default Results; \ No newline at end of file From b42f0b4075fc3e8fa1a0baa773b17cb2711e07ed Mon Sep 17 00:00:00 2001 From: Xhofe Date: Fri, 8 Apr 2022 20:31:58 +0800 Subject: [PATCH 04/11] fix: readme display --- src/pages/list/layout/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/list/layout/index.tsx b/src/pages/list/layout/index.tsx index a7cf03f..022ffb5 100644 --- a/src/pages/list/layout/index.tsx +++ b/src/pages/list/layout/index.tsx @@ -108,7 +108,7 @@ const KuttyHero = () => { )} - {type !== "loading" && readme && ( + {type === "folder" && readme && ( Date: Fri, 8 Apr 2022 20:32:20 +0800 Subject: [PATCH 05/11] fix: switch to folder --- src/pages/list/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/list/index.tsx b/src/pages/list/index.tsx index f4b21dc..cf452ec 100644 --- a/src/pages/list/index.tsx +++ b/src/pages/list/index.tsx @@ -172,7 +172,9 @@ const Do = (props: any) => { return false; }; useEffect(() => { - switchToSearch(); + if(!switchToSearch()){ + allRefresh(); + } }, [location.search]); const { isOpen, onClose, onOpen } = useDisclosure(); const initialRef = React.useRef(); From 498e06ac423d13c4c7ac59d7c289da27a15d3008 Mon Sep 17 00:00:00 2001 From: Xhofe Date: Fri, 8 Apr 2022 22:47:29 +0800 Subject: [PATCH 06/11] feat: search results --- src/pages/list/layout/results/index.tsx | 112 +++++++++++++++++++++-- src/pages/list/layout/results/result.tsx | 80 ++++++++++++++++ 2 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 src/pages/list/layout/results/result.tsx diff --git a/src/pages/list/layout/results/index.tsx b/src/pages/list/layout/results/index.tsx index 3646d77..5b66459 100644 --- a/src/pages/list/layout/results/index.tsx +++ b/src/pages/list/layout/results/index.tsx @@ -1,11 +1,107 @@ -import React from "react"; +import { + Center, + Flex, + HStack, + Spinner, + VStack, + Text, + useToast, +} from "@chakra-ui/react"; +import React, { useContext, useEffect, useState } from "react"; +import { useLocation } from "react-router-dom"; +import { IContext, Resp } from "../../context"; +import request from "~/utils/public"; +import { useTranslation } from "react-i18next"; +import Result from "./result"; -const Results = ()=>{ - return ( -
-

Results

-
- ) +export interface Result { + path: string; + name: string; + size: number; + type: number; } -export default Results; \ No newline at end of file +const Results = () => { + const location = useLocation(); + const [loading, setLoading] = useState(true); + const { getSetting } = useContext(IContext); + const toast = useToast(); + const [results, setResults] = useState([]); + const search = () => { + const searchParams = new URLSearchParams(location.search); + const path = location.pathname; + const keyword = searchParams.get("search"); + setLoading(true); + request + .post("search", { + path, + keyword, + }) + .then((resp) => { + setLoading(false); + const res: Resp = resp.data; + if (res.code === 200) { + setResults(res.data); + } else { + toast({ + title: res.message, + status: "error", + duration: 3000, + isClosable: true, + }); + } + }); + }; + useEffect(() => { + search(); + }, [location.search]); + const { t } = useTranslation(); + if (loading) { + return ( +
+ +
+ ); + } + return ( + + + {[ + { name: "name", base: 2 / 3, md: "50%", textAlign: "left" }, + { name: "size", base: 1 / 3, md: 1 / 6, textAlign: "right" }, + { name: "path", base: 0, md: 1 / 3, textAlign: "right" }, + ].map((item) => { + return ( + + + {t(item.name)} + + + ); + })} + + {results.map((result) => { + return ; + })} + + ); +}; + +export default Results; diff --git a/src/pages/list/layout/results/result.tsx b/src/pages/list/layout/results/result.tsx new file mode 100644 index 0000000..07de19c --- /dev/null +++ b/src/pages/list/layout/results/result.tsx @@ -0,0 +1,80 @@ +import { + Box, + Flex, + HStack, + Icon, + LinkBox, + LinkOverlay, + Text, + Tooltip, +} from "@chakra-ui/react"; +import React, { useContext } from "react"; +import { Link } from "react-router-dom"; +import { getFileSize, pathJoin } from "~/utils/file"; +import getIcon from "~/utils/icon"; +import { Result } from "."; +import { IContext } from "../../context"; + +const Result = (file: Result) => { + const { getSetting } = useContext(IContext); + + return ( + + + + + + + + + {file.name} + + + + {getFileSize(file.size)} + + + {file.path} + + + + + + + ); +}; + +export default Result; From befe71f7c151518798ceb406506076cbaa316c39 Mon Sep 17 00:00:00 2001 From: Xhofe Date: Tue, 12 Apr 2022 10:34:17 +0800 Subject: [PATCH 07/11] feat: add account loading --- src/pages/manage/accounts.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/manage/accounts.tsx b/src/pages/manage/accounts.tsx index 14b3895..7cbeb6d 100644 --- a/src/pages/manage/accounts.tsx +++ b/src/pages/manage/accounts.tsx @@ -172,6 +172,7 @@ const Accounts = () => { React.useState(EmptyAccount); const [isEdit, setIsEdit] = React.useState(false); const [loading, setLoading] = React.useState(false); + const [addAccountLoading, setAddAccountLoading] = React.useState(false); const editDisclosure = useDisclosure(); const initialDrivers = () => { admin.get("drivers").then((resp) => { @@ -464,11 +465,14 @@ const Accounts = () => { {t("Paste")}