diff --git a/ExtrasNode/css/extras_node_styles.css b/ExtrasNode/css/extras_node_styles.css index ece04ee..f25367d 100644 --- a/ExtrasNode/css/extras_node_styles.css +++ b/ExtrasNode/css/extras_node_styles.css @@ -63,3 +63,10 @@ .alekpet_extras_node_recognition_clear:not(:checked) { opacity: 0.5; } + +.alekpet_extras_node_speech_icon_playing::after { + content: "✖"; + position: absolute; + right: 3px; + color: var(--error-text); +} diff --git a/ExtrasNode/lib/extras_node_widgets.js b/ExtrasNode/lib/extras_node_widgets.js index d5df786..d93a5eb 100644 --- a/ExtrasNode/lib/extras_node_widgets.js +++ b/ExtrasNode/lib/extras_node_widgets.js @@ -184,57 +184,94 @@ function SpeechWidget(node, inputName, inputData, widgetsText) { ); } - if (SpeechSynthesis) { + if (SpeechSynthesis && speechSynthesis) { + // Function return utterance function speak(text, options = {}) { - if (!SpeechSynthesis && speechSynthesis.speaking) return; const utterance = new SpeechSynthesisUtterance(text); Object.assign(utterance, { ...options }); return utterance; } + function buttonsStyles( + speechesButtons, + action = "add", + className = "alekpet_extras_node_speech_icon_playing" + ) { + speechesButtons?.forEach((speechButton) => + speechButton?.classList[action](className) + ); + } + buttons.push( $el("span.alekpet_extras_node_speech_icon", { onclick: function () { - const info = widget.element.querySelector( - ".alekpet_extras_node_info span" - ); - - // Already playing - if (SpeechSynthesis && speechSynthesis.speaking) { - info.textContent = "wait..."; - setTimeout(() => (info.textContent = ""), 2000); - return; - } + try { + const info = widget.element.querySelector( + ".alekpet_extras_node_info span" + ); + + const speechesButtons = Array.from( + document.querySelectorAll(".alekpet_extras_node_speech_icon") + ); + + // Already playing + if (speechSynthesis.speaking) { + SpeechSynthesis.cancel(); - // Start playing text - const text = widgetsText?.inputEl.value; - if (text.trim() !== "") { - const utterance = speak(text, { - onend: (e) => { - this.style.opacity = 1; - info.textContent = ""; - }, - }); - - if (utterance) { - this.style.opacity = 0.7; - info.textContent = "saying now"; - - SpeechSynthesis.speak(utterance); + info.textContent = "canceled"; + this.title = "Speak text"; + + buttonsStyles(speechesButtons, "remove"); + setTimeout(() => (info.textContent = ""), 2000); + return; } - } else { - if (text.trim() === "") { + + // Start playing text + const text = widgetsText?.inputEl.value; + if (text.trim() !== "") { + const utterance = speak(text, { + onend: (e) => { + this.style.opacity = 1; + this.title = "Speak text"; + info.textContent = ""; + + buttonsStyles(speechesButtons, "remove"); + }, + }); + + if (utterance) { + this.style.opacity = 0.7; + this.title = "Cancel speech"; + info.textContent = "saying now"; + + buttonsStyles(speechesButtons); + SpeechSynthesis.speak(utterance); + } + } else { const utterance = speak( - `${widgetsText?.name || "This"}}, field is empty!` + `${widgetsText?.name || "This"}}, field is empty!`, + { + onend: (e) => { + this.style.opacity = 1; + this.title = "Speak text"; + info.textContent = ""; + + buttonsStyles(speechesButtons, "remove"); + }, + } ); - utterance && SpeechSynthesis.speak(utterance); - info.textContent = "empty text!"; - } else { - info.textContent = "error speak!"; + + if (utterance) { + this.style.opacity = 0.7; + this.title = "Cancel speech"; + info.textContent = "empty text!"; + buttonsStyles(speechesButtons); + SpeechSynthesis.speak(utterance); + } } - this.style.opacity = 1; - setTimeout(() => (info.textContent = ""), 2000); + } catch (err) { + console.log(err); } }, textContent: "🔊", diff --git a/pyproject.toml b/pyproject.toml index a42cb97..b13f098 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui_custom_nodes_alekpet" description = "Nodes: PoseNode, PainterNode, TranslateTextNode, TranslateCLIPTextEncodeNode, DeepTranslatorTextNode, DeepTranslatorCLIPTextEncodeNode, ArgosTranslateTextNode, ArgosTranslateCLIPTextEncodeNode, PreviewTextNode, HexToHueNode, ColorsCorrectNode, IDENode." -version = "1.0.19" +version = "1.0.20" license = { file = "LICENSE" } [project.urls]