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;
|
border-bottom-right-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.messageLive {
|
||||||
|
opacity: 0.7;
|
||||||
|
font-style: italic;
|
||||||
|
border: 1px dashed rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.messageAssistant .messageBubble {
|
.messageAssistant .messageBubble {
|
||||||
background: var(--bg-card, #f5f5f5);
|
background: var(--bg-card, #f5f5f5);
|
||||||
color: var(--text-primary, #333);
|
color: var(--text-primary, #333);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
const transcriptPartsRef = useRef<string[]>([]);
|
const transcriptPartsRef = useRef<string[]>([]);
|
||||||
const [isListening, setIsListening] = useState(false);
|
const [isListening, setIsListening] = useState(false);
|
||||||
const [isUserSpeaking, setIsUserSpeaking] = useState(false);
|
const [isUserSpeaking, setIsUserSpeaking] = useState(false);
|
||||||
|
const [liveTranscript, setLiveTranscript] = useState('');
|
||||||
|
|
||||||
const handleSend = useCallback(async () => {
|
const handleSend = useCallback(async () => {
|
||||||
if (!coach.inputValue.trim() || coach.isStreaming) return;
|
if (!coach.inputValue.trim() || coach.isStreaming) return;
|
||||||
|
|
@ -124,16 +125,26 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
setIsUserSpeaking(true);
|
setIsUserSpeaking(true);
|
||||||
transcriptPartsRef.current = [];
|
transcriptPartsRef.current = [];
|
||||||
|
setLiveTranscript('');
|
||||||
};
|
};
|
||||||
|
|
||||||
recognition.onresult = (event: SpeechRecognitionEvent) => {
|
recognition.onresult = (event: SpeechRecognitionEvent) => {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
const result = event.results[event.resultIndex];
|
const finalized: string[] = [];
|
||||||
if (!result.isFinal) return;
|
let currentInterim = '';
|
||||||
const transcript = result[0].transcript.trim();
|
for (let i = 0; i < event.results.length; i++) {
|
||||||
if (transcript) transcriptPartsRef.current.push(transcript);
|
const r = event.results[i];
|
||||||
const wordCount = transcript.split(/\s+/).filter(Boolean).length;
|
if (r.isFinal) {
|
||||||
if (wordCount >= MIN_WORDS_TO_INTERRUPT) coach.stopTts();
|
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 = () => {
|
recognition.onspeechend = () => {
|
||||||
|
|
@ -144,6 +155,7 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
if (wordCount >= MIN_WORDS_TO_INTERRUPT) coach.sendMessage(fullTranscript);
|
if (wordCount >= MIN_WORDS_TO_INTERRUPT) coach.sendMessage(fullTranscript);
|
||||||
}
|
}
|
||||||
transcriptPartsRef.current = [];
|
transcriptPartsRef.current = [];
|
||||||
|
setLiveTranscript('');
|
||||||
setIsUserSpeaking(false);
|
setIsUserSpeaking(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -302,7 +314,7 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</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}>
|
<div className={styles.messages}>
|
||||||
{coach.messages.map(msg => (
|
{coach.messages.map(msg => (
|
||||||
<div
|
<div
|
||||||
|
|
@ -319,6 +331,13 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
{liveTranscript && (
|
||||||
|
<div className={`${styles.message} ${styles.messageUser}`}>
|
||||||
|
<div className={`${styles.messageBubble} ${styles.messageLive}`}>
|
||||||
|
{liveTranscript}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{coach.isStreaming && (
|
{coach.isStreaming && (
|
||||||
<div className={`${styles.message} ${styles.messageAssistant}`}>
|
<div className={`${styles.message} ${styles.messageAssistant}`}>
|
||||||
<div className={styles.messageBubble}>
|
<div className={styles.messageBubble}>
|
||||||
|
|
@ -341,7 +360,7 @@ export const CommcoachCoachingView: React.FC = () => {
|
||||||
: coach.isStreaming
|
: coach.isStreaming
|
||||||
? (coach.streamingStatus || 'Coach antwortet...')
|
? (coach.streamingStatus || 'Coach antwortet...')
|
||||||
: isUserSpeaking
|
: isUserSpeaking
|
||||||
? 'Aufnahme...'
|
? 'Spricht...'
|
||||||
: isListening
|
: isListening
|
||||||
? 'Mikrofon an – bitte sprechen'
|
? 'Mikrofon an – bitte sprechen'
|
||||||
: 'Mikrofon wird gestartet...'}
|
: 'Mikrofon wird gestartet...'}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue