-
Notifications
You must be signed in to change notification settings - Fork 1
/
ChatModal.tsx
106 lines (93 loc) · 3.07 KB
/
ChatModal.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { Address } from 'viem';
import useXMTPClient from '../hooks/useXMTPClient';
import { Button, HStack, Input, InputGroup, InputRightElement, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, VStack } from '@chakra-ui/react';
import { useEffect, useState } from 'react';
import { Conversation, DecodedMessage } from '@xmtp/xmtp-js';
import { Text } from '@chakra-ui/react';
interface ChatModalProps {
isOpen: boolean;
isLoading?: boolean;
title: string;
companion: Address;
counterparty: string;
onClose: () => void;
}
const ChatModal = ({ isOpen, title, counterparty, companion, onClose }: ChatModalProps) => {
const xmtpClient = useXMTPClient();
const [conversation, setConversation] = useState<Conversation>();
const [messages, setMessages] = useState<DecodedMessage[]>([]);
const [text, setText] = useState('');
const onSend = async () => {
conversation?.send(text);
setText('');
};
useEffect(() => {
if (!xmtpClient) {
return;
}
xmtpClient.conversations.newConversation(companion)
.then((conversation) => {
setConversation(conversation);
conversation.messages().then(setMessages);
});
}, [xmtpClient, companion]);
useEffect(() => {
if (!conversation) {
return;
}
// Function to stream new messages in the conversation
const streamMessages = async () => {
const newStream = await conversation.streamMessages();
for await (const msg of newStream) {
const exists = messages.find((m) => m.id === msg.id);
if (!exists) {
setMessages((prevMessages) => [...prevMessages, msg]);
}
}
};
streamMessages();
}, [conversation, messages]);
return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>{title}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VStack spacing={2} align="stretch">
{
messages.filter(
(v, i, a) => a.findIndex((t) => t.id === v.id) === i
).map((msg) => (
<HStack key={`chatmsg-${msg.id}`}>
<Text as="b">
{msg.senderAddress.toLowerCase() === companion.toLocaleLowerCase() ? counterparty : 'You'}
</Text>
<Text>{msg.content}</Text>
</HStack>
))
}
</VStack>
</ModalBody>
<ModalFooter>
<InputGroup>
<Input
type="text"
pr="4.5rem"
placeholder="Hello..."
value={text}
onKeyDown={(e) => e.key === 'Enter' && onSend()}
onChange={(e) => setText(e.target.value)}
/>
<InputRightElement width="4.5rem">
<Button h="1.75rem" size="sm" colorScheme="blue" onClick={onSend}>
Send
</Button>
</InputRightElement>
</InputGroup>
</ModalFooter>
</ModalContent>
</Modal>
);
};
export default ChatModal;