Make ESC key dismiss MediaEditor and TextStoryCreator modals

This commit is contained in:
Alvaro 2022-08-15 13:35:30 -06:00 committed by GitHub
parent 385eb63fd5
commit 95be24e8f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 9 deletions

View file

@ -97,6 +97,8 @@ export const MediaEditor = ({
}: PropsType): JSX.Element | null => { }: PropsType): JSX.Element | null => {
const [fabricCanvas, setFabricCanvas] = useState<fabric.Canvas | undefined>(); const [fabricCanvas, setFabricCanvas] = useState<fabric.Canvas | undefined>();
const [image, setImage] = useState<HTMLImageElement>(new Image()); const [image, setImage] = useState<HTMLImageElement>(new Image());
const [isStickerPopperOpen, setIsStickerPopperOpen] =
useState<boolean>(false);
const canvasId = useUniqueId(); const canvasId = useUniqueId();
@ -147,6 +149,8 @@ export const MediaEditor = ({
}; };
}, [canvasId, fabricCanvas, imageSrc, onClose, takeSnapshot]); }, [canvasId, fabricCanvas, imageSrc, onClose, takeSnapshot]);
const [editMode, setEditMode] = useState<EditMode | undefined>();
// Keyboard support // Keyboard support
useEffect(() => { useEffect(() => {
if (!fabricCanvas) { if (!fabricCanvas) {
@ -173,7 +177,19 @@ export const MediaEditor = ({
[ [
ev => ev.key === 'Escape', 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()) { if (fabricCanvas.getActiveObject()) {
fabricCanvas.discardActiveObject(); fabricCanvas.discardActiveObject();
@ -307,7 +323,14 @@ export const MediaEditor = ({
return () => { return () => {
document.removeEventListener('keydown', handleKeydown); document.removeEventListener('keydown', handleKeydown);
}; };
}, [fabricCanvas, redoIfPossible, undoIfPossible]); }, [
fabricCanvas,
editMode,
isStickerPopperOpen,
onClose,
redoIfPossible,
undoIfPossible,
]);
const [containerWidth, setContainerWidth] = useState(0); const [containerWidth, setContainerWidth] = useState(0);
const [containerHeight, setContainerHeight] = useState(0); const [containerHeight, setContainerHeight] = useState(0);
@ -349,7 +372,6 @@ export const MediaEditor = ({
const [cropAspectRatioLock, setCropAspectRatioLock] = useState(false); const [cropAspectRatioLock, setCropAspectRatioLock] = useState(false);
const [drawTool, setDrawTool] = useState<DrawTool>(DrawTool.Pen); const [drawTool, setDrawTool] = useState<DrawTool>(DrawTool.Pen);
const [drawWidth, setDrawWidth] = useState<DrawWidth>(DrawWidth.Regular); const [drawWidth, setDrawWidth] = useState<DrawWidth>(DrawWidth.Regular);
const [editMode, setEditMode] = useState<EditMode | undefined>();
const [sliderValue, setSliderValue] = useState<number>(0); const [sliderValue, setSliderValue] = useState<number>(0);
const [textStyle, setTextStyle] = useState<TextStyle>(TextStyle.Regular); const [textStyle, setTextStyle] = useState<TextStyle>(TextStyle.Regular);
@ -921,6 +943,9 @@ export const MediaEditor = ({
MediaEditor__control: true, MediaEditor__control: true,
'MediaEditor__control--sticker': true, 'MediaEditor__control--sticker': true,
})} })}
onOpenStateChanged={value => {
setIsStickerPopperOpen(value);
}}
clearInstalledStickerPack={noop} clearInstalledStickerPack={noop}
clearShowIntroduction={() => { clearShowIntroduction={() => {
// We're using this as a callback for when the sticker button // We're using this as a callback for when the sticker button

View file

@ -214,9 +214,19 @@ export const TextStoryCreator = ({
}; };
const handleEscape = (event: KeyboardEvent) => { const handleEscape = (event: KeyboardEvent) => {
if (event.key === 'Escape') { if (event.key === 'Escape') {
setIsColorPickerShowing(false); if (
event.preventDefault(); isColorPickerShowing ||
event.stopPropagation(); 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('click', handleOutsideClick);
document.removeEventListener('keydown', handleEscape); document.removeEventListener('keydown', handleEscape);
}; };
}, [isColorPickerShowing, colorPickerPopperButtonRef]); }, [
isColorPickerShowing,
isEditingText,
isLinkPreviewInputShowing,
colorPickerPopperButtonRef,
onClose,
]);
const sliderColorNumber = getRGBANumber(sliderValue); const sliderColorNumber = getRGBANumber(sliderValue);

View file

@ -26,6 +26,7 @@ export type OwnProps = {
readonly knownPacks: ReadonlyArray<StickerPackType>; readonly knownPacks: ReadonlyArray<StickerPackType>;
readonly installedPack?: StickerPackType | null; readonly installedPack?: StickerPackType | null;
readonly recentStickers: ReadonlyArray<StickerType>; readonly recentStickers: ReadonlyArray<StickerType>;
readonly onOpenStateChanged?: (isOpen: boolean) => void;
readonly clearInstalledStickerPack: () => unknown; readonly clearInstalledStickerPack: () => unknown;
readonly onClickAddPack?: () => unknown; readonly onClickAddPack?: () => unknown;
readonly onPickSticker: ( readonly onPickSticker: (
@ -51,6 +52,7 @@ export const StickerButton = React.memo(
onClickAddPack, onClickAddPack,
onPickSticker, onPickSticker,
recentStickers, recentStickers,
onOpenStateChanged,
receivedPacks, receivedPacks,
installedPack, installedPack,
installedPacks, installedPacks,
@ -63,7 +65,16 @@ export const StickerButton = React.memo(
position = 'top-end', position = 'top-end',
theme, theme,
}: Props) => { }: 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>( const [popperRoot, setPopperRoot] = React.useState<HTMLElement | null>(
null null
); );
@ -110,7 +121,7 @@ export const StickerButton = React.memo(
clearShowPickerHint(); clearShowPickerHint();
} }
onClickAddPack?.(); onClickAddPack?.();
}, [onClickAddPack, showPickerHint, clearShowPickerHint]); }, [onClickAddPack, showPickerHint, setOpen, clearShowPickerHint]);
const handleClearIntroduction = React.useCallback(() => { const handleClearIntroduction = React.useCallback(() => {
clearInstalledStickerPack(); clearInstalledStickerPack();