From 791f6a30d5a33a9266c5bab33ecb4b6b89b15c7e Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 14 Jul 2021 14:48:34 +0300 Subject: [PATCH] Composer: Support :+1: emoji format (#1264) --- .../middle/composer/AttachmentModal.tsx | 7 ----- src/components/middle/composer/Composer.tsx | 11 +++++--- .../middle/composer/EmojiTooltip.tsx | 13 --------- .../middle/composer/hooks/useEmojiTooltip.ts | 28 +++++++++++++------ 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/components/middle/composer/AttachmentModal.tsx b/src/components/middle/composer/AttachmentModal.tsx index 583537c62..28d7f2c10 100644 --- a/src/components/middle/composer/AttachmentModal.tsx +++ b/src/components/middle/composer/AttachmentModal.tsx @@ -3,7 +3,6 @@ import React, { } from '../../../lib/teact/teact'; import { ApiAttachment, ApiChatMember, ApiUser } from '../../../api/types'; -import { LangCode } from '../../../types'; import { CONTENT_TYPES_FOR_QUICK_UPLOAD, EDITABLE_INPUT_MODAL_ID } from '../../../config'; import { getFileExtension } from '../../common/helpers/documentInfo'; @@ -32,10 +31,8 @@ export type OwnProps = { groupChatMembers?: ApiChatMember[]; usersById?: Record; recentEmojis: string[]; - language: LangCode; emojiKeywords?: Record; addRecentEmoji: AnyToVoidFunction; - loadEmojiKeywords: AnyToVoidFunction; onCaptionUpdate: (html: string) => void; onSend: () => void; onFileAppend: (files: File[], isQuick: boolean) => void; @@ -52,11 +49,9 @@ const AttachmentModal: FC = ({ currentUserId, usersById, recentEmojis, - language, emojiKeywords, onCaptionUpdate, addRecentEmoji, - loadEmojiKeywords, onSend, onFileAppend, onClear, @@ -237,10 +232,8 @@ const AttachmentModal: FC = ({ isOpen={isEmojiTooltipOpen} emojis={filteredEmojis} onClose={closeEmojiTooltip} - language={language} onEmojiSelect={insertEmoji} addRecentEmoji={addRecentEmoji} - loadEmojiKeywords={loadEmojiKeywords} /> = ({ } }, [isReady, chatId, loadScheduledHistory, lastSyncTime, threadId]); + useEffect(() => { + loadEmojiKeywords({ language: 'en' }); + if (language !== 'en') { + loadEmojiKeywords({ language }); + } + }, [loadEmojiKeywords, language]); + useLayoutEffect(() => { if (!appendixRef.current) return; @@ -710,10 +717,8 @@ const Composer: FC = ({ usersById={usersById} recentEmojis={recentEmojis} onCaptionUpdate={setHtml} - language={language} emojiKeywords={emojiKeywords} addRecentEmoji={addRecentEmoji} - loadEmojiKeywords={loadEmojiKeywords} onSend={shouldSchedule ? openCalendar : handleSend} onFileAppend={handleAppendFiles} onClear={handleClearAttachment} @@ -845,8 +850,6 @@ const Composer: FC = ({ onClose={closeEmojiTooltip} onEmojiSelect={insertEmoji} addRecentEmoji={addRecentEmoji} - loadEmojiKeywords={loadEmojiKeywords} - language={language} /> ) { export type OwnProps = { isOpen: boolean; - language: LangCode; onEmojiSelect: (text: string) => void; onClose: NoneToVoidFunction; addRecentEmoji: AnyToVoidFunction; - loadEmojiKeywords: AnyToVoidFunction; emojis: Emoji[]; }; const EmojiTooltip: FC = ({ isOpen, - language, emojis, onClose, onEmojiSelect, addRecentEmoji, - loadEmojiKeywords, }) => { // eslint-disable-next-line no-null/no-null const containerRef = useRef(null); @@ -78,13 +72,6 @@ const EmojiTooltip: FC = ({ const [selectedIndex, setSelectedIndex] = useState(NO_EMOJI_SELECTED_INDEX); - useEffect(() => { - loadEmojiKeywords({ language: 'en' }); - if (language !== 'en') { - loadEmojiKeywords({ language }); - } - }, [loadEmojiKeywords, language]); - useEffect(() => { setSelectedIndex(0); }, [emojis]); diff --git a/src/components/middle/composer/hooks/useEmojiTooltip.ts b/src/components/middle/composer/hooks/useEmojiTooltip.ts index e214abf4d..e9ac4b44f 100644 --- a/src/components/middle/composer/hooks/useEmojiTooltip.ts +++ b/src/components/middle/composer/hooks/useEmojiTooltip.ts @@ -22,10 +22,10 @@ const EMOJIS_LIMIT = 36; const FILTER_MIN_LENGTH = 2; try { - RE_NOT_EMOJI_SEARCH = new RegExp('[^-_:\\p{L}\\p{N}]+', 'iu'); + RE_NOT_EMOJI_SEARCH = new RegExp('[^-+_:\\p{L}\\p{N}]+', 'iu'); } catch (e) { // Support for older versions of firefox - RE_NOT_EMOJI_SEARCH = new RegExp('[^-_:\\d\\wа-яё]+', 'i'); + RE_NOT_EMOJI_SEARCH = new RegExp('[^-+_:\\d\\wа-яё]+', 'i'); } export default function useEmojiTooltip( @@ -45,6 +45,7 @@ export default function useEmojiTooltip( const [byKeyword, setByKeyword] = useState>({}); const [names, setNames] = useState(); const [byName, setByName] = useState>({}); + const [shouldForceInsertEmoji, setShouldForceInsertEmoji] = useState(false); const [filteredEmojis, setFilteredEmojis] = useState([]); @@ -124,9 +125,12 @@ export default function useEmojiTooltip( return; } - const filter = code.substr(1); + const forceSend = code.length > 2 && code.endsWith(':'); + const filter = code.substr(1, forceSend ? code.length - 2 : undefined); let matched: Emoji[] = []; + setShouldForceInsertEmoji(forceSend); + if (!filter) { matched = recentEmojis; } else if (filter.length >= FILTER_MIN_LENGTH) { @@ -141,18 +145,20 @@ export default function useEmojiTooltip( } if (matched.length) { - markIsOpen(); + if (!forceSend) { + markIsOpen(); + } setFilteredEmojis(matched.slice(0, EMOJIS_LIMIT)); } else { unmarkIsOpen(); } }, [ - byId, byKeyword, keywords, byName, names, - html, isAllowed, markIsOpen, recentEmojis, unmarkIsOpen, + byId, byKeyword, keywords, byName, names, html, isAllowed, markIsOpen, + recentEmojis, unmarkIsOpen, setShouldForceInsertEmoji, ]); - const insertEmoji = useCallback((textEmoji: string) => { - const atIndex = html.lastIndexOf(':'); + const insertEmoji = useCallback((textEmoji: string, isForce?: boolean) => { + const atIndex = html.lastIndexOf(':', isForce ? -1 : undefined); if (atIndex !== -1) { onUpdateHtml(`${html.substr(0, atIndex)}${textEmoji}`); const messageInput = document.getElementById(inputId)!; @@ -166,6 +172,12 @@ export default function useEmojiTooltip( unmarkIsOpen(); }, [html, inputId, onUpdateHtml, unmarkIsOpen]); + useEffect(() => { + if (isOpen && shouldForceInsertEmoji && filteredEmojis.length) { + insertEmoji(filteredEmojis[0].native, true); + } + }, [filteredEmojis, insertEmoji, isOpen, shouldForceInsertEmoji]); + return { isEmojiTooltipOpen: isOpen, closeEmojiTooltip: unmarkIsOpen,