diff --git a/src/people/hiveChat/index.tsx b/src/people/hiveChat/index.tsx index 38fd8b8a..d6f30e9a 100644 --- a/src/people/hiveChat/index.tsx +++ b/src/people/hiveChat/index.tsx @@ -8,6 +8,7 @@ import { SOCKET_MSG } from 'config/socket'; import styled from 'styled-components'; import { EuiLoadingSpinner } from '@elastic/eui'; import MaterialIcon from '@material/react-material-icon'; +import { chatHistoryStore } from 'store/chat.ts'; import { renderMarkdown } from '../utils/RenderMarkdown.tsx'; interface RouteParams { @@ -169,6 +170,7 @@ export const HiveChatView: React.FC = observer(() => { const [title, setTitle] = useState('Talk to Hive - Chat'); const history = useHistory(); const socketRef = useRef(null); + const [isUpdatingTitle, setIsUpdatingTitle] = useState(false); const handleBackClick = () => { history.push(`/workspace/${uuid}`); @@ -177,6 +179,10 @@ export const HiveChatView: React.FC = observer(() => { const refreshChatHistory = useCallback(async () => { try { await chat.loadChatHistory(chatId); + const selectedChat = chat.getChat(chatId); + if (selectedChat?.title) { + setTitle(selectedChat.title); + } if (chatHistoryRef.current) { chatHistoryRef.current.scrollTop = chatHistoryRef.current.scrollHeight; } @@ -192,6 +198,37 @@ export const HiveChatView: React.FC = observer(() => { } }, [chat, chatId, ui]); + const updateChatTitle = async ( + chatId: string, + uuid: string, + newTitle: string, + setIsUpdatingTitle: (status: boolean) => void + ): Promise => { + if (!chatId || !uuid || !newTitle.trim()) return; + + setIsUpdatingTitle(true); + try { + chatHistoryStore.updateChatTitle(chatId, newTitle); + ui.setToasts([ + { + title: 'Success', + text: 'Chat Title Updated' + } + ]); + } catch (error) { + console.error('Error updating chat title:', error); + ui.setToasts([ + { + title: 'Error', + color: 'danger', + text: 'Failed to update chat title' + } + ]); + } finally { + setIsUpdatingTitle(false); + } + }; + useEffect(() => { const initializeChat = async () => { setLoading(true); @@ -210,6 +247,26 @@ export const HiveChatView: React.FC = observer(() => { initializeChat(); }, [chatId, chat]); + let debounceUpdateTitle: ReturnType; + const handleTitleChange = ( + chatId: string, + uuid: string, + title: string, + setIsUpdatingTitle: (status: boolean) => void + ) => { + clearTimeout(debounceUpdateTitle); + + debounceUpdateTitle = setTimeout(() => { + updateChatTitle(chatId, uuid, title, setIsUpdatingTitle); + }, 500); + }; + + const onTitleChange = (event: React.ChangeEvent) => { + const newTitle = event.target.value; + setTitle(newTitle); + handleTitleChange(chatId, uuid, newTitle, setIsUpdatingTitle); + }; + useEffect(() => { const socket = createSocketInstance(); socketRef.current = socket; @@ -365,8 +422,12 @@ export const HiveChatView: React.FC = observer(() => { /> ) => setTitle(e.target.value)} + onChange={onTitleChange} placeholder="Enter chat title..." + disabled={isUpdatingTitle} + style={{ + cursor: isUpdatingTitle ? 'not-allowed' : 'text' + }} /> diff --git a/src/services/index.ts b/src/services/index.ts index 1990ec42..94146366 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -113,6 +113,38 @@ export class ChatService { } } + async updateChatTitle(chat_id: string, title: string): Promise { + try { + if (!uiStore.meInfo) return undefined; + const info = uiStore.meInfo; + + const response = await fetch(`${TribesURL}/hivechat/${chat_id}`, { + method: 'PUT', + mode: 'cors', + headers: { + 'x-jwt': info.tribe_jwt, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ title }) + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.text}`); + } + + const result = await response.json(); + + if (!result.success) { + throw new Error('Invalid chat title update response'); + } + + return result.data; + } catch (error) { + console.error('Error updating chat title:', error); + throw error; + } + } + async sendMessage( chat_id: string, message: string, diff --git a/src/store/chat.ts b/src/store/chat.ts index 8f97d5e1..cf3fdbbb 100644 --- a/src/store/chat.ts +++ b/src/store/chat.ts @@ -120,6 +120,16 @@ export class ChatHistoryStore implements ChatStore { return chat; } + async updateChatTitle(chat_id: string, newTitle: string): Promise { + try { + await chatService.updateChatTitle(chat_id, newTitle); + this.updateChat(chat_id, { title: newTitle }); + } catch (error) { + console.error('Error updating chat title in store:', error); + throw error; + } + } + async loadChatHistory(chat_id: string): Promise { try { const messages = await chatService.getChatHistory(chat_id);