@@ -10839,6 +10839,102 @@ class FastSearchCard extends HTMLElement {
1083910839 this.updateTTSButtonState('error');
1084010840 }
1084110841 }
10842+
10843+ updateTTSButtonState(state) {
10844+ // Finde den aktuell aktiven TTS Button
10845+ const activeTTSContainer = this.shadowRoot?.querySelector('.device-control-presets.tts-presets.visible') ||
10846+ document.querySelector('.device-control-presets.tts-presets.visible');
10847+
10848+ if (!activeTTSContainer) return;
10849+
10850+ const speakBtn = activeTTSContainer.querySelector('.tts-speak-btn');
10851+ const btnIcon = speakBtn?.querySelector('.tts-btn-icon');
10852+ const btnText = speakBtn?.querySelector('.tts-btn-text');
10853+
10854+ if (!speakBtn || !btnIcon || !btnText) return;
10855+
10856+ switch (state) {
10857+ case 'speaking':
10858+ speakBtn.disabled = true;
10859+ speakBtn.style.background = '#4CAF50'; // Grün
10860+ btnIcon.textContent = '🔊';
10861+ btnText.textContent = 'Spreche...';
10862+
10863+ // Auto-Reset nach geschätzter Zeit (150 Wörter/min)
10864+ const textarea = activeTTSContainer.querySelector('.tts-textarea');
10865+ if (textarea) {
10866+ const wordCount = textarea.value.trim().split(/\s+/).length;
10867+ const estimatedDuration = Math.max(3000, (wordCount / 150) * 60 * 1000); // Min 3 Sekunden
10868+
10869+ setTimeout(() => {
10870+ this.updateTTSButtonState('ready');
10871+ }, estimatedDuration);
10872+ }
10873+ break;
10874+
10875+ case 'error':
10876+ speakBtn.disabled = false;
10877+ speakBtn.style.background = '#f44336'; // Rot
10878+ btnIcon.textContent = '❌';
10879+ btnText.textContent = 'Fehler - Erneut versuchen';
10880+
10881+ // Reset nach 3 Sekunden
10882+ setTimeout(() => {
10883+ this.updateTTSButtonState('ready');
10884+ }, 3000);
10885+ break;
10886+
10887+ case 'ready':
10888+ default:
10889+ speakBtn.disabled = false;
10890+ speakBtn.style.background = 'var(--accent)'; // Standard Blau
10891+ btnIcon.textContent = '▶️';
10892+ btnText.textContent = 'Sprechen';
10893+ break;
10894+ }
10895+ }
10896+
10897+ setupTTSEventListeners(item, container) {
10898+ const textarea = container.querySelector('.tts-textarea');
10899+ const speakBtn = container.querySelector('.tts-speak-btn');
10900+ const counter = container.querySelector('.tts-counter');
10901+
10902+ if (!textarea || !speakBtn || !counter) {
10903+ console.warn('⚠️ TTS elements not found in container');
10904+ return;
10905+ }
10906+
10907+ // Verhindere doppelte Event Listener
10908+ if (container.dataset.ttsListenersAttached === 'true') return;
10909+ container.dataset.ttsListenersAttached = 'true';
10910+
10911+ // Zeichenzähler Update
10912+ textarea.addEventListener('input', () => {
10913+ const length = textarea.value.length;
10914+ counter.textContent = `${length}/300`;
10915+
10916+ // Warnung bei >250 Zeichen
10917+ if (length > 250) {
10918+ counter.classList.add('warning');
10919+ } else {
10920+ counter.classList.remove('warning');
10921+ }
10922+
10923+ // Button aktivieren/deaktivieren
10924+ speakBtn.disabled = length === 0;
10925+ });
10926+
10927+ // Sprechen Button
10928+ speakBtn.addEventListener('click', () => {
10929+ const text = textarea.value.trim();
10930+ if (text && !speakBtn.disabled) {
10931+ this.speakTTS(text, item.id);
10932+ }
10933+ });
10934+
10935+ console.log('✅ TTS Event Listeners attached for', item.id);
10936+ }
10937+
1084210938
1084310939 getMediaPlayerControlsHTML(item) {
1084410940 const state = this._hass.states[item.id];
@@ -10894,7 +10990,7 @@ class FastSearchCard extends HTMLElement {
1089410990 </div>
1089510991
1089610992 <div class="device-control-presets tts-presets" data-is-open="false">
10897- TTS coming soon
10993+ ${this.getTTSHTML()}
1089810994 </div>
1089910995 </div>
1090010996
0 commit comments