Composer: Support 👍 emoji format (#1264)
This commit is contained in:
parent
1c6f3fe06a
commit
791f6a30d5
@ -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<number, ApiUser>;
|
||||
recentEmojis: string[];
|
||||
language: LangCode;
|
||||
emojiKeywords?: Record<string, string[]>;
|
||||
addRecentEmoji: AnyToVoidFunction;
|
||||
loadEmojiKeywords: AnyToVoidFunction;
|
||||
onCaptionUpdate: (html: string) => void;
|
||||
onSend: () => void;
|
||||
onFileAppend: (files: File[], isQuick: boolean) => void;
|
||||
@ -52,11 +49,9 @@ const AttachmentModal: FC<OwnProps> = ({
|
||||
currentUserId,
|
||||
usersById,
|
||||
recentEmojis,
|
||||
language,
|
||||
emojiKeywords,
|
||||
onCaptionUpdate,
|
||||
addRecentEmoji,
|
||||
loadEmojiKeywords,
|
||||
onSend,
|
||||
onFileAppend,
|
||||
onClear,
|
||||
@ -237,10 +232,8 @@ const AttachmentModal: FC<OwnProps> = ({
|
||||
isOpen={isEmojiTooltipOpen}
|
||||
emojis={filteredEmojis}
|
||||
onClose={closeEmojiTooltip}
|
||||
language={language}
|
||||
onEmojiSelect={insertEmoji}
|
||||
addRecentEmoji={addRecentEmoji}
|
||||
loadEmojiKeywords={loadEmojiKeywords}
|
||||
/>
|
||||
<MessageInput
|
||||
id="caption-input-text"
|
||||
|
||||
@ -232,6 +232,13 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
}
|
||||
}, [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<OwnProps & StateProps & DispatchProps> = ({
|
||||
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<OwnProps & StateProps & DispatchProps> = ({
|
||||
onClose={closeEmojiTooltip}
|
||||
onEmojiSelect={insertEmoji}
|
||||
addRecentEmoji={addRecentEmoji}
|
||||
loadEmojiKeywords={loadEmojiKeywords}
|
||||
language={language}
|
||||
/>
|
||||
<AttachMenu
|
||||
isOpen={isAttachMenuOpen}
|
||||
|
||||
@ -2,8 +2,6 @@ import React, {
|
||||
FC, memo, useCallback, useEffect, useRef, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
|
||||
import { LangCode } from '../../../types';
|
||||
|
||||
import { IS_TOUCH_ENV } from '../../../util/environment';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import cycleRestrict from '../../../util/cycleRestrict';
|
||||
@ -54,22 +52,18 @@ function setItemVisible(index: number, containerRef: Record<string, any>) {
|
||||
|
||||
export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
language: LangCode;
|
||||
onEmojiSelect: (text: string) => void;
|
||||
onClose: NoneToVoidFunction;
|
||||
addRecentEmoji: AnyToVoidFunction;
|
||||
loadEmojiKeywords: AnyToVoidFunction;
|
||||
emojis: Emoji[];
|
||||
};
|
||||
|
||||
const EmojiTooltip: FC<OwnProps> = ({
|
||||
isOpen,
|
||||
language,
|
||||
emojis,
|
||||
onClose,
|
||||
onEmojiSelect,
|
||||
addRecentEmoji,
|
||||
loadEmojiKeywords,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@ -78,13 +72,6 @@ const EmojiTooltip: FC<OwnProps> = ({
|
||||
|
||||
const [selectedIndex, setSelectedIndex] = useState(NO_EMOJI_SELECTED_INDEX);
|
||||
|
||||
useEffect(() => {
|
||||
loadEmojiKeywords({ language: 'en' });
|
||||
if (language !== 'en') {
|
||||
loadEmojiKeywords({ language });
|
||||
}
|
||||
}, [loadEmojiKeywords, language]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedIndex(0);
|
||||
}, [emojis]);
|
||||
|
||||
@ -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<Record<string, Emoji[]>>({});
|
||||
const [names, setNames] = useState<string[]>();
|
||||
const [byName, setByName] = useState<Record<string, Emoji[]>>({});
|
||||
const [shouldForceInsertEmoji, setShouldForceInsertEmoji] = useState(false);
|
||||
|
||||
const [filteredEmojis, setFilteredEmojis] = useState<Emoji[]>([]);
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user