[RAPID-fix] 캡처 프리캐싱: 메신저 열릴 때 백그라운드 domToPng → 버튼 클릭 즉시 오버레이

This commit is contained in:
2026-03-31 15:57:58 +09:00
parent be8e37b6c9
commit 999cfef6ce

View File

@@ -33,35 +33,41 @@ export function MessengerModal() {
const capturePromiseRef = useRef<Promise<HTMLImageElement> | null>(null);
const messageInputRef = useRef<MessageInputHandle>(null);
// Pre-capture when messenger opens so button click is instant
const startBackgroundCapture = useCallback(() => {
capturePromiseRef.current = (async (): Promise<HTMLImageElement> => {
const { domToPng } = await import("modern-screenshot");
const dataUrl = await domToPng(document.body, {
width: window.innerWidth,
height: window.innerHeight,
scale: window.devicePixelRatio || 1,
font: false,
});
const img = new Image();
img.src = dataUrl;
await new Promise<void>((res) => { img.onload = () => res(); });
capturedImgRef.current = img;
return img;
})();
}, []);
useEffect(() => {
const count = (serverUnread as any)?.unread_count ?? serverUnread ?? 0;
setUnreadCount(Number(count));
}, [serverUnread, setUnreadCount]);
// Start background capture when messenger opens (so capture button is instant)
useEffect(() => {
if (isOpen) startBackgroundCapture();
}, [isOpen, startBackgroundCapture]);
const selectedRoom = rooms.find((r) => r.id === selectedRoomId) || null;
const handleCaptureClick = useCallback(() => {
// Set promise ref BEFORE setCapturing so ScreenCapture condition is true on render
capturePromiseRef.current = new Promise<HTMLImageElement>((resolve, reject) => {
// Wait 2 rAF frames so the overlay renders first, then start heavy work
requestAnimationFrame(() => requestAnimationFrame(async () => {
try {
const { domToPng } = await import("modern-screenshot");
const dataUrl = await domToPng(document.body, {
width: window.innerWidth,
height: window.innerHeight,
scale: window.devicePixelRatio || 1,
font: false,
});
const img = new Image();
img.src = dataUrl;
img.onload = () => resolve(img);
img.onerror = reject;
} catch (e) { reject(e); }
}));
});
setCapturing(true); // Show overlay immediately
}, []);
// If no cache yet, start now (fallback)
if (!capturePromiseRef.current) startBackgroundCapture();
setCapturing(true);
}, [startBackgroundCapture]);
// Position & size state
const [pos, setPos] = useState({ x: 0, y: 0 });
@@ -189,8 +195,13 @@ export function MessengerModal() {
onCapture={(file) => {
setCapturing(false);
messageInputRef.current?.addFiles([file]);
// Pre-cache next capture immediately
startBackgroundCapture();
}}
onCancel={() => {
setCapturing(false);
startBackgroundCapture();
}}
onCancel={() => setCapturing(false)}
/>
)}
<div