export function findJumboEmojiElement(targetEventId: string): HTMLElement | null { const message = document.querySelector(`[data-message-id="${CSS.escape(targetEventId)}"]`); if (!message) return null; const jumbo = message.querySelector('[data-jumbo-emoji]'); return jumbo instanceof HTMLElement ? jumbo : null; } export type JumboGlyphMetrics = { /** Outer jumbo mount (message body) — hide/show this. */ mount: HTMLElement; /** Visual glyph center in viewport coords. */ x: number; y: number; /** CSS px size matching the rendered emoji (usually computed font-size). */ size: number; }; /** * Measure the on-screen jumbo glyph. Prefer computed font-size so the canvas * stand-in matches unicode emoji; fall back to the glyph box for images. */ export function measureJumboGlyph(targetEventId: string): JumboGlyphMetrics | null { const mount = findJumboEmojiElement(targetEventId); if (!mount) return null; const glyph = (mount.querySelector('[data-emoticon]') as HTMLElement | null) || (mount.querySelector('img') as HTMLElement | null) || mount; const rect = glyph.getBoundingClientRect(); const fontSize = parseFloat(getComputedStyle(glyph).fontSize) || parseFloat(getComputedStyle(mount).fontSize) || 0; const isImg = glyph instanceof HTMLImageElement || glyph.tagName === 'IMG'; const size = isImg ? Math.max(rect.width, rect.height) : fontSize > 0 ? fontSize : Math.max(rect.width, rect.height); return { mount, x: rect.left + rect.width / 2, y: rect.top + rect.height / 2, size, }; } export function setJumboEmojiHidden(targetEventId: string, hidden: boolean) { const mount = findJumboEmojiElement(targetEventId); if (!mount) return; if (hidden) { mount.style.visibility = 'hidden'; } else { mount.style.removeProperty('visibility'); } } export function getLocalBurstCanvasSize(maskRadius: number): number { return Math.max(300, Math.round(maskRadius * 6.5)); }