Show transcription error status in chatInput placeholder on web, desktop

- Extract flashing status message in chat input placeholder into
  reusable function
- Use emoji prefixes for status messages
- Improve alt text of transcribe button to indicate what the button does
This commit is contained in:
Debanjum Singh Solanky
2023-11-26 01:08:38 -08:00
parent fc040825b2
commit 28090216f6
2 changed files with 46 additions and 24 deletions

View File

@@ -516,6 +516,18 @@
} }
} }
function flashStatusInChatInput(message) {
// Get chat input element and original placeholder
let chatInput = document.getElementById("chat-input");
let originalPlaceholder = chatInput.placeholder;
// Set placeholder to message
chatInput.placeholder = message;
// Reset placeholder after 2 seconds
setTimeout(() => {
chatInput.placeholder = originalPlaceholder;
}, 2000);
}
async function clearConversationHistory() { async function clearConversationHistory() {
let chatInput = document.getElementById("chat-input"); let chatInput = document.getElementById("chat-input");
let originalPlaceholder = chatInput.placeholder; let originalPlaceholder = chatInput.placeholder;
@@ -530,16 +542,11 @@
.then(data => { .then(data => {
chatBody.innerHTML = ""; chatBody.innerHTML = "";
loadChat(); loadChat();
chatInput.placeholder = "Cleared conversation history"; flashStatusInChatInput("🗑 Cleared conversation history");
}) })
.catch(err => { .catch(err => {
chatInput.placeholder = "Failed to clear conversation history"; flashStatusInChatInput("⛔️ Failed to clear conversation history");
}) })
.finally(() => {
setTimeout(() => {
chatInput.placeholder = originalPlaceholder;
}, 2000);
});
} }
let mediaRecorder; let mediaRecorder;
@@ -560,7 +567,11 @@
fetch(url, { method: 'POST', body: formData, headers}) fetch(url, { method: 'POST', body: formData, headers})
.then(response => response.ok ? response.json() : Promise.reject(response)) .then(response => response.ok ? response.json() : Promise.reject(response))
.then(data => { chatInput.value += data.text; }) .then(data => { chatInput.value += data.text; })
.catch(err => err.status == 422 ? console.error("Configure speech-to-text model on server.") : console.error("Failed to transcribe audio")); .catch(err => {
err.status == 422
? flashStatusInChatInput("⛔️ Configure speech-to-text model on server.")
: flashStatusInChatInput("⛔️ Failed to transcribe audio")
});
}; };
const handleRecording = (stream) => { const handleRecording = (stream) => {
@@ -579,7 +590,7 @@
mediaRecorder.start(); mediaRecorder.start();
speakButtonImg.src = './assets/icons/stop-solid.svg'; speakButtonImg.src = './assets/icons/stop-solid.svg';
speakButtonImg.alt = 'Stop Speaking'; speakButtonImg.alt = 'Stop Transcription';
}; };
// Toggle recording // Toggle recording
@@ -588,12 +599,12 @@
.getUserMedia({ audio: true }) .getUserMedia({ audio: true })
.then(handleRecording) .then(handleRecording)
.catch((e) => { .catch((e) => {
console.error(e); flashStatusInChatInput("⛔️ Failed to access microphone");
}); });
} else if (mediaRecorder.state === 'recording') { } else if (mediaRecorder.state === 'recording') {
mediaRecorder.stop(); mediaRecorder.stop();
speakButtonImg.src = './assets/icons/microphone-solid.svg'; speakButtonImg.src = './assets/icons/microphone-solid.svg';
speakButtonImg.alt = 'Speak'; speakButtonImg.alt = 'Transcribe';
} }
} }
@@ -626,7 +637,7 @@
<div id="input-row"> <div id="input-row">
<textarea id="chat-input" class="option" oninput="onChatInput()" onkeydown=incrementalChat(event) autofocus="autofocus" placeholder="Type / to see a list of commands, or just type your questions and hit enter."></textarea> <textarea id="chat-input" class="option" oninput="onChatInput()" onkeydown=incrementalChat(event) autofocus="autofocus" placeholder="Type / to see a list of commands, or just type your questions and hit enter."></textarea>
<button id="speak-button" class="input-row-button" onclick="speechToText()"> <button id="speak-button" class="input-row-button" onclick="speechToText()">
<img id="speak-button-img" src="input-row-button-img" src="./assets/icons/microphone-solid.svg" alt="Speak"></img> <img id="speak-button-img" class="input-row-button-img" src="./assets/icons/microphone-solid.svg" alt="Transcribe"></img>
</button> </button>
<button id="clear-chat" class="input-row-button" onclick="clearConversationHistory()"> <button id="clear-chat" class="input-row-button" onclick="clearConversationHistory()">
<img class="input-row-button-img" src="./assets/icons/trash-solid.svg" alt="Clear Chat History"></img> <img class="input-row-button-img" src="./assets/icons/trash-solid.svg" alt="Clear Chat History"></img>

View File

@@ -543,6 +543,18 @@ To get started, just start typing below. You can also type / to see a list of co
} }
} }
function flashStatusInChatInput(message) {
// Get chat input element and original placeholder
let chatInput = document.getElementById("chat-input");
let originalPlaceholder = chatInput.placeholder;
// Set placeholder to message
chatInput.placeholder = message;
// Reset placeholder after 2 seconds
setTimeout(() => {
chatInput.placeholder = originalPlaceholder;
}, 2000);
}
function clearConversationHistory() { function clearConversationHistory() {
let chatInput = document.getElementById("chat-input"); let chatInput = document.getElementById("chat-input");
let originalPlaceholder = chatInput.placeholder; let originalPlaceholder = chatInput.placeholder;
@@ -553,15 +565,10 @@ To get started, just start typing below. You can also type / to see a list of co
.then(data => { .then(data => {
chatBody.innerHTML = ""; chatBody.innerHTML = "";
loadChat(); loadChat();
chatInput.placeholder = "Cleared conversation history"; flashStatusInChatInput("🗑 Cleared conversation history");
}) })
.catch(err => { .catch(err => {
chatInput.placeholder = "Failed to clear conversation history"; flashStatusInChatInput("⛔️ Failed to clear conversation history");
})
.finally(() => {
setTimeout(() => {
chatInput.placeholder = originalPlaceholder;
}, 2000);
}); });
} }
@@ -578,7 +585,11 @@ To get started, just start typing below. You can also type / to see a list of co
fetch('/api/speak?client=web', { method: 'POST', body: formData }) fetch('/api/speak?client=web', { method: 'POST', body: formData })
.then(response => response.ok ? response.json() : Promise.reject(response)) .then(response => response.ok ? response.json() : Promise.reject(response))
.then(data => { chatInput.value += data.text; }) .then(data => { chatInput.value += data.text; })
.catch(err => err.status == 422 ? console.error("Configure speech-to-text model on server.") : console.error("Failed to transcribe audio")); .catch(err => {
err.status == 422
? flashStatusInChatInput("⛔️ Configure speech-to-text model on server.")
: flashStatusInChatInput("⛔️ Failed to transcribe audio")
});
}; };
const handleRecording = (stream) => { const handleRecording = (stream) => {
@@ -597,7 +608,7 @@ To get started, just start typing below. You can also type / to see a list of co
mediaRecorder.start(); mediaRecorder.start();
speakButtonImg.src = '/static/assets/icons/stop-solid.svg'; speakButtonImg.src = '/static/assets/icons/stop-solid.svg';
speakButtonImg.alt = 'Stop Speaking'; speakButtonImg.alt = 'Stop Transcription';
}; };
// Toggle recording // Toggle recording
@@ -606,12 +617,12 @@ To get started, just start typing below. You can also type / to see a list of co
.getUserMedia({ audio: true }) .getUserMedia({ audio: true })
.then(handleRecording) .then(handleRecording)
.catch((e) => { .catch((e) => {
console.error(e); flashStatusInChatInput("⛔️ Failed to access microphone");
}); });
} else if (mediaRecorder.state === 'recording') { } else if (mediaRecorder.state === 'recording') {
mediaRecorder.stop(); mediaRecorder.stop();
speakButtonImg.src = '/static/assets/icons/microphone-solid.svg'; speakButtonImg.src = '/static/assets/icons/microphone-solid.svg';
speakButtonImg.alt = 'Speak'; speakButtonImg.alt = 'Transcribe';
} }
} }
</script> </script>
@@ -635,7 +646,7 @@ To get started, just start typing below. You can also type / to see a list of co
<div id="input-row"> <div id="input-row">
<textarea id="chat-input" class="option" oninput="onChatInput()" onkeydown=incrementalChat(event) autofocus="autofocus" placeholder="Type / to see a list of commands, or just type your questions and hit enter."></textarea> <textarea id="chat-input" class="option" oninput="onChatInput()" onkeydown=incrementalChat(event) autofocus="autofocus" placeholder="Type / to see a list of commands, or just type your questions and hit enter."></textarea>
<button id="speak-button" class="input-row-button" onclick="speechToText()"> <button id="speak-button" class="input-row-button" onclick="speechToText()">
<img id="speak-button-img" class="input-row-button-img" src="/static/assets/icons/microphone-solid.svg" alt="Speak"></img> <img id="speak-button-img" class="input-row-button-img" src="/static/assets/icons/microphone-solid.svg" alt="Transcribe"></img>
</button> </button>
<button class="input-row-button" onclick="clearConversationHistory()"> <button class="input-row-button" onclick="clearConversationHistory()">
<img class="input-row-button-img" src="/static/assets/icons/trash-solid.svg" alt="Clear Chat History"></img> <img class="input-row-button-img" src="/static/assets/icons/trash-solid.svg" alt="Clear Chat History"></img>