fix: mic appends to existing textarea text instead of replacing it

Previously, tapping the mic button would reset the textarea each time,
clobbering anything the user had already typed or previously dictated.

Fix:
- Capture _prefix = ta.value when recording starts (btn.onclick)
- onresult writes _prefix + (final || interim) so live interim text
  appears after the existing content, not replacing it
- onend commits _prefix + _finalText with smart space insertion:
  if the prefix doesn't end with a space or newline, a space is added
  before the new transcript so words don't run together
- _prefix is reset to '' in _setRecording(false) so each new recording
  session starts with a fresh snapshot

Behaviour now: tap mic, speak, tap again (or wait for auto-stop) ->
transcript is appended to whatever was in the textarea. Tap mic again
-> continues appending further. Text stays fully editable before send.

tests/test_sprint20.py: 6 new tests covering prefix capture, onresult
prepend, onend commit, reset, and smart spacing (52 total, 382 overall).
This commit is contained in:
Nathan Esquenazi
2026-04-03 14:13:29 +00:00
parent efb7293ae8
commit 46fdf3513f
2 changed files with 73 additions and 4 deletions

View File

@@ -27,12 +27,13 @@ $('btnAttach').onclick=()=>$('fileInput').click();
recognition.lang='en-US';
let _finalText='';
let _prefix='';
function _setRecording(on){
window._micActive=on;
btn.classList.toggle('recording',on);
status.style.display=on?'':'none';
if(!on) _finalText='';
if(!on){ _finalText=''; _prefix=''; }
}
recognition.onstart=()=>{ _finalText=''; };
@@ -45,14 +46,20 @@ $('btnAttach').onclick=()=>$('fileInput').click();
if(event.results[i].isFinal){ final+=t; _finalText=final; }
else{ interim+=t; }
}
ta.value=final||interim;
// Append to whatever was already in the textarea before mic started
ta.value=_prefix+(final||interim);
autoResize();
};
recognition.onend=()=>{
// Commit: prefix + final transcription; trim trailing space if prefix was non-empty
const committed=_finalText
? (_prefix&&!_prefix.endsWith(' ')&&!_prefix.endsWith('\n')
? _prefix+' '+_finalText.trimStart()
: _prefix+_finalText)
: ta.value; // no speech detected — leave whatever is there
_setRecording(false);
// Ensure textarea has the committed final text (handles auto-stop on silence)
if(_finalText) ta.value=_finalText;
ta.value=committed;
autoResize();
};
@@ -77,6 +84,8 @@ $('btnAttach').onclick=()=>$('fileInput').click();
// _setRecording(false) will be called by onend
} else {
_finalText='';
// Snapshot existing textarea content so we append rather than replace
_prefix=ta.value;
recognition.start();
_setRecording(true);
}