Copy to clipboard and final polish
The pipeline works. Now we make it pleasant to use. Users want to copy the cleaned transcript, see a loading state while the LLM runs, and record with a keyboard shortcut instead of clicking a button.
const copyToClipboard = (text: string) => {
navigator.clipboard
.writeText(text)
.then(() => {
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
})
.catch((err: Error) => setError('Copy failed: ' + err.message));
};navigator.clipboard.writeText returns a Promise. On success, flip a flag for two seconds so the UI can show a confirmation. On failure, surface the error because the user expected a copy to happen.
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (isProcessing || e.repeat || isKeyDownRef.current) return;
const target = e.target as HTMLElement;
if (e.key.toLowerCase() === 'v' && !['INPUT', 'TEXTAREA'].includes(target.tagName)) {
e.preventDefault();
isKeyDownRef.current = true;
if (!isRecording) void startRecording();
}
};
const handleKeyUp = (e: KeyboardEvent) => {
if (e.key.toLowerCase() === 'v') {
isKeyDownRef.current = false;
if (isRecording) stopRecording();
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
return () => {
window.removeEventListener('keydown', handleKeyDown);
window.removeEventListener('keyup', handleKeyUp);
};
}, [isRecording, isProcessing]);Hold V to record, release to stop. The INPUT/TEXTAREA check stops the shortcut from firing when the user is typing into the prompt textarea. A ref tracks keydown state so browser key-repeat does not spam startRecording.
setRawText(transcribeData.text || '');
setIsProcessing(false);
if (useLLM && transcribeData.text) {
setIsCleaningWithLLM(true);
// ... cleanup fetch
setIsCleaningWithLLM(false);
}isCleaningWithLLM is a separate flag from isProcessing. Raw text shows immediately when transcription completes, and a subtle cleaning indicator appears next to the cleaned text box while the LLM runs.
writeText works without a prompt as long as the call is triggered by a user action like a click and the page is in a secure context. readText requires explicit permission because it exposes potentially sensitive data. Since we only write, the UX is smooth.
Quiz: Quiz
Loading practice…