diff --git a/ts/components/CompositionArea.tsx b/ts/components/CompositionArea.tsx index 5dfb08c70..c6c6a049c 100644 --- a/ts/components/CompositionArea.tsx +++ b/ts/components/CompositionArea.tsx @@ -15,7 +15,10 @@ import type { ErrorDialogAudioRecorderType } from '../state/ducks/audioRecorder' import { RecordingState } from '../state/ducks/audioRecorder'; import type { HandleAttachmentsProcessingArgsType } from '../util/handleAttachmentsProcessing'; import { Spinner } from './Spinner'; -import type { Props as EmojiButtonProps } from './emoji/EmojiButton'; +import type { + Props as EmojiButtonProps, + EmojiButtonAPI, +} from './emoji/EmojiButton'; import { EmojiButton } from './emoji/EmojiButton'; import type { Props as StickerButtonProps } from './stickers/StickerButton'; import { StickerButton } from './stickers/StickerButton'; @@ -259,6 +262,7 @@ export const CompositionArea = ({ AttachmentDraftType | undefined >(); const inputApiRef = useRef(); + const emojiButtonRef = useRef(); const fileInputRef = useRef(null); const handleForceSend = useCallback(() => { @@ -270,6 +274,7 @@ export const CompositionArea = ({ const handleSubmit = useCallback( (message: string, mentions: Array, timestamp: number) => { + emojiButtonRef.current?.close(); onSendMessage({ draftAttachments, mentions, @@ -358,8 +363,8 @@ export const CompositionArea = ({ <>
{ + emojiButtonRef.current?.close(); onSendMessage({ voiceNoteAttachment }); }} startRecording={startRecording} diff --git a/ts/components/emoji/EmojiButton.tsx b/ts/components/emoji/EmojiButton.tsx index ee991e35d..ef35c8950 100644 --- a/ts/components/emoji/EmojiButton.tsx +++ b/ts/components/emoji/EmojiButton.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import * as React from 'react'; +import type { MutableRefObject } from 'react'; import classNames from 'classnames'; import { get, noop } from 'lodash'; import { Manager, Popper, Reference } from 'react-popper'; @@ -13,13 +14,14 @@ import type { LocalizerType } from '../../types/Util'; import { useRefMerger } from '../../hooks/useRefMerger'; import * as KeyboardLayout from '../../services/keyboardLayout'; -export type OwnProps = { - readonly className?: string; - readonly closeOnPick?: boolean; - readonly emoji?: string; - readonly i18n: LocalizerType; - readonly onClose?: () => unknown; -}; +export type OwnProps = Readonly<{ + className?: string; + closeOnPick?: boolean; + emoji?: string; + i18n: LocalizerType; + onClose?: () => unknown; + emojiButtonApi?: MutableRefObject; +}>; export type Props = OwnProps & Pick< @@ -27,11 +29,16 @@ export type Props = OwnProps & 'doSend' | 'onPickEmoji' | 'onSetSkinTone' | 'recentEmojis' | 'skinTone' >; +export type EmojiButtonAPI = Readonly<{ + close: () => void; +}>; + export const EmojiButton = React.memo( ({ className, closeOnPick, emoji, + emojiButtonApi, i18n, doSend, onClose, @@ -62,6 +69,19 @@ export const EmojiButton = React.memo( } }, [setOpen, onClose]); + const api = React.useMemo( + () => ({ + close: () => setOpen(false), + }), + [setOpen] + ); + + if (emojiButtonApi) { + // Using a React.MutableRefObject, so we need to reassign this prop. + // eslint-disable-next-line no-param-reassign + emojiButtonApi.current = api; + } + // Create popper root and handle outside clicks React.useEffect(() => { if (open) { diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 094763953..03bd79a46 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -8964,6 +8964,13 @@ "reasonCategory": "usageTrusted", "updated": "2021-09-23T00:07:11.885Z" }, + { + "rule": "React-useRef", + "path": "ts/components/CompositionArea.tsx", + "line": " const emojiButtonRef = useRef();", + "reasonCategory": "usageTrusted", + "updated": "2022-07-07T20:51:44.602Z" + }, { "rule": "React-useRef", "path": "ts/components/CompositionInput.tsx",