From 1523e8623ba6725355b3cd417d9b925155fb4228 Mon Sep 17 00:00:00 2001 From: Aditya Khatri Date: Wed, 18 Dec 2024 16:33:01 +0545 Subject: [PATCH] Fix screenshot blur issue --- app/components/Screenshot/index.tsx | 181 ++++++++++++++------------- app/components/Screenshot/styles.css | 9 +- 2 files changed, 99 insertions(+), 91 deletions(-) diff --git a/app/components/Screenshot/index.tsx b/app/components/Screenshot/index.tsx index b1f24a5249..d8b0dec5bc 100644 --- a/app/components/Screenshot/index.tsx +++ b/app/components/Screenshot/index.tsx @@ -6,7 +6,7 @@ import { _cs } from '@togglecorp/fujs'; import { extensionChromeUrl } from '#base/configs/env'; -import { getScreenshot } from '#utils/browserExtension'; +import { getScreenshot as getScreenshotFromExtension } from '#utils/browserExtension'; import styles from './styles.css'; @@ -54,6 +54,18 @@ function getCroppedImage( return croppedImage; } +async function getImageFromUrl(imgUrl: string) { + const promise = new Promise((resolve) => { + const image = new Image(); + image.onload = () => { + resolve(image); + }; + image.src = imgUrl; + }); + + return promise; +} + interface Props { className?: string; onCapture: (image: string | undefined) => void; @@ -61,6 +73,15 @@ interface Props { onCancel: () => void; } +interface Rect { + top: number; + right: number; + bottom: number; + left: number; + width: number; + height: number; +} + function Screenshot(props: Props) { const { className, @@ -70,16 +91,16 @@ function Screenshot(props: Props) { } = props; const firstResizeRef = React.useRef(true); - const [imageProps, setImageProps] = React.useState<{ - image: HTMLImageElement | undefined; - offsetX: number; - offsetY: number; - width: number; - height: number - }>({ - image: undefined, - offsetX: 0, - offsetY: 0, + const brushContainerRef = React.useRef(null); + const canvasRef = React.useRef(null); + const containerRef = React.useRef(null); + + const [screenshotImage, setScreenshotImage] = React.useState(null); + const [containerRect, setContainerRect] = React.useState({ + top: 0, + right: 0, + bottom: 0, + left: 0, width: 0, height: 0, }); @@ -89,95 +110,89 @@ function Screenshot(props: Props) { onCancel(); } + const rect = containerRef.current?.getBoundingClientRect(); + if (rect) { + const scale = window.devicePixelRatio; + + setContainerRect({ + top: Math.round(rect.top * scale), + right: Math.round(rect.right * scale), + bottom: Math.round(rect.bottom * scale), + left: Math.round(rect.left * scale), + width: Math.round(rect.width * scale), + height: Math.round(rect.height * scale), + }); + } + firstResizeRef.current = false; }, [onCancel]); - const brushContainerRef = React.useRef(null); - const svgRef = React.useRef(null); - const canvasRef = React.useRef(null); - const handleBrush = React.useCallback((event: { selection: number[][] }) => { if (!onCapture) { return; } const r = event.selection; - if (!canvasRef.current || !imageProps.image || !r) { + if (!canvasRef.current || !screenshotImage || !r) { onCapture(undefined); return; } const croppedImage = getCroppedImage( canvasRef.current, - imageProps.image, + screenshotImage, r[0][0], r[0][1], r[1][0], r[1][1], ); onCapture(croppedImage); - }, [onCapture, imageProps.image]); + }, [onCapture, screenshotImage]); React.useEffect(() => { - getScreenshot().then((result) => { - if (svgRef.current) { - const scale = window.devicePixelRatio; - - const rect = svgRef.current.getBoundingClientRect(); - const offsetX = rect.left * scale; - const offsetY = rect.top * scale; - const width = rect.width * scale; - const height = rect.height * scale; - - const image = new Image(); - image.onload = () => { - setImageProps({ - image, - offsetX, - offsetY, - width, - height, - }); - }; - - image.src = result.image; + async function getScreenshot() { + try { + const screenshotResult = await getScreenshotFromExtension(); + const image = await getImageFromUrl(screenshotResult.image); + setScreenshotImage(image); + } catch { + // FIXME: use strings + const captureError = ( +
+ In order to use the screenshot functionality, + you must have the Chrome extension installed. + You can download it from the chrome web store + + here. + +
+ ); + if (onCaptureError) { + onCaptureError(captureError); + } } - }).catch(() => { - // FIXME: use strings - const captureError = ( -
- In order to use the screenshot functionality, - you must have the Chrome extension installed. - You can download it from the chrome web store - - here. - -
- ); - if (onCaptureError) { - onCaptureError(captureError); - } - }); + } + + getScreenshot(); + }, [onCaptureError]); - if (!svgRef.current || !brushContainerRef.current) { + React.useEffect(() => { + if (!brushContainerRef.current || !containerRect || !screenshotImage) { return undefined; } - const scale = window.devicePixelRatio; - const rect = svgRef.current.getBoundingClientRect(); - const container = select(brushContainerRef.current); const brushGroup = container.append('g').attr('class', 'brush'); const brush = d3Brush() .extent([ - [rect.left * scale, rect.top * scale], - [rect.right * scale, rect.bottom * scale], + [containerRect.left, containerRect.top], + [containerRect.right, containerRect.bottom], ]) .on('end', handleBrush); brushGroup.call(brush); @@ -187,25 +202,21 @@ function Screenshot(props: Props) { brushGroup.remove(); } }; - }, [handleBrush, onCaptureError]); - - const { - image, - offsetX, - offsetY, - width, - height, - } = imageProps; + }, [containerRect, handleBrush, onCaptureError, screenshotImage]); return ( -
- - {image && } - - +
+ {containerRect.width && containerRect.height && ( + + {screenshotImage && } + + + )}