fix(monitor): show the light variant of selfh.st logos in the dark theme

This commit is contained in:
MacRimi
2026-11-03 21:02:06 +01:00
parent e51553ada8
commit 194a959492
+26 -24
View File
@@ -391,30 +391,32 @@ const EMPTY_APP: AppConfig = {
logo_url: "", logo_url: "",
} }
const SELFHST_WEBP_BASE = "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp" // selfh.st publishes a `-light` variant of the logos that are dark, for dark
const SELFHST_THEME_LOGOS: Record<string, { lightTheme: string; darkTheme: string }> = { // backgrounds. These two ship a light logo by default, so the light theme
frigate: { // takes their `-dark` variant.
lightTheme: `${SELFHST_WEBP_BASE}/frigate-dark.webp`, const SELFHST_LIGHT_BY_DEFAULT = new Set(["frigate", "portainer"])
darkTheme: `${SELFHST_WEBP_BASE}/frigate-light.webp`,
},
"llama-cpp": {
lightTheme: `${SELFHST_WEBP_BASE}/llama-cpp.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/llama-cpp-light.webp`,
},
portainer: {
lightTheme: `${SELFHST_WEBP_BASE}/portainer-dark.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/portainer-light.webp`,
},
vaultwarden: {
lightTheme: `${SELFHST_WEBP_BASE}/vaultwarden.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/vaultwarden-light.webp`,
},
}
function selfhstThemeLogos(src: string) { function selfhstThemeLogos(src: string) {
if (!src.toLowerCase().includes("cdn.jsdelivr.net/gh/selfhst/icons")) return null const match = src.match(/^(https:\/\/cdn\.jsdelivr\.net\/gh\/selfhst\/icons@[^/]+\/webp\/)([a-z0-9-]+?)(?:-(?:dark|light))?\.webp(?:[?#].*)?$/i)
const match = src.toLowerCase().match(/\/(frigate|llama-cpp|portainer|vaultwarden)(?:-(?:dark|light))?\.webp(?:[?#].*)?$/) if (!match) return null
return match ? SELFHST_THEME_LOGOS[match[1]] : null const [, base, name] = match
return {
lightTheme: `${base}${name}${SELFHST_LIGHT_BY_DEFAULT.has(name.toLowerCase()) ? "-dark" : ""}.webp`,
darkTheme: `${base}${name}-light.webp`,
}
}
// A logo without the variant keeps the recorded one.
function FallbackLogo({ src, fallback, className }: { src: string; fallback: string; className: string }) {
const [failed, setFailed] = useState(false)
useEffect(() => setFailed(false), [src])
return (
<img src={failed ? fallback : src} alt="" className={className}
onError={(e) => {
if (!failed && fallback !== src) setFailed(true)
else e.currentTarget.style.display = "none"
}} />
)
} }
const LOCAL_LOGO_CACHE_PATH = /^\/api\/vms\/[1-9]\d*\/apps\/logo-cache\/[a-f0-9]{32}$/ const LOCAL_LOGO_CACHE_PATH = /^\/api\/vms\/[1-9]\d*\/apps\/logo-cache\/[a-f0-9]{32}$/
@@ -460,8 +462,8 @@ export function ThemeAwareLogo({ src, className }: { src: string; className: str
} }
return ( return (
<> <>
<img src={themed.lightTheme} alt="" className={`${className} block dark:hidden`} onError={hideBroken} /> <FallbackLogo src={themed.lightTheme} fallback={src} className={`${className} block dark:hidden`} />
<img src={themed.darkTheme} alt="" className={`${className} hidden dark:block`} onError={hideBroken} /> <FallbackLogo src={themed.darkTheme} fallback={src} className={`${className} hidden dark:block`} />
</> </>
) )
} }