🎯 fix: Prevent UI De-sync By Removing Redundant States (#5333)

* fix: remove local state from Dropdown causing de-sync

* refactor: cleanup STT code, avoid redundant states to prevent de-sync and side effects

* fix: reset transcript after sending final text to prevent data loss

* fix: clear timeout on component unmount to prevent memory leaks
This commit is contained in:
Danny Avila 2025-01-16 17:38:59 -05:00 committed by GitHub
parent b55e695541
commit e309c6abef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 149 additions and 145 deletions

View file

@ -1,27 +1,31 @@
import { useState, useEffect, useRef } from 'react';
import { useRecoilState } from 'recoil';
import { useSpeechToTextMutation } from '~/data-provider';
import useGetAudioSettings from './useGetAudioSettings';
import { useToastContext } from '~/Providers';
import store from '~/store';
import useGetAudioSettings from './useGetAudioSettings';
const useSpeechToTextExternal = (onTranscriptionComplete: (text: string) => void) => {
const useSpeechToTextExternal = (
setText: (text: string) => void,
onTranscriptionComplete: (text: string) => void,
) => {
const { showToast } = useToastContext();
const { speechToTextEndpoint } = useGetAudioSettings();
const isExternalSTTEnabled = speechToTextEndpoint === 'external';
const [speechToText] = useRecoilState<boolean>(store.speechToText);
const [autoTranscribeAudio] = useRecoilState<boolean>(store.autoTranscribeAudio);
const [autoSendText] = useRecoilState(store.autoSendText);
const [text, setText] = useState<string>('');
const [isListening, setIsListening] = useState(false);
const audioStream = useRef<MediaStream | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
const audioContextRef = useRef<AudioContext | null>(null);
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const [permission, setPermission] = useState(false);
const [isListening, setIsListening] = useState(false);
const [audioChunks, setAudioChunks] = useState<Blob[]>([]);
const [isRequestBeingMade, setIsRequestBeingMade] = useState(false);
const [minDecibels] = useRecoilState(store.decibelValue);
const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const audioStream = useRef<MediaStream | null>(null);
const audioContextRef = useRef<AudioContext | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
const [autoSendText] = useRecoilState(store.autoSendText);
const [speechToText] = useRecoilState<boolean>(store.speechToText);
const [autoTranscribeAudio] = useRecoilState<boolean>(store.autoTranscribeAudio);
const { mutate: processAudio, isLoading: isProcessing } = useSpeechToTextMutation({
onSuccess: (data) => {
@ -54,10 +58,6 @@ const useSpeechToTextExternal = (onTranscriptionComplete: (text: string) => void
}
};
const clearText = () => {
setText('');
};
const getMicrophonePermission = async () => {
try {
const streamData = await navigator.mediaDevices.getUserMedia({
@ -226,11 +226,9 @@ const useSpeechToTextExternal = (onTranscriptionComplete: (text: string) => void
return {
isListening,
isLoading: isProcessing,
text,
externalStartRecording,
externalStopRecording,
clearText,
externalStartRecording,
isLoading: isProcessing,
};
};