mirror of
https://github.com/danog/telegram-tt.git
synced 2025-01-22 13:21:37 +01:00
Message / Emoji, Emoji Button: Fade-in animation (#1802)
This commit is contained in:
parent
d44d465520
commit
f132faf7cd
@ -3,7 +3,9 @@ import EMOJI_REGEX, { removeVS16s } from '../../../lib/twemojiRegex';
|
||||
|
||||
import { RE_LINK_TEMPLATE, RE_MENTION_TEMPLATE } from '../../../config';
|
||||
import { IS_EMOJI_SUPPORTED } from '../../../util/environment';
|
||||
import { fixNonStandardEmoji, nativeToUnified } from '../../../util/emoji';
|
||||
import {
|
||||
fixNonStandardEmoji, handleEmojiLoad, LOADED_EMOJIS, nativeToUnified,
|
||||
} from '../../../util/emoji';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { compact } from '../../../util/iteratees';
|
||||
|
||||
@ -14,7 +16,7 @@ type TextPart = string | Element;
|
||||
export type TextFilter = (
|
||||
'escape_html' | 'hq_emoji' | 'emoji' | 'emoji_html' | 'br' | 'br_html' | 'highlight' | 'links' |
|
||||
'simple_markdown' | 'simple_markdown_html'
|
||||
);
|
||||
);
|
||||
|
||||
const RE_LETTER_OR_DIGIT = /^[\d\wа-яё]$/i;
|
||||
const SIMPLE_MARKDOWN_REGEX = /(\*\*|__).+?\1/g;
|
||||
@ -102,16 +104,22 @@ function replaceEmojis(textParts: TextPart[], size: 'big' | 'small', type: 'jsx'
|
||||
return emojis.reduce((emojiResult: TextPart[], emoji, i) => {
|
||||
const code = nativeToUnified(removeVS16s(emoji));
|
||||
if (!code) return emojiResult;
|
||||
const src = `./img-apple-${size === 'big' ? '160' : '64'}/${code}.png`;
|
||||
const className = buildClassName(
|
||||
'emoji',
|
||||
size === 'small' && 'emoji-small',
|
||||
);
|
||||
|
||||
if (type === 'jsx') {
|
||||
const isLoaded = LOADED_EMOJIS.has(src);
|
||||
|
||||
emojiResult.push(
|
||||
<img
|
||||
className={className}
|
||||
src={`./img-apple-${size === 'big' ? '160' : '64'}/${code}.png`}
|
||||
src={src}
|
||||
className={`${className}${!isLoaded ? ' opacity-transition slow shown' : ''}`}
|
||||
alt={emoji}
|
||||
data-path={src}
|
||||
onLoad={!isLoaded ? handleEmojiLoad : undefined}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
cursor: pointer;
|
||||
font-size: 1.75rem;
|
||||
line-height: 2.5rem;
|
||||
|
||||
background-color: transparent;
|
||||
transition: background-color 0.15s ease;
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
|
||||
import React, {
|
||||
FC, memo, useCallback,
|
||||
} from '../../../lib/teact/teact';
|
||||
|
||||
import { IS_EMOJI_SUPPORTED } from '../../../util/environment';
|
||||
import { handleEmojiLoad, LOADED_EMOJIS } from '../../../util/emoji';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import './EmojiButton.scss';
|
||||
|
||||
@ -18,15 +22,30 @@ const EmojiButton: FC<OwnProps> = ({ emoji, focus, onClick }) => {
|
||||
onClick(emoji.native, emoji.id);
|
||||
}, [emoji, onClick]);
|
||||
|
||||
const className = buildClassName(
|
||||
'EmojiButton',
|
||||
focus && 'focus',
|
||||
);
|
||||
|
||||
const src = `./img-apple-64/${emoji.image}.png`;
|
||||
const isLoaded = LOADED_EMOJIS.has(src);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`EmojiButton ${focus ? 'focus' : ''}`}
|
||||
className={className}
|
||||
onMouseDown={handleClick}
|
||||
title={`:${emoji.names[0]}:`}
|
||||
>
|
||||
{IS_EMOJI_SUPPORTED
|
||||
? emoji.native
|
||||
: <img src={`./img-apple-64/${emoji.image}.png`} alt={emoji.native} loading="lazy" />}
|
||||
{IS_EMOJI_SUPPORTED ? emoji.native : (
|
||||
<img
|
||||
src={src}
|
||||
className={!isLoaded ? 'opacity-transition shown' : undefined}
|
||||
alt={emoji.native}
|
||||
loading="lazy"
|
||||
data-path={src}
|
||||
onLoad={!isLoaded ? handleEmojiLoad : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -219,7 +219,7 @@ const EmojiPicker: FC<OwnProps & StateProps> = ({
|
||||
|
||||
async function ensureEmojiData() {
|
||||
if (!emojiDataPromise) {
|
||||
emojiDataPromise = import('emoji-data-ios/emoji-data.json') as unknown as Promise<EmojiModule>;
|
||||
emojiDataPromise = import('emoji-data-ios/emoji-data.json');
|
||||
emojiRawData = (await emojiDataPromise).default;
|
||||
|
||||
emojiData = uncompressEmoji(emojiRawData);
|
||||
|
@ -64,6 +64,7 @@ body.cursor-ew-resize {
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
}
|
||||
@ -265,10 +266,12 @@ div[role="button"] {
|
||||
transform: scale(0.5);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
@ -279,6 +282,7 @@ div[role="button"] {
|
||||
transform: scale(1);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
|
@ -28,6 +28,13 @@ function unifiedToNative(unified: string) {
|
||||
return String.fromCodePoint(...codePoints);
|
||||
}
|
||||
|
||||
export const LOADED_EMOJIS = new Set<string>();
|
||||
|
||||
export function handleEmojiLoad(event: React.SyntheticEvent<HTMLImageElement>) {
|
||||
event.currentTarget.classList.add('open');
|
||||
LOADED_EMOJIS.add(event.currentTarget.dataset.path!);
|
||||
}
|
||||
|
||||
export function fixNonStandardEmoji(text: string) {
|
||||
// Non-standard sequences typically parsed as separate emojis, so no need to fix text without any
|
||||
if (!text.match(EMOJI_REGEX)) return text;
|
||||
@ -51,7 +58,7 @@ export function nativeToUnified(emoji: string) {
|
||||
if (emoji.charCodeAt(i + 1) >= 0xdc00 && emoji.charCodeAt(i + 1) <= 0xdfff) {
|
||||
pairs.push(
|
||||
(emoji.charCodeAt(i) - 0xd800) * 0x400
|
||||
+ (emoji.charCodeAt(i + 1) - 0xdc00) + 0x10000,
|
||||
+ (emoji.charCodeAt(i + 1) - 0xdc00) + 0x10000,
|
||||
);
|
||||
}
|
||||
} else if (emoji.charCodeAt(i) < 0xd800 || emoji.charCodeAt(i) > 0xdfff) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user