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