66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
|
|
export function FaviconUpdater() {
|
|
useEffect(() => {
|
|
let isDisposed = false;
|
|
|
|
const existingIcon =
|
|
document.querySelector<HTMLLinkElement>('link[rel="icon"]')?.href ||
|
|
document.querySelector<HTMLLinkElement>('link[rel="shortcut icon"]')?.href ||
|
|
document.querySelector<HTMLLinkElement>('link[rel="apple-touch-icon"]')?.href;
|
|
const urlWithCache = existingIcon || "/api/favicon";
|
|
|
|
Promise.resolve().then(() => {
|
|
if (isDisposed) {
|
|
return;
|
|
}
|
|
|
|
const managedSelector =
|
|
'link[rel="icon"],link[rel="shortcut icon"],link[rel="apple-touch-icon"]';
|
|
const existingLinks = document.querySelectorAll<HTMLLinkElement>(
|
|
managedSelector
|
|
);
|
|
|
|
existingLinks.forEach((link) => {
|
|
link.href = urlWithCache;
|
|
link.setAttribute("data-managed-favicon", "true");
|
|
if (link.rel === "icon") {
|
|
link.type = "image/x-icon";
|
|
link.setAttribute("sizes", "any");
|
|
}
|
|
});
|
|
|
|
const ensureLink = (rel: string, type?: string) => {
|
|
let link = document.querySelector(
|
|
`link[rel="${rel}"]`
|
|
) as HTMLLinkElement | null;
|
|
if (!link) {
|
|
link = document.createElement("link");
|
|
link.rel = rel;
|
|
document.head.appendChild(link);
|
|
}
|
|
link.href = urlWithCache;
|
|
link.setAttribute("data-managed-favicon", "true");
|
|
if (type) {
|
|
link.type = type;
|
|
}
|
|
if (rel === "icon") {
|
|
link.setAttribute("sizes", "any");
|
|
}
|
|
};
|
|
|
|
ensureLink("icon", "image/x-icon");
|
|
ensureLink("apple-touch-icon");
|
|
ensureLink("shortcut icon");
|
|
});
|
|
|
|
return () => {
|
|
isDisposed = true;
|
|
};
|
|
}, []);
|
|
|
|
return null;
|
|
}
|