Spoilers: Various fixes

This commit is contained in:
Alexander Zinchuk 2022-01-28 02:11:02 +01:00
parent bc18224114
commit a71a13414a
6 changed files with 59 additions and 54 deletions

View File

@ -305,7 +305,7 @@ function processEntity(
if (isSimple) { if (isSimple) {
const text = renderNestedMessagePart(); const text = renderNestedMessagePart();
if (entity.type === ApiMessageEntityTypes.Spoiler) { if (entity.type === ApiMessageEntityTypes.Spoiler) {
return <Spoiler isInactive>{text}</Spoiler>; return <Spoiler>{text}</Spoiler>;
} }
return text; return text;
} }

View File

@ -1,31 +1,34 @@
.Spoiler { .Spoiler {
transition: color 250ms ease; &.concealed {
.text-entity-link {
transition: color 250ms ease;
}
&:not(.is-revealed) {
cursor: pointer; cursor: pointer;
color: transparent;
background-image: url('../../../assets/spoiler-dots-black.png'); background-image: url('../../../assets/spoiler-dots-black.png');
background-size: auto 100%; background-size: auto min(100%, 1.125rem);
border-radius: 0.5rem; border-radius: 0.5rem;
&.animate { html.theme-dark &,
animation: pulse-opacity-light 1.75s linear infinite; html.theme-light .ListItem.selected &,
.ActionMessage &,
.MediaViewerFooter & {
background-image: url('../../../assets/spoiler-dots-white.png');
} }
.text-entity-link { .emoji-only & {
color: transparent !important; background-size: auto 1.125rem;
pointer-events: none;
} }
} }
html.theme-dark &:not(.is-revealed), &.animated {
html.theme-light .ListItem.selected &:not(.is-revealed), animation: pulse-opacity-light 1.75s linear infinite;
html.theme-light .ActionMessage &:not(.is-revealed) { }
background-image: url('../../../assets/spoiler-dots-white.png');
span {
opacity: 1;
transition: opacity 250ms ease;
}
&.concealed span {
visibility: hidden;
opacity: 0;
} }
} }

View File

@ -1,3 +1,4 @@
import { MouseEvent as ReactMouseEvent } from 'react';
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
@ -10,7 +11,6 @@ import './Spoiler.scss';
type OwnProps = { type OwnProps = {
children?: React.ReactNode; children?: React.ReactNode;
messageId?: number; messageId?: number;
isInactive?: boolean;
}; };
const spoilersByMessageId: Map<number, VoidFunction[]> = new Map(); const spoilersByMessageId: Map<number, VoidFunction[]> = new Map();
@ -18,22 +18,17 @@ const spoilersByMessageId: Map<number, VoidFunction[]> = new Map();
const Spoiler: FC<OwnProps> = ({ const Spoiler: FC<OwnProps> = ({
children, children,
messageId, messageId,
isInactive,
}) => { }) => {
const [isRevealed, reveal] = useFlag(); const [isRevealed, reveal] = useFlag();
const handleClick = useCallback(() => { const handleClick = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
if (!messageId) return; e.preventDefault();
e.stopPropagation();
spoilersByMessageId.get(messageId)?.forEach((_reveal) => _reveal()); spoilersByMessageId.get(messageId!)?.forEach((_reveal) => _reveal());
}, [messageId]); }, [messageId]);
useEffect(() => { useEffect(() => {
if (isRevealed && messageId) {
spoilersByMessageId.delete(messageId);
return undefined;
}
if (!messageId) { if (!messageId) {
return undefined; return undefined;
} }
@ -53,12 +48,14 @@ const Spoiler: FC<OwnProps> = ({
<span <span
className={buildClassName( className={buildClassName(
'Spoiler', 'Spoiler',
isRevealed && 'is-revealed', !isRevealed && 'concealed',
!isInactive && 'animate', !isRevealed && Boolean(messageId) && 'animated',
)} )}
onClick={!isInactive && !isRevealed ? handleClick : undefined} onClick={messageId && !isRevealed ? handleClick : undefined}
> >
{children} <span>
{children}
</span>
</span> </span>
); );
}; };

View File

@ -430,7 +430,7 @@ const MediaViewer: FC<StateProps> = ({
return captureEvents(element, { return captureEvents(element, {
// eslint-disable-next-line max-len // 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, onClick: close,
}); });
}, [close, isGif, isZoomed, messageId]); }, [close, isGif, isZoomed, messageId]);

View File

@ -5,6 +5,7 @@ import {
getMessageMediaHash, getMessageMediaHash,
getMessagePhoto, getMessagePhoto,
getMessageText, getMessageText,
getMessageTextWithSpoilers,
getMessageWebPagePhoto, getMessageWebPagePhoto,
getMessageWebPageVideo, getMessageWebPageVideo,
hasMessageLocalBlobUrl, hasMessageLocalBlobUrl,
@ -52,7 +53,7 @@ export function getMessageCopyOptions(
options.push({ options.push({
label: getCopyLabel(hasSelection), label: getCopyLabel(hasSelection),
handler: () => { handler: () => {
const clipboardText = hasSelection && selection ? selection.toString() : text; const clipboardText = hasSelection && selection ? selection.toString() : getMessageTextWithSpoilers(message)!;
copyTextToClipboard(clipboardText); copyTextToClipboard(clipboardText);
if (afterEffect) { if (afterEffect) {

View File

@ -15,30 +15,34 @@ export function getMessageSummaryText(
) { ) {
const emoji = !noEmoji && getMessageSummaryEmoji(message); const emoji = !noEmoji && getMessageSummaryEmoji(message);
const emojiWithSpace = emoji ? `${emoji} ` : ''; const emojiWithSpace = emoji ? `${emoji} ` : '';
const text = getMessageTextWithSpoilers(message)?.substr(0, truncateLength);
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 description = getMessageSummaryDescription(lang, message, text); const description = getMessageSummaryDescription(lang, message, text);
return `${emojiWithSpace}${description}`; 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) { export function getMessageSummaryEmoji(message: ApiMessage) {
const { const {
photo, video, audio, voice, document, sticker, poll, photo, video, audio, voice, document, sticker, poll,