[251030] fix: WebSpeech SilenceDetection disable
🕐 커밋 시간: 2025. 10. 30. 07:12:09 📊 변경 통계: • 총 파일: 3개 • 추가: +72줄 • 삭제: -54줄 📝 수정된 파일: ~ com.twin.app.shoptime/.gitignore ~ com.twin.app.shoptime/src/hooks/useReviews/useReviews.js ~ com.twin.app.shoptime/src/views/SearchPanel/VoiceInputOverlay/VoiceInputOverlay.jsx 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선 • 소규모 기능 개선 • 코드 정리 및 최적화
This commit is contained in:
4
com.twin.app.shoptime/.gitignore
vendored
4
com.twin.app.shoptime/.gitignore
vendored
@@ -15,6 +15,10 @@ npm-debug.log
|
||||
# ipk file
|
||||
srcBackup
|
||||
# com.lgshop.app_*.ipk
|
||||
.doc
|
||||
.docs
|
||||
nul
|
||||
.txt
|
||||
|
||||
.optimal
|
||||
OPTIMAL.md
|
||||
|
||||
@@ -28,27 +28,27 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
||||
// Redux 상태에서 리뷰 데이터 가져오기 - reviewVersion에 따라 선택
|
||||
const reviewData = useSelector((state) => {
|
||||
// v2 디버깅: 전체 product state 확인
|
||||
if (reviewVersion === 2) {
|
||||
console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', {
|
||||
keys: Object.keys(state.product),
|
||||
reviewData: state.product.reviewData,
|
||||
reviewListData: state.product.reviewListData,
|
||||
loadedPrdtId: state.product.loadedPrdtId,
|
||||
loadedListPrdtId: state.product.loadedListPrdtId
|
||||
});
|
||||
}
|
||||
// if (reviewVersion === 2) {
|
||||
// console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', {
|
||||
// keys: Object.keys(state.product),
|
||||
// reviewData: state.product.reviewData,
|
||||
// reviewListData: state.product.reviewListData,
|
||||
// loadedPrdtId: state.product.loadedPrdtId,
|
||||
// loadedListPrdtId: state.product.loadedListPrdtId
|
||||
// });
|
||||
// }
|
||||
|
||||
const data = reviewVersion === 1
|
||||
? state.product.reviewData
|
||||
: state.product.reviewListData;
|
||||
|
||||
console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', {
|
||||
reviewVersion,
|
||||
selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData',
|
||||
dataExists: !!data,
|
||||
dataKeys: data ? Object.keys(data) : 'null',
|
||||
reviewListLength: data?.reviewList?.length || 0
|
||||
});
|
||||
// console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', {
|
||||
// reviewVersion,
|
||||
// selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData',
|
||||
// dataExists: !!data,
|
||||
// dataKeys: data ? Object.keys(data) : 'null',
|
||||
// reviewListLength: data?.reviewList?.length || 0
|
||||
// });
|
||||
|
||||
return data;
|
||||
});
|
||||
@@ -58,11 +58,11 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
||||
? state.product.loadedPrdtId
|
||||
: state.product.loadedListPrdtId;
|
||||
|
||||
console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', {
|
||||
reviewVersion,
|
||||
selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId',
|
||||
loadedPrdtId: id
|
||||
});
|
||||
// console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', {
|
||||
// reviewVersion,
|
||||
// selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId',
|
||||
// loadedPrdtId: id
|
||||
// });
|
||||
|
||||
return id;
|
||||
});
|
||||
@@ -647,17 +647,17 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
||||
totalRatingCount: actualReviewCount, // 실제로 받은 리뷰 개수 사용
|
||||
};
|
||||
|
||||
console.log('[useReviews_useReviewList] 📊 stats 계산:', {
|
||||
actualReviewCount,
|
||||
apiTotalCount,
|
||||
allReviewsLength: allReviews.length,
|
||||
hasLoadedData,
|
||||
isLoading,
|
||||
isCurrentProductLoaded,
|
||||
reviewVersion,
|
||||
loadedPrdtId,
|
||||
prdtId
|
||||
});
|
||||
// console.log('[useReviews_useReviewList] 📊 stats 계산:', {
|
||||
// actualReviewCount,
|
||||
// apiTotalCount,
|
||||
// allReviewsLength: allReviews.length,
|
||||
// hasLoadedData,
|
||||
// isLoading,
|
||||
// isCurrentProductLoaded,
|
||||
// reviewVersion,
|
||||
// loadedPrdtId,
|
||||
// prdtId
|
||||
// });
|
||||
|
||||
return result;
|
||||
}, [allReviews.length, filteredReviews.length, displayReviews.length, reviewDetail, hasLoadedData, isLoading, isCurrentProductLoaded, reviewVersion, loadedPrdtId, prdtId]);
|
||||
@@ -675,18 +675,18 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
||||
const hasReviews = allReviews.length > 0 && hasLoadedData && !isLoading && isCurrentProductLoaded;
|
||||
|
||||
// hasReviews 계산 로그
|
||||
useEffect(() => {
|
||||
console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', {
|
||||
allReviewsLength: allReviews.length,
|
||||
hasLoadedData,
|
||||
isLoading,
|
||||
isCurrentProductLoaded,
|
||||
loadedPrdtId,
|
||||
prdtId,
|
||||
resultHasReviews: hasReviews,
|
||||
reviewVersion
|
||||
});
|
||||
}, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]);
|
||||
// useEffect(() => {
|
||||
// console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', {
|
||||
// allReviewsLength: allReviews.length,
|
||||
// hasLoadedData,
|
||||
// isLoading,
|
||||
// isCurrentProductLoaded,
|
||||
// loadedPrdtId,
|
||||
// prdtId,
|
||||
// resultHasReviews: hasReviews,
|
||||
// reviewVersion
|
||||
// });
|
||||
// }, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]);
|
||||
|
||||
return {
|
||||
// 🔥 핵심 API 함수 - useReviews가 모든 API 호출 담당
|
||||
|
||||
@@ -95,6 +95,11 @@ const DEFAULT_SUGGESTIONS = [
|
||||
// false로 설정하면 이 기능은 완전히 비활성화됩니다
|
||||
const ENABLE_WAKE_WORD = false;
|
||||
|
||||
// 🔧 Silence Detection 활성화 여부
|
||||
// continuous: true에서 노이즈를 interim으로 감지할 수 있어
|
||||
// 사용자가 준비 단계에서 조기 종료될 수 있으므로 false로 설정
|
||||
const IS_SILENCE_CHECK_ENABLED = false;
|
||||
|
||||
// Utility function to clear a single timer ref (timeout)
|
||||
const clearTimerRef = (timerRef) => {
|
||||
if (timerRef.current) {
|
||||
@@ -852,29 +857,38 @@ const VoiceInputOverlay = ({
|
||||
// }
|
||||
// }, [voiceInputMode, currentMode, isListening, startListening, stopListening]);
|
||||
|
||||
// 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트 + 3초 silence detection
|
||||
// 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트
|
||||
// Silence Detection은 IS_SILENCE_CHECK_ENABLED에 따라 제어
|
||||
useEffect(() => {
|
||||
if (currentMode !== VOICE_MODES.LISTENING) {
|
||||
// ✅ LISTENING 모드가 아니면 타이머 정리
|
||||
clearTimerRef(silenceDetectionTimerRef);
|
||||
silenceDetectionTimerRef.current = null;
|
||||
if (IS_SILENCE_CHECK_ENABLED) {
|
||||
clearTimerRef(silenceDetectionTimerRef);
|
||||
silenceDetectionTimerRef.current = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ Ref 업데이트 (15초 타이머에서 최신 값을 읽을 수 있도록)
|
||||
interimTextRef.current = interimText || '';
|
||||
|
||||
// ✨ TInput에 실시간으로 텍스트 표시
|
||||
if (onSearchChange && interimText) {
|
||||
onSearchChange({ value: interimText });
|
||||
}
|
||||
|
||||
// ✅ Silence Detection (IS_SILENCE_CHECK_ENABLED === true일 때만)
|
||||
if (!IS_SILENCE_CHECK_ENABLED) {
|
||||
// Silence Detection 비활성화 - 15초 타이머에만 의존
|
||||
return;
|
||||
}
|
||||
|
||||
if (!interimText) {
|
||||
// 입력이 없으면 silence detection 시작하지 않음
|
||||
return;
|
||||
}
|
||||
|
||||
// ✨ TInput에 실시간으로 텍스트 표시
|
||||
if (onSearchChange) {
|
||||
onSearchChange({ value: interimText });
|
||||
}
|
||||
|
||||
// ✅ 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
|
||||
// 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
|
||||
clearTimerRef(silenceDetectionTimerRef);
|
||||
silenceDetectionTimerRef.current = setTimeout(() => {
|
||||
console.log('[VoiceInput] 🔇 3초 동안 입력 없음 - 자동 종료');
|
||||
@@ -887,7 +901,7 @@ const VoiceInputOverlay = ({
|
||||
clearTimerRef(silenceDetectionTimerRef);
|
||||
silenceDetectionTimerRef.current = null;
|
||||
};
|
||||
}, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog]);
|
||||
}, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog, IS_SILENCE_CHECK_ENABLED]);
|
||||
|
||||
// 🎉 Wake Word Detection: PROMPT 모드에서 백그라운드 리스닝 시작
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user