feat: refine ui

This commit is contained in:
lyonbot committed 2025-01-21 19:07:15 +08:00
1 parent 187dc83f17
commit f5b966278c
6 files changed
+39 -32

No files matched your search

+8
View File
@@ -24,6 +24,9 @@ importers:
web:
dependencies:
dayjs:
specifier: ^1.11.13
version: 1.11.13
jotai:
specifier: ^2.11.0
version: 2.11.0(@types/react@19.0.2)(react@19.0.0)
@@ -1664,6 +1667,9 @@ packages:
date-fns@4.1.0:
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
dayjs@1.11.13:
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
@@ -4728,6 +4734,8 @@ snapshots:
date-fns@4.1.0: {}
dayjs@1.11.13: {}
debug@4.4.0:
dependencies:
ms: 2.1.3
+19 -13
View File
@@ -84,6 +84,15 @@ app.post("/api/upload", authWithPassword, async (c) => {
return c.json({ record });
});
app.get("/api/download/:slug/message", async (c) => {
const slug = c.req.param("slug");
const record = await getUploadRecordBySlug(c.env.DB, slug);
if (!record) return c.status(404);
return c.text(record.message);
})
const RE_ASSET_SUFFIX = /\.(jpg|png|gif|avif|mp4|mov|txt|html|js|css|json|ya?ml)/;
app.get("/api/download/:slug/:index", async (c) => {
const slug = c.req.param("slug");
const index = c.req.param("index");
@@ -92,17 +101,13 @@ app.get("/api/download/:slug/:index", async (c) => {
return c.status(404);
}
if (index === "message") {
return c.text(record.message);
}
const filePath = record.files[+index]?.path;
if (!filePath) {
return c.status(404);
}
const r = await c.env.MY_BUCKET.get(filePath, {
range: c.req.header("range"),
range: c.req.raw.headers
});
if (!r) {
@@ -112,16 +117,17 @@ app.get("/api/download/:slug/:index", async (c) => {
const basename = filePath.split("/").pop()!.replace(/\?.*/, "");
const headers = new Headers();
headers.set("accept-ranges", "bytes");
if (
!/\.(jpg|png|gif|avif|mp4|mov|txt|html|js|css|json|ya?ml)/.test(basename)
) {
headers.set("content-disposition", `attachment; filename="${basename}"`);
}
r.writeHttpMetadata(headers);
return new Response(r.body, { headers });
if (r.range && c.req.header('Range')) {
c.status(206);
headers.set("content-range", generateContentRangeHeader(r.range, r.size));
}
headers.set("accept-ranges", "bytes");
if (!RE_ASSET_SUFFIX.test(basename)) headers.set("content-disposition", `attachment; filename="${basename}"`);
headers.forEach((value, key) => c.header(key, value));
return c.body(r.body)
});
app.post("/api/delete", authWithPassword, async (c) => {
+2 -1
View File
@@ -12,6 +12,7 @@
"@cloudflare/workers-types/2023-07-01"
],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
"jsxImportSource": "hono/jsx",
"isolatedModules": true,
},
}
+1
View File
@@ -8,6 +8,7 @@
"preview": "rsbuild preview"
},
"dependencies": {
"dayjs": "^1.11.13",
"jotai": "^2.11.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
-14
View File
@@ -7,20 +7,6 @@ export const configRsPack: ModifyRspackConfigFn = (config, ctx) => {
config.experiments ??= {};
config.experiments.css = true;
ctx.addRules({
test: /\.(sass|scss|css)$/,
exclude: /node_modules/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {},
},
},
],
type: 'css/auto',
});
ctx.prependPlugins([
new InjectManifest({
swSrc: './src/sw.ts',
+9 -4
View File
@@ -1,9 +1,14 @@
import { memo, useEffect, useMemo } from 'react';
import useSWRInfinite from 'swr/infinite';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import type { UploadRecord } from '../../../src/database';
import { fetchAPI } from '../store/auth';
interface Props {}
dayjs.extend(relativeTime);
interface Props { }
export const UploadRecords = memo<Props>((props) => {
// all records. newest first
@@ -51,12 +56,12 @@ const UploadRecordItem = memo((props: { record: UploadRecord }) => {
<i className="i-mdi-user mr-1"></i>
{props.record.uploader}
</span>
<span>
<span title={dayjs(props.record.ctime).format('YYYY-MM-DD HH:mm:ss')}>
<i className="i-mdi-clock mr-1"></i>
{new Date(props.record.ctime).toLocaleString()}
{dayjs(props.record.ctime).fromNow()}
</span>
{!!props.record.size && (
<span>
<span title={`${props.record.size} bytes`}>
<i className="i-mdi-database mr-1"></i>
{toReadableSize(props.record.size)}
</span>