feat: refine ui
This commit is contained in:
1 parent
187dc83f17
commit
f5b966278c
6 files changed
+39
-32
No files matched your search
Generated
+8
@@ -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
@@ -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
@@ -12,6 +12,7 @@
|
||||
"@cloudflare/workers-types/2023-07-01"
|
||||
],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx"
|
||||
"jsxImportSource": "hono/jsx",
|
||||
"isolatedModules": true,
|
||||
},
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user