From 511c4299272be297377b235f97e5e352fbaf056d Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Fri, 29 May 2026 12:44:43 -0400 Subject: [PATCH] tts: purge cached audio and dequeue on message delete When a message is deleted, drop its cached TTS audio (keys `${messageId}-${voice}`), remove any pending entries from the playback queue, and if it is the message currently playing, stop it and advance the queue. Track currentQueuedMessageId so the active item can be identified. Keeps auto-play sequencing correct and prevents a deleted message's stale audio from replaying. --- templates/chat.html | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/templates/chat.html b/templates/chat.html index 4cf5998..c4943e8 100644 --- a/templates/chat.html +++ b/templates/chat.html @@ -143,6 +143,7 @@ const dompurify_config = { let userHasScrolledUp = false; let currentAudio = null; // To keep track of the currently playing audio let currentQueuedAudio = null; // To keep track of currently playing queued TTS audio +let currentQueuedMessageId = null; // messageId of the queued audio currently playing (for cleanup on delete) let audioCache = {}; // Cache to store audio blobs // Flag to prevent mutual updates on desktop/mobile @@ -1240,8 +1241,9 @@ function processNextTTS() { isPlayingTTS = true; const { text, playButton, messageId } = ttsQueue.shift(); + currentQueuedMessageId = messageId; console.log("Processing TTS from queue:", messageId); - + // Use non-blocking async processing speakTextQueued(text, playButton, messageId) .then(() => { @@ -1252,6 +1254,7 @@ function processNextTTS() { }) .finally(() => { isPlayingTTS = false; + currentQueuedMessageId = null; // Schedule next item with minimal delay to prevent blocking setTimeout(processNextTTS, 10); }); @@ -1331,8 +1334,9 @@ function toggleAutoPlayTTS() { currentQueuedAudio.currentTime = 0; currentQueuedAudio = null; } + currentQueuedMessageId = null; } - + updateAutoPlayTTSDisplay(); } @@ -1804,6 +1808,30 @@ socket.on("message_deleted", (data) => { if (messageElement) { messageElement.remove(); } + + // Drop cached TTS audio for this message (keys are `${messageId}-${voice}`). + // The trailing dash keeps "12-" from matching "120-...". + const cachePrefix = data.message_id + "-"; + Object.keys(audioCache).forEach((key) => { + if (key.startsWith(cachePrefix)) { + delete audioCache[key]; + } + }); + + // Remove any pending queue entries for this message so the rest play in order. + ttsQueue = ttsQueue.filter((item) => item.messageId != data.message_id); + + // If it's the message currently playing, stop it and advance the queue. + if (currentQueuedMessageId != null && currentQueuedMessageId == data.message_id) { + if (currentQueuedAudio) { + currentQueuedAudio.pause(); + currentQueuedAudio.currentTime = 0; + currentQueuedAudio = null; + } + currentQueuedMessageId = null; + isPlayingTTS = false; + setTimeout(processNextTTS, 10); + } }); // Socket event for when a message is updated