Update.
This commit is contained in:
		
							parent
							
								
									e96cb5bdaa
								
							
						
					
					
						commit
						88bb78fb23
					
				@ -1,22 +1,19 @@
 | 
			
		||||
class STTButton extends HTMLElement {
 | 
			
		||||
  /** monitor target attribute so it can change on-the-fly */
 | 
			
		||||
  static get observedAttributes() { return ['target']; }
 | 
			
		||||
 | 
			
		||||
  simulateTypingWithEvents(element, text, delay = 100) {
 | 
			
		||||
    let resolver = null;
 | 
			
		||||
    let promise = new Promise((resolve) => {
 | 
			
		||||
      resolver = resolve;
 | 
			
		||||
    });
 | 
			
		||||
    const promise = new Promise((resolve) => resolver = resolve);
 | 
			
		||||
    let index = 0;
 | 
			
		||||
 | 
			
		||||
    function triggerEvent(type, key) {
 | 
			
		||||
    const triggerEvent = (type, key) => {
 | 
			
		||||
      const event = new KeyboardEvent(type, {
 | 
			
		||||
        key: key,
 | 
			
		||||
        bubbles: true,
 | 
			
		||||
        cancelable: true,
 | 
			
		||||
      });
 | 
			
		||||
      element.dispatchEvent(event);
 | 
			
		||||
    }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const interval = setInterval(() => {
 | 
			
		||||
      if (index < text.length) {
 | 
			
		||||
@ -32,7 +29,6 @@ class STTButton extends HTMLElement {
 | 
			
		||||
 | 
			
		||||
        triggerEvent('keypress', char);
 | 
			
		||||
        triggerEvent('keyup', char);
 | 
			
		||||
 | 
			
		||||
        index++;
 | 
			
		||||
      } else {
 | 
			
		||||
        clearInterval(interval);
 | 
			
		||||
@ -58,8 +54,8 @@ class STTButton extends HTMLElement {
 | 
			
		||||
      button         { all:unset; cursor:pointer; }
 | 
			
		||||
      button:hover   { background:#e8e8e8; }
 | 
			
		||||
      :host([listening]) button {
 | 
			
		||||
                       background:#d32f2f; color:#fff;
 | 
			
		||||
                       animation:pulse 1.2s ease-in-out infinite; }
 | 
			
		||||
        background:#d32f2f; color:#fff;
 | 
			
		||||
        animation:pulse 1.2s ease-in-out infinite; }
 | 
			
		||||
      @keyframes pulse {
 | 
			
		||||
        0%,100% { transform:scale(1);   box-shadow:0 0 0 0 rgba(211,47,47,.6);}
 | 
			
		||||
        50%     { transform:scale(1.12);box-shadow:0 0 0 12px rgba(211,47,47,0);}
 | 
			
		||||
@ -80,12 +76,14 @@ class STTButton extends HTMLElement {
 | 
			
		||||
 | 
			
		||||
    let interim = '';
 | 
			
		||||
    let committed = '';
 | 
			
		||||
    let previousInterim = '';
 | 
			
		||||
 | 
			
		||||
    this.recog.onresult = (e) => {
 | 
			
		||||
      interim = '';
 | 
			
		||||
      for (let i = e.resultIndex; i < e.results.length; i++) {
 | 
			
		||||
        const res = e.results[i];
 | 
			
		||||
        const txt = res[0].transcript.trim();
 | 
			
		||||
        const alt = res[0];
 | 
			
		||||
        const txt = alt.transcript.trim();
 | 
			
		||||
 | 
			
		||||
        if (res.isFinal) {
 | 
			
		||||
          const sentence = txt.charAt(0).toUpperCase() + txt.slice(1);
 | 
			
		||||
@ -94,26 +92,46 @@ class STTButton extends HTMLElement {
 | 
			
		||||
          committed += punctuated + ' ';
 | 
			
		||||
          if (this.targetEl) {
 | 
			
		||||
            this.targetEl.focus();
 | 
			
		||||
            punctuated = punctuated.replace(/\./g, ".\n");
 | 
			
		||||
            punctuated = punctuated.replace(/\?/g, "?\n");
 | 
			
		||||
            punctuated = punctuated.replace(/\!/g, "!\n");
 | 
			
		||||
            punctuated = punctuated.replace(/\./g, ".\n")
 | 
			
		||||
                                   .replace(/\?/g, "?\n")
 | 
			
		||||
                                   .replace(/\!/g, "!\n");
 | 
			
		||||
 | 
			
		||||
            this.simulateTypingWithEvents(this.targetEl, punctuated, 1).then(() => {
 | 
			
		||||
              this.targetEl.value = ''; // punctuated;
 | 
			
		||||
          this.simulateTypingWithEvents(this.targetEl, punctuated, 1).then(() => {
 | 
			
		||||
              const chatInput = document.querySelector('chat-input');
 | 
			
		||||
              chatInput.finalizeMessage();
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          previousInterim = '';
 | 
			
		||||
        } else {
 | 
			
		||||
          interim += txt + ' ';
 | 
			
		||||
          if (alt.confidence >= 0.85) {
 | 
			
		||||
            interim += txt + ' ';
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (interim && this.targetEl) {
 | 
			
		||||
        const el = this.targetEl;
 | 
			
		||||
        el.focus();
 | 
			
		||||
 | 
			
		||||
        if (el.isContentEditable) {
 | 
			
		||||
          el.innerText = el.innerText.replace(new RegExp(previousInterim + '$'), interim);
 | 
			
		||||
        } else {
 | 
			
		||||
            el.value = interim
 | 
			
		||||
          //el.value = el.value.replace(new RegExp(previousInterim + '$'), interim);
 | 
			
		||||
        }
 | 
			
		||||
       /* 
 | 
			
		||||
        this.simulateTypingWithEvents(el, interim, 0).then(() => {
 | 
			
		||||
          previousInterim = interim;
 | 
			
		||||
        });*/
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    this.recog.onend = () => {
 | 
			
		||||
      // Auto-restart recognition unless we explicitly stopped
 | 
			
		||||
      if (this.listening) {
 | 
			
		||||
        try {
 | 
			
		||||
          this.recog.start(); // attempt restart
 | 
			
		||||
          this.recog.start();
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          console.warn('Failed to restart speech recognition:', e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user