diff --git a/native/chat/inner-robotext-message.react.js b/native/chat/inner-robotext-message.react.js index 38b9b6eac..e981f79aa 100644 --- a/native/chat/inner-robotext-message.react.js +++ b/native/chat/inner-robotext-message.react.js @@ -1,157 +1,150 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { Text, TouchableWithoutFeedback, View } from 'react-native'; import type { ReactionInfo } from 'lib/selectors/chat-selectors.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; import { entityTextToReact, entityTextToRawString, useENSNamesForEntityText, type EntityText, } from 'lib/utils/entity-text.js'; import { DummyInlineEngagementNode } from './inline-engagement.react.js'; import { useNavigateToThread } from './message-list-types.js'; import Markdown from '../markdown/markdown.react.js'; import { inlineMarkdownRules } from '../markdown/rules.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { useOverlayStyles } from '../themes/colors.js'; import type { ChatRobotextMessageInfoItemWithHeight } from '../types/chat-types.js'; function dummyNodeForRobotextMessageHeightMeasurement( robotext: EntityText, threadID: string, sidebarInfo: ?ThreadInfo, reactions: ReactionInfo, ): React.Element { return ( {entityTextToRawString(robotext, { threadID })} ); } type InnerRobotextMessageProps = { +item: ChatRobotextMessageInfoItemWithHeight, +onPress: () => void, +onLongPress?: () => void, }; function InnerRobotextMessage(props: InnerRobotextMessageProps): React.Node { const { item, onLongPress, onPress } = props; const activeTheme = useSelector(state => state.globalThemeInfo.activeTheme); const styles = useOverlayStyles(unboundStyles); const { messageInfo, robotext } = item; const { threadID } = messageInfo; const robotextWithENSNames = useENSNamesForEntityText(robotext); invariant( robotextWithENSNames, 'useENSNamesForEntityText only returns falsey when passed falsey', ); const textParts = React.useMemo(() => { const darkColor = activeTheme === 'dark'; return entityTextToReact(robotextWithENSNames, threadID, { // eslint-disable-next-line react/display-name renderText: ({ text }) => ( {text} ), // eslint-disable-next-line react/display-name renderThread: ({ id, name }) => , // eslint-disable-next-line react/display-name renderColor: ({ hex }) => , }); }, [robotextWithENSNames, activeTheme, threadID, styles.robotext]); - const viewStyle = [styles.robotextContainer]; - if (!__DEV__) { - // We don't force view height in dev mode because we - // want to measure it in Message to see if it's correct - viewStyle.push({ height: item.contentHeight }); - } - return ( - + {textParts} ); } type ThreadEntityProps = { +id: string, +name: string, }; function ThreadEntity(props: ThreadEntityProps) { const threadID = props.id; const threadInfo = useSelector(state => threadInfoSelector(state)[threadID]); const styles = useOverlayStyles(unboundStyles); const navigateToThread = useNavigateToThread(); const onPressThread = React.useCallback(() => { invariant(threadInfo, 'onPressThread should have threadInfo'); navigateToThread({ threadInfo }); }, [threadInfo, navigateToThread]); if (!threadInfo) { return {props.name}; } return ( {props.name} ); } function ColorEntity(props: { +color: string }) { const colorStyle = { color: props.color }; return {props.color}; } const unboundStyles = { link: { color: 'link', }, robotextContainer: { paddingTop: 6, paddingBottom: 11, paddingHorizontal: 24, }, robotext: { color: 'listForegroundSecondaryLabel', fontFamily: 'Arial', fontSize: 15, textAlign: 'center', }, dummyRobotext: { fontFamily: 'Arial', fontSize: 15, textAlign: 'center', }, }; const MemoizedInnerRobotextMessage: React.ComponentType = React.memo(InnerRobotextMessage); export { dummyNodeForRobotextMessageHeightMeasurement, MemoizedInnerRobotextMessage as InnerRobotextMessage, }; diff --git a/native/chat/robotext-message.react.js b/native/chat/robotext-message.react.js index fbbf12e55..c5cf7a235 100644 --- a/native/chat/robotext-message.react.js +++ b/native/chat/robotext-message.react.js @@ -1,226 +1,233 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { View } from 'react-native'; import { messageKey } from 'lib/shared/message-utils.js'; import { useCanCreateSidebarFromMessage } from 'lib/shared/thread-utils.js'; import { inlineEngagementCenterStyle } from './chat-constants.js'; import type { ChatNavigationProp } from './chat.react.js'; import { InlineEngagement } from './inline-engagement.react.js'; import { InnerRobotextMessage } from './inner-robotext-message.react.js'; import { Timestamp } from './timestamp.react.js'; import { getMessageTooltipKey, useContentAndHeaderOpacity } from './utils.js'; import { ChatContext } from '../chat/chat-context.js'; import { KeyboardContext } from '../keyboard/keyboard-state.js'; import type { AppNavigationProp } from '../navigation/app-navigator.react'; import { OverlayContext } from '../navigation/overlay-context.js'; import { RobotextMessageTooltipModalRouteName } from '../navigation/route-names.js'; import type { NavigationRoute } from '../navigation/route-names.js'; import { useStyles } from '../themes/colors.js'; import { fixedTooltipHeight } from '../tooltip/tooltip.react.js'; import type { ChatRobotextMessageInfoItemWithHeight } from '../types/chat-types.js'; import type { VerticalBounds } from '../types/layout-types.js'; import { AnimatedView } from '../types/styles.js'; type Props = { ...React.ElementConfig, +item: ChatRobotextMessageInfoItemWithHeight, +navigation: | ChatNavigationProp<'MessageList'> | AppNavigationProp<'TogglePinModal'> | ChatNavigationProp<'MessageResultsScreen'> | ChatNavigationProp<'MessageSearch'>, +route: | NavigationRoute<'MessageList'> | NavigationRoute<'TogglePinModal'> | NavigationRoute<'MessageResultsScreen'> | NavigationRoute<'MessageSearch'>, +focused: boolean, +toggleFocus: (messageKey: string) => void, +verticalBounds: ?VerticalBounds, }; function RobotextMessage(props: Props): React.Node { const { item, navigation, route, focused, toggleFocus, verticalBounds, ...viewProps } = props; let timestamp = null; if (focused || item.startsConversation) { timestamp = ( ); } const styles = useStyles(unboundStyles); let inlineEngagement = null; if (item.threadCreatedFromMessage || Object.keys(item.reactions).length > 0) { inlineEngagement = ( ); } const chatContext = React.useContext(ChatContext); const keyboardState = React.useContext(KeyboardContext); const key = messageKey(item.messageInfo); const onPress = React.useCallback(() => { const didDismiss = keyboardState && keyboardState.dismissKeyboardIfShowing(); if (!didDismiss) { toggleFocus(key); } }, [keyboardState, toggleFocus, key]); const overlayContext = React.useContext(OverlayContext); const viewRef = React.useRef>(); const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage( item.threadInfo, item.messageInfo, ); const visibleEntryIDs = React.useMemo(() => { const result = []; if (item.threadCreatedFromMessage || canCreateSidebarFromMessage) { result.push('sidebar'); } return result; }, [item.threadCreatedFromMessage, canCreateSidebarFromMessage]); const openRobotextTooltipModal = React.useCallback( (x, y, width, height, pageX, pageY) => { invariant( verticalBounds, 'verticalBounds should be present in openRobotextTooltipModal', ); const coordinates = { x: pageX, y: pageY, width, height }; const messageTop = pageY; const messageBottom = pageY + height; const boundsTop = verticalBounds.y; const boundsBottom = verticalBounds.y + verticalBounds.height; const belowMargin = 20; const belowSpace = fixedTooltipHeight + belowMargin; const { isViewer } = item.messageInfo.creator; const aboveMargin = isViewer ? 30 : 50; const aboveSpace = fixedTooltipHeight + aboveMargin; let margin = 0; if ( messageBottom + belowSpace > boundsBottom && messageTop - aboveSpace > boundsTop ) { margin = aboveMargin; } const currentInputBarHeight = chatContext?.chatInputBarHeights.get(item.threadInfo.id) ?? 0; props.navigation.navigate<'RobotextMessageTooltipModal'>({ name: RobotextMessageTooltipModalRouteName, params: { presentedFrom: props.route.key, initialCoordinates: coordinates, verticalBounds, visibleEntryIDs, tooltipLocation: 'fixed', margin, item, chatInputBarHeight: currentInputBarHeight, }, key: getMessageTooltipKey(item), }); }, [ item, props.navigation, props.route.key, verticalBounds, visibleEntryIDs, chatContext, ], ); const onLongPress = React.useCallback(() => { if (keyboardState && keyboardState.dismissKeyboardIfShowing()) { return; } if (visibleEntryIDs.length === 0) { return; } if (!viewRef.current || !verticalBounds) { return; } if (!focused) { toggleFocus(messageKey(item.messageInfo)); } invariant(overlayContext, 'RobotextMessage should have OverlayContext'); overlayContext.setScrollBlockingModalStatus('open'); viewRef.current?.measure(openRobotextTooltipModal); }, [ focused, item, keyboardState, overlayContext, toggleFocus, verticalBounds, viewRef, visibleEntryIDs, openRobotextTooltipModal, ]); const onLayout = React.useCallback(() => {}, []); const contentAndHeaderOpacity = useContentAndHeaderOpacity(item); + const viewStyle = {}; + if (!__DEV__) { + // We don't force view height in dev mode because we + // want to measure it in Message to see if it's correct + viewStyle.height = item.contentHeight; + } + return ( {timestamp} - + + {inlineEngagement} - {inlineEngagement} ); } const unboundStyles = { sidebar: { marginTop: inlineEngagementCenterStyle.topOffset, marginBottom: -inlineEngagementCenterStyle.topOffset, alignSelf: 'center', }, }; export { RobotextMessage };