fix(catalog): keep Nitro editor stable during background polling
This commit is contained in:
1 parent
dcb5f46eed
commit
3c24df9b1d
1 file changed
+35
-32
@@ -16,7 +16,7 @@ import {
|
|||||||
Save,
|
Save,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useEffect, useEffectEvent, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { NitroQualityPanel } from "@/components/admin/studio/nitro-quality-panel";
|
import { NitroQualityPanel } from "@/components/admin/studio/nitro-quality-panel";
|
||||||
import { NitroScale32Generator } from "@/components/admin/studio/nitro-scale32-generator";
|
import { NitroScale32Generator } from "@/components/admin/studio/nitro-scale32-generator";
|
||||||
@@ -188,40 +188,43 @@ export function NitroEditorDialog({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchMetadata = useCallback(async () => {
|
const closeAfterLoadError = useEffectEvent(() => onOpenChange(false));
|
||||||
if (!classname) return;
|
useEffect(() => {
|
||||||
|
if (!open || !classname) return;
|
||||||
|
const controller = new AbortController();
|
||||||
|
setActiveTab("visual");
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setJsonError(null);
|
setJsonError(null);
|
||||||
try {
|
setAutoDetectResult(null);
|
||||||
const res = await adminFetch(
|
void (async () => {
|
||||||
`/api/admin/import/furni/nitro-editor?classname=${encodeURIComponent(classname)}`,
|
try {
|
||||||
);
|
const res = await adminFetch(
|
||||||
if (!res.ok) {
|
`/api/admin/import/furni/nitro-editor?classname=${encodeURIComponent(classname)}`,
|
||||||
const err = await res.json().catch(() => ({}));
|
{ signal: controller.signal },
|
||||||
toast.error(err.error || "Failed to load .nitro metadata");
|
);
|
||||||
onOpenChange(false);
|
const data = await res.json();
|
||||||
return;
|
if (controller.signal.aborted) return;
|
||||||
|
if (!res.ok) {
|
||||||
|
toast.error(data.error || "Failed to load .nitro metadata");
|
||||||
|
closeAfterLoadError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setMetadata(data.metadata);
|
||||||
|
setOriginalMetadata(structuredClone(data.metadata));
|
||||||
|
setJsonText(JSON.stringify(data.metadata, null, 2));
|
||||||
|
setFlags(data.flags);
|
||||||
|
setOriginalFlags({ ...data.flags });
|
||||||
|
} catch {
|
||||||
|
if (!controller.signal.aborted) {
|
||||||
|
toast.error("Network error loading .nitro metadata");
|
||||||
|
closeAfterLoadError();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (!controller.signal.aborted) setLoading(false);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
})();
|
||||||
setMetadata(data.metadata);
|
return () => controller.abort();
|
||||||
setOriginalMetadata(JSON.parse(JSON.stringify(data.metadata)));
|
}, [open, classname]);
|
||||||
setJsonText(JSON.stringify(data.metadata, null, 2));
|
|
||||||
setFlags(data.flags);
|
|
||||||
setOriginalFlags({ ...data.flags });
|
|
||||||
} catch {
|
|
||||||
toast.error("Network error loading .nitro metadata");
|
|
||||||
onOpenChange(false);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [classname, onOpenChange]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (open && classname) {
|
|
||||||
setActiveTab("visual");
|
|
||||||
fetchMetadata();
|
|
||||||
}
|
|
||||||
}, [open, classname, fetchMetadata]);
|
|
||||||
|
|
||||||
const handleTabChange = (newTab: string) => {
|
const handleTabChange = (newTab: string) => {
|
||||||
if (activeTab === "json" && newTab !== "json") {
|
if (activeTab === "json" && newTab !== "json") {
|
||||||
|
|||||||
Reference in new issue
Block a user