diff --git a/native/markdown/markdown-context-provider.react.js b/native/markdown/markdown-context-provider.react.js --- a/native/markdown/markdown-context-provider.react.js +++ b/native/markdown/markdown-context-provider.react.js @@ -16,9 +16,16 @@ [key: string]: boolean, }>({}); + const [spoilerRevealed, setSpoilerRevealed] = React.useState<{ + [key: string]: { + [key: number]: boolean, + }, + }>({}); + const clearMarkdownContextData = React.useCallback(() => { setLinkModalActive({}); setLinkPressActive({}); + setSpoilerRevealed({}); }, []); const contextValue = React.useMemo( @@ -27,6 +34,8 @@ linkModalActive, setLinkPressActive, linkPressActive, + setSpoilerRevealed, + spoilerRevealed, clearMarkdownContextData, }), [ @@ -34,6 +43,8 @@ linkModalActive, setLinkPressActive, linkPressActive, + setSpoilerRevealed, + spoilerRevealed, clearMarkdownContextData, ], ); diff --git a/native/markdown/markdown-context.js b/native/markdown/markdown-context.js --- a/native/markdown/markdown-context.js +++ b/native/markdown/markdown-context.js @@ -9,6 +9,8 @@ +linkModalActive: { [key: string]: boolean }, +setLinkPressActive: SetState<{ [key: string]: boolean }>, +linkPressActive: { [key: string]: boolean }, + +setSpoilerRevealed: SetState<{ [key: string]: { [key: number]: boolean } }>, + +spoilerRevealed: { [key: string]: { [key: number]: boolean } }, +clearMarkdownContextData: () => void, }; 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 @@ -5,32 +5,75 @@ import type { ReactElement } from 'lib/shared/markdown'; +import { MessageContext } from '../chat/message-context.react'; +import GestureTouchableOpacity from '../components/gesture-touchable-opacity.react'; import { useStyles } from '../themes/colors'; +import { MarkdownContext } from './markdown-context'; type MarkdownSpoilerProps = { + +spoilerIdentifier: string | number | void, +text: ReactElement, +children?: React.Node, }; function MarkdownSpoiler(props: MarkdownSpoilerProps): React.Node { - const [isRevealed, setIsRevealed] = React.useState(false); + const markdownContext = React.useContext(MarkdownContext); + const messageContext = React.useContext(MessageContext); const styles = useStyles(unboundStyles); - const { text } = props; + + const { messageID } = messageContext; + const { text, spoilerIdentifier } = props; + + const setSpoilerRevealed = markdownContext?.setSpoilerRevealed; + const spoilerRevealed = markdownContext?.spoilerRevealed; + const parsedSpoilerIdentifier = spoilerIdentifier + ? parseInt(spoilerIdentifier) + : -1; + + const isRevealed = + spoilerRevealed?.[messageID]?.[parsedSpoilerIdentifier] ?? false; + + const styleBasedOnSpoilerState = React.useMemo(() => { + if (isRevealed) { + return null; + } + return styles.spoilerHidden; + }, [isRevealed, styles.spoilerHidden]); const onSpoilerClick = React.useCallback(() => { - setIsRevealed(true); - }, []); + if (isRevealed) { + return; + } + + if ( + spoilerRevealed && + setSpoilerRevealed && + messageID && + parsedSpoilerIdentifier + ) { + setSpoilerRevealed({ + ...spoilerRevealed, + [messageID]: { + ...spoilerRevealed[messageID], + [parsedSpoilerIdentifier]: true, + }, + }); + } + }, [ + isRevealed, + spoilerRevealed, + setSpoilerRevealed, + messageID, + parsedSpoilerIdentifier, + ]); const memoizedSpoiler = React.useMemo(() => { return ( - - {text} - + + {text} + ); - }, [onSpoilerClick, isRevealed, styles.spoilerHidden, text]); + }, [onSpoilerClick, styleBasedOnSpoilerState, text]); return memoizedSpoiler; } 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 @@ -200,7 +200,11 @@ output: SharedMarkdown.Output, state: SharedMarkdown.State, ) => ( - + ), }, inlineCode: {