import React, { PropsWithChildren, useContext } from 'react'; import { getDisplayName } from '../utils/getDisplayName'; import type { Attachment } from 'stream-chat'; import type { ActionHandler } from '../../components/Attachment/Attachment'; import type { TouchableHandlerPayload } from '../../components/Message/Message'; import type { GroupType, MessageType } from '../../components/MessageList/hooks/useMessageList'; import type { ChannelContextValue } from '../../contexts/channelContext/ChannelContext'; import type { MessageContentType } from '../../contexts/messagesContext/MessagesContext'; import type { DefaultAttachmentType, DefaultChannelType, DefaultCommandType, DefaultEventType, DefaultMessageType, DefaultReactionType, DefaultUserType, UnknownType, } from '../../types/types'; export type Alignment = 'right' | 'left'; export type Reactions = { own: boolean; type: string; }[]; export type MessageContextValue< 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, > = { /** Whether or not actions can be performed on message */ actionsEnabled: boolean; /** Position of the message, either 'right' or 'left' */ alignment: Alignment; /** * Function that returns a boolean indicating whether or not the user can edit/delete the message. */ canModifyMessage: boolean; /** The files attached to a message */ files: Attachment[]; /** * Position of message in group - top, bottom, middle, single. * * Message group is a group of consecutive messages from same user. groupStyles can be used to style message as per their position in message group * e.g., user avatar (to which message belongs to) is only showed for last (bottom) message in group. */ groupStyles: GroupType[]; /** Handler for actions. Actions in combination with attachments can be used to build [commands](https://getstream.io/chat/docs/#channel_commands). */ handleAction: ActionHandler; handleDeleteMessage: () => Promise; handleEditMessage: () => void; handleQuotedReplyMessage: () => void; handleResendMessage: () => Promise; handleToggleBanUser: () => Promise; handleToggleMuteUser: () => Promise; handleToggleReaction: (reactionType: string) => Promise; /** Whether or not message has reactions */ hasReactions: boolean; /** The images attached to a message */ images: Attachment[]; /** Whether or not this is the active user's message */ isMyMessage: boolean; /** Whether or not this is the last message in a group of messages */ lastGroupMessage: boolean; /** Current [message object](https://getstream.io/chat/docs/#message_format) */ message: MessageType; /** Order to render the message content */ messageContentOrder: MessageContentType[]; /** * You can call methods available on the Message * component such as handleEdit, handleDelete, handleAction etc. * * Source - [Message](https://github.com/GetStream/stream-chat-react-native/blob/master/src/components/Message/Message.tsx) * * By default, we show the overlay with all the message actions on long press. * * @param event Event object for onLongPress event */ onLongPress: (payload: TouchableHandlerPayload) => void; /** Whether the message is only text and the text is only emojis */ onlyEmojis: boolean; /** Handler to open a thread on a message */ onOpenThread: () => void; /** * You can call methods available on the Message * component such as handleEdit, handleDelete, handleAction etc. * * Source - [Message](https://github.com/GetStream/stream-chat-react-native/blob/master/src/components/Message/Message.tsx) * * By default, we will dismiss the keyboard on press. * * @param event Event object for onPress event */ onPress: (payload: TouchableHandlerPayload) => void; onPressIn: ((payload: TouchableHandlerPayload) => void) | null; /** The images attached to a message */ otherAttachments: Attachment[]; reactions: Reactions; showMessageOverlay: (messageReactions?: boolean) => void; showMessageStatus: boolean; /** Whether or not the Message is part of a Thread */ threadList: boolean; goToMessage?: (messageId: string) => void; /** Latest message id on current channel */ lastReceivedId?: string; /** Prevent message being pressed for image viewer view */ preventPress?: boolean; /** Whether or not the avatar show show next to Message */ showAvatar?: boolean; } & Pick< ChannelContextValue, 'channel' | 'disabled' | 'members' | 'readEventsEnabled' >; export const MessageContext = React.createContext({} as MessageContextValue); export const MessageProvider = < 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, >({ children, value, }: PropsWithChildren<{ value?: MessageContextValue; }>) => ( {children} ); export const useMessageContext = < 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, >() => useContext(MessageContext) as unknown as MessageContextValue; /** * Typescript currently does not support partial inference so if MessageContext * typing is desired while using the HOC withMessageContextContext the Props for the * wrapped component must be provided as the first generic. */ export const withMessageContext = < P extends UnknownType, 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, >( Component: React.ComponentType

, ): React.FC>> => { const WithMessageContextComponent = ( props: Omit>, ) => { const messageContext = useMessageContext(); return ; }; WithMessageContextComponent.displayName = `WithMessageContext${getDisplayName(Component)}`; return WithMessageContextComponent; };