diff --git a/src/components/file-view/fview.scss b/src/components/file-view/fview.scss index f55685f..1964101 100644 --- a/src/components/file-view/fview.scss +++ b/src/components/file-view/fview.scss @@ -1,50 +1,37 @@ .ka-fileview { width: 100%; display: flex; - margin: 1rem 0; - min-height: 300px; + align-items: center; flex-direction: column; - border-top: 1px solid var(--foreground); - border-bottom: 1px solid var(--foreground); + justify-content: center; - .title { + .action-row { width: 100%; display: flex; align-items: center; - flex-direction: row; - padding: 0.25rem 10px; - justify-content: space-between; - background-color: var(--nav-color); - border-bottom: 1px solid var(--foreground); - .name { + .link { display: flex; - width: fit-content; align-items: center; - b { - margin: 0 5px; + span { + margin: 0.2rem 0; } } + } - .action-row { - display: flex; - width: fit-content; - align-items: center; - justify-content: center; + #icon { + margin: 3.5rem 0; + } - .btn { - padding: 0; + #download { + margin: 1rem 0; + + a { + margin: 0 5px; + span { margin-left: 5px; } } } - - pre, code { - margin: 0; - width: 100%; - padding: 10px; - display: flex; - border-radius: 0 0 15px 15px; - } } \ No newline at end of file diff --git a/src/components/file-view/index.tsx b/src/components/file-view/index.tsx index b7e1a63..72005d2 100644 --- a/src/components/file-view/index.tsx +++ b/src/components/file-view/index.tsx @@ -1,68 +1,126 @@ -import { useEffect, useState } from "react"; -import { useRaw } from "../../store/raw"; import { useLocation } from "react-router"; -import { DynamicIcon } from "lucide-react/dynamic"; +import { useEffect, useState } from "react"; +import { convert } from "../../util/unit"; +import { usePath } from "../../store/path"; +import { DynamicIcon, IconName } from "lucide-react/dynamic"; import "./fview.scss"; function FileView() { - const raw = useRaw(); + const path = usePath(); const location = useLocation(); const [load, setLoad] = useState(false); + const [type, setType] = useState("file"); useEffect(() => { if (!load) { - raw.update(location.pathname.substring(1, location.pathname.length)); - setLoad(true); + path.update(location.pathname.substring(1, location.pathname.length)).then(() => { + setLoad(true); + + switch (true) { + case path.data?.path.endsWith(".zip"): + case path.data?.path.endsWith(".tar"): + case path.data?.path.endsWith(".tar.gz"): + case path.data?.path.endsWith(".tar.xz"): + case path.data?.path.endsWith(".7z"): + case path.data?.path.endsWith(".rar"): + setType("file-archive"); + break; + case path.data?.path.endsWith(".pdf"): + setType("file-pen-line"); + break; + case path.data?.path.endsWith(".doc"): + case path.data?.path.endsWith(".docx"): + setType("file-chart-pie"); + break; + case path.data?.path.endsWith(".xls"): + case path.data?.path.endsWith(".xlsx"): + setType("file-spreadsheet"); + break; + case path.data?.path.endsWith(".ppt"): + case path.data?.path.endsWith(".pptx"): + setType("file-sliders"); + break; + case path.data?.path.endsWith(".jpg"): + case path.data?.path.endsWith(".jpeg"): + case path.data?.path.endsWith(".png"): + case path.data?.path.endsWith(".gif"): + setType("file-image"); + break; + case path.data?.path.endsWith(".mp3"): + case path.data?.path.endsWith(".wav"): + setType("file-audio"); + break; + case path.data?.path.endsWith(".mp4"): + case path.data?.path.endsWith(".mkv"): + setType("file-video"); + break; + case path.data?.path.endsWith(".c"): + case path.data?.path.endsWith(".cpp"): + case path.data?.path.endsWith(".js"): + case path.data?.path.endsWith(".ts"): + case path.data?.path.endsWith(".jsx"): + case path.data?.path.endsWith(".tsx"): + case path.data?.path.endsWith(".py"): + case path.data?.path.endsWith(".java"): + case path.data?.path.endsWith(".rb"): + case path.data?.path.endsWith(".go"): + case path.data?.path.endsWith(".rs"): + case path.data?.path.endsWith(".php"): + case path.data?.path.endsWith(".html"): + case path.data?.path.endsWith(".css"): + case path.data?.path.endsWith(".scss"): + setType("file-code"); + break; + case path.data?.path.endsWith(".sh"): + case path.data?.path.endsWith(".bat"): + setType("file-terminal"); + break; + case path.data?.path.endsWith(".json"): + setType("file-json"); + break; + default: + setType("file"); + break; + } + }); return; } - }, [raw, location, load]); + }, [path, location, load]); + + if (typeof path.data === "undefined") + return <>; return (
- -
- - - - {decodeURIComponent(location.pathname)} -
-
- - - - { - ev.preventDefault(); - navigator.clipboard.writeText(`${document.location.origin}/api/raw${location.pathname}`) - .then(() => alert("url copied to clipboard")) - .catch(err => console.error("Failed to copy text: ", err)); - }}> - - - { - ev.preventDefault(); - fetch(`/api/download${location.pathname}`) - .then(response => response.blob()) - .then(blob => { - const url = window.URL.createObjectURL(blob); - const a = document.createElement("a"); +
+ { + ev.preventDefault(); + document.location.href = document.location.href.substring(0, document.location.href.lastIndexOf("/")); + }}> + + Back to directory + +
+ + {path.data.path} + {convert(path.data.total)} - a.style.display = "none"; - a.href = url; - a.download = location.pathname.split("/").pop() || "download"; - - document.body.appendChild(a); - a.click(); - - window.URL.revokeObjectURL(url); - }) - .catch(error => console.error("Download failed:", error)); - }}> - - -
-
-
{raw.data}
+
+ +
); } diff --git a/src/store/raw.ts b/src/store/raw.ts deleted file mode 100644 index 278dd6f..0000000 --- a/src/store/raw.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { create } from "zustand"; - -interface RawState { - data: string | undefined; - update(path: string): Promise; -} - -export const useRaw = create((set) => ({ - data: undefined, - update: async (path: string) => { - const res = await fetch(`/api/raw/${path}`, { - cache: "no-cache" - }); - if (res.status !== 200 && res.status !== 304) { - set({ data: undefined }); - return; - } - - const contentType = res.headers.get("Content-Type"); - if (contentType && contentType.includes("text")) { - const text = await res.text(); - set({ data: text }); - return; - } - - set({ data: "this file is not supported showing preview" }); - } -}));