import React, { useMemo } from 'react'; import { Pressable, StyleSheet, Text, View } from 'react-native'; import { formatMessage } from 'stream-chat'; import { ChannelContextValue, useChannelContext, } from '../../../../contexts/channelContext/ChannelContext'; import { useMessageContext } from '../../../../contexts/messageContext/MessageContext'; import { useTheme } from '../../../../contexts/themeContext/ThemeContext'; import { useThreadContext } from '../../../../contexts/threadContext/ThreadContext'; import { useTranslationContext } from '../../../../contexts/translationContext/TranslationContext'; import { useStableCallback } from '../../../../hooks'; import { ArrowUpRight } from '../../../../icons/arrow-up-right'; import { primitives } from '../../../../theme'; import { useShouldUseOverlayStyles } from '../../hooks/useShouldUseOverlayStyles'; type SentToChannelHeaderPropsWithContext = Pick & { /** * Function to handle press on the sent to channel header * @returns void */ onPress: () => void; /** * Boolean to show the view text * @default false */ showViewText?: boolean; }; const SentToChannelHeaderWithContext = (props: SentToChannelHeaderPropsWithContext) => { const { threadList, onPress, showViewText } = props; const { t } = useTranslationContext(); const styles = useStyles(); return ( {threadList ? t('Also sent in channel') : t('Replied to a thread')} {showViewText ? ( <> ยท {t('View')} ) : null} ); }; const MemoizedSentToChannelHeader = React.memo( SentToChannelHeaderWithContext, ) as typeof SentToChannelHeaderWithContext; export type SentToChannelHeaderProps = Partial; export const SentToChannelHeader = (props: SentToChannelHeaderProps) => { const { onAlsoSentToChannelHeaderPress } = useThreadContext(); const { channel, threadList } = useChannelContext(); const { message } = useMessageContext(); // TODO: V9: This should be handled by the channel/thread entirely. We should only fetch // if we don't have the message in state already. const handleOnPress = useStableCallback(async () => { if (threadList) { onAlsoSentToChannelHeaderPress?.({ targetedMessageId: message.id }); return; } if (!message.parent_id) { return; } try { const { messages } = await channel.getMessagesById([message.parent_id]); const parentThreadMessage = formatMessage(messages?.[0]); if (!parentThreadMessage) { return; } onAlsoSentToChannelHeaderPress?.({ parentMessage: formatMessage(parentThreadMessage), targetedMessageId: message.id, }); } catch (error) { console.error('Error querying parent message:', error); } }); const showViewText = useMemo(() => { return !!onAlsoSentToChannelHeaderPress; }, [onAlsoSentToChannelHeaderPress]); return ( ); }; const useStyles = () => { const { theme: { semantics, messageItemView: { sentToChannelHeader: { container, label, dot, link }, }, }, } = useTheme(); const shouldUseOverlayStyles = useShouldUseOverlayStyles(); return useMemo(() => { return StyleSheet.create({ container: { alignItems: 'center', flexDirection: 'row', gap: primitives.spacingXxs, paddingVertical: primitives.spacingXxs, ...container, }, label: { color: shouldUseOverlayStyles ? semantics.textOnAccent : semantics.textPrimary, fontSize: primitives.typographyFontSizeXs, fontWeight: primitives.typographyFontWeightSemiBold, lineHeight: primitives.typographyLineHeightTight, ...label, }, dot: { color: shouldUseOverlayStyles ? semantics.textOnAccent : semantics.textPrimary, fontSize: primitives.typographyFontSizeXs, fontWeight: primitives.typographyFontWeightSemiBold, lineHeight: primitives.typographyLineHeightTight, ...dot, }, link: { color: shouldUseOverlayStyles ? semantics.buttonPrimaryTextOnAccent : semantics.accentPrimary, fontSize: primitives.typographyFontSizeXs, fontWeight: primitives.typographyFontWeightRegular, lineHeight: primitives.typographyLineHeightTight, ...link, }, }); }, [shouldUseOverlayStyles, container, semantics, label, dot, link]); };