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
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue