fix login crash from DOM cleanup race
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-11 23:19:35 +08:00
parent bd80723ee6
commit 83f7f3d6d1
2 changed files with 49 additions and 30 deletions

View File

@ -23,13 +23,20 @@ export function AntigravityBackground() {
useEffect(() => {
if (!mounted || !sceneRef.current) return;
const safeRemoveCanvas = (render: Matter.Render | null) => {
const canvas = render?.canvas;
if (canvas?.parentNode) {
canvas.parentNode.removeChild(canvas);
}
};
// 清理旧实例
if (engineRef.current) {
Matter.Engine.clear(engineRef.current);
}
if (renderRef.current) {
Matter.Render.stop(renderRef.current);
renderRef.current.canvas.remove();
safeRemoveCanvas(renderRef.current);
}
// 创建物理引擎
@ -224,15 +231,18 @@ export function AntigravityBackground() {
if (mouseConstraintRef.current) {
Matter.Composite.remove(engine.world, mouseConstraintRef.current);
mouseConstraintRef.current = null;
}
if (renderRef.current) {
Matter.Render.stop(renderRef.current);
renderRef.current.canvas.remove();
safeRemoveCanvas(renderRef.current);
renderRef.current = null;
}
if (engineRef.current) {
Matter.Engine.clear(engineRef.current);
engineRef.current = null;
}
Matter.Runner.stop(runner);

View File

@ -4,44 +4,53 @@ import { useEffect } from "react";
export function FaviconUpdater() {
useEffect(() => {
let isDisposed = false;
// 从 API 获取最新的 favicon 设置
fetch("/api/site-settings")
.then((res) => res.json())
.then((settings) => {
if (settings.favicon) {
const faviconUrl = settings.favicon;
const timestamp = Date.now();
const urlWithCache = `${faviconUrl}${faviconUrl.includes("?") ? "&" : "?"}v=${timestamp}`;
// 移除所有旧的 favicon link 标签
const oldLinks = document.querySelectorAll('link[rel*="icon"]');
oldLinks.forEach((link) => link.remove());
// 添加新的 favicon link 标签
const link = document.createElement("link");
link.rel = "icon";
link.type = "image/x-icon";
link.href = urlWithCache;
document.head.appendChild(link);
// 添加 Apple touch icon
const appleLink = document.createElement("link");
appleLink.rel = "apple-touch-icon";
appleLink.href = urlWithCache;
document.head.appendChild(appleLink);
// 添加 shortcut icon
const shortcutLink = document.createElement("link");
shortcutLink.rel = "shortcut icon";
shortcutLink.href = urlWithCache;
document.head.appendChild(shortcutLink);
if (!settings.favicon || isDisposed) {
return;
}
const faviconUrl = settings.favicon;
const timestamp = Date.now();
const urlWithCache = `${faviconUrl}${faviconUrl.includes("?") ? "&" : "?"}v=${timestamp}`;
// 仅处理本组件创建的 link,避免删除 Next/React 管理的 head 节点
const oldLinks = document.querySelectorAll(
'link[data-managed-favicon="true"]'
);
oldLinks.forEach((link) => {
if (link.parentNode) {
link.parentNode.removeChild(link);
}
});
const createManagedLink = (rel: string, href: string, type?: string) => {
const link = document.createElement("link");
link.rel = rel;
link.href = href;
link.setAttribute("data-managed-favicon", "true");
if (type) {
link.type = type;
}
document.head.appendChild(link);
};
createManagedLink("icon", urlWithCache, "image/x-icon");
createManagedLink("apple-touch-icon", urlWithCache);
createManagedLink("shortcut icon", urlWithCache);
})
.catch((error) => {
console.error("[Favicon] Error updating favicon:", error);
});
return () => {
isDisposed = true;
};
}, []);
return null;
}