diff --git a/src/components/common/helpers/renderMessageText.tsx b/src/components/common/helpers/renderMessageText.tsx index 01be7df4..8e482e33 100644 --- a/src/components/common/helpers/renderMessageText.tsx +++ b/src/components/common/helpers/renderMessageText.tsx @@ -305,7 +305,7 @@ function processEntity( if (isSimple) { const text = renderNestedMessagePart(); if (entity.type === ApiMessageEntityTypes.Spoiler) { - return {text}; + return {text}; } return text; } diff --git a/src/components/common/spoiler/Spoiler.scss b/src/components/common/spoiler/Spoiler.scss index a29b316e..5135962c 100644 --- a/src/components/common/spoiler/Spoiler.scss +++ b/src/components/common/spoiler/Spoiler.scss @@ -1,31 +1,34 @@ .Spoiler { - transition: color 250ms ease; - - .text-entity-link { - transition: color 250ms ease; - } - - &:not(.is-revealed) { + &.concealed { cursor: pointer; - color: transparent; background-image: url('../../../assets/spoiler-dots-black.png'); - background-size: auto 100%; + background-size: auto min(100%, 1.125rem); border-radius: 0.5rem; - &.animate { - animation: pulse-opacity-light 1.75s linear infinite; + html.theme-dark &, + html.theme-light .ListItem.selected &, + .ActionMessage &, + .MediaViewerFooter & { + background-image: url('../../../assets/spoiler-dots-white.png'); } - .text-entity-link { - color: transparent !important; - pointer-events: none; + .emoji-only & { + background-size: auto 1.125rem; } } - html.theme-dark &:not(.is-revealed), - html.theme-light .ListItem.selected &:not(.is-revealed), - html.theme-light .ActionMessage &:not(.is-revealed) { - background-image: url('../../../assets/spoiler-dots-white.png'); + &.animated { + animation: pulse-opacity-light 1.75s linear infinite; + } + + span { + opacity: 1; + transition: opacity 250ms ease; + } + + &.concealed span { + visibility: hidden; + opacity: 0; } } diff --git a/src/components/common/spoiler/Spoiler.tsx b/src/components/common/spoiler/Spoiler.tsx index 817beceb..fd3b5a51 100644 --- a/src/components/common/spoiler/Spoiler.tsx +++ b/src/components/common/spoiler/Spoiler.tsx @@ -1,3 +1,4 @@ +import { MouseEvent as ReactMouseEvent } from 'react'; import React, { FC, memo, useCallback, useEffect, } from '../../../lib/teact/teact'; @@ -10,7 +11,6 @@ import './Spoiler.scss'; type OwnProps = { children?: React.ReactNode; messageId?: number; - isInactive?: boolean; }; const spoilersByMessageId: Map = new Map(); @@ -18,22 +18,17 @@ const spoilersByMessageId: Map = new Map(); const Spoiler: FC = ({ children, messageId, - isInactive, }) => { const [isRevealed, reveal] = useFlag(); - const handleClick = useCallback(() => { - if (!messageId) return; + const handleClick = useCallback((e: ReactMouseEvent) => { + e.preventDefault(); + e.stopPropagation(); - spoilersByMessageId.get(messageId)?.forEach((_reveal) => _reveal()); + spoilersByMessageId.get(messageId!)?.forEach((_reveal) => _reveal()); }, [messageId]); useEffect(() => { - if (isRevealed && messageId) { - spoilersByMessageId.delete(messageId); - return undefined; - } - if (!messageId) { return undefined; } @@ -53,12 +48,14 @@ const Spoiler: FC = ({ - {children} + + {children} + ); }; diff --git a/src/components/mediaViewer/MediaViewer.tsx b/src/components/mediaViewer/MediaViewer.tsx index 9cdb3ca4..73875c8e 100644 --- a/src/components/mediaViewer/MediaViewer.tsx +++ b/src/components/mediaViewer/MediaViewer.tsx @@ -430,7 +430,7 @@ const MediaViewer: FC = ({ return captureEvents(element, { // eslint-disable-next-line max-len - excludedClosestSelector: `.backdrop, .navigation, .media-viewer-head, .media-viewer-footer${!shouldCloseOnVideo ? ', .VideoPlayer' : ''}`, + excludedClosestSelector: `.backdrop, .navigation, .media-viewer-head, .Spoiler, .media-viewer-footer${!shouldCloseOnVideo ? ', .VideoPlayer' : ''}`, onClick: close, }); }, [close, isGif, isZoomed, messageId]); diff --git a/src/components/middle/message/helpers/copyOptions.ts b/src/components/middle/message/helpers/copyOptions.ts index 69432db7..633bfc3f 100644 --- a/src/components/middle/message/helpers/copyOptions.ts +++ b/src/components/middle/message/helpers/copyOptions.ts @@ -5,6 +5,7 @@ import { getMessageMediaHash, getMessagePhoto, getMessageText, + getMessageTextWithSpoilers, getMessageWebPagePhoto, getMessageWebPageVideo, hasMessageLocalBlobUrl, @@ -52,7 +53,7 @@ export function getMessageCopyOptions( options.push({ label: getCopyLabel(hasSelection), handler: () => { - const clipboardText = hasSelection && selection ? selection.toString() : text; + const clipboardText = hasSelection && selection ? selection.toString() : getMessageTextWithSpoilers(message)!; copyTextToClipboard(clipboardText); if (afterEffect) { diff --git a/src/modules/helpers/messageSummary.ts b/src/modules/helpers/messageSummary.ts index 60ddab03..6b2239d3 100644 --- a/src/modules/helpers/messageSummary.ts +++ b/src/modules/helpers/messageSummary.ts @@ -15,30 +15,34 @@ export function getMessageSummaryText( ) { const emoji = !noEmoji && getMessageSummaryEmoji(message); const emojiWithSpace = emoji ? `${emoji} ` : ''; - - let text = getMessageText(message); - if (text) { - const { entities } = message.content.text || {}; - if (entities?.length) { - text = entities.reduce((accText, { type, offset, length }) => { - if (type !== ApiMessageEntityTypes.Spoiler) { - return accText; - } - - const spoiler = generateBrailleSpoiler(length); - - return `${accText.substr(0, offset)}${spoiler}${accText.substr(offset + length, accText.length)}`; - }, text); - } - - text = text.substr(0, truncateLength); - } - + const text = getMessageTextWithSpoilers(message)?.substr(0, truncateLength); const description = getMessageSummaryDescription(lang, message, text); return `${emojiWithSpace}${description}`; } +export function getMessageTextWithSpoilers(message: ApiMessage) { + const text = getMessageText(message); + if (!text) { + return undefined; + } + + const { entities } = message.content.text || {}; + if (!entities?.length) { + return text; + } + + return entities.reduce((accText, { type, offset, length }) => { + if (type !== ApiMessageEntityTypes.Spoiler) { + return accText; + } + + const spoiler = generateBrailleSpoiler(length); + + return `${accText.substr(0, offset)}${spoiler}${accText.substr(offset + length, accText.length)}`; + }, text); +} + export function getMessageSummaryEmoji(message: ApiMessage) { const { photo, video, audio, voice, document, sticker, poll,