@rohitninawe/chat-uikit-react-native
Version:
Ready-to-use Chat UI Components for React Native
188 lines • 10.4 kB
JavaScript
import React, { useContext, useState, useEffect, useCallback } from 'react';
import { CometChat } from "@cometchat/chat-sdk-react-native";
import { View, Text, TextInput, Dimensions, TouchableOpacity, Image, FlatList } from 'react-native';
import { CometChatBottomSheet, CometChatContext, CometChatDate, CometChatListItem, CometChatReceipt, CometChatTextBubble, localize } from '../../shared';
import { CloseIcon } from './resources';
import { ICONS } from '../../shared/framework/resources';
import { ICONS as MessageIcons } from '../../shared/assets/images';
import { getUnixTimestamp, getUnixTimestampInMilliseconds } from '../../shared/utils/CometChatMessageHelper';
import { CometChatMessageBubble } from '../../shared/views/CometChatMessageBubble';
import { ReceiverTypeConstants } from '../../shared/constants/UIKitConstants';
const AIAssistBotView = (props) => {
const { height } = Dimensions.get('window');
const { title, bot, sender, closeCallback, configuration, onSend } = props;
const { theme } = useContext(CometChatContext);
const [question, setQuestion] = useState("");
const [messages, setMessages] = useState([]);
const style = {
titleColor: configuration?.style?.titleColor || theme.palette.getAccent(),
titleFont: configuration?.style?.titleFont || theme.typography.name,
closeIconTint: configuration?.style?.closeIconTint || theme.palette.getAccent(),
sendIconTint: configuration?.style?.sendIconTint || question ? theme.palette.getPrimary() : theme.palette.getAccent600(),
messageInputStyle: configuration?.messageInputStyle || {},
subtitleColor: configuration?.style?.subtitleColor || theme.palette.getAccent500(),
subtitleFont: configuration?.style?.subtitleFont || theme.typography.subtitle2,
...configuration?.style
};
const { titleColor, titleFont, closeIconTint, sendIconTint, subtitleColor, subtitleFont } = style;
useEffect(() => {
let botFirstMessage = "";
if (configuration?.botFirstMessageText) {
botFirstMessage = configuration.botFirstMessageText(bot);
}
else {
botFirstMessage = localize("COMETCHAT_BOT_FIRST_MESSAGE");
}
const message = new CometChat.TextMessage(sender?.getUid(), botFirstMessage, ReceiverTypeConstants.user);
message.setSentAt(getUnixTimestamp());
message.setMuid(String(getUnixTimestampInMilliseconds()));
message.setSender(bot);
let newMessages = [...messages];
newMessages.unshift(message);
setMessages(newMessages);
}, []);
const onClose = () => {
closeCallback && closeCallback();
};
const onChangeText = (value) => {
setQuestion(value);
};
const onMsgSend = () => {
if (!question)
return;
if (messages[0]?.sender?.getUid() === sender?.getUid())
return;
let newMessages = [...messages];
const MUID = String(getUnixTimestampInMilliseconds());
const message = new CometChat.TextMessage(bot.getUid(), question, ReceiverTypeConstants.user);
message.setSentAt(getUnixTimestamp());
message.setMuid(MUID);
message.setSender(sender);
message.setStatus("WAIT");
newMessages.unshift(message);
setMessages(newMessages);
onSend(question, bot)
.then(botReply => {
const message = new CometChat.TextMessage(sender?.getUid(), botReply, ReceiverTypeConstants.user);
message.setSentAt(getUnixTimestamp());
message.setMuid(String(getUnixTimestampInMilliseconds()));
message.setSender(bot);
message.setStatus(undefined);
const messageList = newMessages.map((message) => {
if (message.getMuid() === MUID) {
message.setStatus(undefined);
}
return message;
});
messageList.unshift(message);
setMessages(messageList);
})
.catch(err => {
const messageList = newMessages.map((message) => {
if (message.getMuid() === MUID) {
message.setStatus("ERROR");
}
return message;
});
setMessages(messageList);
});
setQuestion("");
};
const RenderMessageItem = ({ item, index }) => {
const contentView = (message, theme, alignment, configuration) => {
let style = {};
if (alignment === "right") {
style = configuration?.senderMessageBubbleStyle || {};
}
else {
style = configuration?.botMessageBubbleStyle || {};
}
const defaultStyle = {
textFont: style?.textFont || theme.typography.text1,
borderRadius: style?.borderRadius || 12,
width: style?.width || "100%",
};
if (alignment === "right") {
defaultStyle["textColor"] = style?.textColor || theme.palette.getSecondary();
defaultStyle["backgroundColor"] = style?.backgroundColor || theme.palette.getPrimary();
}
else {
defaultStyle["textColor"] = style?.textColor || theme.palette.getAccent();
defaultStyle["backgroundColor"] = style?.backgroundColor || theme.palette.getSecondary();
}
return (<CometChatTextBubble text={item.text} style={defaultStyle} textContainerStyle={defaultStyle}/>);
};
function getBubbleAlignment(message, sender) {
if (message.sender?.getUid() === sender?.getUid()) {
return "right";
}
else {
return "left";
}
}
function getMessageBubbleStyle(message, theme, sender, configuration) {
if (message.sender?.getUid() === sender?.getUid()) {
const style = configuration?.senderMessageBubbleStyle || {};
return {
background: style.backgroundColor || theme.palette.getPrimary(),
borderRadius: style.borderRadius || 12,
border: style.border || undefined,
};
}
else {
const style = configuration?.botMessageBubbleStyle || {};
if (configuration?.botMessageBubbleStyle) {
return configuration?.botMessageBubbleStyle;
}
return {
background: style.backgroundColor || theme.palette.getSecondary(),
borderRadius: style.borderRadius || 12,
border: style.border || undefined,
};
}
}
;
const getFooterView = (item, bubbleAlignment) => {
let isSender = (item.getSender()?.getUid() || item['sender']['uid']) == (sender?.getUid() || sender['uid']);
return <View style={[{ flexDirection: "row", justifyContent: bubbleAlignment === "right" ? "flex-end" : "flex-start" }]}>
<CometChatDate timeStamp={((item.getDeletedAt() || item.getReadAt() || item.getDeliveredAt() || item.getSentAt()) * 1000)} style={{ textColor: theme?.palette?.getAccent600() }} pattern={"timeFormat"}/>
{isSender ?
<CometChatReceipt receipt={item.getStatus()} waitIcon={configuration?.loadingIconURL || MessageIcons.WAITING} errorIcon={configuration?.errorIconURL || MessageIcons.ERROR_TICK}/> :
null}
</View>;
};
return (<View style={{ marginBottom: 15, marginHorizontal: 2 }} key={index}>
<CometChatMessageBubble id={`${item.id}`} ContentView={() => contentView(item, theme, getBubbleAlignment(item, sender), configuration)} FooterView={() => getFooterView(item, getBubbleAlignment(item, sender))} alignment={getBubbleAlignment(item, sender)} style={getMessageBubbleStyle(item, theme, sender, configuration)}/>
</View>);
};
const keyExtractor = useCallback((item) => `${item.getMuid()}`, []);
return (<CometChatBottomSheet onClose={onClose} style={{
lineHeight: 15,
borderRadius: 20
}}>
<View style={{ height: height * .5, }}>
<CometChatListItem id={bot.getUid()} title={title || bot.getName()} avatarStyle={configuration?.avatarStyle} avatarName={title || bot.getName()} avatarURL={bot.getAvatar() ? { uri: bot.getAvatar() } : undefined} SubtitleView={() => <Text style={[{ color: subtitleColor }, subtitleFont]}>{localize("COMETCHAT_ASK_BOT_SUBTITLE")}</Text>} TailView={() => <TouchableOpacity onPress={onClose}>
<Image style={{ width: 20, height: 20, tintColor: closeIconTint }} source={configuration?.closeIconURL || CloseIcon}/>
</TouchableOpacity>} listItemStyle={{
titleColor, titleFont,
}}/>
<View style={{ flex: 1 }}>
<FlatList inverted={true} data={messages} keyExtractor={keyExtractor} renderItem={RenderMessageItem}/>
</View>
<View style={{
flexDirection: "row", alignItems: "center", justifyContent: "center", paddingTop: 10,
borderTopWidth: 1, borderColor: style?.messageInputStyle?.dividerTint || theme.palette.getAccent200()
}}>
<TextInput placeholder={localize('ENTER_YOUR_MESSAGE_HERE')} placeholderTextColor={style?.messageInputStyle?.placeholderTextColor} value={question} style={[{
padding: 8, flex: 1, borderWidth: 1, borderColor: theme.palette.getAccent500(), borderRadius: 20,
marginLeft: 10, color: style.messageInputStyle.textColor,
}, style.messageInputStyle.placeholderTextFont, style.messageInputStyle.textFont]} onChangeText={onChangeText}/>
<TouchableOpacity activeOpacity={!question && 1} onPress={onMsgSend}>
<Image style={{ width: 30, height: 30, tintColor: sendIconTint, marginHorizontal: 10 }} source={configuration?.sendIconURL || ICONS.SEND}/>
</TouchableOpacity>
</View>
</View>
</CometChatBottomSheet>);
};
export default AIAssistBotView;
//# sourceMappingURL=AIAssistBotView.js.map