import { useCallback, useEffect } from 'react'; import { Toast, useUIKit } from '@tencentcloud/uikit-base-component-react'; import cs from 'classnames'; import { View, GroupStore } from 'tuikit-atomicx-react/chat'; import { useChatUIState } from '../../context/useChatUIState'; import { AttachmentPicker, FilePicker, ImagePicker, VideoPicker } from './AttachmentPicker'; import { EmojiPicker } from './EmojiPicker'; import classes from './MessageInput.module.scss'; import { MessageInputContext } from './MessageInputContext'; import { QuotedMessagePreview } from './QuotedMessagePreview'; import { SendButton } from './SendButton'; import { TextEditor } from './TextEditor'; import { getSendErrorMessage } from './utils/getSendErrorMessage'; import type { CustomAction, IMessageInputProps } from './types'; const DEFAULT_ACTIONS = [ { key: 'EmojiPicker', component: EmojiPicker }, { key: 'AttachmentPicker', component: AttachmentPicker }, { key: 'FilePicker', component: FilePicker }, { key: 'ImagePicker', component: ImagePicker }, { key: 'VideoPicker', component: VideoPicker }, ]; /** * Picks specified properties from an object, automatically filtering out undefined properties * @param sourceObject The source object to pick properties from * @param propertyKeys Array of property keys to pick * @returns A new object containing only the specified properties */ const pickProps = ( sourceObject: T, propertyKeys: K[], ): Pick => Object.fromEntries( propertyKeys .map(key => [key, sourceObject[key]]) .filter(([_, value]) => value !== undefined), ) as Pick; const getActionList = (actions: IMessageInputProps['actions'] = ['EmojiPicker', 'AttachmentPicker']) => { const resolveStringAction = (actionKey: string) => { const { component = () => null } = DEFAULT_ACTIONS.find(({ key }) => key === actionKey) ?? {}; return { Component: component, props: {} }; }; const resolveObjectAction = (action: CustomAction) => { const { key: actionKey, component, ...restProps } = action; const defaultComponent = DEFAULT_ACTIONS.find(({ key }) => key === actionKey)?.component ?? (() => null); return { Component: component ?? defaultComponent, props: pickProps(restProps, ['label', 'className', 'style', 'iconSize', 'disabled']), }; }; return actions .map(action => typeof action === 'string' ? resolveStringAction(action) : resolveObjectAction(action as CustomAction)) .filter(({ Component }) => Component !== null); }; function MessageInput({ autoFocus: propAutoFocus, disabled: propDisabled, disableMention = false, hideSendButton: propHideSendButton = true, placeholder: propPlaceholder, className = '', style = {}, maxLength, attachmentPickerMode: propAttachmentPickerMode, actions, slots, TextEditor: CustomTextEditor, EmojiPicker: CustomEmojiPicker, AttachmentPicker: CustomAttachmentPicker, FilePicker: CustomFilePicker, ImagePicker: CustomImagePicker, VideoPicker: CustomVideoPicker, setOfflinePushInfo, }: IMessageInputProps) { const { sendInputMessage, } = useChatUIState(); const { loadJoinedGroups } = GroupStore(); useEffect(() => { loadJoinedGroups(); }, [loadJoinedGroups]); // const { groupID, isInGroup } = useGroupSettingState(); const { messageInputConfig, direction, t } = useUIKit(); // const shouldDisableInput = Boolean(groupID && !isInGroup); const resolvedAutoFocus = propAutoFocus ?? messageInputConfig?.autoFocus ?? true; // const resolvedDisabled = propDisabled ?? shouldDisableInput ?? messageInputConfig?.disabled ?? false; const resolvedDisabled = propDisabled ?? messageInputConfig?.disabled ?? false; const resolvedHideSendButton = propHideSendButton ?? messageInputConfig?.hideSendButton ?? true; const resolvedPlaceholder = propPlaceholder ?? messageInputConfig?.placeholder ?? ''; const resolvedAttachmentPickerMode = propAttachmentPickerMode ?? messageInputConfig?.attachmentPickerMode ?? 'collapsed'; const handleSendMessage = useCallback(() => { sendInputMessage().catch((error) => { Toast.error({ message: getSendErrorMessage(t, error), }); }); }, [sendInputMessage, t]); return ( {slots?.headerToolbar?.() ?? null}
{slots?.leftInline?.() ?? (
{getActionList(actions).map(({ Component, props }, index) => { // Check if custom component is provided const ActualComponent = Component; if (Component === EmojiPicker && CustomEmojiPicker) { return CustomEmojiPicker; } if (Component === AttachmentPicker && CustomAttachmentPicker) { return CustomAttachmentPicker; } if (Component === FilePicker && CustomFilePicker) { return CustomFilePicker; } if (Component === ImagePicker && CustomImagePicker) { return CustomImagePicker; } if (Component === VideoPicker && CustomVideoPicker) { return CustomVideoPicker; } const additionalProps = Component === AttachmentPicker ? { attachmentPickerMode: resolvedAttachmentPickerMode } : {}; return ; })}
)} {CustomTextEditor || ( )} {slots?.rightInline?.() ?? ( !resolvedHideSendButton && (
) )}
{slots?.footerToolbar?.() ?? null}
); } export { MessageInput }; export type { IMessageInputProps };