From cc6b299ab6cf3e7eefce2cfd31ca1524060455a8 Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Thu, 6 Jul 2023 15:17:06 -0400 Subject: [PATCH] Attach composition keyboard handlers only when quill has focus --- ts/components/CompositionArea.tsx | 12 ++++++++++-- ts/components/CompositionInput.tsx | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/ts/components/CompositionArea.tsx b/ts/components/CompositionArea.tsx index 31a4d7662187..6335138b8915 100644 --- a/ts/components/CompositionArea.tsx +++ b/ts/components/CompositionArea.tsx @@ -54,7 +54,7 @@ import { countStickers } from './stickers/lib'; import { useAttachFileShortcut, useEditLastMessageSent, - useKeyboardShortcuts, + useKeyboardShortcutsConditionally, } from '../hooks/useKeyboardShortcuts'; import { MediaEditor } from './MediaEditor'; import { isImageTypeSupported } from '../util/GoogleChrome'; @@ -416,9 +416,15 @@ export function CompositionArea({ setMessageToEdit, ]); + const [hasFocus, setHasFocus] = useState(false); + const attachFileShortcut = useAttachFileShortcut(launchAttachmentPicker); const editLastMessageSent = useEditLastMessageSent(maybeEditMessage); - useKeyboardShortcuts(attachFileShortcut, editLastMessageSent); + useKeyboardShortcutsConditionally( + hasFocus, + attachFileShortcut, + editLastMessageSent + ); // Focus input on first mount const previousFocusCounter = usePrevious( @@ -954,6 +960,8 @@ export function CompositionArea({ large={large} linkPreviewLoading={linkPreviewLoading} linkPreviewResult={linkPreviewResult} + onBlur={() => setHasFocus(false)} + onFocus={() => setHasFocus(true)} onCloseLinkPreview={onCloseLinkPreview} onDirtyChange={setDirty} onEditorStateChange={onEditorStateChange} diff --git a/ts/components/CompositionInput.tsx b/ts/components/CompositionInput.tsx index 3e77b2842a8d..c07ebf89cc42 100644 --- a/ts/components/CompositionInput.tsx +++ b/ts/components/CompositionInput.tsx @@ -120,6 +120,8 @@ export type Props = Readonly<{ }): unknown; onTextTooLong(): unknown; onPickEmoji(o: EmojiPickDataType): unknown; + onBlur?: () => unknown; + onFocus?: () => unknown; onSubmit( message: string, bodyRanges: DraftBodyRanges, @@ -159,6 +161,8 @@ export function CompositionInput(props: Props): React.ReactElement { linkPreviewResult, moduleClassName, onCloseLinkPreview, + onBlur, + onFocus, onPickEmoji, onScroll, onSubmit, @@ -610,6 +614,29 @@ export function CompositionInput(props: Props): React.ReactElement { quill.focus(); }, [disabled]); + React.useEffect(() => { + const quill = quillRef.current; + + if (quill === undefined) { + return; + } + + function handleFocus() { + onFocus?.(); + } + function handleBlur() { + onBlur?.(); + } + + quill.root.addEventListener('focus', handleFocus); + quill.root.addEventListener('blur', handleBlur); + + return () => { + quill.root.removeEventListener('focus', handleFocus); + quill.root.removeEventListener('blur', handleBlur); + }; + }, [onFocus, onBlur]); + React.useEffect(() => { const emojiCompletion = emojiCompletionRef.current;