diff --git a/native/chat/text-message.react.js b/native/chat/text-message.react.js --- a/native/chat/text-message.react.js +++ b/native/chat/text-message.react.js @@ -12,7 +12,10 @@ import { threadPermissions } from 'lib/types/thread-types'; import { ChatContext, type ChatContextType } from '../chat/chat-context'; -import { MarkdownContext } from '../markdown/markdown-context'; +import { + MarkdownContext, + type MarkdownContextType, +} from '../markdown/markdown-context'; import { OverlayContext, type OverlayContextType, @@ -47,8 +50,10 @@ // ChatContext +chatContext: ?ChatContextType, // MarkdownContext + +markdownContext: MarkdownContextType, +isLinkModalActive: boolean, +linkIsBlockingPresses: boolean, + +spoilerPressActive: boolean, }; class TextMessage extends React.PureComponent { message: ?React.ElementRef; @@ -63,8 +68,10 @@ verticalBounds, overlayContext, chatContext, + markdownContext, isLinkModalActive, linkIsBlockingPresses, + spoilerPressActive, canCreateSidebarFromMessage, ...viewProps } = this.props; @@ -146,10 +153,23 @@ const { message, - props: { verticalBounds, linkIsBlockingPresses }, + props: { + verticalBounds, + markdownContext, + linkIsBlockingPresses, + spoilerPressActive, + }, } = this; - if (!message || !verticalBounds || linkIsBlockingPresses) { + const { setSpoilerPressActive } = markdownContext; + setSpoilerPressActive(false); + + if ( + !message || + !verticalBounds || + linkIsBlockingPresses || + spoilerPressActive + ) { return; } @@ -216,6 +236,7 @@ const { linkModalActive, linkPressActive, + spoilerPressActive, clearMarkdownContextData, } = markdownContext; @@ -258,7 +279,9 @@ overlayContext={overlayContext} chatContext={chatContext} isLinkModalActive={isLinkModalActive} + markdownContext={markdownContext} linkIsBlockingPresses={linkIsBlockingPresses} + spoilerPressActive={spoilerPressActive} /> ); 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,20 @@ [key: string]: boolean, }>({}); + const [spoilerRevealed, setSpoilerRevealed] = React.useState<{ + [key: string]: { + [key: number]: boolean, + }, + }>({}); + const [spoilerPressActive, setSpoilerPressActive] = React.useState( + false, + ); + const clearMarkdownContextData = React.useCallback(() => { setLinkModalActive({}); setLinkPressActive({}); + setSpoilerRevealed({}); + setSpoilerPressActive(false); }, []); const contextValue = React.useMemo( @@ -27,6 +38,10 @@ linkModalActive, setLinkPressActive, linkPressActive, + setSpoilerRevealed, + spoilerRevealed, + setSpoilerPressActive, + spoilerPressActive, clearMarkdownContextData, }), [ @@ -34,6 +49,10 @@ linkModalActive, setLinkPressActive, linkPressActive, + setSpoilerRevealed, + spoilerRevealed, + setSpoilerPressActive, + spoilerPressActive, 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,11 @@ +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 } }, + +setSpoilerPressActive: SetState, + +spoilerPressActive: 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,62 @@ import type { ReactElement } from 'lib/shared/markdown'; +import { MessageContext } from '../chat/message-context.react'; import { useStyles } from '../themes/colors'; +import { MarkdownContext } from './markdown-context'; type MarkdownSpoilerProps = { + +identifier: 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 [styleBasedOnState, setStyleBasedOnState] = React.useState( + styles.spoilerHidden, + ); + + const { messageID } = messageContext; + const { text, identifier } = props; + + const setSpoilerRevealed = markdownContext?.setSpoilerRevealed; + const spoilerRevealed = markdownContext?.spoilerRevealed; + const setSpoilerPressActive = markdownContext?.setSpoilerPressActive; const onSpoilerClick = React.useCallback(() => { - setIsRevealed(true); - }, []); + if (styleBasedOnState === null) { + setSpoilerPressActive && setSpoilerPressActive(false); + return; + } + + if (spoilerRevealed && setSpoilerRevealed && messageID && identifier) { + setSpoilerRevealed({ + ...spoilerRevealed, + [messageID]: { ...spoilerRevealed[messageID], [identifier]: true }, + }); + } + setSpoilerPressActive && setSpoilerPressActive(true); + setStyleBasedOnState(null); + }, [ + setSpoilerPressActive, + spoilerRevealed, + setSpoilerRevealed, + messageID, + identifier, + styleBasedOnState, + ]); const memoizedSpoiler = React.useMemo(() => { return ( - + {text} ); - }, [onSpoilerClick, isRevealed, styles.spoilerHidden, text]); + }, [onSpoilerClick, styleBasedOnState, 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: {