import type { EnvironmentId } from "@t3tools/contracts";import { isProjectFaviconFallbackUrl } from "@t3tools/shared/projectFavicon";import { FolderIcon } from "lucide-react";import { useState } from "react";import { useAssetUrl } from "../assets/assetUrls"; const loadedProjectFaviconSrcs = new Set<string>(); export function ProjectFavicon(input: { environmentId: EnvironmentId; cwd: string; className?: string | undefined;}) { const src = useAssetUrl(input.environmentId, { _tag: "project-favicon", cwd: input.cwd, }); if (!src || isProjectFaviconFallbackUrl(src)) { return <ProjectFaviconFallback className={input.className} />; } return <ProjectFaviconImage key={src} src={src} className={input.className} />;} function ProjectFaviconFallback({ className }: { readonly className?: string | undefined }) { return <FolderIcon className={`size-3.5 shrink-0 text-muted-foreground/50 ${className ?? ""}`} />;} function ProjectFaviconImage({ src, className,}: { readonly src: string; readonly className?: string | undefined;}) { const [status, setStatus] = useState<"loading" | "loaded" | "error">(() => loadedProjectFaviconSrcs.has(src) ? "loaded" : "loading", ); return ( <> {status !== "loaded" ? <ProjectFaviconFallback className={className} /> : null} <img src={src} alt="" className={`size-3.5 shrink-0 rounded-sm object-contain ${status === "loaded" ? "" : "hidden"} ${className ?? ""}`} onLoad={() => { loadedProjectFaviconSrcs.add(src); setStatus("loaded"); }} onError={() => setStatus("error")} /> </> );}
import type { EnvironmentId } from "@t3tools/contracts";
import { isProjectFaviconFallbackUrl } from "@t3tools/shared/projectFavicon";
import { FolderIcon } from "lucide-react";
import { useState } from "react";
import { useAssetUrl } from "../assets/assetUrls";
const loadedProjectFaviconSrcs = new Set<string>();
export function ProjectFavicon(input: {
environmentId: EnvironmentId;
cwd: string;
className?: string | undefined;
}) {
const src = useAssetUrl(input.environmentId, {
_tag: "project-favicon",
cwd: input.cwd,
});
if (!src || isProjectFaviconFallbackUrl(src)) {
return <ProjectFaviconFallback className={input.className} />;
}
return <ProjectFaviconImage key={src} src={src} className={input.className} />;
}
function ProjectFaviconFallback({ className }: { readonly className?: string | undefined }) {
return <FolderIcon className={`size-3.5 shrink-0 text-muted-foreground/50 ${className ?? ""}`} />;
}
function ProjectFaviconImage({
src,
className,
}: {
readonly src: string;
readonly className?: string | undefined;
}) {
const [status, setStatus] = useState<"loading" | "loaded" | "error">(() =>
loadedProjectFaviconSrcs.has(src) ? "loaded" : "loading",
);
return (
<>
{status !== "loaded" ? <ProjectFaviconFallback className={className} /> : null}
<img
src={src}
alt=""
className={`size-3.5 shrink-0 rounded-sm object-contain ${status === "loaded" ? "" : "hidden"} ${className ?? ""}`}
onLoad={() => {
loadedProjectFaviconSrcs.add(src);
setStatus("loaded");
}}
onError={() => setStatus("error")}
/>
</>
);
}