diff --git a/com.twin.app.shoptime/src/App/App.js b/com.twin.app.shoptime/src/App/App.js index 01f13fdc..a52e5f09 100644 --- a/com.twin.app.shoptime/src/App/App.js +++ b/com.twin.app.shoptime/src/App/App.js @@ -456,6 +456,7 @@ function AppBase(props) { // const termsFlag = useSelector((state) => state.common.termsFlag); const termsData = useSelector((state) => state.home.termsData); + // 🔽 Spotlight focus/blur 로그 (옵션) useEffect(() => { if (!Config.FOCUS_DEBUG) { return undefined; diff --git a/com.twin.app.shoptime/src/actions/panelActions.js b/com.twin.app.shoptime/src/actions/panelActions.js index 2d91355e..72bd8d59 100644 --- a/com.twin.app.shoptime/src/actions/panelActions.js +++ b/com.twin.app.shoptime/src/actions/panelActions.js @@ -1,6 +1,8 @@ import { types } from './actionTypes'; import Spotlight from '@enact/spotlight'; +import { getContainerId } from '@enact/spotlight/src/container'; import { panel_names } from '../utils/Config'; +import { updateHomeInfo } from './homeActions'; // 시작 메뉴 추적을 위한 상수 export const SOURCE_MENUS = { @@ -67,6 +69,17 @@ export const navigateToDetail = ({ additionalInfo = {}, }) => { return (dispatch, getState) => { + // 🔽 현재 포커스 정보 저장 (HomePanel 복귀 시 포커스 복원용) + const currentSpotNode = Spotlight.getCurrent(); + const currentSpotId = currentSpotNode?.getAttribute('data-spotlight-id'); + const currentContainerId = currentSpotNode ? getContainerId(currentSpotNode) : null; + const focusSnapshot = currentSpotId + ? { + lastFocusedTargetId: currentContainerId || currentSpotId, + currentSpot: currentSpotId, + } + : {}; + const panelInfo = { patnrId, prdtId, @@ -100,6 +113,18 @@ export const navigateToDetail = ({ case SOURCE_MENUS.HOME_RANDOM_UNIT: case SOURCE_MENUS.HOME_ROLLING_UNIT: case SOURCE_MENUS.HOME_GENERAL: { + // HomePanel Redux 상태에 포커스 스냅샷 저장 (Detail→Home 복귀 시 사용) + if (Object.keys(focusSnapshot).length > 0) { + dispatch( + updateHomeInfo({ + name: panel_names.HOME_PANEL, + panelInfo: { + ...focusSnapshot, + }, + }) + ); + } + // 🔽 모든 HomePanel에서 DetailPanel로 이동 시 HomeBanner modal 비디오 정지 const state = getState(); const playerPanelInfo = state.panels.panels.find( @@ -115,6 +140,7 @@ export const navigateToDetail = ({ panelInfo: { lastSelectedProduct: { patnrId, prdtId }, lastActionSource: sourceMenu, + ...focusSnapshot, ...additionalInfo, }, }) @@ -147,6 +173,7 @@ export const navigateToDetail = ({ videoStateToRestore, lastSelectedProduct: { patnrId, prdtId }, lastActionSource: sourceMenu, + ...focusSnapshot, ...additionalInfo, }, }) @@ -163,6 +190,7 @@ export const navigateToDetail = ({ panelInfo: { lastSelectedProduct: { patnrId, prdtId }, lastActionSource: sourceMenu, + ...focusSnapshot, ...additionalInfo, }, }) @@ -176,6 +204,7 @@ export const navigateToDetail = ({ panelInfo: { lastSelectedProduct: { patnrId, prdtId }, lastActionSource: sourceMenu, + ...focusSnapshot, ...additionalInfo, }, }) diff --git a/com.twin.app.shoptime/src/actions/playActions.js b/com.twin.app.shoptime/src/actions/playActions.js index c669101b..716fc317 100644 --- a/com.twin.app.shoptime/src/actions/playActions.js +++ b/com.twin.app.shoptime/src/actions/playActions.js @@ -244,7 +244,7 @@ export const startVideoPlayerNew = }; export const finishVideoPreview = () => (dispatch, getState) => { - console.log('@@@@@@@@@@@@@@@@@-finishVideoPreview'); + console.log('###-finishVideoPreview'); const panels = getState().panels.panels; const topPanel = panels[panels.length - 1]; if (topPanel && topPanel.name === panel_names.PLAYER_PANEL && topPanel.panelInfo.modal) { @@ -258,7 +258,7 @@ export const finishVideoPreview = () => (dispatch, getState) => { export const finishModalVideoForce = () => (dispatch, getState) => { const panels = getState().panels.panels; - + console.log('###-finishModalVideoForce'); // modal PlayerPanel이 존재하는지 확인 (스택 어디에 있든) const hasModalPlayerPanel = panels.some( (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal @@ -277,7 +277,7 @@ export const finishModalVideoForce = () => (dispatch, getState) => { // 모든 PlayerPanel을 강제 제거 (modal과 fullscreen 모두) export const finishAllVideoForce = () => (dispatch, getState) => { const panels = getState().panels.panels; - + console.log('###-finishAllVideoForce'); // 모든 PlayerPanel이 존재하는지 확인 (스택 어디에 있든) const hasPlayerPanel = panels.some((panel) => panel.name === panel_names.PLAYER_PANEL); @@ -294,6 +294,7 @@ export const finishAllVideoForce = () => (dispatch, getState) => { // 모달 비디오를 일시정지 (패널은 유지) export const pauseModalVideo = () => (dispatch, getState) => { const panels = getState().panels.panels; + console.log('###-pauseModalVideo'); // modal PlayerPanel 찾기 const modalPlayerPanel = panels.find( @@ -317,7 +318,7 @@ export const pauseModalVideo = () => (dispatch, getState) => { // 모달 비디오를 재생 (일시정지 해제) export const resumeModalVideo = () => (dispatch, getState) => { const panels = getState().panels.panels; - + // modal PlayerPanel 찾기 const modalPlayerPanel = panels.find( (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal diff --git a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx index bea6cd05..0cd162e6 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx @@ -768,6 +768,18 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) { } }, [panels]); + // PlayerPanel이 modal=true인 경우 비디오 미리보기 중지 + useEffect(() => { + const hasPlayerPanel = panels.some( + (panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal === true + ); + + if (hasPlayerPanel) { + console.log('[DetailPanel] PlayerPanel modal=true detected - stopping video preview'); + dispatch(finishVideoPreview()); + } + }, [panels, dispatch]); + return (
diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx index aeedba62..6e9c1bdb 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx @@ -490,6 +490,24 @@ export default function RandomUnit({ finishAndUnlock(); } + // 🔖 DetailPanel로 이동하기 전에 현재 포커스 대상 저장 (HomePanel 복귀 시 복원) + if (isNavigatingToDetail) { + const currentSpot = Spotlight.getCurrent(); + const lastFocusedTargetId = getContainerId(currentSpot); + if (lastFocusedTargetId) { + dispatch( + updateHomeInfo({ + name: panel_names.HOME_PANEL, + panelInfo: { + lastFocusedTargetId, + currentSpot: currentSpot?.getAttribute('data-spotlight-id'), + focusedContainerId: TEMPLATE_CODE_CONF.TOP, + }, + }) + ); + } + } + dispatch(action(linkInfo)); sendBannerLog(true); dispatch( diff --git a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx index 9ea8033f..07239e28 100644 --- a/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx +++ b/com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx @@ -139,6 +139,8 @@ const HomePanel = ({ isOnTop }) => { const [cateNm, setCateNm] = useState(panelInfo.currentCateName ?? null); const { entryMenu, nowMenu } = useSelector((state) => state.common.menu); const [focusedContainerId, setFocusedContainerId] = useState(panelInfo.focusedContainerId); + // DetailPanel 진입 시 포커스 대상 저장 + const lastFocusedTargetRef = useRef(panelInfo.lastFocusedTargetId || null); const isInitialRender = useRef(true); const verticalPagenatorRef = useRef(null); @@ -790,6 +792,20 @@ const HomePanel = ({ isOnTop }) => { }) ); + // 🔽 DetailPanel에서 돌아온 뒤 포커스를 마지막 포커스 대상에 복원 + console.log('[HomePanel] *** 🎯 Focus 복원 준비'); + const targetFocusId = panelInfo.lastFocusedTargetId || lastFocusedTargetRef.current; + console.log('[HomePanel] *** 📍 targetFocusId:', targetFocusId, '(panelInfo.lastFocusedTargetId:', panelInfo.lastFocusedTargetId, ', lastFocusedTargetRef:', lastFocusedTargetRef.current, ')'); + if (targetFocusId) { + console.log('[HomePanel] *** ⏰ 300ms 후 Spotlight.focus 호출 예정'); + setTimeout(() => { + console.log('[HomePanel] *** 🔍 Spotlight.focus 호출:', targetFocusId); + Spotlight.focus(targetFocusId); + }, 300); + } else { + console.log('[HomePanel] *** ⚠️ targetFocusId가 없음 - Focus 복원 스킵'); + } + // refs 초기화 videoPlayIntentRef.current = null; lastPlayedBannerIdRef.current = null; @@ -821,6 +837,7 @@ const HomePanel = ({ isOnTop }) => { currentCatCd: targetSpotlightCatcd, currentCateName: targetSpotlightCateNm, focusedContainerId: focusedContainerIdRef.current, + lastFocusedTargetId: lastFocusedTargetRef.current || panelInfo.lastFocusedTargetId, }, }) );