[251024] [251025] feat: Voice검색 후 포커스 문제
🕐 커밋 시간: 2025. 10. 24. 21:16:53 📊 변경 통계: • 총 파일: 2개 • 추가: +76줄 • 삭제: -21줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/SearchPanel/SearchPanel.new.v2.jsx ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx 🔧 주요 변경 내용: • 소규모 기능 개선
This commit is contained in:
@@ -183,6 +183,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
const [voiceOverlayMode, setVoiceOverlayMode] = useState(VOICE_MODES.PROMPT);
|
||||
const [voiceOverlayResponseText, setVoiceOverlayResponseText] = useState('');
|
||||
const [isVoiceOverlayBubbleSearch, setIsVoiceOverlayBubbleSearch] = useState(false);
|
||||
const [shouldFocusVoiceResult, setShouldFocusVoiceResult] = useState(false);
|
||||
|
||||
// 🐛 [DEBUG] shopperHouseData 상태 변경 추적 (DEBUG_MODE가 true일 경우에만)
|
||||
useEffect(() => {
|
||||
@@ -657,11 +658,15 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
setVoiceOverlayResponseText('');
|
||||
setIsVoiceOverlayBubbleSearch(false);
|
||||
setIsVoiceOverlayVisible(false);
|
||||
// ✅ VoiceOverlay가 닫힐 때 항상 TInput으로 포커스 이동
|
||||
setTimeout(() => {
|
||||
Spotlight.focus(SPOTLIGHT_IDS.SEARCH_INPUT_BOX);
|
||||
}, 150); // Overlay 닫히는 시간을 고려한 지연
|
||||
}, []);
|
||||
setShouldFocusVoiceResult(false);
|
||||
|
||||
// ShopperHouse 데이터가 없을 때만 검색 인풋으로 포커스 복원
|
||||
if (!shopperHouseData) {
|
||||
setTimeout(() => {
|
||||
Spotlight.focus(SPOTLIGHT_IDS.SEARCH_INPUT_BOX);
|
||||
}, 150); // Overlay 닫히는 시간을 고려한 지연
|
||||
}
|
||||
}, [shopperHouseData]);
|
||||
|
||||
const handleHowAboutTheseQueryClick = useCallback(
|
||||
(rawQuery) => {
|
||||
@@ -678,6 +683,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
setVoiceOverlayMode(VOICE_MODES.RESPONSE);
|
||||
setIsVoiceOverlayBubbleSearch(true);
|
||||
setIsVoiceOverlayVisible(true);
|
||||
setShouldFocusVoiceResult(false);
|
||||
|
||||
dispatch(getShopperHouseSearch(trimmedQuery, shopperHouseSearchId));
|
||||
},
|
||||
@@ -1161,7 +1167,47 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
clearTimeout(focusTimer);
|
||||
};
|
||||
}
|
||||
}, [shopperHouseData, isOnTop, currentMode]);
|
||||
}, [shopperHouseData, isOnTop, currentMode, DEBUG_MODE]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isOnTop &&
|
||||
currentMode === SEARCH_PANEL_MODES.VOICE_RESULT &&
|
||||
shopperHouseData?.results?.[0]?.docs?.length > 0 &&
|
||||
!isVoiceOverlayVisible
|
||||
) {
|
||||
if (DEBUG_MODE) {
|
||||
console.log('[DEBUG] 🎯 ShopperHouse 데이터 감지 - 상품 포커스 예약');
|
||||
}
|
||||
setShouldFocusVoiceResult(true);
|
||||
}
|
||||
}, [isOnTop, currentMode, shopperHouseData, isVoiceOverlayVisible, DEBUG_MODE]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldFocusVoiceResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
const focusTimer = setTimeout(() => {
|
||||
const targetId = 'searchItemContents0';
|
||||
const targetElement = document.querySelector(`[data-spotlight-id="${targetId}"]`);
|
||||
|
||||
if (targetElement) {
|
||||
Spotlight.focus(targetId);
|
||||
if (DEBUG_MODE) {
|
||||
console.log('[DEBUG] 🎯 ShopperHouse 첫 상품으로 포커스 이동:', targetId);
|
||||
}
|
||||
} else if (DEBUG_MODE) {
|
||||
console.log('[DEBUG] ⚠️ ShopperHouse 첫 상품을 찾지 못했습니다');
|
||||
}
|
||||
|
||||
setShouldFocusVoiceResult(false);
|
||||
}, 200);
|
||||
|
||||
return () => {
|
||||
clearTimeout(focusTimer);
|
||||
};
|
||||
}, [shouldFocusVoiceResult, DEBUG_MODE]);
|
||||
|
||||
/**
|
||||
* LOG 용도,
|
||||
|
||||
@@ -151,6 +151,7 @@ const SearchResultsNew = ({
|
||||
const buttonTabList = useMemo(() => getButtonTabList(), [getButtonTabList]);
|
||||
|
||||
// 현재 탭의 데이터 가져오기 - ShopperHouse 데이터 우선
|
||||
const hasShopperHouseItems = convertedShopperHouseItems?.length > 0;
|
||||
const currentData = tab === 0 ? convertedShopperHouseItems || itemInfo : showInfo;
|
||||
|
||||
// 표시할 데이터 (처음부터 visibleCount 개수만큼)
|
||||
@@ -209,20 +210,22 @@ const SearchResultsNew = ({
|
||||
}
|
||||
|
||||
const targetId =
|
||||
themeInfo?.length > 0
|
||||
? 'searchProduct-0'
|
||||
: itemInfo?.length > 0
|
||||
? 'searchItemContents0'
|
||||
: showInfo?.length > 0
|
||||
? 'categoryShowContents0'
|
||||
: null;
|
||||
hasShopperHouseItems
|
||||
? 'searchItemContents0'
|
||||
: themeInfo?.length > 0
|
||||
? 'searchProduct-0'
|
||||
: itemInfo?.length > 0
|
||||
? 'searchItemContents0'
|
||||
: showInfo?.length > 0
|
||||
? 'categoryShowContents0'
|
||||
: null;
|
||||
|
||||
if (!targetId) {
|
||||
Spotlight.focus('search-input-box');
|
||||
} else {
|
||||
Spotlight.focus(targetId);
|
||||
}
|
||||
}, []);
|
||||
}, [hasShopperHouseItems, themeInfo, itemInfo, showInfo]);
|
||||
|
||||
// 10개씩 추가 로드 (아래 버튼)
|
||||
const downBtnClick = useCallback(() => {
|
||||
@@ -283,13 +286,15 @@ const SearchResultsNew = ({
|
||||
useEffect(() => {
|
||||
const targetId = panelInfo?.currentSpot
|
||||
? panelInfo?.currentSpot
|
||||
: themeInfo?.length > 0
|
||||
? 'searchProduct-0'
|
||||
: itemInfo?.length > 0
|
||||
? 'searchItemContents0'
|
||||
: showInfo?.length > 0
|
||||
? 'categoryShowContents0'
|
||||
: null;
|
||||
: hasShopperHouseItems
|
||||
? 'searchItemContents0'
|
||||
: themeInfo?.length > 0
|
||||
? 'searchProduct-0'
|
||||
: itemInfo?.length > 0
|
||||
? 'searchItemContents0'
|
||||
: showInfo?.length > 0
|
||||
? 'categoryShowContents0'
|
||||
: null;
|
||||
|
||||
if (!targetId) return;
|
||||
|
||||
@@ -301,6 +306,10 @@ const SearchResultsNew = ({
|
||||
itemInfo?.length,
|
||||
showInfo?.length,
|
||||
convertedShopperHouseItems?.length, // shopperHouseInfo 대신 구체적인 의존성 사용
|
||||
hasShopperHouseItems,
|
||||
themeInfo,
|
||||
itemInfo,
|
||||
showInfo,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user