diff --git a/com.twin.app.shoptime/src/actions/mediaActions.js b/com.twin.app.shoptime/src/actions/mediaActions.js index 5759c020..2bb49f52 100644 --- a/com.twin.app.shoptime/src/actions/mediaActions.js +++ b/com.twin.app.shoptime/src/actions/mediaActions.js @@ -99,17 +99,25 @@ export const finishMediaPreview = () => (dispatch, getState) => { export const finishModalMediaForce = () => (dispatch, getState) => { const panels = getState().panels.panels; + console.log('[🟡UNIQUE_DETAIL_CLEANUP🟡] finishModalMediaForce called', { + panelCount: panels.length, + panelNames: panels.map((p) => p.name), + }); + const hasProductVideoPanel = panels.some( (panel) => panel.name === panel_names.MEDIA_PANEL && (panel.panelInfo?.modal || panel.panelInfo?.modalContainerId === 'product-video-player') ); + console.log('[🟡UNIQUE_DETAIL_CLEANUP🟡] hasProductVideoPanel:', hasProductVideoPanel); + if (hasProductVideoPanel) { if (startMediaFocusTimer) { clearTimeout(startMediaFocusTimer); startMediaFocusTimer = null; } + console.log('[🟡UNIQUE_DETAIL_CLEANUP🟡] Calling popPanel(panel_names.MEDIA_PANEL)'); dispatch(popPanel(panel_names.MEDIA_PANEL)); } }; diff --git a/com.twin.app.shoptime/src/actions/panelActions.js b/com.twin.app.shoptime/src/actions/panelActions.js index 8e5fcddf..00663efb 100644 --- a/com.twin.app.shoptime/src/actions/panelActions.js +++ b/com.twin.app.shoptime/src/actions/panelActions.js @@ -40,12 +40,20 @@ export const pushPanel = (panel, duplicatable = false) => ({ }); export const popPanel = (panelName) => { + const stack = new Error().stack; + const stackLines = stack?.split('\n') || []; + + console.log('[💜UNIQUE_PANEL_STACK💜] popPanel action dispatcher - REMOVING PANEL:', { + panelName, + timestamp: Date.now(), + fullStack: stackLines.slice(1, 6).map((line) => line.trim()), + }); + if (DEBUG_MODE) { - console.log('[PANEL-TRACE] popPanel action creator', { + console.log('[💜UNIQUE_PANEL_STACK💜] popPanel action creator stack:', { panelName, - caller: new Error().stack?.split('\n')[2]?.trim(), + caller: stackLines[2]?.trim(), }); - console.trace('[PANEL-TRACE] popPanel stack trace'); } return { type: types.POP_PANEL, diff --git a/com.twin.app.shoptime/src/reducers/panelReducer.js b/com.twin.app.shoptime/src/reducers/panelReducer.js index a1518e47..1276843a 100644 --- a/com.twin.app.shoptime/src/reducers/panelReducer.js +++ b/com.twin.app.shoptime/src/reducers/panelReducer.js @@ -94,6 +94,12 @@ export const panelsReducer = (state = initialState, action) => { } case types.POP_PANEL: { + console.log('[💜UNIQUE_PANEL_STACK💜] POP_PANEL reducer START', { + targetPanel: action.payload || 'last_panel', + currentPanels: state.panels.map((p) => p.name), + timestamp: Date.now(), + }); + dlog('[panelReducer] 🔴 POP_PANEL START', { targetPanel: action.payload || 'last_panel', currentPanels: state.panels.map((p) => p.name), @@ -118,6 +124,13 @@ export const panelsReducer = (state = initialState, action) => { resultPanels = state.panels.slice(0, state.panels.length - 1); } + console.log('[💜UNIQUE_PANEL_STACK💜] POP_PANEL reducer END', { + resultPanels: resultPanels.map((p) => p.name), + panelCount: resultPanels.length, + lastAction, + timestamp: Date.now(), + }); + dlog('[panelReducer] 🔴 POP_PANEL END', { resultPanels: resultPanels.map((p) => p.name), lastAction, diff --git a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx index e47699a0..9a657e9d 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx @@ -280,6 +280,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { useEffect(() => { return () => { + console.log('[🟡UNIQUE_DETAIL_CLEANUP🟡] DetailPanel cleanup - calling finishModalMediaForce'); dispatch(finishModalMediaForce()); }; }, [dispatch]); @@ -303,16 +304,15 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { const sourcePanel = panelInfo?.sourcePanel; const sourceMenu = panelInfo?.sourceMenu; - console.log('[DP-TRACE] Detail unmount start', { + console.log('[🔴UNIQUE_DETAIL_UNMOUNT🔴] DetailPanel cleanup/unmount triggered', { sourcePanel, sourceMenu, panelsSnapshot: panels.map((p) => p.name), + timestamp: Date.now(), }); - console.log('[Detail-BG] 306-line sourcePanel:', sourcePanel, 'sourceMenu:', sourceMenu); - // DetailPanel이 unmount되는 시점 - console.log('[DetailPanel] unmount:', { + console.log('[🔴UNIQUE_DETAIL_UNMOUNT🔴] DetailPanel unmount details:', { sourcePanel, sourceMenu, timestamp: Date.now(), @@ -385,6 +385,14 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { const sourcePanel = panelInfo?.sourcePanel; const sourceMenu = panelInfo?.sourceMenu; + console.log('[🟠UNIQUE_DETAIL_BACK🟠] onBackClick triggered', { + sourcePanel, + sourceMenu, + isCancelClick, + currentPanels: panels.map((p) => p.name), + timestamp: Date.now(), + }); + fp.pipe( () => { dispatch(clearAllToasts()); // BuyOption Toast 포함 모든 토스트 제거 @@ -393,7 +401,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { switch (sourcePanel) { case panel_names.PLAYER_PANEL: // PlayerPanel에서 온 경우: 플레이어 비디오는 그대로 두고 모달만 정리 - console.log('[DetailPanel] onBackClick - PlayerPanel 출신: 모달 정리만 수행'); + console.log('[🟠UNIQUE_DETAIL_BACK🟠] PlayerPanel 출신: 모달 정리만 수행'); dispatch(finishModalMediaForce()); // MEDIA_PANEL(ProductVideo) 강제 종료 dispatch(finishVideoPreview()); break; @@ -403,7 +411,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { default: // HomePanel, SearchPanel 등에서 온 경우: 백그라운드 비디오 일시 중지 console.log( - '[DetailPanel] onBackClick - source panel:', + '[🟠UNIQUE_DETAIL_BACK🟠] source panel:', sourcePanel, '백그라운드 비디오 일시 중지' ); @@ -413,6 +421,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { break; } + console.log('[🟠UNIQUE_DETAIL_BACK🟠] Calling popPanel(DETAIL_PANEL)'); dispatch(popPanel(panel_names.DETAIL_PANEL)); }, () => { diff --git a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.jsx b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.jsx index ac86dc10..63f526ff 100644 --- a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.jsx +++ b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.jsx @@ -391,6 +391,7 @@ const MediaPanel = React.forwardRef( const onEnded = useCallback( (e) => { debugLog('[MediaPanel] Video ended'); + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] MediaPanel onEnded triggered - will pop after 1500ms'); // continuousPlay는 MediaPlayer(VideoPlayer) 컴포넌트 내부에서 loop 속성으로 처리 // onEnded가 호출되면 loop=false 인 경우이므로 패널을 닫음 Spotlight.pause(); @@ -402,6 +403,7 @@ const MediaPanel = React.forwardRef( // ✅ 새로운 타이머 저장 (cleanup 시 정리용) onEndedTimerRef.current = setTimeout(() => { + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] Executing popPanel(MEDIA_PANEL) after 1500ms'); Spotlight.resume(); dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); onEndedTimerRef.current = null; diff --git a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx index a911deb1..7bf1f086 100644 --- a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx +++ b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx @@ -912,7 +912,7 @@ const MediaPanel = React.forwardRef( } if (!panelInfo.modal) { - dispatch(PanelActions.popPanel()); + dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); dispatch(changeAppStatus({ cursorVisible: false })); document?.dispatchEvent?.(new CustomEvent('detailpanel-scroll-reset')); @@ -937,7 +937,7 @@ const MediaPanel = React.forwardRef( // 패널이 2개 존재할때만 popPanel 진행 // fullscreen 전환 중이면 popPanel하지 않음 if (panelInfo.modal && !isOnTop && !isTransitioningToFullscreen.current) { - dispatch(PanelActions.popPanel()); + dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); } else { Spotlight.focus('tbody'); } @@ -1576,7 +1576,7 @@ const MediaPanel = React.forwardRef( ) { // case: Featured Brands if (panelInfo?.sourcePanel === panel_names.FEATURED_BRANDS_PANEL) { - dispatch(PanelActions.popPanel()); + dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); } } }, [ @@ -2043,19 +2043,25 @@ const MediaPanel = React.forwardRef( (e) => { const currentInfo = panelInfoRef.current; + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] onEnded triggered - shptmBanrTpNm:', currentInfo?.shptmBanrTpNm); + // MEDIA: 기존 동작 유지 (배경 복원 없이 즉시 pop) if (currentInfo.shptmBanrTpNm === 'MEDIA') { - console.log('[MediaPanel] 🚫 Skipping background restoration for ended media'); + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] MEDIA type - popPanel will be called'); Spotlight.pause(); setTimeout(() => { + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] setTimeout fired - dispatching popPanel(MEDIA_PANEL)'); Spotlight.resume(); - dispatch(PanelActions.popPanel()); + dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); }, VIDEO_END_ACTION_DELAY); + e?.stopPropagation(); + e?.preventDefault(); return; } // VOD: modal 여부에 따라 동작 분리 if (currentInfo.shptmBanrTpNm === 'VOD') { + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] VOD type - popPanel will be called'); Spotlight.pause(); setTimeout(() => { stopExternalPlayer(); @@ -2074,6 +2080,8 @@ const MediaPanel = React.forwardRef( e?.preventDefault(); return; } + + console.log('[🔥UNIQUE_MEDIA_ENDED🔥] Unknown shptmBanrTpNm - no action taken'); }, [dispatch, focusBackButtonOrFallback, stopExternalPlayer] );