完善站点运营设置:分路由管理、登录可见评论、邮件模板内联与关闭注册 SSR。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { createContext, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
|
||||
import { apiGetSettings, type PublicSettings } from "@/lib/api";
|
||||
import { siteDocumentTitle, normalizeBrandLogoFit, normalizeBrandLogoSize, normalizeBrandMark } from "@/lib/brand";
|
||||
import { siteDocumentTitle, normalizeBrandLogoFit, normalizeBrandLogoSize, normalizeBrandMark, normalizeFooterLinks } from "@/lib/brand";
|
||||
import { realtime, RT_SETTINGS_CHANGED, type RtSettingsData } from "@/lib/realtime";
|
||||
import { onDocumentVisible, VISIBLE_RECONCILE_GAP_MS } from "@/lib/visibilityReconcile";
|
||||
|
||||
@@ -52,29 +52,18 @@ function sameBrand(a: SiteBrand, b: SiteBrand): boolean {
|
||||
}
|
||||
|
||||
function applyFavicon(url: string) {
|
||||
const existing = document.querySelectorAll<HTMLLinkElement>('link[rel~="icon"]');
|
||||
if (!url) {
|
||||
document.getElementById("j13-favicon")?.remove();
|
||||
const hasDefault = [...existing].some((el) => el.id !== "j13-favicon" && el.href.includes("favicon"));
|
||||
if (!hasDefault) {
|
||||
const link = document.createElement("link");
|
||||
link.rel = "icon";
|
||||
link.href = "/favicon.ico";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
return;
|
||||
}
|
||||
existing.forEach((el) => {
|
||||
if (el.id !== "j13-favicon") el.remove();
|
||||
});
|
||||
// 只管理 #j13-favicon,禁止 remove 其它 icon 节点:
|
||||
// Next Metadata 注入的 <link rel="icon"> 由 React 持有,手动删会导致 removeChild 空指针。
|
||||
let link = document.getElementById("j13-favicon") as HTMLLinkElement | null;
|
||||
if (!link) {
|
||||
link = document.createElement("link");
|
||||
link.id = "j13-favicon";
|
||||
link.rel = "icon";
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
if (link.getAttribute("href") !== url) link.href = url;
|
||||
const href = url || "/favicon.ico";
|
||||
if (link.getAttribute("href") !== href) link.href = href;
|
||||
// 挪到 head 末尾,优先于 SSR 注入的 icon
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function retitle(prev: SiteBrand, next: SiteBrand) {
|
||||
@@ -132,7 +121,7 @@ export default function SiteBrandProvider({
|
||||
setBrand((prev) => {
|
||||
if (sameBrand(prev, next)) return prev;
|
||||
retitle(prev, next);
|
||||
applyFavicon(next.favicon_url);
|
||||
if (prev.favicon_url !== next.favicon_url) applyFavicon(next.favicon_url);
|
||||
return next;
|
||||
});
|
||||
}, [initial]);
|
||||
@@ -150,11 +139,13 @@ export default function SiteBrandProvider({
|
||||
brand_mark: normalizeBrandMark(raw.brand_mark ?? prev.brand_mark),
|
||||
brand_logo_size: normalizeBrandLogoSize(raw.brand_logo_size ?? prev.brand_logo_size),
|
||||
brand_logo_fit: normalizeBrandLogoFit(raw.brand_logo_fit ?? prev.brand_logo_fit),
|
||||
footer_links: Array.isArray(raw.footer_links) ? raw.footer_links : prev.footer_links,
|
||||
footer_links: Array.isArray(raw.footer_links)
|
||||
? normalizeFooterLinks(raw.footer_links)
|
||||
: prev.footer_links,
|
||||
};
|
||||
if (sameBrand(prev, next)) return;
|
||||
retitle(prev, next);
|
||||
applyFavicon(next.favicon_url);
|
||||
if (prev.favicon_url !== next.favicon_url) applyFavicon(next.favicon_url);
|
||||
brandRef.current = next;
|
||||
setBrand(next);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user