@@ -3,14 +3,15 @@ import type { ComponentType, VNode, h as hType } from 'preact';
33// biome-ignore lint: needed for preact
44import { h } from 'preact' ; // eslint-disable-line @typescript-eslint/no-unused-vars
55import { useCallback , useEffect , useMemo , useRef , useState } from 'preact/hooks' ;
6- import { DOCUMENT , WINDOW } from '../../constants' ;
6+ import { CROP_COLOR , DOCUMENT , WINDOW } from '../../constants' ;
77import type { Dialog } from '../../types' ;
88import { createScreenshotInputStyles } from './ScreenshotInput.css' ;
99import { useTakeScreenshot } from './useTakeScreenshot' ;
1010
1111const CROP_BUTTON_SIZE = 30 ;
1212const CROP_BUTTON_BORDER = 3 ;
1313const CROP_BUTTON_OFFSET = CROP_BUTTON_SIZE + CROP_BUTTON_BORDER ;
14+ const DPI = WINDOW . devicePixelRatio ;
1415
1516interface FactoryParams {
1617 h : typeof hType ;
@@ -79,8 +80,14 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
7980 const cropper = croppingRef . current ;
8081 const imageDimensions = constructRect ( getContainedSize ( imageBuffer ) ) ;
8182 if ( cropper ) {
82- cropper . width = imageDimensions . width ;
83- cropper . height = imageDimensions . height ;
83+ cropper . width = imageDimensions . width * DPI ;
84+ cropper . height = imageDimensions . height * DPI ;
85+ cropper . style . width = `${ imageDimensions . width } px` ;
86+ cropper . style . height = `${ imageDimensions . height } px` ;
87+ const ctx = cropper . getContext ( '2d' ) ;
88+ if ( ctx ) {
89+ ctx . scale ( DPI , DPI ) ;
90+ }
8491 }
8592
8693 const cropButton = cropContainerRef . current ;
@@ -104,9 +111,9 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
104111 if ( ! ctx ) {
105112 return ;
106113 }
114+
107115 const imageDimensions = constructRect ( getContainedSize ( imageBuffer ) ) ;
108116 const croppingBox = constructRect ( croppingRect ) ;
109-
110117 ctx . clearRect ( 0 , 0 , imageDimensions . width , imageDimensions . height ) ;
111118
112119 // draw gray overlay around the selection
@@ -115,9 +122,12 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
115122 ctx . clearRect ( croppingBox . x , croppingBox . y , croppingBox . width , croppingBox . height ) ;
116123
117124 // draw selection border
118- ctx . strokeStyle = 'purple' ;
125+ ctx . strokeStyle = CROP_COLOR ;
119126 ctx . lineWidth = 3 ;
120- ctx . strokeRect ( croppingBox . x , croppingBox . y , croppingBox . width , croppingBox . height ) ;
127+ ctx . strokeRect ( croppingBox . x + 1 , croppingBox . y + 1 , croppingBox . width - 2 , croppingBox . height - 2 ) ;
128+ ctx . strokeStyle = '#000000' ;
129+ ctx . lineWidth = 1 ;
130+ ctx . strokeRect ( croppingBox . x + 3 , croppingBox . y + 3 , croppingBox . width - 6 , croppingBox . height - 6 ) ;
121131 } , [ croppingRect ] ) ;
122132
123133 function onGrabButton ( e : Event , corner : string ) : void {
@@ -143,32 +153,32 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
143153 const mouseX = e . clientX - cropBoundingRect . x ;
144154 const mouseY = e . clientY - cropBoundingRect . y ;
145155 switch ( corner ) {
146- case 'topleft ' :
156+ case 'top-left ' :
147157 setCroppingRect ( prev => ( {
148158 ...prev ,
149159 startX : Math . min ( Math . max ( 0 , mouseX ) , prev . endX - CROP_BUTTON_OFFSET ) ,
150160 startY : Math . min ( Math . max ( 0 , mouseY ) , prev . endY - CROP_BUTTON_OFFSET ) ,
151161 } ) ) ;
152162 break ;
153- case 'topright ' :
163+ case 'top-right ' :
154164 setCroppingRect ( prev => ( {
155165 ...prev ,
156- endX : Math . max ( Math . min ( mouseX , cropCanvas . width ) , prev . startX + CROP_BUTTON_OFFSET ) ,
166+ endX : Math . max ( Math . min ( mouseX , cropCanvas . width / DPI ) , prev . startX + CROP_BUTTON_OFFSET ) ,
157167 startY : Math . min ( Math . max ( 0 , mouseY ) , prev . endY - CROP_BUTTON_OFFSET ) ,
158168 } ) ) ;
159169 break ;
160- case 'bottomleft ' :
170+ case 'bottom-left ' :
161171 setCroppingRect ( prev => ( {
162172 ...prev ,
163173 startX : Math . min ( Math . max ( 0 , mouseX ) , prev . endX - CROP_BUTTON_OFFSET ) ,
164- endY : Math . max ( Math . min ( mouseY , cropCanvas . height ) , prev . startY + CROP_BUTTON_OFFSET ) ,
174+ endY : Math . max ( Math . min ( mouseY , cropCanvas . height / DPI ) , prev . startY + CROP_BUTTON_OFFSET ) ,
165175 } ) ) ;
166176 break ;
167- case 'bottomright ' :
177+ case 'bottom-right ' :
168178 setCroppingRect ( prev => ( {
169179 ...prev ,
170- endX : Math . max ( Math . min ( mouseX , cropCanvas . width ) , prev . startX + CROP_BUTTON_OFFSET ) ,
171- endY : Math . max ( Math . min ( mouseY , cropCanvas . height ) , prev . startY + CROP_BUTTON_OFFSET ) ,
180+ endX : Math . max ( Math . min ( mouseX , cropCanvas . width / DPI ) , prev . startX + CROP_BUTTON_OFFSET ) ,
181+ endY : Math . max ( Math . min ( mouseY , cropCanvas . height / DPI ) , prev . startY + CROP_BUTTON_OFFSET ) ,
172182 } ) ) ;
173183 break ;
174184 }
@@ -238,40 +248,40 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
238248 return (
239249 < div class = "editor" >
240250 < style dangerouslySetInnerHTML = { styles } />
241- < div class = "canvasContainer " ref = { canvasContainerRef } >
242- < div class = "cropButtonContainer " style = { { position : 'absolute' } } ref = { cropContainerRef } >
251+ < div class = "editor__canvas-container " ref = { canvasContainerRef } >
252+ < div class = "editor__crop-container " style = { { position : 'absolute' } } ref = { cropContainerRef } >
243253 < canvas style = { { position : 'absolute' } } ref = { croppingRef } > </ canvas >
244254 < CropCorner
245- left = { croppingRect . startX }
246- top = { croppingRect . startY }
255+ left = { croppingRect . startX - CROP_BUTTON_BORDER }
256+ top = { croppingRect . startY - CROP_BUTTON_BORDER }
247257 onGrabButton = { onGrabButton }
248- corner = "topleft "
258+ corner = "top-left "
249259 > </ CropCorner >
250260 < CropCorner
251- left = { croppingRect . endX - CROP_BUTTON_SIZE }
252- top = { croppingRect . startY }
261+ left = { croppingRect . endX - CROP_BUTTON_SIZE + CROP_BUTTON_BORDER }
262+ top = { croppingRect . startY - CROP_BUTTON_BORDER }
253263 onGrabButton = { onGrabButton }
254- corner = "topright "
264+ corner = "top-right "
255265 > </ CropCorner >
256266 < CropCorner
257- left = { croppingRect . startX }
258- top = { croppingRect . endY - CROP_BUTTON_SIZE }
267+ left = { croppingRect . startX - CROP_BUTTON_BORDER }
268+ top = { croppingRect . endY - CROP_BUTTON_SIZE + CROP_BUTTON_BORDER }
259269 onGrabButton = { onGrabButton }
260- corner = "bottomleft "
270+ corner = "bottom-left "
261271 > </ CropCorner >
262272 < CropCorner
263- left = { croppingRect . endX - CROP_BUTTON_SIZE }
264- top = { croppingRect . endY - CROP_BUTTON_SIZE }
273+ left = { croppingRect . endX - CROP_BUTTON_SIZE + CROP_BUTTON_BORDER }
274+ top = { croppingRect . endY - CROP_BUTTON_SIZE + CROP_BUTTON_BORDER }
265275 onGrabButton = { onGrabButton }
266- corner = "bottomright "
276+ corner = "bottom-right "
267277 > </ CropCorner >
268278 < div
269279 style = { {
270280 left : Math . max ( 0 , croppingRect . endX - 191 ) ,
271281 top : Math . max ( 0 , croppingRect . endY + 8 ) ,
272282 display : confirmCrop ? 'flex' : 'none' ,
273283 } }
274- class = "crop -btn-group"
284+ class = "editor__crop -btn-group"
275285 >
276286 < button
277287 onClick = { e => {
@@ -280,8 +290,8 @@ export function makeScreenshotEditorComponent({ h, imageBuffer, dialog }: Factor
280290 setCroppingRect ( {
281291 startX : 0 ,
282292 startY : 0 ,
283- endX : croppingRef . current . width ,
284- endY : croppingRef . current . height ,
293+ endX : croppingRef . current . width / DPI ,
294+ endY : croppingRef . current . height / DPI ,
285295 } ) ;
286296 }
287297 setConfirmCrop ( false ) ;
@@ -321,16 +331,10 @@ function CropCorner({
321331} ) : VNode {
322332 return (
323333 < button
324- class = "crop-btn"
334+ class = { `editor__crop-corner editor__crop-corner-- ${ corner } ` }
325335 style = { {
326336 top : top ,
327337 left : left ,
328- borderTop : corner === 'topleft' || corner === 'topright' ? 'solid purple' : 'none' ,
329- borderLeft : corner === 'topleft' || corner === 'bottomleft' ? 'solid purple' : 'none' ,
330- borderRight : corner === 'topright' || corner === 'bottomright' ? 'solid purple' : 'none' ,
331- borderBottom : corner === 'bottomleft' || corner === 'bottomright' ? 'solid purple' : 'none' ,
332- borderWidth : `${ CROP_BUTTON_BORDER } px` ,
333- cursor : corner === 'topleft' || corner === 'bottomright' ? 'nwse-resize' : 'nesw-resize' ,
334338 } }
335339 onMouseDown = { e => {
336340 e . preventDefault ( ) ;
0 commit comments