44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import { isEmojiId } from '@/lib/emoji-catalog';
|
|
import { EMOJI_NATIVE_MAP, emojiIdToNative, resolveNativeEmojiContent } from '@/lib/emoji-native-map';
|
|
|
|
function countGraphemes(text: string) {
|
|
if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {
|
|
return [...new Intl.Segmenter('ru', { granularity: 'grapheme' }).segment(text)].length;
|
|
}
|
|
return [...text].length;
|
|
}
|
|
|
|
function resolveEmojiDisplayText(content?: string | null, visibleText?: string | null) {
|
|
const raw = (visibleText ?? content ?? '').trim();
|
|
if (!raw) return '';
|
|
if (isEmojiId(raw)) return emojiIdToNative(raw) ?? raw;
|
|
if (EMOJI_NATIVE_MAP[raw]) return EMOJI_NATIVE_MAP[raw]!;
|
|
return resolveNativeEmojiContent(raw).trim();
|
|
}
|
|
|
|
export function isSingleEmojiMessage(options: {
|
|
type?: string;
|
|
content?: string | null;
|
|
visibleText?: string | null;
|
|
}) {
|
|
if (options.type === 'POLL' || options.type === 'IMAGE' || options.type === 'VOICE' || options.type === 'AUDIO' || options.type === 'FILE') {
|
|
return false;
|
|
}
|
|
|
|
const text = resolveEmojiDisplayText(options.content, options.visibleText);
|
|
if (!text) return false;
|
|
if (countGraphemes(text) !== 1) return false;
|
|
return /\p{Extended_Pictographic}/u.test(text);
|
|
}
|
|
|
|
export function getSingleEmojiNative(options: {
|
|
type?: string;
|
|
content?: string | null;
|
|
visibleText?: string | null;
|
|
}) {
|
|
if (options.type === 'EMOJI') {
|
|
return resolveEmojiDisplayText(options.content, options.visibleText);
|
|
}
|
|
return resolveEmojiDisplayText(options.content, options.visibleText);
|
|
}
|