import React, { useCallback, useState } from 'react'; import { TextInput, View, StyleSheet, Image, TouchableOpacity, Keyboard, ViewStyle, ImageStyle, } from 'react-native'; import { IGif } from '@livelike/javascript'; import { useAnalytics, useChatMessageActions, useChatRoomState, useCustomFontStyle, useStyles, useTheme, useTrackKeyboardEffect, } from '../../hooks'; import { ComponentStyleProp, LLComponentStyleFn } from '../../types'; import { LLComposerSendButton, LLComposerSendButtonProps, } from './LLComposerSendButton'; import { LLGifPicker, LLGifPickerProps } from '../LLGifPicker'; import { LLStickerPicker, LLStickerPickerProps } from '../LLStickerPicker'; export type LLChatMessageComposerStyles = { composerContainer: ViewStyle; composerInput: ViewStyle; composerIcon: ImageStyle; }; export type LLChatMessageComposerProps = ComponentStyleProp & { roomId: string; TextInputComponent?: typeof TextInput; GifPickerComponent?: typeof LLGifPicker; GifPickerComponentStyles?: LLGifPickerProps['styles']; StickerPickerComponent?: typeof LLStickerPicker; StickerPickerComponentStyles?: LLStickerPickerProps['styles']; SendButtonComponent?: typeof LLComposerSendButton; SendButtonComponentStyles?: LLComposerSendButtonProps['styles']; }; export function LLChatMessageComposer({ roomId, styles: stylesProp, TextInputComponent = TextInput, GifPickerComponentStyles, StickerPickerComponentStyles, SendButtonComponentStyles, StickerPickerComponent = LLStickerPicker, GifPickerComponent = LLGifPicker, SendButtonComponent = LLComposerSendButton, }: LLChatMessageComposerProps) { const [inputValue, setInputValue] = useState(''); const [isGifPickerVisible, setIsGifPickerVisible] = useState(false); const [isStickerPickerVisible, setIsStickerPickerVisible] = useState(false); const [isSendingMessage, setIsSendingMessage] = useState(false); const { theme, themeAssets } = useTheme(); const messageComposerStyles = useStyles({ componentStylesFn: getMessageComposerStyles, stylesProp, }); const { sendChatMessage } = useChatMessageActions({ roomId }); const { userAvatarUrl } = useChatRoomState({ roomId }); const { trackEvent } = useAnalytics(); const composerInputStyles = useCustomFontStyle({ style: messageComposerStyles.composerInput, }); useTrackKeyboardEffect(); const onSendMessage = useCallback(() => { const textValue = inputValue.trim(); if (!textValue) { return; } setIsSendingMessage(true); sendChatMessage({ roomId, message: textValue, sender_image_url: userAvatarUrl, }) .then((messageRes) => { setInputValue(''); }) .finally(() => { setIsSendingMessage(false); }); }, [roomId, inputValue, sendChatMessage, userAvatarUrl]); const onSelectSticker = useCallback( (stickerShortcode: string) => { sendChatMessage({ roomId, message: `:${stickerShortcode}:`, sender_image_url: userAvatarUrl, }).then((imageMessageRes) => { setIsStickerPickerVisible(false); }); }, [roomId, sendChatMessage, userAvatarUrl] ); const onSelectGif = useCallback( (gif: IGif) => { sendChatMessage({ roomId, sender_image_url: userAvatarUrl, image_url: gif.images.downsized.url, image_width: gif.images.downsized.width, image_height: gif.images.downsized.height, }).then((imageMessageRes) => { Keyboard.dismiss(); setIsGifPickerVisible(false); }); }, [sendChatMessage, roomId, userAvatarUrl] ); const onStickerPanelOpen = useCallback(() => { trackEvent('Sticker Panel Opened', { roomId }); }, [roomId]); const onStickerPanelClose = useCallback(() => { trackEvent('Sticker Panel Closed', { roomId }); }, [roomId]); const onGifPanelOpen = useCallback(() => { trackEvent('GIF Panel Opened', { roomId }); }, [roomId]); const onGifPanelClose = useCallback(() => { trackEvent('GIF Panel Closed', { roomId }); }, [roomId]); const toggleStickerPicker = useCallback(() => { if (!isStickerPickerVisible) { Keyboard.dismiss(); setIsStickerPickerVisible(true); } else { setIsStickerPickerVisible(false); } }, [isStickerPickerVisible]); const toggleGifPicker = useCallback(() => { if (!isGifPickerVisible) { Keyboard.dismiss(); setIsGifPickerVisible(true); } else { setIsGifPickerVisible(false); } }, [isGifPickerVisible]); const onInputPressIn = useCallback(() => { if (isStickerPickerVisible) { setIsStickerPickerVisible(false); } else if (isGifPickerVisible) { setIsGifPickerVisible(false); } }, [isStickerPickerVisible, isGifPickerVisible]); if (isGifPickerVisible) { return ( ); } if (isStickerPickerVisible) { return ( ); } return ( {inputValue.length === 0 ? ( <> ) : ( )} ); } const getMessageComposerStyles: LLComponentStyleFn< LLChatMessageComposerStyles > = ({ theme }) => StyleSheet.create({ composerContainer: { flexDirection: 'row', alignItems: 'center', padding: 10, backgroundColor: theme.secondaryBackground, }, composerInput: { flex: 1, height: 45, borderRadius: 10, paddingHorizontal: 12, marginRight: 10, color: theme.text, backgroundColor: theme.background, }, composerIcon: { height: 24, width: 24, marginHorizontal: 10, }, });