diff --git a/src/assets/styles/nav.css b/src/assets/styles/nav.css index 58a88ff..44bd64b 100644 --- a/src/assets/styles/nav.css +++ b/src/assets/styles/nav.css @@ -29,10 +29,19 @@ } .mobile-menu-dropdown.open { - max-height: 500px; + max-height: none; + overflow: visible; + padding-bottom: 0.75rem; opacity: 1; } +.mobile-menu-dropdown a { + font-size: 0.95rem; + line-height: 1.25rem; + padding: 0.6rem 0.75rem; + border-radius: 12px; +} + @media (min-width: 768px) { .mobile-menu-dropdown { display: none; diff --git a/src/components/TRip/RequestManagement.tsx b/src/components/TRip/RequestManagement.tsx index 1ce9ad7..1bd946b 100644 --- a/src/components/TRip/RequestManagement.tsx +++ b/src/components/TRip/RequestManagement.tsx @@ -17,9 +17,9 @@ interface RequestJob { tracks: number; quality: string; status: string; - progress: number; + progress: number | string | null; type?: string; - tarball_path?: string; + tarball?: string; created_at?: string; updated_at?: string; [key: string]: unknown; @@ -40,9 +40,13 @@ export default function RequestManagement() { const pollingDetailRef = useRef | null>(null); + const resolveTarballPath = (job: RequestJob) => job.tarball; + const tarballUrl = (absPath: string | undefined, quality: string) => { if (!absPath) return null; const filename = absPath.split("/").pop(); // get "SOMETHING.tar.gz" + // If the backend already stores a fully qualified URL, return as-is + if (/^https?:\/\//i.test(absPath)) return absPath; return `${TAR_BASE_URL}/${quality}/${filename}`; }; @@ -172,24 +176,21 @@ export default function RequestManagement() { const formatProgress = (p: unknown) => { if (p === null || p === undefined || p === "") return "—"; - const num = Number(p); - if (Number.isNaN(num)) return "—"; - const pct = num > 1 ? Math.round(num) : num; + const pct = computePct(p); return `${pct}%`; }; const computePct = (p: unknown) => { if (p === null || p === undefined || p === "") return 0; const num = Number(p); - if (Number.isNaN(num)) return 0; - return Math.min(100, Math.max(0, num > 1 ? Math.round(num) : Math.round(num * 100))); + if (!Number.isFinite(num)) return 0; + const normalized = num > 1 ? num : num * 100; + return Math.min(100, Math.max(0, Math.round(normalized))); }; const progressBarTemplate = (rowData: RequestJob) => { const p = rowData.progress; - if (p === null || p === undefined || p === 0) return "—"; - const num = Number(p); - if (Number.isNaN(num)) return "—"; + if (p === null || p === undefined || p === "") return "—"; const pct = computePct(p); const getProgressColor = () => { @@ -341,7 +342,7 @@ export default function RequestManagement() { } body={(row: RequestJob) => { - const url = tarballUrl(row.tarball_path, row.quality || "FLAC"); + const url = tarballUrl(resolveTarballPath(row as RequestJob), row.quality || "FLAC"); if (!url) return "—"; const encodedURL = encodeURI(url); @@ -409,18 +410,25 @@ export default function RequestManagement() { Progress:
+ {(() => { + const pctDialog = computePct(selectedRequest.progress); + const status = selectedRequest.status; + const fillColor = status === "Failed" ? "bg-red-500" : status === "Finished" ? "bg-green-500" : "bg-blue-500"; + return (
= 100 ? '999px' : 0, - borderBottomRightRadius: computePct(selectedRequest.progress) >= 100 ? '999px' : 0 - }} - data-pct={computePct(selectedRequest.progress)} - aria-valuenow={Math.min(100, Math.max(0, Number(selectedRequest.progress) > 1 ? Math.round(selectedRequest.progress) : selectedRequest.progress * 100))} - aria-valuemin={0} - aria-valuemax={100} - /> + className={`rm-progress-fill ${fillColor}`} + style={{ + ['--rm-progress' as string]: (pctDialog / 100).toString(), + borderTopRightRadius: pctDialog >= 100 ? '999px' : 0, + borderBottomRightRadius: pctDialog >= 100 ? '999px' : 0 + }} + data-pct={pctDialog} + aria-valuenow={pctDialog} + aria-valuemin={0} + aria-valuemax={100} + /> + ); + })()}
{formatProgress(selectedRequest.progress)}
@@ -437,17 +445,17 @@ export default function RequestManagement() { {/* --- Tarball Card --- */} { - selectedRequest.tarball_path && ( + selectedRequest.tarball && (

Tarball:{" "} - {tarballUrl(selectedRequest.tarball_path, selectedRequest.quality)?.split("/").pop()} + {tarballUrl(resolveTarballPath(selectedRequest), selectedRequest.quality)?.split("/").pop()}

diff --git a/src/pages/api/discord/channels.ts b/src/pages/api/discord/channels.ts index 3e025a0..8aa19b2 100644 --- a/src/pages/api/discord/channels.ts +++ b/src/pages/api/discord/channels.ts @@ -27,9 +27,9 @@ interface ChannelRow { export async function GET({ request }: APIContext): Promise { // Rate limit check const rateCheck = checkRateLimit(request, { - limit: 20, + limit: 60, windowMs: 1000, - burstLimit: 100, + burstLimit: 240, burstWindowMs: 10_000, }); diff --git a/src/pages/api/discord/members.ts b/src/pages/api/discord/members.ts index 99edef3..73e785a 100644 --- a/src/pages/api/discord/members.ts +++ b/src/pages/api/discord/members.ts @@ -143,9 +143,9 @@ async function getChannelVisibleMembers(channelId: string, guildId: string): Pro export async function GET({ request }) { // Rate limit check const rateCheck = checkRateLimit(request, { - limit: 20, + limit: 80, windowMs: 1000, - burstLimit: 100, + burstLimit: 320, burstWindowMs: 10_000, }); diff --git a/src/pages/api/discord/messages.ts b/src/pages/api/discord/messages.ts index bb477f5..753621a 100644 --- a/src/pages/api/discord/messages.ts +++ b/src/pages/api/discord/messages.ts @@ -99,9 +99,9 @@ function getSafeImageUrl(originalUrl: string | null, baseUrl: string): string | export async function GET({ request }: APIContext) { // Rate limit check const rateCheck = checkRateLimit(request, { - limit: 30, + limit: 100, windowMs: 1000, - burstLimit: 150, + burstLimit: 400, burstWindowMs: 10_000, }); diff --git a/src/pages/lighting.astro b/src/pages/lighting.astro index eb81e6c..6b983e5 100644 --- a/src/pages/lighting.astro +++ b/src/pages/lighting.astro @@ -7,7 +7,7 @@ import Root from "@/components/AppLayout.jsx"; const user = Astro.locals.user as any; --- - +
diff --git a/src/pages/login.astro b/src/pages/login.astro index 5a8d787..cbc19c2 100644 --- a/src/pages/login.astro +++ b/src/pages/login.astro @@ -9,7 +9,7 @@ const accessDenied = Astro.locals.accessDenied || false; const requiredRoles = Astro.locals.requiredRoles || []; --- - +
diff --git a/src/pages/memes.astro b/src/pages/memes.astro index 5b7f6f0..387bcfc 100644 --- a/src/pages/memes.astro +++ b/src/pages/memes.astro @@ -4,7 +4,7 @@ import Root from "../components/AppLayout.jsx"; import "@styles/MemeGrid.css"; --- - +