From 99767907a73a210c4a4b36d7254fa737015a75e9 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Sun, 13 Nov 2022 17:06:17 +0400 Subject: [PATCH] Spoiler: Fixes for emojis (#2132) --- src/components/common/MessageText.tsx | 5 +++++ src/components/common/spoiler/Spoiler.tsx | 25 ++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/components/common/MessageText.tsx b/src/components/common/MessageText.tsx index 69a2ec9ee..ed583b19e 100644 --- a/src/components/common/MessageText.tsx +++ b/src/components/common/MessageText.tsx @@ -42,6 +42,11 @@ function MessageText({ const { text, entities } = message.content.text || {}; 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; diff --git a/src/components/common/spoiler/Spoiler.tsx b/src/components/common/spoiler/Spoiler.tsx index 255933531..9be13a3de 100644 --- a/src/components/common/spoiler/Spoiler.tsx +++ b/src/components/common/spoiler/Spoiler.tsx @@ -22,6 +22,7 @@ const MAX_HIDE_TIMEOUT = 60000; // 1m const actionsByMessageId: Map = new Map(); const buildClassName = createClassNameBuilder('Spoiler'); @@ -35,14 +36,26 @@ const Spoiler: FC = ({ const [isRevealed, reveal, conceal] = useFlag(); + const getContentLength = useCallback(() => { + if (!contentRef.current) { + return 0; + } + + const textLength = contentRef.current.textContent?.length || 0; + const emojiCount = contentRef.current.querySelectorAll('.emoji').length; + // Optimization: ignore alt, assume that viewing emoji takes same time as viewing 4 characters + return textLength + emojiCount * 4; + }, []); + const handleClick = useCallback((e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); actionsByMessageId.get(messageId!)?.forEach((actions) => actions.reveal()); - const contentLength = contentRef.current!.innerText.length; - const readingMs = Math.round(contentLength / READING_SYMBOLS_PER_SECOND) * 1000; + const totalContentLength = actionsByMessageId.get(messageId!) + ?.reduce((acc, actions) => acc + actions.contentLength, 0) || 0; + const readingMs = Math.round(totalContentLength / READING_SYMBOLS_PER_SECOND) * 1000; const timeoutMs = Math.max(MIN_HIDE_TIMEOUT, Math.min(readingMs, MAX_HIDE_TIMEOUT)); setTimeout(() => { @@ -56,16 +69,18 @@ const Spoiler: FC = ({ return undefined; } + const contentLength = getContentLength(); + if (actionsByMessageId.has(messageId)) { - actionsByMessageId.get(messageId)!.push({ reveal, conceal }); + actionsByMessageId.get(messageId)!.push({ reveal, conceal, contentLength }); } else { - actionsByMessageId.set(messageId, [{ reveal, conceal }]); + actionsByMessageId.set(messageId, [{ reveal, conceal, contentLength }]); } return () => { actionsByMessageId.delete(messageId); }; - }, [conceal, handleClick, isRevealed, messageId, reveal]); + }, [conceal, getContentLength, handleClick, isRevealed, messageId, reveal]); return (