122 lines
3.2 KiB
TypeScript
122 lines
3.2 KiB
TypeScript
import { Fragment, useEffect, useRef, useState } from 'react'
|
|
import { styled } from '@nextui-org/react'
|
|
import { useRouter } from 'next/router'
|
|
import { useSnapshot } from 'valtio'
|
|
|
|
import ChatboxInput from '@/components/ChatboxInput'
|
|
import ChatMessage from '@/components/ChatMessage'
|
|
import PageHeader from '@/components/PageHeader'
|
|
import { demoAddressResolver } from '@/config/chatConstants'
|
|
import SettingsStore from '@/store/SettingsStore'
|
|
import { chatClient } from '@/utils/WalletConnectUtil'
|
|
|
|
const ChatContainer = styled('div', {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
flexGrow: 1,
|
|
height: '84%',
|
|
maxWidth: '100%'
|
|
} as any)
|
|
|
|
const MessagesContainer = styled('div', {
|
|
display: 'flex',
|
|
flexGrow: 1,
|
|
flexDirection: 'column',
|
|
overflowY: 'scroll',
|
|
padding: '10px'
|
|
} as any)
|
|
|
|
/**
|
|
* Component
|
|
*/
|
|
export default function ChatPage() {
|
|
const [topic, setTopic] = useState('')
|
|
const [messages, setMessages] = useState<
|
|
{
|
|
message: string
|
|
authorAccount: string
|
|
}[]
|
|
>([])
|
|
const { eip155Address } = useSnapshot(SettingsStore.state)
|
|
const { query } = useRouter()
|
|
const lastMessageRef = useRef<null | HTMLDivElement>(null)
|
|
|
|
const fullEip155Address = `eip155:1:${eip155Address}`
|
|
|
|
async function onOutgoingMessage(outgoingMessage: string) {
|
|
await chatClient.message({
|
|
topic,
|
|
payload: {
|
|
message: outgoingMessage,
|
|
authorAccount: fullEip155Address,
|
|
timestamp: Date.now()
|
|
}
|
|
})
|
|
|
|
if (chatClient.getMessages({ topic }).length) {
|
|
setMessages(chatClient.getMessages({ topic }))
|
|
}
|
|
}
|
|
|
|
function isOutgoingMessage(authorAccount: string) {
|
|
return authorAccount === fullEip155Address
|
|
}
|
|
|
|
function getChatTitle() {
|
|
if (typeof query.peerAccount !== 'string') return ''
|
|
|
|
return demoAddressResolver[query.peerAccount] ?? query.peerAccount
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (query?.topic) {
|
|
setTopic(query.topic as string)
|
|
}
|
|
}, [query])
|
|
|
|
useEffect(() => {
|
|
// Set existing messages on load.
|
|
if (topic) {
|
|
try {
|
|
const messages = chatClient.getMessages({ topic })
|
|
console.log('getMessages for topic: ', topic, messages)
|
|
setMessages(messages)
|
|
} catch (error) {}
|
|
}
|
|
}, [topic])
|
|
|
|
useEffect(() => {
|
|
lastMessageRef.current?.scrollIntoView({ behavior: 'smooth' })
|
|
}, [messages])
|
|
|
|
useEffect(() => {
|
|
if (topic) {
|
|
// Update local messages state on new message.
|
|
chatClient.once('chat_message', eventArgs => {
|
|
console.log('new chat message:', eventArgs)
|
|
|
|
setMessages(chatClient.getMessages({ topic }))
|
|
})
|
|
}
|
|
}, [messages, topic])
|
|
|
|
return (
|
|
<Fragment>
|
|
<PageHeader title={getChatTitle()} backButtonHref="/chats" withBackButton />
|
|
<ChatContainer>
|
|
<MessagesContainer>
|
|
{messages.map(({ message, authorAccount }, i) => (
|
|
<ChatMessage
|
|
key={i}
|
|
message={message}
|
|
messageType={isOutgoingMessage(authorAccount) ? 'outgoing' : 'incoming'}
|
|
/>
|
|
))}
|
|
<div ref={lastMessageRef}></div>
|
|
</MessagesContainer>
|
|
<ChatboxInput handleSend={onOutgoingMessage} />
|
|
</ChatContainer>
|
|
</Fragment>
|
|
)
|
|
}
|