From 48813e6dcdd8fba431f7e165e8fd8ec597db6d36 Mon Sep 17 00:00:00 2001 From: Ivan Kavalerov Date: Tue, 6 May 2025 08:33:09 +0100 Subject: [PATCH 1/4] Change to Ably chat --- components/Chat.jsx | 18 +++++--- components/ChatBox.jsx | 62 +++++++++++++------------ package-lock.json | 102 +++++++++++++++++++++++++++++++++++++---- package.json | 3 +- 4 files changed, 139 insertions(+), 46 deletions(-) diff --git a/components/Chat.jsx b/components/Chat.jsx index d5ded85..d8f64fd 100644 --- a/components/Chat.jsx +++ b/components/Chat.jsx @@ -1,17 +1,23 @@ 'use client'; import * as Ably from 'ably'; -import { AblyProvider, ChannelProvider } from 'ably/react'; +import { ChatClient } from '@ably/chat'; +import { ChatClientProvider, ChatRoomProvider } from '@ably/chat/react'; import ChatBox from './ChatBox.jsx'; +const roomOptions = { + history: { limit: 50 }, +}; + export default function Chat() { - const client = new Ably.Realtime({ authUrl: '/api' }); + const realtimeClient = new Ably.Realtime({ authUrl: '/api' }); + const chatClient = new ChatClient(realtimeClient); return ( - - + + - - + + ); } diff --git a/components/ChatBox.jsx b/components/ChatBox.jsx index 5a1d6ea..465e8cd 100644 --- a/components/ChatBox.jsx +++ b/components/ChatBox.jsx @@ -1,24 +1,32 @@ -import React, { useEffect, useState } from 'react'; -import { useChannel } from 'ably/react'; +import React, { useEffect, useState, useRef } from 'react'; +import { useMessages } from '@ably/chat/react'; import styles from './ChatBox.module.css'; export default function ChatBox() { - let inputBox = null; - let messageEnd = null; + const inputBox = useRef(null); + const messageEndRef = useRef(null); const [messageText, setMessageText] = useState(''); - const [receivedMessages, setMessages] = useState([]); + const [messages, setMessages] = useState([]); const messageTextIsEmpty = messageText.trim().length === 0; - const { channel, ably } = useChannel('chat-demo', (message) => { - const history = receivedMessages.slice(-199); - setMessages([...history, message]); + const { send: sendMessage } = useMessages({ + listener: (payload) => { + setMessages((prevMessages) => [...prevMessages, payload.message]); + }, }); - const sendChatMessage = (messageText) => { - channel.publish({ name: 'chat-message', data: messageText }); - setMessageText(''); - inputBox.focus(); + const sendChatMessage = async (text) => { + if (!sendMessage) { + return; + } + try { + await sendMessage({ text: text }); + setMessageText(''); + inputBox.current?.focus(); + } catch (error) { + console.error('Error sending message:', error); + } }; const handleFormSubmission = (event) => { @@ -27,43 +35,37 @@ export default function ChatBox() { }; const handleKeyPress = (event) => { - if (event.charCode !== 13 || messageTextIsEmpty) { + if (event.key !== 'Enter' || event.shiftKey) { return; } - sendChatMessage(messageText); event.preventDefault(); + sendChatMessage(messageText); }; - const messages = receivedMessages.map((message, index) => { - const author = message.connectionId === ably.connection.id ? 'me' : 'other'; + const messageElements = messages.map((message, index) => { + const key = message.id ?? index; return ( - - {message.data} + + {message.text} ); }); useEffect(() => { - messageEnd.scrollIntoView({ behaviour: 'smooth' }); - }); + messageEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }, [messages]); return (
- {messages} -
{ - messageEnd = element; - }} - >
+ {messageElements} +