diff --git a/ts/components/MediaEditor.tsx b/ts/components/MediaEditor.tsx index 9a39ebe68a..45df98f082 100644 --- a/ts/components/MediaEditor.tsx +++ b/ts/components/MediaEditor.tsx @@ -97,6 +97,8 @@ export const MediaEditor = ({ }: PropsType): JSX.Element | null => { const [fabricCanvas, setFabricCanvas] = useState(); const [image, setImage] = useState(new Image()); + const [isStickerPopperOpen, setIsStickerPopperOpen] = + useState(false); const canvasId = useUniqueId(); @@ -147,6 +149,8 @@ export const MediaEditor = ({ }; }, [canvasId, fabricCanvas, imageSrc, onClose, takeSnapshot]); + const [editMode, setEditMode] = useState(); + // 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.Pen); const [drawWidth, setDrawWidth] = useState(DrawWidth.Regular); - const [editMode, setEditMode] = useState(); const [sliderValue, setSliderValue] = useState(0); const [textStyle, setTextStyle] = useState(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 diff --git a/ts/components/TextStoryCreator.tsx b/ts/components/TextStoryCreator.tsx index be6f4b80c0..9e5d0e642d 100644 --- a/ts/components/TextStoryCreator.tsx +++ b/ts/components/TextStoryCreator.tsx @@ -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); diff --git a/ts/components/stickers/StickerButton.tsx b/ts/components/stickers/StickerButton.tsx index e616a5699d..1c80262df2 100644 --- a/ts/components/stickers/StickerButton.tsx +++ b/ts/components/stickers/StickerButton.tsx @@ -26,6 +26,7 @@ export type OwnProps = { readonly knownPacks: ReadonlyArray; readonly installedPack?: StickerPackType | null; readonly recentStickers: ReadonlyArray; + 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( null ); @@ -110,7 +121,7 @@ export const StickerButton = React.memo( clearShowPickerHint(); } onClickAddPack?.(); - }, [onClickAddPack, showPickerHint, clearShowPickerHint]); + }, [onClickAddPack, showPickerHint, setOpen, clearShowPickerHint]); const handleClearIntroduction = React.useCallback(() => { clearInstalledStickerPack();