mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-13 08:05:01 +00:00
feat: make toast notifications persist until audio/speech completes
This commit is contained in:
parent
c98d409f0a
commit
ad76355299
1 changed files with 61 additions and 10 deletions
|
@ -145,6 +145,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
// Track active toast elements
|
||||||
|
let activeToast = null;
|
||||||
|
|
||||||
// Function to display toast notification
|
// Function to display toast notification
|
||||||
function showToast(text) {
|
function showToast(text) {
|
||||||
// Get the appropriate container based on fullscreen state
|
// Get the appropriate container based on fullscreen state
|
||||||
|
@ -176,6 +179,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
container = fsContainer;
|
container = fsContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove any existing toast
|
||||||
|
if (activeToast) {
|
||||||
|
hideToast(activeToast);
|
||||||
|
}
|
||||||
|
|
||||||
// Create toast element
|
// Create toast element
|
||||||
const toast = document.createElement('div');
|
const toast = document.createElement('div');
|
||||||
toast.className = 'toast-notification';
|
toast.className = 'toast-notification';
|
||||||
|
@ -184,24 +192,40 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Add to container
|
// Add to container
|
||||||
container.appendChild(toast);
|
container.appendChild(toast);
|
||||||
|
|
||||||
|
// Store reference to active toast
|
||||||
|
activeToast = {
|
||||||
|
element: toast,
|
||||||
|
container: container
|
||||||
|
};
|
||||||
|
|
||||||
// Trigger animation
|
// Trigger animation
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.style.opacity = '1';
|
toast.style.opacity = '1';
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
// Remove after 3 seconds
|
return activeToast;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to hide a toast
|
||||||
|
function hideToast(toastInfo) {
|
||||||
|
if (!toastInfo || !toastInfo.element) return;
|
||||||
|
|
||||||
|
toastInfo.element.style.opacity = '0';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.style.opacity = '0';
|
if (toastInfo.container && toastInfo.container.contains(toastInfo.element)) {
|
||||||
setTimeout(() => {
|
toastInfo.container.removeChild(toastInfo.element);
|
||||||
if (container && container.contains(toast)) {
|
}
|
||||||
container.removeChild(toast);
|
|
||||||
}
|
// If this was the active toast, clear the reference
|
||||||
}, 300); // Wait for fade out animation
|
if (activeToast === toastInfo) {
|
||||||
}, 3000);
|
activeToast = null;
|
||||||
|
}
|
||||||
|
}, 300); // Wait for fade out animation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track if TTS is currently in progress to prevent duplicates
|
// Track if TTS is currently in progress to prevent duplicates
|
||||||
let ttsInProgress = false;
|
let ttsInProgress = false;
|
||||||
|
let currentToast = null;
|
||||||
|
|
||||||
// Improved browser TTS function
|
// Improved browser TTS function
|
||||||
function useBrowserTTS(text) {
|
function useBrowserTTS(text) {
|
||||||
|
@ -234,10 +258,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
utterance.onend = () => {
|
utterance.onend = () => {
|
||||||
console.log('Speech ended');
|
console.log('Speech ended');
|
||||||
ttsInProgress = false; // Reset flag when speech completes
|
ttsInProgress = false; // Reset flag when speech completes
|
||||||
|
|
||||||
|
// Hide toast when speech ends
|
||||||
|
if (currentToast) {
|
||||||
|
hideToast(currentToast);
|
||||||
|
currentToast = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
utterance.onerror = (e) => {
|
utterance.onerror = (e) => {
|
||||||
console.warn('Speech error:', e);
|
console.warn('Speech error:', e);
|
||||||
ttsInProgress = false; // Reset flag on error
|
ttsInProgress = false; // Reset flag on error
|
||||||
|
|
||||||
|
// Also hide toast on error
|
||||||
|
if (currentToast) {
|
||||||
|
hideToast(currentToast);
|
||||||
|
currentToast = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.speechSynthesis.speak(utterance);
|
window.speechSynthesis.speak(utterance);
|
||||||
|
@ -249,6 +285,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
|
||||||
// Function to play pre-generated TTS audio files
|
// Function to play pre-generated TTS audio files
|
||||||
function speakText(text, timeInSeconds) {
|
function speakText(text, timeInSeconds) {
|
||||||
|
// Show the toast and keep reference
|
||||||
|
currentToast = showToast(text);
|
||||||
|
|
||||||
// Format time for filename (MM-SS)
|
// Format time for filename (MM-SS)
|
||||||
const minutes = Math.floor(timeInSeconds / 60);
|
const minutes = Math.floor(timeInSeconds / 60);
|
||||||
const seconds = timeInSeconds % 60;
|
const seconds = timeInSeconds % 60;
|
||||||
|
@ -279,11 +318,24 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up event handlers
|
// Set up event handlers
|
||||||
|
globalAudio.onended = () => {
|
||||||
|
console.log('Audio playback ended');
|
||||||
|
// Hide toast when audio ends
|
||||||
|
if (currentToast) {
|
||||||
|
hideToast(currentToast);
|
||||||
|
currentToast = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
globalAudio.onerror = (e) => {
|
globalAudio.onerror = (e) => {
|
||||||
console.warn(`Audio error: ${e.type}`, e);
|
console.warn(`Audio error: ${e.type}`, e);
|
||||||
if (!fallenBackToTTS) {
|
if (!fallenBackToTTS) {
|
||||||
fallenBackToTTS = true;
|
fallenBackToTTS = true;
|
||||||
useBrowserTTS(text);
|
useBrowserTTS(text);
|
||||||
|
} else if (currentToast) {
|
||||||
|
// If we've already tried TTS and that failed too, hide the toast
|
||||||
|
hideToast(currentToast);
|
||||||
|
currentToast = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -362,9 +414,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
const { index, time, label } = event;
|
const { index, time, label } = event;
|
||||||
console.log(`marker! ${index} - ${time} - ${label}`);
|
console.log(`marker! ${index} - ${time} - ${label}`);
|
||||||
|
|
||||||
// Speak the marker label and show toast
|
// Speak the marker label (toast is now shown within speakText)
|
||||||
speakText(label, time);
|
speakText(label, time);
|
||||||
showToast(label);
|
|
||||||
|
|
||||||
// Highlight the corresponding timestamp in the transcript
|
// Highlight the corresponding timestamp in the transcript
|
||||||
highlightTimestamp(time);
|
highlightTimestamp(time);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue