|
|
|
|
@@ -64,7 +64,7 @@ import TabContainerV2 from './PlayerTabContents/v2/TabContainer.v2';
|
|
|
|
|
// import ShopNowButton from './PlayerTabContents/v2/ShopNowButton';
|
|
|
|
|
|
|
|
|
|
const Container = SpotlightContainerDecorator(
|
|
|
|
|
{ enterTo: 'default-element', preserveld: true },
|
|
|
|
|
{ enterTo: 'last-focused', preserveId: true },
|
|
|
|
|
'div'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
@@ -172,6 +172,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const videoPlayer = useRef(null);
|
|
|
|
|
const prevModal = usePrevious(panelInfo?.modal);
|
|
|
|
|
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
|
|
|
|
|
const [shopNowInfo, setShopNowInfo] = USE_STATE('shopNowInfo');
|
|
|
|
|
const [backupInitialIndex, setBackupInitialIndex] = USE_STATE('backupInitialIndex', 0);
|
|
|
|
|
@@ -369,6 +370,25 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
}
|
|
|
|
|
}, [panelInfo?.isPaused]);
|
|
|
|
|
|
|
|
|
|
// Modal 상태 변화 감지 (true → false)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (prevModal !== undefined && prevModal === true && panelInfo?.modal === false) {
|
|
|
|
|
console.log('[PlayerPanel] 🔄 Modal 상태 변화: true → false (전체화면 모드로 복귀)');
|
|
|
|
|
console.log('[PlayerPanel] 🎯 포커스 복원 준비 - lastFocusedTargetId:', panelInfo?.lastFocusedTargetId);
|
|
|
|
|
|
|
|
|
|
// DetailPanel에서 복귀 시 포커스 복원
|
|
|
|
|
const lastFocusedTargetId = panelInfo?.lastFocusedTargetId;
|
|
|
|
|
|
|
|
|
|
if (lastFocusedTargetId) {
|
|
|
|
|
// ShopNowContents가 렌더링될 때까지 대기 후 포커스 복원
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
console.log('[PlayerPanel] 🔍 800ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
|
|
|
|
Spotlight.focus(lastFocusedTargetId);
|
|
|
|
|
}, 800);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, [panelInfo?.modal, prevModal, panelInfo?.lastFocusedTargetId]);
|
|
|
|
|
|
|
|
|
|
// creating live log params
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (currentLiveShowInfo && Object.keys(currentLiveShowInfo).length > 0) {
|
|
|
|
|
@@ -1867,6 +1887,8 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
const [initialEnterV2, setInitialEnterV2] = USE_STATE('initialEnterV2', true);
|
|
|
|
|
const timerId = useRef(null);
|
|
|
|
|
const timerIdV2 = useRef(null);
|
|
|
|
|
const timerIdTabAutoAdvance = useRef(null);
|
|
|
|
|
const prevTabIndexV2 = useRef(null);
|
|
|
|
|
|
|
|
|
|
const showSideContents = useMemo(() => {
|
|
|
|
|
return (
|
|
|
|
|
@@ -1949,45 +1971,76 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
|
|
|
|
|
const resetTimerV2 = useCallback(
|
|
|
|
|
(timeout) => {
|
|
|
|
|
// console.log('[TabContainerV2] resetTimerV2 호출', timeout);
|
|
|
|
|
console.log('[TabContainerV2] resetTimerV2 호출', timeout);
|
|
|
|
|
if (timerIdV2.current) {
|
|
|
|
|
// console.log('[TabContainerV2] 기존 타이머 클리어');
|
|
|
|
|
console.log('[TabContainerV2] 기존 타이머 클리어');
|
|
|
|
|
clearTimerV2();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (initialEnterV2) {
|
|
|
|
|
// console.log('[TabContainerV2] initialEnterV2 false로 변경');
|
|
|
|
|
console.log('[TabContainerV2] initialEnterV2 false로 변경');
|
|
|
|
|
setInitialEnterV2(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timerIdV2.current = setTimeout(() => {
|
|
|
|
|
// console.log('[TabContainerV2] 타이머 실행 - belowContentsVisible false로 변경');
|
|
|
|
|
console.log('[TabContainerV2] 타이머 실행 - belowContentsVisible false로 변경 (30초 경과)');
|
|
|
|
|
setBelowContentsVisible(false);
|
|
|
|
|
}, timeout);
|
|
|
|
|
},
|
|
|
|
|
[clearTimerV2, initialEnterV2, setInitialEnterV2, setBelowContentsVisible]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const clearTimerTabAutoAdvance = useCallback(() => {
|
|
|
|
|
clearTimeout(timerIdTabAutoAdvance.current);
|
|
|
|
|
timerIdTabAutoAdvance.current = null;
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const resetTimerTabAutoAdvance = useCallback(
|
|
|
|
|
(timeout) => {
|
|
|
|
|
if (timerIdTabAutoAdvance.current) {
|
|
|
|
|
clearTimerTabAutoAdvance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
timerIdTabAutoAdvance.current = setTimeout(() => {
|
|
|
|
|
setTabIndexV2(2);
|
|
|
|
|
}, timeout);
|
|
|
|
|
},
|
|
|
|
|
[clearTimerTabAutoAdvance]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Redux로 오버레이 숨김
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (shouldHideOverlays) {
|
|
|
|
|
console.log('[PlayerPanel] shouldHideOverlays true - 오버레이 숨김');
|
|
|
|
|
setSideContentsVisible(false);
|
|
|
|
|
console.log('[setBelowContentsVisible] Redux로 오버레이 숨김 - false로 변경');
|
|
|
|
|
setBelowContentsVisible(false);
|
|
|
|
|
|
|
|
|
|
if (videoPlayer.current?.hideControls) {
|
|
|
|
|
videoPlayer.current.hideControls();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 모든 타이머 클리어
|
|
|
|
|
if (timerId.current) {
|
|
|
|
|
clearTimer();
|
|
|
|
|
}
|
|
|
|
|
if (timerIdV2.current) {
|
|
|
|
|
clearTimerV2();
|
|
|
|
|
}
|
|
|
|
|
if (timerIdTabAutoAdvance.current) {
|
|
|
|
|
clearTimerTabAutoAdvance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dispatch(resetPlayerOverlays());
|
|
|
|
|
}
|
|
|
|
|
}, [shouldHideOverlays, dispatch]);
|
|
|
|
|
}, [shouldHideOverlays, dispatch, clearTimer, clearTimerV2, clearTimerTabAutoAdvance]);
|
|
|
|
|
|
|
|
|
|
// Redux로 오버레이 표시
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (shouldShowOverlays) {
|
|
|
|
|
console.log('[PlayerPanel] shouldShowOverlays true - 오버레이 표시');
|
|
|
|
|
setSideContentsVisible(true);
|
|
|
|
|
console.log('[setBelowContentsVisible] Redux로 오버레이 표시 - true로 변경');
|
|
|
|
|
setBelowContentsVisible(true);
|
|
|
|
|
|
|
|
|
|
if (videoPlayer.current?.showControls) {
|
|
|
|
|
@@ -2001,12 +2054,25 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
// PlayerPanel이 최상단이 될 때 오버레이 표시 (DetailPanel에서 복귀)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (isOnTop && !panelInfo.modal && !videoVerticalVisible) {
|
|
|
|
|
console.log('[PlayerPanel] isOnTop true - 오버레이 표시');
|
|
|
|
|
console.log('[PlayerPanel] ✅ DetailPanel에서 복귀함! - 오버레이 표시');
|
|
|
|
|
setSideContentsVisible(true);
|
|
|
|
|
console.log('[setBelowContentsVisible] DetailPanel에서 복귀 - true로 변경');
|
|
|
|
|
setBelowContentsVisible(true);
|
|
|
|
|
// VideoPlayer가 belowContentsVisible prop을 감지해서 자동으로 controls 표시함
|
|
|
|
|
|
|
|
|
|
// DetailPanel에서 복귀 시 포커스 복원 시도
|
|
|
|
|
const lastFocusedTargetId = panelInfo?.lastFocusedTargetId;
|
|
|
|
|
console.log('[PlayerPanel] 🎯 DetailPanel 복귀 - lastFocusedTargetId:', lastFocusedTargetId);
|
|
|
|
|
|
|
|
|
|
if (lastFocusedTargetId) {
|
|
|
|
|
// ShopNowContents가 렌더링될 때까지 잠시 대기 후 포커스 복원
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
console.log('[PlayerPanel] 🔍 500ms 후 포커스 복원 시도:', lastFocusedTargetId);
|
|
|
|
|
Spotlight.focus(lastFocusedTargetId);
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, [isOnTop, panelInfo.modal, videoVerticalVisible]);
|
|
|
|
|
}, [isOnTop, panelInfo.modal, videoVerticalVisible, panelInfo?.lastFocusedTargetId]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
// tabContainerVersion === 1일 때만 실행
|
|
|
|
|
@@ -2055,54 +2121,71 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
};
|
|
|
|
|
}, [sideContentsVisible]);
|
|
|
|
|
|
|
|
|
|
// TabContainerV2 자동 닫기
|
|
|
|
|
// TabContainerV2 자동 닫기 (tabIndex 1 → 2 변경 감지)
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
// tabContainerVersion === 2일 때만 실행
|
|
|
|
|
if (tabContainerVersion !== 2) return;
|
|
|
|
|
|
|
|
|
|
// console.log('[TabContainerV2] useEffect 시작', {
|
|
|
|
|
// showBelowContents,
|
|
|
|
|
// videoVerticalVisible,
|
|
|
|
|
// initialEnterV2,
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
const node = document.querySelector(`[data-spotlight-id=${TAB_CONTAINER_V2_SPOTLIGHT_ID}]`);
|
|
|
|
|
// console.log('[TabContainerV2] DOM node:', node);
|
|
|
|
|
|
|
|
|
|
if (!showBelowContents || !node || videoVerticalVisible) {
|
|
|
|
|
// console.log('[TabContainerV2] early return');
|
|
|
|
|
if (tabContainerVersion !== 2) {
|
|
|
|
|
prevTabIndexV2.current = tabIndexV2;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE 탭이 표시될 때마다 타이머 시작 (첫 진입은 30초, 이후에는 REGULAR_TIMEOUT)
|
|
|
|
|
resetTimerV2(initialEnterV2 ? INITIAL_TIMEOUT : REGULAR_TIMEOUT);
|
|
|
|
|
// tabIndexV2가 1에서 2로 정확하게 변경되는 시점만 감지
|
|
|
|
|
const isTransitionedTo2 = prevTabIndexV2.current === 1 && tabIndexV2 === 2;
|
|
|
|
|
prevTabIndexV2.current = tabIndexV2;
|
|
|
|
|
|
|
|
|
|
const handleEvent = (e) => {
|
|
|
|
|
// console.log('[TabContainerV2] 이벤트 발생:', e.type);
|
|
|
|
|
resetTimerV2(REGULAR_TIMEOUT);
|
|
|
|
|
};
|
|
|
|
|
TARGET_EVENTS.forEach((event) => {
|
|
|
|
|
// console.log('[TabContainerV2] 이벤트 리스너 등록:', event);
|
|
|
|
|
node.addEventListener(event, handleEvent);
|
|
|
|
|
});
|
|
|
|
|
if (!isTransitionedTo2) {
|
|
|
|
|
if (timerIdV2.current) {
|
|
|
|
|
console.log('[TabContainerV2] 타이머 클리어 - tabIndex가 2가 아님', tabIndexV2);
|
|
|
|
|
clearTimerV2();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('[TabContainerV2] tabIndex 1 → 2 감지, 타이머 시작');
|
|
|
|
|
|
|
|
|
|
if (!belowContentsVisible || videoVerticalVisible) {
|
|
|
|
|
console.log('[TabContainerV2] early return - belowContentsVisible 또는 videoVerticalVisible 조건 불만족');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tabIndex 1 → 2로 변경된 정확한 시점에 30초 타이머 시작
|
|
|
|
|
console.log('[TabContainerV2] 30초 타이머 시작');
|
|
|
|
|
resetTimerV2(REGULAR_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
// console.log('[TabContainerV2] cleanup');
|
|
|
|
|
TARGET_EVENTS.forEach((event) => node.removeEventListener(event, handleEvent));
|
|
|
|
|
|
|
|
|
|
if (timerIdV2.current) {
|
|
|
|
|
clearTimerV2();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}, [
|
|
|
|
|
showBelowContents,
|
|
|
|
|
videoVerticalVisible,
|
|
|
|
|
tabContainerVersion,
|
|
|
|
|
tabIndexV2,
|
|
|
|
|
belowContentsVisible,
|
|
|
|
|
videoVerticalVisible,
|
|
|
|
|
resetTimerV2,
|
|
|
|
|
initialEnterV2,
|
|
|
|
|
clearTimerV2,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// TabIndex 1 자동 다음 단계로 이동
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
// tabIndex === 1일 때만 실행
|
|
|
|
|
if (tabIndexV2 !== 1 || !belowContentsVisible || videoVerticalVisible) {
|
|
|
|
|
if (timerIdTabAutoAdvance.current) {
|
|
|
|
|
clearTimerTabAutoAdvance();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 10초 후 tabIndex를 2로 변경
|
|
|
|
|
resetTimerTabAutoAdvance(10000);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
if (timerIdTabAutoAdvance.current) {
|
|
|
|
|
clearTimerTabAutoAdvance();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}, [tabIndexV2, belowContentsVisible, videoVerticalVisible, resetTimerTabAutoAdvance, clearTimerTabAutoAdvance]);
|
|
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
const videoContainer = document.querySelector(`.${css.videoContainer}`);
|
|
|
|
|
|
|
|
|
|
@@ -2383,7 +2466,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|
|
|
|
tabIndex={tabIndexV2}
|
|
|
|
|
onShopNowButtonClick={() => setTabIndexV2(0)}
|
|
|
|
|
onLiveChannelButtonClick={() => setTabIndexV2(2)}
|
|
|
|
|
onLiveNext={handleIndicatorDownClick}
|
|
|
|
|
onLiveNext={() => setTabIndexV2(1)}
|
|
|
|
|
onTabClose={(newTabIndex) => setTabIndexV2(newTabIndex)}
|
|
|
|
|
tabVisible={belowContentsVisible}
|
|
|
|
|
/>
|
|
|
|
|
|