fix(webui): prevent redundant thread and media reloads (#5164)

This commit is contained in:
chengyongru
2026-07-30 10:25:22 +08:00
committed by GitHub
parent fc73d5ff39
commit 11fcd9cc5f
29 changed files with 1465 additions and 247 deletions
+17 -14
View File
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import type { CSSProperties, PointerEvent as ReactPointerEvent } from "react";
import { AlertCircle, ChevronRight, Loader2, X } from "lucide-react";
import { useTranslation } from "react-i18next";
@@ -21,7 +21,7 @@ interface FilePreviewPanelProps {
type PreviewState =
| { status: "loading" }
| { status: "error"; message: string }
| { status: "error"; error: unknown }
| { status: "ready"; payload: FilePreviewPayload };
export function FilePreviewPanel({
@@ -36,6 +36,8 @@ export function FilePreviewPanel({
const { t } = useTranslation();
const [state, setState] = useState<PreviewState>({ status: "loading" });
const [entered, setEntered] = useState(false);
const tokenRef = useRef(token);
tokenRef.current = token;
useEffect(() => {
const frame = window.requestAnimationFrame(() => setEntered(true));
@@ -45,25 +47,17 @@ export function FilePreviewPanel({
useEffect(() => {
let cancelled = false;
setState({ status: "loading" });
fetchFilePreview(token, sessionKey, path)
fetchFilePreview(tokenRef.current, sessionKey, path)
.then((payload) => {
if (!cancelled) setState({ status: "ready", payload });
})
.catch((error: unknown) => {
if (cancelled) return;
const message = error instanceof ApiError
? (error.status === 404 && /API route not found/i.test(error.message)
? t("filePreview.routeMissing", {
defaultValue: "File preview needs the latest gateway. Restart nanobot gateway and try again.",
})
: error.message)
: t("filePreview.failed", { defaultValue: "Could not preview this file." });
setState({ status: "error", message });
if (!cancelled) setState({ status: "error", error });
});
return () => {
cancelled = true;
};
}, [path, sessionKey, t, token]);
}, [path, sessionKey]);
const displayPath = state.status === "ready" ? state.payload.display_path : path;
const previewPath = state.status === "ready" ? state.payload.path : displayPath;
@@ -92,6 +86,15 @@ export function FilePreviewPanel({
...directoryParts,
fileName,
].join("/")}`;
const errorMessage = state.status === "error"
? (state.error instanceof ApiError
? (state.error.status === 404 && /API route not found/i.test(state.error.message)
? t("filePreview.routeMissing", {
defaultValue: "File preview needs the latest gateway. Restart nanobot gateway and try again.",
})
: state.error.message)
: t("filePreview.failed", { defaultValue: "Could not preview this file." }))
: null;
return (
<aside
@@ -222,7 +225,7 @@ export function FilePreviewPanel({
className="mx-auto mb-3 h-5 w-5 text-muted-foreground/70"
aria-hidden
/>
<p>{state.message}</p>
<p>{errorMessage}</p>
</div>
</div>
) : (