"use client"; import { motion } from "motion/react"; import { useEffect, useRef, useState } from "react"; import { sse } from "@/lib/db/sse-endpoints"; import { pausePass } from "@/lib/utils"; import { getDonateBar } from "./api"; type Data = Awaited>; export default function TopDonateWidget() { const [bar, setBar] = useState(); const textRef = useRef(null); const stableSize = useRef>({}); const [resizeTick, setResizeTick] = useState(0); useEffect(() => { async function update() { if (textRef.current) void getDonateBar().then(pausePass(10000)).then(setBar); else void getDonateBar().then(setBar); } queueMicrotask(update); const { clean } = sse.donate.subMany({ update, ping: update, refresh: () => location.reload(), }); const backupInterval = setInterval(update, 300000); return () => { clean(); clearInterval(backupInterval); }; }, []); // the most idiomatic way possible but it works useEffect(() => { // oxlint-disable-next-line no-unused-expressions resizeTick; // trigger re-run on window resize if (!textRef.current) return; var fontSize = 48, count = 0; const el = textRef.current, parent = el.parentElement!, key = `${bar?.goal}`; if (stableSize.current[key]) { el.classList.add("opacity-100"); el.style.fontSize = `${stableSize.current[key]}px`; return; } el.classList.remove("opacity-100"); const interval = setInterval(() => { console.log(el.scrollHeight, parent.clientHeight); fontSize = (fontSize * parent.clientHeight) / el.scrollHeight; el.style.fontSize = `${fontSize}px`; count++; if (count > 10) { stableSize.current[key] = fontSize; el.classList.add("opacity-100"); clearInterval(interval); } }, 100); return () => { el.classList.add("opacity-100"); clearInterval(interval); }; }, [bar, resizeTick]); useEffect(() => { const onResize = () => { stableSize.current = {}; setResizeTick((t) => t + 1); }; window.addEventListener("resize", onResize); return () => window.removeEventListener("resize", onResize); }, [bar]); return bar ? (
{bar.goal}฿
) : ( "" ); }