diff --git a/Frontend/src/pages/message/message.js b/Frontend/src/pages/message/message.js index 827fdee..2757a3d 100644 --- a/Frontend/src/pages/message/message.js +++ b/Frontend/src/pages/message/message.js @@ -1,7 +1,8 @@ +import React, { useCallback, useContext, useEffect, useRef, useState } from "react"; +import { FaMicrophone } from "react-icons/fa"; import { useNavigate } from "react-router-dom"; import { Logo } from "../../svgs/logoSVG"; import styles from "./message.module.css"; -import { useCallback, useContext, useEffect, useRef, useState } from "react"; import axios from "axios"; import Markdown from "react-markdown"; import LoginContext from "../../context/context"; @@ -34,7 +35,8 @@ function Message() { const [chatState, setChatState] = useState("busy"); const [chatInit, setChatInit] = useState(false); const [message, setMessage] = useState(""); - let ws = useRef(null); + const ws = useRef(null); + const [isListening, setIsListening] = useState(false); useEffect(() => { if (mainRef.current) { @@ -42,6 +44,7 @@ function Message() { container.scrollTop = container.scrollHeight; } }, [chat]); + useEffect(() => { async function fetchData() { try { @@ -56,25 +59,26 @@ function Message() { } fetchData(); }, []); + useEffect(() => { if (chatId !== null) { - //make a websocket connection here let wss = new WebSocket(`wss://mindmate-ws.onrender.com?id=${chatId}`); + ws.current = wss; + console.log(wss); + wss.addEventListener("open", () => { console.log("Websocket connected"); ws.current.send(JSON.stringify({ type: "client:connected" })); ws.current.send(JSON.stringify({ type: "client:chathist" })); }); + wss.addEventListener("message", (event) => { - // console.log(event.data); const data = JSON.parse(event.data); - if (data?.type === "server:chathist") { - // console.log(data.data); const histdata = data?.data; if (!histdata) return; - for (let conv of histdata) { + histdata.forEach((conv) => { if (conv.prompt) { setChat((prevchat) => [ ...prevchat, @@ -87,62 +91,58 @@ function Message() { { message: conv.response, own: false }, ]); } - } + }); setChatState("idle"); setChatInit(true); - // promptBut.disabled = false; - } else if (data?.type === "server:response:start") { - // setChat((prevchat) => [ - // ...prevchat, - // { message: "", own: false, isLoading: true }, - // ]); } else if (data?.type === "server:response:chunk") { setChat((prevchat) => { - // prevchat.at(-1).message += data.chunk; - // console.log("!!!", prevchat); - // console.log("!!!", prevchat.slice(-1)); - return [ - ...prevchat.slice(0, -1), - { - message: `${prevchat.at(prevchat.length - 1).message}${ - data.chunk - }`, - own: false, - isLoading: true, - }, - ]; + const lastMessageIndex = prevchat.length - 1; + const lastMessage = prevchat[lastMessageIndex]; + + + if (lastMessage && lastMessage.own) { + return [ + ...prevchat, + { message: data.chunk, own: false, isLoading: true }, + ]; + } else if (lastMessage && !lastMessage.isLoading) { + + const updatedMessage = { + ...lastMessage, + message: lastMessage.message + data.chunk, + }; + return [...prevchat.slice(0, lastMessageIndex), updatedMessage]; + } else { + + const updatedMessage = { + ...lastMessage, + message: lastMessage.message + data.chunk, + }; + return [...prevchat.slice(0, lastMessageIndex), updatedMessage]; + } }); - // console.log("@text", data.chunk); } else if (data?.type === "server:response:end") { - // response = ""; - // promptBut.disabled = false; setChat((prevchat) => { - return [ - ...prevchat.slice(0, -1), - { - message: prevchat.at(prevchat.length - 1).message, - own: false, - isLoading: false, - }, - ]; + const lastMessageIndex = prevchat.length - 1; + const lastMessage = prevchat[lastMessageIndex]; + if (lastMessage && lastMessage.isLoading) { + const updatedMessage = { ...lastMessage, isLoading: false }; + return [...prevchat.slice(0, lastMessageIndex), updatedMessage]; + } + return prevchat; }); setChatState("idle"); } }); - ws.current = wss; } }, [chatId]); const handleClick = () => { setChat((prevchat) => [...prevchat, { message, own: true }]); - console.log(message); - ws.current?.send( - JSON.stringify({ - type: "client:prompt", - prompt: message, - }) - ); + if (ws.current) { + ws.current.send(JSON.stringify({ type: "client:prompt", prompt: message })); + } setMessage(""); setChatState("busy"); setChat((prevchat) => [ @@ -168,19 +168,76 @@ function Message() { } }; + const handleSpeechRecognition = () => { + const SpeechRecognition = + window.SpeechRecognition || window.webkitSpeechRecognition; + + if (!SpeechRecognition) { + console.error("Speech Recognition is not supported in this browser."); + return; + } + + const recognition = new SpeechRecognition(); + recognition.continuous = true; + recognition.interimResults = true; + recognition.lang = "en-US"; + + let recognitionTimeout; + + const stopRecognition = () => { + clearTimeout(recognitionTimeout); + recognition.stop(); + setIsListening(false); + }; + + recognition.start(); + setIsListening(true); + + recognition.onresult = (event) => { + let finalTranscript = ""; + for (let i = event.resultIndex; i < event.results.length; i++) { + const transcript = event.results[i][0].transcript; + if (event.results[i].isFinal) { + finalTranscript += transcript; + } + } + + if (finalTranscript) { + setChat((prevchat) => [...prevchat, { message: finalTranscript, own: true }]); + if (ws.current) { + ws.current.send(JSON.stringify({ type: "client:prompt", prompt: finalTranscript })); + } + setChatState("busy"); + setChat((prevchat) => [ + ...prevchat, + { message: "", own: false, isLoading: true }, + ]); + clearTimeout(recognitionTimeout); + recognitionTimeout = setTimeout(stopRecognition, 2000); + } + }; + + recognition.onerror = (event) => { + console.error("Speech Recognition Error:", event.error); + stopRecognition(); + }; + recognition.onend = stopRecognition; + }; return (