fix(appearance): 本地保存站点 Logo 并支持登录视频自动播放 (#435)

This commit is contained in:
Ray
2026-09-07 22:28:32 +08:00
committed by GitHub
parent 6a7605ec33
commit bdfccf51d1
13 changed files with 328 additions and 38 deletions

View File

@@ -1,4 +1,4 @@
import type { CSSProperties, ReactNode } from "react";
import { useState, type CSSProperties, type ReactNode } from "react";
import { cn } from "@/lib/utils";
import { appearanceLogoURL, useAppearanceStore } from "@/stores/use-appearance-store";
@@ -14,8 +14,24 @@ type BrandLogoProps = {
export function BrandLogo({ className, fallback, alt = "", theme = "auto" }: BrandLogoProps) {
const appearance = useAppearanceStore((state) => state.appearance);
const currentTheme = useThemeStore((state) => state.theme);
const source = appearanceLogoURL(appearance, theme === "auto" ? currentTheme : theme);
const [failedSource, setFailedSource] = useState<string | null>(null);
if (!appearance.logoConfigured) return <>{fallback}</>;
return <img src={appearanceLogoURL(appearance, theme === "auto" ? currentTheme : theme)} alt={alt} className={cn("block object-contain", className)} draggable={false} />;
// A configured custom logo must never fall through to the built-in brand
// when its file becomes unavailable. Keep its footprint neutral instead.
if (failedSource === source) return <span className={cn("block", className)} aria-hidden="true" />;
return (
<img
src={source}
alt={alt}
className={cn("block object-contain", className)}
draggable={false}
onError={(event) => {
event.currentTarget.style.visibility = "hidden";
setFailedSource(source);
}}
/>
);
}
export function BrandLogoFrame({ className, logoClassName, fallback, alt = "", theme = "auto" }: BrandLogoProps & { logoClassName?: string }) {