From 18e6b3e4d8169dc5a895121e8e6f1a4e3722a2f6 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Mon, 2 Mar 2026 21:10:36 +0100 Subject: [PATCH] fixed coaching rules --- .../CommcoachCoachingView.module.css | 6 ++++ .../views/commcoach/CommcoachCoachingView.tsx | 35 ++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/pages/views/commcoach/CommcoachCoachingView.module.css b/src/pages/views/commcoach/CommcoachCoachingView.module.css index 0d21d69..b898159 100644 --- a/src/pages/views/commcoach/CommcoachCoachingView.module.css +++ b/src/pages/views/commcoach/CommcoachCoachingView.module.css @@ -268,6 +268,12 @@ border-bottom-right-radius: 4px; } +.messageLive { + opacity: 0.7; + font-style: italic; + border: 1px dashed rgba(255, 255, 255, 0.4); +} + .messageAssistant .messageBubble { background: var(--bg-card, #f5f5f5); color: var(--text-primary, #333); diff --git a/src/pages/views/commcoach/CommcoachCoachingView.tsx b/src/pages/views/commcoach/CommcoachCoachingView.tsx index 06f96c9..38bd1a3 100644 --- a/src/pages/views/commcoach/CommcoachCoachingView.tsx +++ b/src/pages/views/commcoach/CommcoachCoachingView.tsx @@ -28,6 +28,7 @@ export const CommcoachCoachingView: React.FC = () => { const transcriptPartsRef = useRef([]); const [isListening, setIsListening] = useState(false); const [isUserSpeaking, setIsUserSpeaking] = useState(false); + const [liveTranscript, setLiveTranscript] = useState(''); const handleSend = useCallback(async () => { if (!coach.inputValue.trim() || coach.isStreaming) return; @@ -124,16 +125,26 @@ export const CommcoachCoachingView: React.FC = () => { if (cancelled) return; setIsUserSpeaking(true); transcriptPartsRef.current = []; + setLiveTranscript(''); }; recognition.onresult = (event: SpeechRecognitionEvent) => { if (cancelled) return; - const result = event.results[event.resultIndex]; - if (!result.isFinal) return; - const transcript = result[0].transcript.trim(); - if (transcript) transcriptPartsRef.current.push(transcript); - const wordCount = transcript.split(/\s+/).filter(Boolean).length; - if (wordCount >= MIN_WORDS_TO_INTERRUPT) coach.stopTts(); + const finalized: string[] = []; + let currentInterim = ''; + for (let i = 0; i < event.results.length; i++) { + const r = event.results[i]; + if (r.isFinal) { + finalized.push(r[0].transcript.trim()); + } else { + currentInterim = r[0].transcript.trim(); + } + } + transcriptPartsRef.current = finalized.filter(Boolean); + const preview = [...transcriptPartsRef.current, currentInterim].join(' ').trim(); + setLiveTranscript(preview); + const totalWords = preview.split(/\s+/).filter(Boolean).length; + if (totalWords >= MIN_WORDS_TO_INTERRUPT) coach.stopTts(); }; recognition.onspeechend = () => { @@ -144,6 +155,7 @@ export const CommcoachCoachingView: React.FC = () => { if (wordCount >= MIN_WORDS_TO_INTERRUPT) coach.sendMessage(fullTranscript); } transcriptPartsRef.current = []; + setLiveTranscript(''); setIsUserSpeaking(false); }; @@ -302,7 +314,7 @@ export const CommcoachCoachingView: React.FC = () => { - +
{coach.messages.map(msg => (
{
))} + {liveTranscript && ( +
+
+ {liveTranscript} +
+
+ )} {coach.isStreaming && (
@@ -341,7 +360,7 @@ export const CommcoachCoachingView: React.FC = () => { : coach.isStreaming ? (coach.streamingStatus || 'Coach antwortet...') : isUserSpeaking - ? 'Aufnahme...' + ? 'Spricht...' : isListening ? 'Mikrofon an – bitte sprechen' : 'Mikrofon wird gestartet...'}