TelegramPWA/src/components/common/MessageText.tsx
2023-03-03 14:30:25 +01:00

104 lines
3.1 KiB
TypeScript

import React, {
memo, useMemo, useRef,
} from '../../lib/teact/teact';
import type { ApiFormattedText, ApiMessage } from '../../api/types';
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
import { ApiMessageEntityTypes } from '../../api/types';
import trimText from '../../util/trimText';
import { getMessageText, stripCustomEmoji } from '../../global/helpers';
import { renderTextWithEntities } from './helpers/renderTextWithEntities';
import useSyncEffect from '../../hooks/useSyncEffect';
interface OwnProps {
message: ApiMessage;
translatedText?: ApiFormattedText;
isForAnimation?: boolean;
emojiSize?: number;
highlight?: string;
isSimple?: boolean;
truncateLength?: number;
isProtected?: boolean;
observeIntersectionForLoading?: ObserveFn;
observeIntersectionForPlaying?: ObserveFn;
withTranslucentThumbs?: boolean;
shouldRenderAsHtml?: boolean;
}
const MIN_CUSTOM_EMOJIS_FOR_SHARED_CANVAS = 3;
function MessageText({
message,
translatedText,
isForAnimation,
emojiSize,
highlight,
isSimple,
truncateLength,
isProtected,
observeIntersectionForLoading,
observeIntersectionForPlaying,
withTranslucentThumbs,
shouldRenderAsHtml,
}: OwnProps) {
// eslint-disable-next-line no-null/no-null
const sharedCanvasRef = useRef<HTMLCanvasElement>(null);
// eslint-disable-next-line no-null/no-null
const sharedCanvasHqRef = useRef<HTMLCanvasElement>(null);
const textCacheBusterRef = useRef(0);
const formattedText = translatedText || message.content.text || undefined;
const adaptedFormattedText = isForAnimation && formattedText ? stripCustomEmoji(formattedText) : formattedText;
const { text, entities } = adaptedFormattedText || {};
useSyncEffect(() => {
textCacheBusterRef.current += 1;
}, [text, entities]);
const withSharedCanvas = useMemo(() => {
const hasSpoilers = entities?.some((e) => e.type === ApiMessageEntityTypes.Spoiler);
if (hasSpoilers) {
return false;
}
const customEmojisCount = entities?.filter((e) => e.type === ApiMessageEntityTypes.CustomEmoji).length || 0;
return customEmojisCount >= MIN_CUSTOM_EMOJIS_FOR_SHARED_CANVAS;
}, [entities]) || 0;
if (!text) {
const contentNotSupportedText = getMessageText(message);
return contentNotSupportedText ? [trimText(contentNotSupportedText, truncateLength)] : undefined as any;
}
return (
<>
{[
withSharedCanvas && <canvas ref={sharedCanvasRef} className="shared-canvas" />,
withSharedCanvas && <canvas ref={sharedCanvasHqRef} className="shared-canvas" />,
renderTextWithEntities(
trimText(text!, truncateLength),
entities,
highlight,
emojiSize,
shouldRenderAsHtml,
message.id,
isSimple,
isProtected,
observeIntersectionForLoading,
observeIntersectionForPlaying,
withTranslucentThumbs,
sharedCanvasRef,
sharedCanvasHqRef,
textCacheBusterRef.current.toString(),
),
].flat().filter(Boolean)}
</>
);
}
export default memo(MessageText);