[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
|
# ipk file
|
||||||
srcBackup
|
srcBackup
|
||||||
# com.lgshop.app_*.ipk
|
# com.lgshop.app_*.ipk
|
||||||
|
.doc
|
||||||
.docs
|
.docs
|
||||||
nul
|
nul
|
||||||
.txt
|
.txt
|
||||||
|
|
||||||
|
.optimal
|
||||||
|
OPTIMAL.md
|
||||||
|
|||||||
@@ -28,27 +28,27 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
|||||||
// Redux 상태에서 리뷰 데이터 가져오기 - reviewVersion에 따라 선택
|
// Redux 상태에서 리뷰 데이터 가져오기 - reviewVersion에 따라 선택
|
||||||
const reviewData = useSelector((state) => {
|
const reviewData = useSelector((state) => {
|
||||||
// v2 디버깅: 전체 product state 확인
|
// v2 디버깅: 전체 product state 확인
|
||||||
if (reviewVersion === 2) {
|
// if (reviewVersion === 2) {
|
||||||
console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', {
|
// console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', {
|
||||||
keys: Object.keys(state.product),
|
// keys: Object.keys(state.product),
|
||||||
reviewData: state.product.reviewData,
|
// reviewData: state.product.reviewData,
|
||||||
reviewListData: state.product.reviewListData,
|
// reviewListData: state.product.reviewListData,
|
||||||
loadedPrdtId: state.product.loadedPrdtId,
|
// loadedPrdtId: state.product.loadedPrdtId,
|
||||||
loadedListPrdtId: state.product.loadedListPrdtId
|
// loadedListPrdtId: state.product.loadedListPrdtId
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
const data = reviewVersion === 1
|
const data = reviewVersion === 1
|
||||||
? state.product.reviewData
|
? state.product.reviewData
|
||||||
: state.product.reviewListData;
|
: state.product.reviewListData;
|
||||||
|
|
||||||
console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', {
|
// console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', {
|
||||||
reviewVersion,
|
// reviewVersion,
|
||||||
selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData',
|
// selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData',
|
||||||
dataExists: !!data,
|
// dataExists: !!data,
|
||||||
dataKeys: data ? Object.keys(data) : 'null',
|
// dataKeys: data ? Object.keys(data) : 'null',
|
||||||
reviewListLength: data?.reviewList?.length || 0
|
// reviewListLength: data?.reviewList?.length || 0
|
||||||
});
|
// });
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
@@ -58,11 +58,11 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
|||||||
? state.product.loadedPrdtId
|
? state.product.loadedPrdtId
|
||||||
: state.product.loadedListPrdtId;
|
: state.product.loadedListPrdtId;
|
||||||
|
|
||||||
console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', {
|
// console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', {
|
||||||
reviewVersion,
|
// reviewVersion,
|
||||||
selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId',
|
// selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId',
|
||||||
loadedPrdtId: id
|
// loadedPrdtId: id
|
||||||
});
|
// });
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
});
|
});
|
||||||
@@ -647,17 +647,17 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
|
|||||||
totalRatingCount: actualReviewCount, // 실제로 받은 리뷰 개수 사용
|
totalRatingCount: actualReviewCount, // 실제로 받은 리뷰 개수 사용
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('[useReviews_useReviewList] 📊 stats 계산:', {
|
// console.log('[useReviews_useReviewList] 📊 stats 계산:', {
|
||||||
actualReviewCount,
|
// actualReviewCount,
|
||||||
apiTotalCount,
|
// apiTotalCount,
|
||||||
allReviewsLength: allReviews.length,
|
// allReviewsLength: allReviews.length,
|
||||||
hasLoadedData,
|
// hasLoadedData,
|
||||||
isLoading,
|
// isLoading,
|
||||||
isCurrentProductLoaded,
|
// isCurrentProductLoaded,
|
||||||
reviewVersion,
|
// reviewVersion,
|
||||||
loadedPrdtId,
|
// loadedPrdtId,
|
||||||
prdtId
|
// prdtId
|
||||||
});
|
// });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, [allReviews.length, filteredReviews.length, displayReviews.length, reviewDetail, hasLoadedData, isLoading, isCurrentProductLoaded, reviewVersion, loadedPrdtId, prdtId]);
|
}, [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;
|
const hasReviews = allReviews.length > 0 && hasLoadedData && !isLoading && isCurrentProductLoaded;
|
||||||
|
|
||||||
// hasReviews 계산 로그
|
// hasReviews 계산 로그
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', {
|
// console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', {
|
||||||
allReviewsLength: allReviews.length,
|
// allReviewsLength: allReviews.length,
|
||||||
hasLoadedData,
|
// hasLoadedData,
|
||||||
isLoading,
|
// isLoading,
|
||||||
isCurrentProductLoaded,
|
// isCurrentProductLoaded,
|
||||||
loadedPrdtId,
|
// loadedPrdtId,
|
||||||
prdtId,
|
// prdtId,
|
||||||
resultHasReviews: hasReviews,
|
// resultHasReviews: hasReviews,
|
||||||
reviewVersion
|
// reviewVersion
|
||||||
});
|
// });
|
||||||
}, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]);
|
// }, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// 🔥 핵심 API 함수 - useReviews가 모든 API 호출 담당
|
// 🔥 핵심 API 함수 - useReviews가 모든 API 호출 담당
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ const DEFAULT_SUGGESTIONS = [
|
|||||||
// false로 설정하면 이 기능은 완전히 비활성화됩니다
|
// false로 설정하면 이 기능은 완전히 비활성화됩니다
|
||||||
const ENABLE_WAKE_WORD = 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)
|
// Utility function to clear a single timer ref (timeout)
|
||||||
const clearTimerRef = (timerRef) => {
|
const clearTimerRef = (timerRef) => {
|
||||||
if (timerRef.current) {
|
if (timerRef.current) {
|
||||||
@@ -852,29 +857,38 @@ const VoiceInputOverlay = ({
|
|||||||
// }
|
// }
|
||||||
// }, [voiceInputMode, currentMode, isListening, startListening, stopListening]);
|
// }, [voiceInputMode, currentMode, isListening, startListening, stopListening]);
|
||||||
|
|
||||||
// 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트 + 3초 silence detection
|
// 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트
|
||||||
|
// Silence Detection은 IS_SILENCE_CHECK_ENABLED에 따라 제어
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentMode !== VOICE_MODES.LISTENING) {
|
if (currentMode !== VOICE_MODES.LISTENING) {
|
||||||
// ✅ LISTENING 모드가 아니면 타이머 정리
|
// ✅ LISTENING 모드가 아니면 타이머 정리
|
||||||
|
if (IS_SILENCE_CHECK_ENABLED) {
|
||||||
clearTimerRef(silenceDetectionTimerRef);
|
clearTimerRef(silenceDetectionTimerRef);
|
||||||
silenceDetectionTimerRef.current = null;
|
silenceDetectionTimerRef.current = null;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Ref 업데이트 (15초 타이머에서 최신 값을 읽을 수 있도록)
|
// ✅ Ref 업데이트 (15초 타이머에서 최신 값을 읽을 수 있도록)
|
||||||
interimTextRef.current = interimText || '';
|
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) {
|
if (!interimText) {
|
||||||
// 입력이 없으면 silence detection 시작하지 않음
|
// 입력이 없으면 silence detection 시작하지 않음
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✨ TInput에 실시간으로 텍스트 표시
|
// 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
|
||||||
if (onSearchChange) {
|
|
||||||
onSearchChange({ value: interimText });
|
|
||||||
}
|
|
||||||
|
|
||||||
// ✅ 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
|
|
||||||
clearTimerRef(silenceDetectionTimerRef);
|
clearTimerRef(silenceDetectionTimerRef);
|
||||||
silenceDetectionTimerRef.current = setTimeout(() => {
|
silenceDetectionTimerRef.current = setTimeout(() => {
|
||||||
console.log('[VoiceInput] 🔇 3초 동안 입력 없음 - 자동 종료');
|
console.log('[VoiceInput] 🔇 3초 동안 입력 없음 - 자동 종료');
|
||||||
@@ -887,7 +901,7 @@ const VoiceInputOverlay = ({
|
|||||||
clearTimerRef(silenceDetectionTimerRef);
|
clearTimerRef(silenceDetectionTimerRef);
|
||||||
silenceDetectionTimerRef.current = null;
|
silenceDetectionTimerRef.current = null;
|
||||||
};
|
};
|
||||||
}, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog]);
|
}, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog, IS_SILENCE_CHECK_ENABLED]);
|
||||||
|
|
||||||
// 🎉 Wake Word Detection: PROMPT 모드에서 백그라운드 리스닝 시작
|
// 🎉 Wake Word Detection: PROMPT 모드에서 백그라운드 리스닝 시작
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user