fixed coaching rules
This commit is contained in:
parent
0518ee48d5
commit
18e6b3e4d8
2 changed files with 33 additions and 8 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export const CommcoachCoachingView: React.FC = () => {
|
|||
const transcriptPartsRef = useRef<string[]>([]);
|
||||
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 = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<AutoScroll scrollDependency={coach.messages.length + (coach.isStreaming ? 1 : 0)}>
|
||||
<AutoScroll scrollDependency={coach.messages.length + (coach.isStreaming ? 1 : 0) + liveTranscript.length}>
|
||||
<div className={styles.messages}>
|
||||
{coach.messages.map(msg => (
|
||||
<div
|
||||
|
|
@ -319,6 +331,13 @@ export const CommcoachCoachingView: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
))}
|
||||
{liveTranscript && (
|
||||
<div className={`${styles.message} ${styles.messageUser}`}>
|
||||
<div className={`${styles.messageBubble} ${styles.messageLive}`}>
|
||||
{liveTranscript}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{coach.isStreaming && (
|
||||
<div className={`${styles.message} ${styles.messageAssistant}`}>
|
||||
<div className={styles.messageBubble}>
|
||||
|
|
@ -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...'}
|
||||
|
|
|
|||
Loading…
Reference in a new issue