diff --git a/src/components/common/spoiler/Spoiler.tsx b/src/components/common/spoiler/Spoiler.tsx index 118566d1..5bf8a1d1 100644 --- a/src/components/common/spoiler/Spoiler.tsx +++ b/src/components/common/spoiler/Spoiler.tsx @@ -1,6 +1,6 @@ import { MouseEvent as ReactMouseEvent } from 'react'; import React, { - FC, memo, useCallback, useEffect, + FC, memo, useCallback, useEffect, useRef, } from '../../../lib/teact/teact'; import { createClassNameBuilder } from '../../../util/buildClassName'; @@ -13,7 +13,9 @@ type OwnProps = { messageId?: number; }; -const AUTO_HIDE_TIMEOUT = 5000; // 5s +const READING_SYMBOLS_PER_SECOND = 23; // Heuristics +const MIN_HIDE_TIMEOUT = 5000; // 5s +const MAX_HIDE_TIMEOUT = 60000; // 1m const actionsByMessageId: Map = ({ children, messageId, }) => { + // eslint-disable-next-line no-null/no-null + const contentRef = useRef(null); + const [isRevealed, reveal, conceal] = useFlag(); const handleClick = useCallback((e: ReactMouseEvent) => { @@ -34,10 +39,14 @@ const Spoiler: FC = ({ actionsByMessageId.get(messageId!)?.forEach((actions) => actions.reveal()); + const contentLength = contentRef.current!.innerText.length; + const readingMs = Math.round(contentLength / READING_SYMBOLS_PER_SECOND) * 1000; + const timeoutMs = Math.max(MIN_HIDE_TIMEOUT, Math.min(readingMs, MAX_HIDE_TIMEOUT)); + setTimeout(() => { actionsByMessageId.get(messageId!)?.forEach((actions) => actions.conceal()); conceal(); - }, AUTO_HIDE_TIMEOUT); + }, timeoutMs); }, [conceal, messageId]); useEffect(() => { @@ -65,7 +74,7 @@ const Spoiler: FC = ({ )} onClick={messageId && !isRevealed ? handleClick : undefined} > - + {children}