import React from 'react'; import { Image, ImageStyle, Linking, StyleProp, StyleSheet, Text, TextStyle, TouchableOpacity, View, ViewStyle, } from 'react-native'; import { MessageContextValue, useMessageContext, } from '../../contexts/messageContext/MessageContext'; import { MessagesContextValue, useMessagesContext, } from '../../contexts/messagesContext/MessagesContext'; import { useTheme } from '../../contexts/themeContext/ThemeContext'; import { makeImageCompatibleUrl } from '../../utils/utils'; import type { Attachment } from 'stream-chat'; import type { DefaultAttachmentType, DefaultChannelType, DefaultCommandType, DefaultEventType, DefaultMessageType, DefaultReactionType, DefaultUserType, UnknownType, } from '../../types/types'; const styles = StyleSheet.create({ authorName: { fontSize: 14.5, fontWeight: '600' }, authorNameContainer: { borderTopRightRadius: 15, paddingHorizontal: 8, paddingTop: 8, }, authorNameFooter: { fontSize: 14.5, fontWeight: '600', padding: 8, }, authorNameMask: { bottom: 0, left: 8, position: 'absolute', }, cardCover: { borderRadius: 8, height: 140, marginHorizontal: 8, }, cardFooter: { flexDirection: 'row', justifyContent: 'space-between', padding: 10, }, container: { overflow: 'hidden', width: 256, }, description: { fontSize: 12, marginHorizontal: 8, }, title: { fontSize: 12, marginHorizontal: 8, }, }); const goToURL = (url?: string) => { if (!url) return; Linking.canOpenURL(url).then((supported) => { if (supported) { Linking.openURL(url); } else { console.log(`Don't know how to open URI: ${url}`); } }); }; export type CardPropsWithContext< At extends UnknownType = DefaultAttachmentType, Ch extends UnknownType = DefaultChannelType, Co extends string = DefaultCommandType, Ev extends UnknownType = DefaultEventType, Me extends UnknownType = DefaultMessageType, Re extends UnknownType = DefaultReactionType, Us extends UnknownType = DefaultUserType, > = Attachment & Pick< MessageContextValue, 'onLongPress' | 'onPress' | 'onPressIn' | 'preventPress' > & Pick< MessagesContextValue, 'additionalTouchableProps' | 'CardCover' | 'CardFooter' | 'CardHeader' > & { styles?: Partial<{ authorName: StyleProp; authorNameContainer: StyleProp; authorNameFooter: StyleProp; authorNameFooterContainer: StyleProp; authorNameMask: StyleProp; cardCover: StyleProp; cardFooter: StyleProp; container: StyleProp; description: StyleProp; title: StyleProp; }>; }; const CardWithContext = < At extends UnknownType = DefaultAttachmentType, Ch extends UnknownType = DefaultChannelType, Co extends string = DefaultCommandType, Ev extends UnknownType = DefaultEventType, Me extends UnknownType = DefaultMessageType, Re extends UnknownType = DefaultReactionType, Us extends UnknownType = DefaultUserType, >( props: CardPropsWithContext, ) => { const { additionalTouchableProps, author_name, CardCover, CardFooter, CardHeader, image_url, og_scrape_url, onLongPress, onPress, onPressIn, preventPress, styles: stylesProp = {}, text, thumb_url, title, } = props; const { theme: { colors: { accent_blue, black, blue_alice, transparent }, messageSimple: { card: { authorName, authorNameContainer, authorNameFooter, authorNameFooterContainer, authorNameMask, container, cover, footer: { description, title: titleStyle, ...footerStyle }, noURI, }, }, }, } = useTheme(); const uri = image_url || thumb_url; const defaultOnPress = () => goToURL(og_scrape_url || uri); return ( { if (onLongPress) { onLongPress({ emitter: 'card', event, }); } }} onPress={(event) => { if (onPress) { onPress({ defaultHandler: defaultOnPress, emitter: 'card', event, }); } }} onPressIn={(event) => { if (onPressIn) { onPressIn({ defaultHandler: defaultOnPress, emitter: 'card', event, }); } }} style={[styles.container, container, stylesProp.container]} testID='card-attachment' {...additionalTouchableProps} > {CardHeader && } {CardCover && } {uri && !CardCover && ( {author_name && ( {author_name} )} )} {CardFooter ? ( ) : ( {!uri && author_name && ( {author_name} )} {title && ( {title} )} {text && ( {text} )} )} ); }; const MemoizedCard = React.memo(CardWithContext, () => true) as typeof CardWithContext; export type CardProps< At extends UnknownType = DefaultAttachmentType, Ch extends UnknownType = DefaultChannelType, Co extends string = DefaultCommandType, Ev extends UnknownType = DefaultEventType, Me extends UnknownType = DefaultMessageType, Re extends UnknownType = DefaultReactionType, Us extends UnknownType = DefaultUserType, > = Attachment & Partial< Pick, 'onLongPress' | 'onPress' | 'onPressIn'> & Pick< MessagesContextValue, 'additionalTouchableProps' | 'CardCover' | 'CardFooter' | 'CardHeader' > >; /** * UI component for card in attachments. */ export const Card = < At extends UnknownType = DefaultAttachmentType, Ch extends UnknownType = DefaultChannelType, Co extends string = DefaultCommandType, Ev extends UnknownType = DefaultEventType, Me extends UnknownType = DefaultMessageType, Re extends UnknownType = DefaultReactionType, Us extends UnknownType = DefaultUserType, >( props: CardProps, ) => { const { onLongPress, onPress, onPressIn, preventPress } = useMessageContext(); const { additionalTouchableProps, CardCover, CardFooter, CardHeader } = useMessagesContext(); return ( ); }; Card.displayName = 'Card{messageSimple{card}}';