Make ESC key dismiss MediaEditor and TextStoryCreator modals
This commit is contained in:
parent
385eb63fd5
commit
95be24e8f7
3 changed files with 61 additions and 9 deletions
ts/components
|
@ -97,6 +97,8 @@ export const MediaEditor = ({
|
|||
}: PropsType): JSX.Element | null => {
|
||||
const [fabricCanvas, setFabricCanvas] = useState<fabric.Canvas | undefined>();
|
||||
const [image, setImage] = useState<HTMLImageElement>(new Image());
|
||||
const [isStickerPopperOpen, setIsStickerPopperOpen] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const canvasId = useUniqueId();
|
||||
|
||||
|
@ -147,6 +149,8 @@ export const MediaEditor = ({
|
|||
};
|
||||
}, [canvasId, fabricCanvas, imageSrc, onClose, takeSnapshot]);
|
||||
|
||||
const [editMode, setEditMode] = useState<EditMode | undefined>();
|
||||
|
||||
// Keyboard support
|
||||
useEffect(() => {
|
||||
if (!fabricCanvas) {
|
||||
|
@ -173,7 +177,19 @@ export const MediaEditor = ({
|
|||
[
|
||||
ev => ev.key === 'Escape',
|
||||
() => {
|
||||
setEditMode(undefined);
|
||||
// close window if the user is not in the middle of something
|
||||
if (editMode === undefined) {
|
||||
// if the stickers popper is open,
|
||||
// it will use the escape key to close itself
|
||||
//
|
||||
// there's no easy way to prevent an ESC meant for the
|
||||
// sticker-picker from hitting this handler first
|
||||
if (!isStickerPopperOpen) {
|
||||
onClose();
|
||||
}
|
||||
} else {
|
||||
setEditMode(undefined);
|
||||
}
|
||||
|
||||
if (fabricCanvas.getActiveObject()) {
|
||||
fabricCanvas.discardActiveObject();
|
||||
|
@ -307,7 +323,14 @@ export const MediaEditor = ({
|
|||
return () => {
|
||||
document.removeEventListener('keydown', handleKeydown);
|
||||
};
|
||||
}, [fabricCanvas, redoIfPossible, undoIfPossible]);
|
||||
}, [
|
||||
fabricCanvas,
|
||||
editMode,
|
||||
isStickerPopperOpen,
|
||||
onClose,
|
||||
redoIfPossible,
|
||||
undoIfPossible,
|
||||
]);
|
||||
|
||||
const [containerWidth, setContainerWidth] = useState(0);
|
||||
const [containerHeight, setContainerHeight] = useState(0);
|
||||
|
@ -349,7 +372,6 @@ export const MediaEditor = ({
|
|||
const [cropAspectRatioLock, setCropAspectRatioLock] = useState(false);
|
||||
const [drawTool, setDrawTool] = useState<DrawTool>(DrawTool.Pen);
|
||||
const [drawWidth, setDrawWidth] = useState<DrawWidth>(DrawWidth.Regular);
|
||||
const [editMode, setEditMode] = useState<EditMode | undefined>();
|
||||
const [sliderValue, setSliderValue] = useState<number>(0);
|
||||
const [textStyle, setTextStyle] = useState<TextStyle>(TextStyle.Regular);
|
||||
|
||||
|
@ -921,6 +943,9 @@ export const MediaEditor = ({
|
|||
MediaEditor__control: true,
|
||||
'MediaEditor__control--sticker': true,
|
||||
})}
|
||||
onOpenStateChanged={value => {
|
||||
setIsStickerPopperOpen(value);
|
||||
}}
|
||||
clearInstalledStickerPack={noop}
|
||||
clearShowIntroduction={() => {
|
||||
// We're using this as a callback for when the sticker button
|
||||
|
|
|
@ -214,9 +214,19 @@ export const TextStoryCreator = ({
|
|||
};
|
||||
const handleEscape = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
setIsColorPickerShowing(false);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (
|
||||
isColorPickerShowing ||
|
||||
isEditingText ||
|
||||
isLinkPreviewInputShowing
|
||||
) {
|
||||
setIsColorPickerShowing(false);
|
||||
setIsEditingText(false);
|
||||
setIsLinkPreviewInputShowing(false);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -227,7 +237,13 @@ export const TextStoryCreator = ({
|
|||
document.removeEventListener('click', handleOutsideClick);
|
||||
document.removeEventListener('keydown', handleEscape);
|
||||
};
|
||||
}, [isColorPickerShowing, colorPickerPopperButtonRef]);
|
||||
}, [
|
||||
isColorPickerShowing,
|
||||
isEditingText,
|
||||
isLinkPreviewInputShowing,
|
||||
colorPickerPopperButtonRef,
|
||||
onClose,
|
||||
]);
|
||||
|
||||
const sliderColorNumber = getRGBANumber(sliderValue);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ export type OwnProps = {
|
|||
readonly knownPacks: ReadonlyArray<StickerPackType>;
|
||||
readonly installedPack?: StickerPackType | null;
|
||||
readonly recentStickers: ReadonlyArray<StickerType>;
|
||||
readonly onOpenStateChanged?: (isOpen: boolean) => void;
|
||||
readonly clearInstalledStickerPack: () => unknown;
|
||||
readonly onClickAddPack?: () => unknown;
|
||||
readonly onPickSticker: (
|
||||
|
@ -51,6 +52,7 @@ export const StickerButton = React.memo(
|
|||
onClickAddPack,
|
||||
onPickSticker,
|
||||
recentStickers,
|
||||
onOpenStateChanged,
|
||||
receivedPacks,
|
||||
installedPack,
|
||||
installedPacks,
|
||||
|
@ -63,7 +65,16 @@ export const StickerButton = React.memo(
|
|||
position = 'top-end',
|
||||
theme,
|
||||
}: Props) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [open, internalSetOpen] = React.useState(false);
|
||||
|
||||
const setOpen = React.useCallback(
|
||||
(value: boolean) => {
|
||||
internalSetOpen(value);
|
||||
if (onOpenStateChanged) onOpenStateChanged(value);
|
||||
},
|
||||
[internalSetOpen, onOpenStateChanged]
|
||||
);
|
||||
|
||||
const [popperRoot, setPopperRoot] = React.useState<HTMLElement | null>(
|
||||
null
|
||||
);
|
||||
|
@ -110,7 +121,7 @@ export const StickerButton = React.memo(
|
|||
clearShowPickerHint();
|
||||
}
|
||||
onClickAddPack?.();
|
||||
}, [onClickAddPack, showPickerHint, clearShowPickerHint]);
|
||||
}, [onClickAddPack, showPickerHint, setOpen, clearShowPickerHint]);
|
||||
|
||||
const handleClearIntroduction = React.useCallback(() => {
|
||||
clearInstalledStickerPack();
|
||||
|
|
Loading…
Add table
Reference in a new issue