Loading packages/client/src/components/Toolbar/CanvasMeta.tsx +7 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import { useCompactPalette, } from "../../hooks/useCompactPalette"; import { useIsMobile } from "../../hooks/useIsMobile"; import { setAvailablePixelsFavicon } from "../../lib/favicon"; const getTimeLeft = (available: number, config: ClientConfig) => { /** Loading Loading @@ -120,6 +121,12 @@ export const CanvasMeta = () => { }; }, []); useEffect(() => { setAvailablePixelsFavicon(user ? available : 0); return () => setAvailablePixelsFavicon(0); }, [available, user]); return ( <> <motion.div Loading packages/client/src/lib/favicon.ts 0 → 100644 +46 −0 Original line number Diff line number Diff line import logoUrl from "../assets/logo.webp"; const favicon = document.querySelector<HTMLLinkElement>('link[rel="icon"]'); const defaultFavicon = favicon?.href; let renderVersion = 0; export const setAvailablePixelsFavicon = (available: number) => { if (!favicon) return; const version = ++renderVersion; if (available <= 0) { if (defaultFavicon) favicon.href = defaultFavicon; return; } const image = new Image(); image.src = logoUrl; image.onload = () => { if (version !== renderVersion) return; const size = 64; const canvas = document.createElement("canvas"); canvas.width = size; canvas.height = size; const context = canvas.getContext("2d"); if (!context) return; context.drawImage(image, 0, 0, size, size); const label = available > 99 ? "99+" : String(available); const fontSize = label.length > 2 ? 34 : label.length > 1 ? 42 : 50; context.font = `900 ${fontSize}px sans-serif`; context.lineJoin = "round"; context.strokeStyle = "rgba(0, 0, 0, 0.9)"; context.lineWidth = 8; context.fillStyle = "#fff"; context.textAlign = "center"; context.textBaseline = "middle"; context.strokeText(label, size / 2, size / 2 + 5); context.fillText(label, size / 2, size / 2 + 5); favicon.href = canvas.toDataURL("image/png"); }; }; Loading
packages/client/src/components/Toolbar/CanvasMeta.tsx +7 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import { useCompactPalette, } from "../../hooks/useCompactPalette"; import { useIsMobile } from "../../hooks/useIsMobile"; import { setAvailablePixelsFavicon } from "../../lib/favicon"; const getTimeLeft = (available: number, config: ClientConfig) => { /** Loading Loading @@ -120,6 +121,12 @@ export const CanvasMeta = () => { }; }, []); useEffect(() => { setAvailablePixelsFavicon(user ? available : 0); return () => setAvailablePixelsFavicon(0); }, [available, user]); return ( <> <motion.div Loading
packages/client/src/lib/favicon.ts 0 → 100644 +46 −0 Original line number Diff line number Diff line import logoUrl from "../assets/logo.webp"; const favicon = document.querySelector<HTMLLinkElement>('link[rel="icon"]'); const defaultFavicon = favicon?.href; let renderVersion = 0; export const setAvailablePixelsFavicon = (available: number) => { if (!favicon) return; const version = ++renderVersion; if (available <= 0) { if (defaultFavicon) favicon.href = defaultFavicon; return; } const image = new Image(); image.src = logoUrl; image.onload = () => { if (version !== renderVersion) return; const size = 64; const canvas = document.createElement("canvas"); canvas.width = size; canvas.height = size; const context = canvas.getContext("2d"); if (!context) return; context.drawImage(image, 0, 0, size, size); const label = available > 99 ? "99+" : String(available); const fontSize = label.length > 2 ? 34 : label.length > 1 ? 42 : 50; context.font = `900 ${fontSize}px sans-serif`; context.lineJoin = "round"; context.strokeStyle = "rgba(0, 0, 0, 0.9)"; context.lineWidth = 8; context.fillStyle = "#fff"; context.textAlign = "center"; context.textBaseline = "middle"; context.strokeText(label, size / 2, size / 2 + 5); context.fillText(label, size / 2, size / 2 + 5); favicon.href = canvas.toDataURL("image/png"); }; };