FuturesonyAi / static /script.js
Futuresony's picture
Create static/script.js
b7453ff verified
raw
history blame
8.64 kB
<script>
let isRecording = false;
let recognition;
let responsesHistory = {}; // Holds all responses per prompt
let currentIndex = {}; // Track current response index
function initSpeechRecognition() {
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
recognition = new SpeechRecognition();
recognition.lang = 'en-US';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.onresult = function(event) {
const transcript = event.results[0][0].transcript;
sendMessageFromVoice(transcript);
};
recognition.onerror = function(event) {
console.log("Speech recognition error:", event.error);
};
}
const micIcon = document.getElementById('mic-icon');
micIcon.addEventListener('mousedown', function() {
isRecording = true;
micIcon.textContent = 'mic_off';
recognition.start();
});
micIcon.addEventListener('mouseup', function() {
isRecording = false;
micIcon.textContent = 'mic';
recognition.stop();
});
function appendMessage(text, className) {
let chatbox = document.getElementById('chatbox');
let messageDiv = document.createElement('div');
messageDiv.className = 'message ' + className;
messageDiv.innerHTML = text;
chatbox.appendChild(messageDiv);
chatbox.scrollTop = chatbox.scrollHeight;
}
function sendMessageFromVoice(message) {
appendMessage(message, 'user');
fetchMessageFromAI(message);
}
function sendMessage() {
let userInput = document.getElementById('user-input');
let message = userInput.value.trim();
if (message === '') return;
appendMessage(message, 'user');
userInput.value = '';
fetchMessageFromAI(message);
}
function fetchMessageFromAI(message) {
document.getElementById('typing-indicator').style.display = 'flex';
fetch('/message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: message })
})
.then(response => {
if (!response.ok) {
throw new Error(`Server error: ${response.statusText}`);
}
return response.json();
})
.then(data => {
document.getElementById('typing-indicator').style.display = 'none';
if (data.response) {
addAIResponse(data.response, message);
} else {
console.error("No response from the server.");
}
})
.catch(error => {
document.getElementById('typing-indicator').style.display = 'none';
console.error('Error:', error);
appendMessage("An error occurred. Please try again later.", 'ai');
});
}
function addAIResponse(responseText, userPrompt) {
const responseId = Date.now();
responsesHistory[responseId] = [responseText];
currentIndex[responseId] = 0;
renderAIResponse(responseText, responseId, userPrompt);
}
function renderAIResponse(responseText, responseId, userPrompt) {
let chatbox = document.getElementById('chatbox');
let messageDiv = document.createElement('div');
messageDiv.className = 'message ai';
messageDiv.dataset.responseId = responseId;
messageDiv.dataset.userPrompt = userPrompt; // Store the prompt
let responseTextDiv = document.createElement('div');
responseTextDiv.className = 'response-text';
responseTextDiv.innerHTML = responseText;
messageDiv.appendChild(responseTextDiv);
let iconsDiv = document.createElement('div');
iconsDiv.className = 'icons';
let speakerIcon = document.createElement('span');
speakerIcon.className = 'material-icons';
speakerIcon.innerText = 'volume_up';
speakerIcon.onclick = () => speakText(responseId);
let copyIcon = document.createElement('span');
copyIcon.className = 'material-icons';
copyIcon.innerText = 'content_copy';
copyIcon.onclick = () => copyResponse(responseId);
let regenerateIcon = document.createElement('span');
regenerateIcon.className = 'material-icons';
regenerateIcon.innerText = 'replay';
regenerateIcon.onclick = () => regenerateResponse(responseId, responseTextDiv, iconsDiv);
iconsDiv.appendChild(speakerIcon);
iconsDiv.appendChild(copyIcon);
iconsDiv.appendChild(regenerateIcon);
messageDiv.appendChild(iconsDiv);
chatbox.appendChild(messageDiv);
chatbox.scrollTop = chatbox.scrollHeight;
}
function regenerateResponse(responseId, responseTextDiv, iconsDiv) {
responseTextDiv.innerHTML = 'Generating new response...';
// Get the original prompt from the dataset
const messageDiv = document.querySelector(`[data-response-id="${responseId}"]`);
const originalPrompt = messageDiv.dataset.userPrompt;
fetch('/message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: originalPrompt }) // Use the original prompt
})
.then(response => response.json())
.then(data => {
if (data.response) {
responsesHistory[responseId].push(data.response);
currentIndex[responseId] = responsesHistory[responseId].length - 1;
displayUpdatedResponse(responseId, data.response, iconsDiv);
} else {
responseTextDiv.innerHTML = 'Error generating response';
}
})
.catch(error => {
console.error('Error:', error);
responseTextDiv.innerHTML = 'Error generating response';
});
}
function displayUpdatedResponse(responseId, newResponse, iconsDiv) {
let messageDiv = document.querySelector(`[data-response-id="${responseId}"]`);
let responseTextDiv = messageDiv.querySelector('.response-text');
responseTextDiv.innerHTML = newResponse;
// Remove existing navigation if present
const existingNav = messageDiv.querySelector('.navigation');
if (existingNav) {
existingNav.remove();
}
let navigationDiv = document.createElement('div');
navigationDiv.className = 'navigation';
iconsDiv.appendChild(navigationDiv);
let backIcon = document.createElement('span');
backIcon.className = 'material-icons';
backIcon.innerText = 'arrow_back';
backIcon.onclick = () => navigateResponse(responseId, -1, responseTextDiv, navigationDiv);
let nextIcon = document.createElement('span');
nextIcon.className = 'material-icons';
nextIcon.innerText = 'arrow_forward';
nextIcon.onclick = () => navigateResponse(responseId, 1, responseTextDiv, navigationDiv);
let responseIndexText = document.createElement('span');
responseIndexText.className = 'response-index';
navigationDiv.appendChild(backIcon);
navigationDiv.appendChild(responseIndexText);
navigationDiv.appendChild(nextIcon);
updateResponseIndex(responseId, responseIndexText);
}
function navigateResponse(responseId, direction, responseTextDiv, navigationDiv) {
currentIndex[responseId] += direction;
currentIndex[responseId] = Math.max(0, Math.min(currentIndex[responseId], responsesHistory[responseId].length - 1));
responseTextDiv.innerHTML = responsesHistory[responseId][currentIndex[responseId]];
updateResponseIndex(responseId, navigationDiv.querySelector('.response-index'));
}
function updateResponseIndex(responseId, responseIndexText) {
responseIndexText.innerText = `${currentIndex[responseId] + 1}/${responsesHistory[responseId].length}`;
}
// Updated function to speak the current response
function speakText(responseId) {
const text = responsesHistory[responseId][currentIndex[responseId]];
const utterance = new SpeechSynthesisUtterance(text);
speechSynthesis.speak(utterance);
}
// Updated function to copy the current response
function copyResponse(responseId) {
const text = responsesHistory[responseId][currentIndex[responseId]];
navigator.clipboard.writeText(text);
alert("Copied: " + text);
}
document.addEventListener('DOMContentLoaded', initSpeechRecognition);