diff --git a/src/components/common/helpers/renderMessageText.tsx b/src/components/common/helpers/renderMessageText.tsx
index 8e482e333..c69ec2f8e 100644
--- a/src/components/common/helpers/renderMessageText.tsx
+++ b/src/components/common/helpers/renderMessageText.tsx
@@ -18,7 +18,9 @@ import SafeLink from '../SafeLink';
import Spoiler from '../spoiler/Spoiler';
import { LangFn } from '../../../hooks/useLang';
-export type TextPart = string | Element;
+export type TextPart =
+ string
+ | Element;
export function renderMessageSummary(
lang: LangFn,
@@ -500,7 +502,10 @@ function processEntityAsHtml(
dir="auto"
>${renderedContent}`;
case ApiMessageEntityTypes.Spoiler:
- return `||${renderedContent}||`;
+ return `${renderedContent}`;
default:
return renderedContent;
}
diff --git a/src/components/middle/composer/Composer.scss b/src/components/middle/composer/Composer.scss
index bfc551b04..21201d4fd 100644
--- a/src/components/middle/composer/Composer.scss
+++ b/src/components/middle/composer/Composer.scss
@@ -399,6 +399,18 @@
}
}
+ .spoiler {
+ background-image: url('../../../assets/spoiler-dots-black.png');
+ background-size: auto min(100%, 1.125rem);
+ border-radius: 0.5rem;
+ padding: 0 0.3125rem 0.125rem 0.3125rem;
+ text-shadow: -2px -2px 0 var(--color-background), 2px -2px 0 var(--color-background), -2px 2px 0 var(--color-background), 2px 2px 0 var(--color-background);
+ }
+
+ html.theme-dark & .spoiler {
+ background-image: url('../../../assets/spoiler-dots-white.png');
+ }
+
.clone {
position: absolute;
top: 0;
diff --git a/src/components/middle/composer/TextFormatter.tsx b/src/components/middle/composer/TextFormatter.tsx
index 190b421cd..171b1cd18 100644
--- a/src/components/middle/composer/TextFormatter.tsx
+++ b/src/components/middle/composer/TextFormatter.tsx
@@ -3,6 +3,7 @@ import React, {
} from '../../../lib/teact/teact';
import { IAnchorPosition } from '../../../types';
+import { ApiMessageEntityTypes } from '../../../api/types';
import { EDITABLE_INPUT_ID } from '../../../config';
import buildClassName from '../../../util/buildClassName';
@@ -32,6 +33,7 @@ interface ISelectedTextFormats {
underline?: boolean;
strikethrough?: boolean;
monospace?: boolean;
+ spoiler?: boolean;
}
const TEXT_FORMAT_BY_TAG_NAME: Record = {
@@ -42,6 +44,7 @@ const TEXT_FORMAT_BY_TAG_NAME: Record = {
U: 'underline',
DEL: 'strikethrough',
CODE: 'monospace',
+ SPAN: 'spoiler',
};
const fragmentEl = document.createElement('div');
@@ -188,6 +191,34 @@ const TextFormatter: FC = ({
return undefined;
}
+ const handleSpoilerText = useCallback(() => {
+ if (selectedTextFormats.spoiler) {
+ const element = getSelectedElement();
+ if (
+ !selectedRange
+ || !element
+ || element.dataset.entityType !== ApiMessageEntityTypes.Spoiler
+ || !element.textContent
+ ) {
+ return;
+ }
+
+ element.replaceWith(element.textContent);
+ setSelectedTextFormats((selectedFormats) => ({
+ ...selectedFormats,
+ spoiler: false,
+ }));
+
+ return;
+ }
+
+ const text = getSelectedText();
+ document.execCommand(
+ 'insertHTML', false, `${text}`,
+ );
+ onClose();
+ }, [getSelectedElement, getSelectedText, onClose, selectedRange, selectedTextFormats.spoiler]);
+
const handleBoldText = useCallback(() => {
setSelectedTextFormats((selectedFormats) => {
// Somehow re-applying 'bold' command to already bold text doesn't work
@@ -249,16 +280,9 @@ const TextFormatter: FC = ({
document.execCommand('insertHTML', false, `${text}`);
onClose();
}, [
- getSelectedElement, getSelectedText, onClose,
- selectedRange, selectedTextFormats.strikethrough,
+ getSelectedElement, getSelectedText, onClose, selectedRange, selectedTextFormats.strikethrough,
]);
- const handleSpoilerText = useCallback(() => {
- const text = getSelectedText();
- document.execCommand('insertHTML', false, `||${text}||`);
- onClose();
- }, [getSelectedText, onClose]);
-
const handleMonospaceText = useCallback(() => {
if (selectedTextFormats.monospace) {
const element = getSelectedElement();
@@ -276,6 +300,7 @@ const TextFormatter: FC = ({
...selectedFormats,
monospace: false,
}));
+
return;
}
@@ -283,8 +308,7 @@ const TextFormatter: FC = ({
document.execCommand('insertHTML', false, `${text}`);
onClose();
}, [
- getSelectedElement, getSelectedText, onClose,
- selectedRange, selectedTextFormats.monospace,
+ getSelectedElement, getSelectedText, onClose, selectedRange, selectedTextFormats.monospace,
]);
function handleLinkUrlConfirm() {
@@ -299,6 +323,7 @@ const TextFormatter: FC = ({
(element as HTMLAnchorElement).href = formattedLinkUrl;
onClose();
+
return;
}
@@ -389,10 +414,12 @@ const TextFormatter: FC = ({
+