Skip to content

Commit

Permalink
removed stupid duplicated hotkey functionality and replaced it with (…
Browse files Browse the repository at this point in the history
…almost) automatic component-based hotkey handling, added feature to delete uploaded image
  • Loading branch information
arttu76 committed Dec 4, 2023
1 parent 0a00a8a commit bcbca3f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 167 deletions.
31 changes: 30 additions & 1 deletion src/components/CustomElements.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useEffect, useRef } from "react";
import "../styles/CustomElements.scss";

import { Icon } from "./Icon";
Expand All @@ -17,7 +18,19 @@ export const Button: React.FC<
> = (props) => {
const { dimmed = false, tooltip, hotkey, icon, ...buttonProps } = props;
const tooltipContent = tooltip + (hotkey ? ` (${hotkey})` : '');

const buttonRef = useRef<HTMLButtonElement>(null);

useEffect(() => {
if (!hotkey) return;

const handleKeyDown = (e: KeyboardEvent) => e.key.toLowerCase() === hotkey.toLowerCase() && buttonRef.current?.click();
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);

return <button
ref={buttonRef}
className="CustomElements"
style={{ opacity: dimmed ? 0.5 : 1 }}
{...buttonProps}
Expand All @@ -31,8 +44,12 @@ export const Button: React.FC<
export const Input: React.FC<
CommonCustomElementProps
& React.InputHTMLAttributes<HTMLInputElement>
& {
hotkey?: string;
hotkeyFunc?: () => void;
}
> = (props) => {
const { dimmed, tooltip, ...inputProps } = props;
const { dimmed, tooltip, hotkey, hotkeyFunc, ...inputProps } = props;

if (props.type === 'checkbox') {
return <Icon
Expand All @@ -47,6 +64,18 @@ export const Input: React.FC<
/>
}

useEffect(() => {
if (!hotkey || !hotkeyFunc) return;

const handleKeyDown = (e: KeyboardEvent) => {
if (e.key.toLowerCase() === hotkey.toLowerCase()) {
hotkeyFunc();
}
}
document.addEventListener('keydown', handleKeyDown);

return () => document.removeEventListener('keydown', handleKeyDown);
}, []);

return <input
className="CustomElements"
Expand Down
96 changes: 55 additions & 41 deletions src/components/LayerEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
expandLayer,
preserveLayerAspectRatio,
removeLayer,
removeLayerImage,
setActive,
setLayerBlue,
setLayerBlur,
Expand Down Expand Up @@ -57,6 +58,8 @@ import { Icon } from './Icon';

export const LayerEditor: React.FC<{ layer: Layer }> = ({ layer }) => {

const dispatch = useAppDispatch();

// for uploads
const [imageUrl, setImageUrl] = useState<string | null>(null);
const imageUploadInputRef = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -162,7 +165,12 @@ export const LayerEditor: React.FC<{ layer: Layer }> = ({ layer }) => {
}
}

const dispatch = useAppDispatch();
const removeUploadedImage = () => {
if (!confirm('Are you sure you want to remove the uploaded image? Your mask and manual pixels and attributes will not be deleted.')) {
return;
}
dispatch(removeLayerImage({ layer }));
}

type LayerKey = keyof Layer;
// any below is { layer: Layer; } & Partial<Layer>
Expand Down Expand Up @@ -242,7 +250,11 @@ export const LayerEditor: React.FC<{ layer: Layer }> = ({ layer }) => {
</div>

<div>
<Group title="Paste or upload image">
<Group title="Paste or upload image"
className='ImageUploader'
cornerIcon={layer.imageId ? "delete" : undefined}
cornerIconTooltip={layer.imageId ? "Remove uploaded image" : undefined}
cornerIconOnClick={layer.imageId ? removeUploadedImage : undefined}>
<div className="ImageUploaderIcon">
Paste (right-click) or click to upload image
<div className="IconPasteArea"
Expand Down Expand Up @@ -285,44 +297,46 @@ export const LayerEditor: React.FC<{ layer: Layer }> = ({ layer }) => {
max={192}
allowOutOfBounds={true}
/>
<LayerPropertyEditor
title="Width"
layer={layer}
fieldName="width"
change={changeLayerAttribute(setLayerWidth)}
reset={layer.originalWidth}
min={1}
max={safeZero(layer.originalWidth) * 2}
allowOutOfBounds={true}
extra={Math.round(safeDivide((safeZero(layer.width) * 1000), layer.originalWidth)) / 10 + "%"}
/>
<div style={{ textAlign: "center" }}>
<Button
tooltip={layer.preserveLayerAspectRatio ? 'Preserve original aspect ratio' : 'Do not preserve aspect ratio'}
icon={layer.preserveLayerAspectRatio ? 'lock' : 'lock_open_right'}
onClick={() => changeLayerAttribute(preserveLayerAspectRatio)(layer, 'preserveLayerAspectRatio', !layer.preserveLayerAspectRatio)}
></Button>
</div>
<LayerPropertyEditor
title="Height"
layer={layer}
fieldName="height"
change={changeLayerAttribute(setLayerHeight)}
reset={layer.originalHeight}
min={1}
max={safeZero(layer.originalHeight) * 2}
allowOutOfBounds={true}
extra={Math.round(safeDivide((safeZero(layer.height) * 1000), layer.originalHeight)) / 10 + "%"}
/>
<LayerPropertyEditor
title="Rotate"
layer={layer}
fieldName="rotate"
change={changeLayerAttribute(setLayerRotate)}
reset={0}
min={-360}
max={360}
/>
{layer.imageId && <>
<LayerPropertyEditor
title="Width"
layer={layer}
fieldName="width"
change={changeLayerAttribute(setLayerWidth)}
reset={layer.originalWidth}
min={1}
max={safeZero(layer.originalWidth) * 2}
allowOutOfBounds={true}
extra={Math.round(safeDivide((safeZero(layer.width) * 1000), layer.originalWidth)) / 10 + "%"}
/>
<div style={{ textAlign: "center" }}>
<Button
tooltip={layer.preserveLayerAspectRatio ? 'Preserve original aspect ratio' : 'Do not preserve aspect ratio'}
icon={layer.preserveLayerAspectRatio ? 'lock' : 'lock_open_right'}
onClick={() => changeLayerAttribute(preserveLayerAspectRatio)(layer, 'preserveLayerAspectRatio', !layer.preserveLayerAspectRatio)}
></Button>
</div>
<LayerPropertyEditor
title="Height"
layer={layer}
fieldName="height"
change={changeLayerAttribute(setLayerHeight)}
reset={layer.originalHeight}
min={1}
max={safeZero(layer.originalHeight) * 2}
allowOutOfBounds={true}
extra={Math.round(safeDivide((safeZero(layer.height) * 1000), layer.originalHeight)) / 10 + "%"}
/>
<LayerPropertyEditor
title="Rotate"
layer={layer}
fieldName="rotate"
change={changeLayerAttribute(setLayerRotate)}
reset={0}
min={-360}
max={360}
/>
</>}
<div style={{ paddingBottom: '10px', display: 'flex', justifyContent: 'space-evenly' }}>
<div>
Flip X:&nbsp;
Expand Down Expand Up @@ -549,6 +563,6 @@ export const LayerEditor: React.FC<{ layer: Layer }> = ({ layer }) => {
</Group>
</div>

</div>
</div >
);
}
Loading

0 comments on commit bcbca3f

Please sign in to comment.