diff --git a/native/chat/inner-text-message.react.js b/native/chat/inner-text-message.react.js
--- a/native/chat/inner-text-message.react.js
+++ b/native/chat/inner-text-message.react.js
@@ -99,30 +99,6 @@
return [styles.text, textStyle];
}, [darkColor]);
- // If we need to render a Text with an onPress prop inside, we're going to
- // have an issue: the GestureTouchableOpacity below will trigger too when the
- // the onPress is pressed. We have to use a GestureTouchableOpacity in order
- // for the message touch gesture to play nice with the message swipe gesture,
- // so we need to find a way to disable the GestureTouchableOpacity.
- //
- // Our solution is to keep using the GestureTouchableOpacity for the padding
- // around the text, and to have the Texts inside ALL implement an onPress prop
- // that will default to the message touch gesture. Luckily, Text with onPress
- // plays nice with the message swipe gesture.
- let secondMessage;
- if (textMessageMarkdown.markdownHasPressable) {
- secondMessage = (
-
-
- {text}
-
-
- );
- }
-
const message = (
@@ -138,7 +114,6 @@
{text}
- {secondMessage}
diff --git a/native/markdown/markdown-spoiler.react.js b/native/markdown/markdown-spoiler.react.js
--- a/native/markdown/markdown-spoiler.react.js
+++ b/native/markdown/markdown-spoiler.react.js
@@ -7,6 +7,7 @@
import type { ReactElement } from 'lib/shared/markdown';
import { TextMessageMarkdownContext } from '../chat/text-message-markdown-context';
+import GestureTouchableOpacity from '../components/gesture-touchable-opacity.react';
import { useStyles } from '../themes/colors';
import { MarkdownContext } from './markdown-context';
@@ -69,15 +70,67 @@
parsedSpoilerIdentifier,
]);
- const memoizedSpoiler = React.useMemo(() => {
- return (
-
- {text}
-
- );
- }, [onSpoilerClick, styleBasedOnSpoilerState, text]);
-
- return memoizedSpoiler;
+ // The idea is to break down the spoiler text into individual words,
+ // and then encompass each word within a Text component, and
+ // each text component within a GestureTouchableOpacity.
+ // This is a way we can resolve the issue of long spoilers
+ // breaking the layout of the message, as the spoiler would force
+ // itself onto a new line if it exceeded the width of a text
+ // message.
+
+ // The conditional for {index !== arrayOfSpoilerText.length - 1 ? ' ' : ''}
+ // is a way to not add a space after the last word in the spoiler text.
+
+ // Sample text with nested markdown:
+ // Hey this is a spoiler **and this is bold text**
+ // This is converted to:
+ // [
+ // "Hey this is a spoiler ",
+ // and this is bold text
+ // ]
+
+ // We split this ReactElement into an array of individual ReactElements
+ // and then map over each individual ReactElement and return it
+ // within a GestureTouchableOpacity.
+
+ const componentsArray: ReactElement[] = React.useMemo(() => {
+ return React.Children.map(text, (child, index) => {
+ // If the element is a string, we split it into an array of words
+ // and wrap each word in a Text within a GestureTouchableOpacity
+ if (typeof child === 'string') {
+ const words = child.split(' ');
+ return words.map((word, wordIndex) => {
+ return (
+
+
+ {word}
+ {wordIndex !== words.length - 1 ? ' ' : ''}
+
+
+ );
+ });
+ }
+ // If it's a nested ReactElement,
+ // we return it within a GestureTouchableOpacity.
+ // We preserve the structure of the nested ReactElement
+ // since we don't want to break the markdown.
+ return (
+
+
+ {child}
+
+
+ );
+ });
+ }, [text, onSpoilerClick, styleBasedOnSpoilerState]);
+
+ return componentsArray;
}
const unboundStyles = {
diff --git a/native/markdown/rules.react.js b/native/markdown/rules.react.js
--- a/native/markdown/rules.react.js
+++ b/native/markdown/rules.react.js
@@ -12,7 +12,6 @@
import { useSelector } from '../redux/redux-utils';
import MarkdownLink from './markdown-link.react';
-import MarkdownParagraph from './markdown-paragraph.react';
import MarkdownSpoiler from './markdown-spoiler.react';
import { getMarkdownStyles } from './styles';
@@ -98,9 +97,9 @@
output: SharedMarkdown.Output,
state: SharedMarkdown.State,
) => (
-
+
{output(node.content, state)}
-
+
),
},
// This is the leaf node in the AST returned by the parse phase