Skip to content

Commit 7c063b3

Browse files
committed
allow zooming/panning while drawing
1 parent 02026f8 commit 7c063b3

24 files changed

+231
-41
lines changed

assets/.DS_Store

0 Bytes
Binary file not shown.

assets/icons/draw-clear-hover.png

8.83 KB
Loading

assets/icons/draw-clear.png

10.2 KB
Loading

assets/icons/draw-decrease-hover.png

3.69 KB
Loading

assets/icons/draw-decrease.png

4.36 KB
Loading

assets/icons/draw-increase-hover.png

3.66 KB
Loading

assets/icons/draw-increase.png

4.27 KB
Loading

components/BinarizeDialog.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ const BinarizeDialog: React.FunctionComponent = (props) => {
2121
functions.updateTheme(theme, transparency)
2222
}
2323
initTheme()
24+
const savedValues = async () => {
25+
const savedBinarize = await ipcRenderer.invoke("get-temp", "binarize")
26+
if (savedBinarize) changeState("binarize", Number(savedBinarize))
27+
}
28+
savedValues()
2429
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2530
functions.updateTheme(theme, transparency)
2631
}
@@ -62,6 +67,7 @@ const BinarizeDialog: React.FunctionComponent = (props) => {
6267
return {...prev, binarize: value}
6368
})
6469
ipcRenderer.invoke("apply-binarize", {...state, binarize: value, realTime: true})
70+
ipcRenderer.invoke("save-temp", "binarize", String(value))
6571
break
6672
}
6773
}

components/BlurDialog.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ const BlurDialog: React.FunctionComponent = (props) => {
2020
functions.updateTheme(theme, transparency)
2121
}
2222
initTheme()
23+
const savedValues = async () => {
24+
const savedBlur= await ipcRenderer.invoke("get-temp", "blur")
25+
const savedSharpen = await ipcRenderer.invoke("get-temp", "sharpen")
26+
if (savedBlur) changeState("blur", Number(savedBlur))
27+
if (savedSharpen) changeState("sharpen", Number(savedSharpen))
28+
}
29+
savedValues()
2330
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2431
functions.updateTheme(theme, transparency)
2532
}
@@ -61,12 +68,14 @@ const BlurDialog: React.FunctionComponent = (props) => {
6168
return {...prev, blur: value}
6269
})
6370
ipcRenderer.invoke("apply-blur", {...state, blur: value, realTime: true})
71+
ipcRenderer.invoke("save-temp", "blur", String(value))
6472
break
6573
case "sharpen":
6674
setState((prev) => {
6775
return {...prev, sharpen: value}
6876
})
6977
ipcRenderer.invoke("apply-blur", {...state, sharpen: value, realTime: true})
78+
ipcRenderer.invoke("save-temp", "sharoen", String(value))
7079
break
7180
}
7281
}

components/BrightnessDialog.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ const BrightnessDialog: React.FunctionComponent = (props) => {
2020
functions.updateTheme(theme, transparency)
2121
}
2222
initTheme()
23+
const savedValues = async () => {
24+
const savedBrightness = await ipcRenderer.invoke("get-temp", "brightness")
25+
const savedContrast = await ipcRenderer.invoke("get-temp", "contrast")
26+
if (savedBrightness) changeState("brightness", Number(savedBrightness))
27+
if (savedContrast) changeState("contrast", Number(savedContrast))
28+
}
29+
savedValues()
2330
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2431
functions.updateTheme(theme, transparency)
2532
}
@@ -61,12 +68,14 @@ const BrightnessDialog: React.FunctionComponent = (props) => {
6168
return {...prev, brightness: value}
6269
})
6370
ipcRenderer.invoke("apply-brightness", {...state, brightness: value, realTime: true})
71+
ipcRenderer.invoke("save-temp", "brightness", String(value))
6472
break
6573
case "contrast":
6674
setState((prev) => {
6775
return {...prev, contrast: value}
6876
})
6977
ipcRenderer.invoke("apply-brightness", {...state, contrast: value, realTime: true})
78+
ipcRenderer.invoke("save-temp", "contrast", String(value))
7079
break
7180
}
7281
}

components/ContextMenu.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,18 @@ const ContextMenu: React.FunctionComponent = (props) => {
4949
ipcRenderer.invoke("copy-address", image)
5050
}
5151

52+
const clearCache = () => {
53+
ipcRenderer.invoke("clear-temp")
54+
}
55+
5256

5357
if (visible) {
5458
return (
5559
<section ref={contextMenu} className="context-menu" onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}>
5660
<button className="context-button" onClick={(event) => copy(event)}>Copy</button>
5761
<button className="context-button" onClick={() => paste()}>Paste</button>
5862
<button className="context-button" onClick={(event) => getInfo(event)}>Get Info</button>
63+
<button className="context-button" onClick={() => clearCache()}>Clear Cache</button>
5964
<button className="context-button" onClick={() => saveImage()}>Save Image</button>
6065
<button className="context-button" onClick={(event) => copyAddress(event)}>Copy Address</button>
6166
</section>

components/CropDialog.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ const CropDialog: React.FunctionComponent = (props) => {
2121
functions.updateTheme(theme, transparency)
2222
}
2323
initTheme()
24+
const savedValues = async () => {
25+
const savedX = await ipcRenderer.invoke("get-temp", "x")
26+
const savedY = await ipcRenderer.invoke("get-temp", "y")
27+
const savedWidth = await ipcRenderer.invoke("get-temp", "width")
28+
const savedHeight = await ipcRenderer.invoke("get-temp", "height")
29+
if (savedX) changeState("x", Number(savedX))
30+
if (savedY) changeState("y", Number(savedY))
31+
if (savedWidth) changeState("width", Number(savedWidth))
32+
if (savedHeight) changeState("height", Number(savedHeight))
33+
}
34+
savedValues()
2435
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2536
functions.updateTheme(theme, transparency)
2637
}
@@ -62,24 +73,28 @@ const CropDialog: React.FunctionComponent = (props) => {
6273
return {...prev, x: value}
6374
})
6475
ipcRenderer.invoke("apply-crop", {...state, x: value, realTime: true})
76+
ipcRenderer.invoke("save-temp", "x", String(value))
6577
break
6678
case "y":
6779
setState((prev) => {
6880
return {...prev, y: value}
6981
})
7082
ipcRenderer.invoke("apply-crop", {...state, y: value, realTime: true})
83+
ipcRenderer.invoke("save-temp", "y", String(value))
7184
break
7285
case "width":
7386
setState((prev) => {
7487
return {...prev, width: value}
7588
})
7689
ipcRenderer.invoke("apply-crop", {...state, width: value, realTime: true})
90+
ipcRenderer.invoke("save-temp", "width", String(value))
7791
break
7892
case "height":
7993
setState((prev) => {
8094
return {...prev, height: value}
8195
})
8296
ipcRenderer.invoke("apply-crop", {...state, height: value, realTime: true})
97+
ipcRenderer.invoke("save-temp", "height", String(value))
8398
break
8499
}
85100
}

components/GIFDialog.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ const GIFDialog: React.FunctionComponent = (props) => {
2929
functions.updateTheme(theme, transparency)
3030
}
3131
initTheme()
32+
const savedValues = async () => {
33+
const savedSpeed = await ipcRenderer.invoke("get-temp", "speed")
34+
const savedReverse = await ipcRenderer.invoke("get-temp", "reverse")
35+
const savedTransparency = await ipcRenderer.invoke("get-temp", "transparency")
36+
const savedTransparentColor = await ipcRenderer.invoke("get-temp", "transparentColor")
37+
if (savedSpeed) changeState("speed", Number(savedSpeed))
38+
if (savedReverse) changeState("reverse", savedReverse === "true")
39+
if (savedTransparency) changeState("transparency", savedTransparency === "true")
40+
if (savedTransparentColor) changeState("transparentColor", savedTransparentColor)
41+
}
42+
savedValues()
3243
const updateTheme = (event: any, theme: string, transparency: boolean) => {
3344
functions.updateTheme(theme, transparency)
3445
}
@@ -74,21 +85,25 @@ const GIFDialog: React.FunctionComponent = (props) => {
7485
setState((prev) => {
7586
return {...prev, speed: value}
7687
})
88+
ipcRenderer.invoke("save-temp", "speed", String(value))
7789
break
7890
case "reverse":
7991
setState((prev) => {
8092
return {...prev, reverse: value}
8193
})
94+
ipcRenderer.invoke("save-temp", "reverse", String(value))
8295
break
8396
case "transparency":
8497
setState((prev) => {
8598
return {...prev, transparency: value}
8699
})
100+
ipcRenderer.invoke("save-temp", "transparency", String(value))
87101
break
88102
case "transparentColor":
89103
setState((prev) => {
90104
return {...prev, transparentColor: value}
91105
})
106+
ipcRenderer.invoke("save-temp", "transparentColor", String(value))
92107
break
93108
}
94109
}

components/HSLDialog.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,23 @@ const HSLDialog: React.FunctionComponent = (props) => {
1414
const [state, setState] = useState(initialState)
1515
const [hover, setHover] = useState(false)
1616

17+
1718
useEffect(() => {
1819
const initTheme = async () => {
1920
const theme = await ipcRenderer.invoke("get-theme")
2021
const transparency = await ipcRenderer.invoke("get-transparency")
2122
functions.updateTheme(theme, transparency)
2223
}
2324
initTheme()
25+
const savedValues = async () => {
26+
const savedHue = await ipcRenderer.invoke("get-temp", "hue")
27+
const savedSaturation = await ipcRenderer.invoke("get-temp", "saturation")
28+
const savedLightness = await ipcRenderer.invoke("get-temp", "lightness")
29+
if (savedHue) changeState("hue", Number(savedHue))
30+
if (savedSaturation) changeState("saturation", Number(savedSaturation))
31+
if (savedLightness) changeState("lightness", Number(savedLightness))
32+
}
33+
savedValues()
2434
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2535
functions.updateTheme(theme, transparency)
2636
}
@@ -62,18 +72,21 @@ const HSLDialog: React.FunctionComponent = (props) => {
6272
return {...prev, hue: value}
6373
})
6474
ipcRenderer.invoke("apply-hsl", {...state, hue: value, realTime: true})
75+
ipcRenderer.invoke("save-temp", "hue", String(value))
6576
break
6677
case "saturation":
6778
setState((prev) => {
6879
return {...prev, saturation: value}
6980
})
7081
ipcRenderer.invoke("apply-hsl", {...state, saturation: value, realTime: true})
82+
ipcRenderer.invoke("save-temp", "saturation", String(value))
7183
break
7284
case "lightness":
7385
setState((prev) => {
7486
return {...prev, lightness: value}
7587
})
7688
ipcRenderer.invoke("apply-hsl", {...state, lightness: value, realTime: true})
89+
ipcRenderer.invoke("save-temp", "lightness", String(value))
7790
break
7891
}
7992
}

components/PhotoViewer.tsx

+24-7
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ const PhotoViewer: React.FunctionComponent = (props) => {
164164
ipcRenderer.on("bulk-process", bulkProcess)
165165
ipcRenderer.on("draw", draw)
166166
ipcRenderer.on("draw-undo", undoDraw)
167-
ipcRenderer.on("draw-invert", invertDraw)
167+
ipcRenderer.on("draw-clear", clearDraw)
168+
ipcRenderer.on("draw-increase-size", increaseBrushSize)
169+
ipcRenderer.on("draw-decrease-size", decreaseBrushSize)
168170
document.addEventListener("dblclick", doubleClick)
169171
return () => {
170172
ipcRenderer.removeListener("open-file", openFile)
@@ -185,12 +187,21 @@ const PhotoViewer: React.FunctionComponent = (props) => {
185187
ipcRenderer.removeListener("bulk-process", bulkProcess)
186188
ipcRenderer.removeListener("draw", draw)
187189
ipcRenderer.removeListener("draw-undo", undoDraw)
188-
ipcRenderer.removeListener("draw-invert", invertDraw)
190+
ipcRenderer.removeListener("draw-clear", clearDraw)
191+
ipcRenderer.removeListener("draw-increase-size", increaseBrushSize)
192+
ipcRenderer.removeListener("draw-decrease-size", decreaseBrushSize)
189193
document.removeEventListener("dblclick", doubleClick)
190194
ipcRenderer.removeListener("apply-crop", bulkCrop)
191195
}
192196
}, [])
193197

198+
useEffect(() => {
199+
ipcRenderer.on("draw-invert", invertDraw)
200+
return () => {
201+
ipcRenderer.removeListener("draw-invert", invertDraw)
202+
}
203+
}, [brushColor])
204+
194205
useEffect(() => {
195206
const triggerUndo = () => {
196207
if (drawing) return undoDraw()
@@ -323,6 +334,7 @@ const PhotoViewer: React.FunctionComponent = (props) => {
323334
document.documentElement.style.setProperty("cursor", "grab", "important")
324335
}
325336
if (event.key === "r") {
337+
if (drawing) return
326338
if (rotateEnabled) {
327339
const selection = document.querySelector(".ReactCrop__crop-selection") as HTMLDivElement
328340
if (selection?.style.opacity === "1") {
@@ -389,6 +401,7 @@ const PhotoViewer: React.FunctionComponent = (props) => {
389401
setRotateEnabled(false)
390402
}
391403
const wheel = (event: WheelEvent) => {
404+
/*
392405
// @ts-ignore
393406
const trackPad = event.wheelDeltaY ? event.wheelDeltaY === -3 * event.deltaY : event.deltaMode === 0
394407
if (event.deltaY < 0) {
@@ -403,7 +416,7 @@ const PhotoViewer: React.FunctionComponent = (props) => {
403416
} else {
404417
increaseBrushSize()
405418
}
406-
}
419+
}*/
407420
}
408421
ipcRenderer.on("accept-action-response", acceptActionResponse)
409422
document.addEventListener("wheel", wheel)
@@ -682,6 +695,10 @@ const PhotoViewer: React.FunctionComponent = (props) => {
682695
}
683696
}
684697

698+
const clearDraw = () => {
699+
drawRef.current.clear()
700+
}
701+
685702
const undoDraw = () => {
686703
drawRef.current.undo()
687704
}
@@ -755,16 +772,16 @@ const PhotoViewer: React.FunctionComponent = (props) => {
755772
<img className="adjustment-img" src={saveHover ? saveButtonHover : saveButton} onClick={() => save()} width={30} height={30} onMouseEnter={() => setSaveHover(true)} onMouseLeave={() => setSaveHover(false)}/>
756773
<img className="adjustment-img" src={resetHover ? resetButtonHover : resetButton} onClick={() => reset()} width={30} height={30} onMouseEnter={() => setResetHover(true)} onMouseLeave={() => setResetHover(false)}/>
757774
</div>
758-
<TransformWrapper ref={zoomRef} minScale={0.5} limitToBounds={false} minPositionX={-200} maxPositionX={200} minPositionY={-200} maxPositionY={200}
759-
onZoomStop={(ref) => setZoomScale(ref.state.scale)} disabled={drawing} wheel={{step: 0.1}} pinch={{disabled: true}} zoomAnimation={{size: 0}}
775+
<TransformWrapper ref={zoomRef} minScale={0.5} limitToBounds={false} minPositionX={-200} maxPositionX={200} minPositionY={-200} maxPositionY={200} onZoom={(ref) => setZoomScale(ref.state.scale)}
776+
onZoomStop={(ref) => setZoomScale(ref.state.scale)} panning={{allowLeftClickPan: !drawing, allowRightClickPan: false}} wheel={{step: 0.1}} pinch={{disabled: true}} zoomAnimation={{size: 0}}
760777
alignmentAnimation={{disabled: true}} doubleClick={{mode: "reset", animationTime: 0}}>
761778
<TransformComponent>
762779
<div className="rotate-photo-container" style={{transform: `rotate(${rotateDegrees}deg)`}}>
763780
{bulk ? <BulkContainer files={bulkFiles}/> :
764781
<div className="photo-container">
765782
{drawing ? <CanvasDraw ref={drawRef} className="draw-img" lazyRadius={0} brushRadius={brushSize} brushColor={brushColor}
766-
catenaryColor="rgba(21, 133, 252, 0)" hideGrid={true} canvasWidth={width} canvasHeight={height} imgSrc={image} erase={erasing}
767-
loadTimeOffset={0} eraseColor="#000000"/> :
783+
catenaryColor="rgba(0, 0, 0, 0)" hideGrid={true} canvasWidth={width} canvasHeight={height} imgSrc={image} erase={erasing}
784+
loadTimeOffset={0} eraseColor="#000000" zoom={zoomScale} style={{transform: `rotate(${-rotateDegrees}deg)`}}/> :
768785
<ReactCrop className="photo" src={image} zoom={zoomScale} spin={rotateDegrees} crop={cropState as any}
769786
onChange={(crop: any, percentCrop: any) => setCropState(percentCrop as any)} disabled={!cropEnabled} keepSelection={true}/>}
770787
</div>}

components/PixelateDialog.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ const PixelateDialog: React.FunctionComponent = (props) => {
1919
functions.updateTheme(theme, transparency)
2020
}
2121
initTheme()
22+
const savedValues = async () => {
23+
const savedPixelate = await ipcRenderer.invoke("get-temp", "pixelate")
24+
if (savedPixelate) changeState("strength", Number(savedPixelate))
25+
}
26+
savedValues()
2227
const updateTheme = (event: any, theme: string, transparency: boolean) => {
2328
functions.updateTheme(theme, transparency)
2429
}
@@ -60,6 +65,7 @@ const PixelateDialog: React.FunctionComponent = (props) => {
6065
return {...prev, strength: value}
6166
})
6267
ipcRenderer.invoke("apply-pixelate", {...state, strength: value, realTime: true})
68+
ipcRenderer.invoke("save-temp", "pixelate", String(value))
6369
break
6470
}
6571
}

components/ResizeDialog.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ const ResizeDialog: React.FunctionComponent = (props) => {
3939
functions.updateTheme(theme, transparency)
4040
}
4141
initTheme()
42+
const savedValues = async () => {
43+
const savedResize = await ipcRenderer.invoke("get-temp", "resize")
44+
if (savedResize) changeState("resize", JSON.parse(savedResize))
45+
}
46+
savedValues()
4247
const updateTheme = (event: any, theme: string, transparency: boolean) => {
4348
functions.updateTheme(theme, transparency)
4449
}
@@ -80,6 +85,7 @@ const ResizeDialog: React.FunctionComponent = (props) => {
8085
return {...prev, width: newState.width, height: newState.height}
8186
})
8287
ipcRenderer.invoke("apply-resize", {...state, width: newState.width, height: newState.height, percent: state.percent, realTime: true})
88+
ipcRenderer.invoke("save-temp", "resize", JSON.stringify(newState))
8389
break
8490
}
8591
}

components/RotateDialog.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ const RotateDialog: React.FunctionComponent = (props) => {
3131
functions.updateTheme(theme, transparency)
3232
}
3333
initTheme()
34+
const savedValues = async () => {
35+
const savedRotation = await ipcRenderer.invoke("get-temp", "rotation")
36+
if (savedRotation) changeState("degrees", Number(savedRotation))
37+
}
38+
savedValues()
3439
const updateTheme = (event: any, theme: string, transparency: boolean) => {
3540
functions.updateTheme(theme, transparency)
3641
}
@@ -72,6 +77,7 @@ const RotateDialog: React.FunctionComponent = (props) => {
7277
return {...prev, degrees: value}
7378
})
7479
ipcRenderer.invoke("apply-rotate", {...state, degrees: value, realTime: true})
80+
ipcRenderer.invoke("get-temp", "rotation", String(value))
7581
break
7682
}
7783
}

0 commit comments

Comments
 (0)