/** * src/actions/panelNavigationActions.js * Panel navigation 순차 처리를 위한 액션 크리에이터 * * Chrome 68 호환성을 위한 callback-free 순차 네비게이션 */ import { pushPanel, updatePanel } from './panelActions'; import { panel_names } from '../utils/Config'; import { createDebugHelpers } from '../utils/debug'; // 디버그 헬퍼 설정 const DEBUG_MODE = false; const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE); /** * 상품 클릭 시 순차 네비게이션 (Search → Detail) * @param {string} patnrId - 파트너 ID * @param {string} prdtId - 상품 ID * @param {string} searchQuery - 검색어 * @param {string} currentSpot - 현재 spotlight ID * @param {Object} additionalInfo - 추가 패널 정보 * @returns {Function} Redux thunk function */ export const navigateToDetailPanel = (patnrId, prdtId, searchQuery, currentSpot, additionalInfo = {}) => (dispatch, getState) => { // 현재 상태에서 lastPanelAction 카운트 저장 const currentActionCount = getState().panels.lastPanelAction || 0; dlog('[PanelNavigation] Starting navigation to detail:', { patnrId, prdtId, searchQuery, currentSpot, currentActionCount, }); // 1. 먼저 현재 패널(예: SearchPanel) 업데이트 dispatch( updatePanel({ name: panel_names.SEARCH_PANEL, panelInfo: { searchVal: searchQuery, currentSpot, tab: 0, ...additionalInfo, }, }) ); // 2. Redux store 구독하여 상태 변화 감지 // 직접 store 접근 대신 타이머 기반 방식 사용 (Chrome 68 호환) const storeUnsubscribe = (() => { let isUnsubscribed = false; const checkStateChange = () => { if (isUnsubscribed) return; const newState = getState(); const newActionCount = newState.panels.lastPanelAction || 0; // updatePanel이 완료되면 (action count가 변경되면) if (newActionCount !== currentActionCount) { dlog('[PanelNavigation] UpdatePanel completed, pushing DetailPanel'); // 구독 해제 isUnsubscribed = true; // 3. DetailPanel push dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, panelInfo: { patnrId, prdtId, fromSearch: true, searchQuery, ...additionalInfo, }, }) ); } }; // 즉시 한번 확인하고, 그 후 주기적으로 확인 setTimeout(checkStateChange, 0); const intervalId = setInterval(checkStateChange, 16); // 60fps return () => { isUnsubscribed = true; clearInterval(intervalId); }; })(); // 타임아웃 방어 (최대 1초 대기) setTimeout(() => { storeUnsubscribe(); dlog('[PanelNavigation] Timeout fallback, pushing DetailPanel'); dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, panelInfo: { patnrId, prdtId, fromSearch: true, searchQuery, ...additionalInfo, }, }) ); }, 1000); }; /** * HomePanel에서 상품 클릭 시 순차 네비게이션 * @param {string} patnrId - 파트너 ID * @param {string} prdtId - 상품 ID * @param {Object} additionalInfo - 추가 패널 정보 * @returns {Function} Redux thunk function */ export const navigateToDetailFromHome = (patnrId, prdtId, additionalInfo = {}) => (dispatch, getState) => { const currentActionCount = getState().panels.lastPanelAction || 0; dlog('[PanelNavigation] Starting navigation from home:', { patnrId, prdtId, currentActionCount, }); dispatch( updatePanel({ name: panel_names.HOME_PANEL, panelInfo: { lastSelectedProduct: { patnrId, prdtId }, ...additionalInfo, }, }) ); const storeUnsubscribe = (() => { let isUnsubscribed = false; const checkStateChange = () => { if (isUnsubscribed) return; const newState = getState(); const newActionCount = newState.panels.lastPanelAction || 0; if (newActionCount !== currentActionCount) { dlog('[PanelNavigation] HomePanel update completed, pushing DetailPanel'); isUnsubscribed = true; dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, panelInfo: { patnrId, prdtId, fromHome: true, ...additionalInfo, }, }) ); } }; setTimeout(checkStateChange, 0); const intervalId = setInterval(checkStateChange, 16); return () => { isUnsubscribed = true; clearInterval(intervalId); }; })(); setTimeout(() => { storeUnsubscribe(); dlog('[PanelNavigation] Timeout fallback from home'); dispatch( pushPanel({ name: panel_names.DETAIL_PANEL, panelInfo: { patnrId, prdtId, fromHome: true, ...additionalInfo, }, }) ); }, 1000); }; /** * JustForYouBanner 클릭 시 순차 네비게이션 (PlayerPanel 제거 → JustForYouTestPanel push) * @returns {Function} Redux thunk function */ export const navigateToJustForYouTestPanel = () => (dispatch, getState) => { const currentActionCount = getState().panels.lastPanelAction || 0; dlog('[PanelNavigation] Starting navigation to JustForYouTestPanel:', { currentActionCount, }); // 1. 먼저 HomePanel 상태 저장 (필요시) dispatch( updatePanel({ name: panel_names.HOME_PANEL, panelInfo: { fromJustForYouBanner: true, timestamp: Date.now(), }, }) ); const storeUnsubscribe = (() => { let isUnsubscribed = false; const checkStateChange = () => { if (isUnsubscribed) return; const newState = getState(); const newActionCount = newState.panels.lastPanelAction || 0; // updatePanel이 완료되면 if (newActionCount !== currentActionCount) { dlog('[PanelNavigation] HomePanel update completed, pushing JustForYouTestPanel'); isUnsubscribed = true; // 2. JustForYouTestPanel push dispatch( pushPanel({ name: panel_names.JUST_FOR_YOU_TEST_PANEL, panelInfo: { fromJustForYouBanner: true, }, }) ); // 3. JustForYouTestPanel이 렌더링된 후 PlayerPanel 제거 setTimeout(() => { dlog('[PanelNavigation] Removing PlayerPanel after JustForYouTestPanel render'); const { finishAllVideoForce } = require('./playActions'); dispatch(finishAllVideoForce()); }, 200); } }; setTimeout(checkStateChange, 0); const intervalId = setInterval(checkStateChange, 16); return () => { isUnsubscribed = true; clearInterval(intervalId); }; })(); // 타임아웃 방어 (최대 1초 대기) setTimeout(() => { storeUnsubscribe(); dlog('[PanelNavigation] Timeout fallback, pushing JustForYouTestPanel'); dispatch( pushPanel({ name: panel_names.JUST_FOR_YOU_TEST_PANEL, panelInfo: { fromJustForYouBanner: true, }, }) ); // fallback으로도 PlayerPanel 제거 setTimeout(() => { dlog('[PanelNavigation] Fallback: removing PlayerPanel'); const { finishAllVideoForce } = require('./playActions'); dispatch(finishAllVideoForce()); }, 200); }, 1000); };