fix: DetailPanel above PlayerPanel , FeaturedBrandsPanel-2
This commit is contained in:
@@ -299,19 +299,28 @@ export const navigateToDetail = ({
|
|||||||
// PlayerPanel에서 온 경우
|
// PlayerPanel에서 온 경우
|
||||||
const { hidePlayerOverlays } = require('./videoPlayActions');
|
const { hidePlayerOverlays } = require('./videoPlayActions');
|
||||||
const statePanels = panels || getState().panels.panels;
|
const statePanels = panels || getState().panels.panels;
|
||||||
const playerPanelEntry = statePanels.find((p) => p.name === panel_names.PLAYER_PANEL);
|
const playerPanelEntry =
|
||||||
|
[...statePanels].reverse().find(
|
||||||
|
(p) => p.name === panel_names.PLAYER_PANEL || p.name === panel_names.PLAYER_PANEL_NEW
|
||||||
|
) || null;
|
||||||
|
|
||||||
// DetailPanel push 전에 VideoPlayer 오버레이 숨김
|
// DetailPanel push 전에 VideoPlayer 오버레이 숨김
|
||||||
dispatch(hidePlayerOverlays());
|
dispatch(hidePlayerOverlays());
|
||||||
|
|
||||||
// PlayerPanel이 modal=true라면 풀스크린 백그라운드로 전환
|
// PlayerPanel이 modal=true라면 풀스크린 백그라운드로 전환 + lockModalFalse 설정 (Detail 동안 modal 복귀 방지)
|
||||||
if (playerPanelEntry?.panelInfo?.modal) {
|
if (playerPanelEntry) {
|
||||||
dispatch(
|
dispatch(
|
||||||
updatePanel({
|
updatePanel({
|
||||||
name: panel_names.PLAYER_PANEL,
|
name: playerPanelEntry.name,
|
||||||
panelInfo: {
|
panelInfo: {
|
||||||
...playerPanelEntry.panelInfo,
|
...playerPanelEntry.panelInfo,
|
||||||
modal: false,
|
modal: false,
|
||||||
|
modalContainerId: undefined,
|
||||||
|
modalStyle: undefined,
|
||||||
|
modalScale: undefined,
|
||||||
|
shouldShrinkTo1px: false,
|
||||||
|
isHidden: false,
|
||||||
|
lockModalFalse: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -73,6 +73,16 @@ export const startVideoPlayer =
|
|||||||
...rest
|
...rest
|
||||||
}) =>
|
}) =>
|
||||||
(dispatch, getState) => {
|
(dispatch, getState) => {
|
||||||
|
const caller = new Error().stack?.split('\n')[2]?.trim();
|
||||||
|
console.log('[PTRACE-SP] startVideoPlayer call', {
|
||||||
|
modal,
|
||||||
|
modalContainerId,
|
||||||
|
modalClassName,
|
||||||
|
videoId,
|
||||||
|
showUrl,
|
||||||
|
caller,
|
||||||
|
});
|
||||||
|
|
||||||
dlog(
|
dlog(
|
||||||
'[startVideoPlayer] ✅ START - videoId:',
|
'[startVideoPlayer] ✅ START - videoId:',
|
||||||
videoId,
|
videoId,
|
||||||
@@ -105,6 +115,9 @@ export const startVideoPlayer =
|
|||||||
|
|
||||||
// 기존 PlayerPanel이 어디든 있으면 완전히 초기화: 타이머 정리 후 pop → 새로 push
|
// 기존 PlayerPanel이 어디든 있으면 완전히 초기화: 타이머 정리 후 pop → 새로 push
|
||||||
if (existingPlayerPanel) {
|
if (existingPlayerPanel) {
|
||||||
|
console.log('[PTRACE-SP] startVideoPlayer: popping existing player before push', {
|
||||||
|
stack: panels.map((p) => p.name),
|
||||||
|
});
|
||||||
dlog('[startVideoPlayer] 🔄 Resetting existing PLAYER_PANEL before start');
|
dlog('[startVideoPlayer] 🔄 Resetting existing PLAYER_PANEL before start');
|
||||||
clearAllVideoTimers();
|
clearAllVideoTimers();
|
||||||
dispatch(popPanel(panel_names.PLAYER_PANEL));
|
dispatch(popPanel(panel_names.PLAYER_PANEL));
|
||||||
@@ -182,6 +195,17 @@ export const startVideoPlayerNew =
|
|||||||
...rest
|
...rest
|
||||||
}) =>
|
}) =>
|
||||||
(dispatch, getState) => {
|
(dispatch, getState) => {
|
||||||
|
const caller = new Error().stack?.split('\n')[2]?.trim();
|
||||||
|
console.log('[PTRACE-SPN] startVideoPlayerNew call', {
|
||||||
|
bannerId,
|
||||||
|
modal,
|
||||||
|
modalContainerId,
|
||||||
|
modalClassName,
|
||||||
|
videoId,
|
||||||
|
showUrl,
|
||||||
|
caller,
|
||||||
|
});
|
||||||
|
|
||||||
dlog(
|
dlog(
|
||||||
'[startVideoPlayerNew] *** ✅ START - bannerId:',
|
'[startVideoPlayerNew] *** ✅ START - bannerId:',
|
||||||
bannerId,
|
bannerId,
|
||||||
@@ -215,6 +239,9 @@ export const startVideoPlayerNew =
|
|||||||
|
|
||||||
// 기존 PlayerPanel이 있으면 완전히 초기화: 타이머 정리 후 pop → 새로 push
|
// 기존 PlayerPanel이 있으면 완전히 초기화: 타이머 정리 후 pop → 새로 push
|
||||||
if (existingPlayerPanel) {
|
if (existingPlayerPanel) {
|
||||||
|
console.log('[PTRACE-SPN] popping existing player before push', {
|
||||||
|
stack: panels.map((p) => p.name),
|
||||||
|
});
|
||||||
dlog('[startVideoPlayerNew] *** 🔄 Resetting existing PLAYER_PANEL before start');
|
dlog('[startVideoPlayerNew] *** 🔄 Resetting existing PLAYER_PANEL before start');
|
||||||
clearAllVideoTimers();
|
clearAllVideoTimers();
|
||||||
dispatch(popPanel(panel_names.PLAYER_PANEL));
|
dispatch(popPanel(panel_names.PLAYER_PANEL));
|
||||||
|
|||||||
@@ -132,6 +132,60 @@ export const panelsReducer = (state = initialState, action) => {
|
|||||||
case types.UPDATE_PANEL: {
|
case types.UPDATE_PANEL: {
|
||||||
let lastIndex = -1;
|
let lastIndex = -1;
|
||||||
let lastAction = 'update';
|
let lastAction = 'update';
|
||||||
|
const hasDetailPanel = state.panels.some((p) => p.name === panel_names.DETAIL_PANEL);
|
||||||
|
const isPlayerPanel =
|
||||||
|
action.payload.name === panel_names.PLAYER_PANEL ||
|
||||||
|
action.payload.name === panel_names.PLAYER_PANEL_NEW;
|
||||||
|
const existingPanel = state.panels.find((p) => p.name === action.payload.name);
|
||||||
|
let nextPanelInfo = action.payload.panelInfo || {};
|
||||||
|
|
||||||
|
// lockModalFalse 플래그 처리: DetailPanel이 스택에 있거나 lock이 이미 true면 modal=true 업데이트를 차단
|
||||||
|
if (isPlayerPanel && existingPanel) {
|
||||||
|
const lockFlag =
|
||||||
|
existingPanel.panelInfo?.lockModalFalse === true || nextPanelInfo.lockModalFalse === true;
|
||||||
|
|
||||||
|
// unlock 명시 시 그대로 진행
|
||||||
|
if (nextPanelInfo.lockModalFalse === false) {
|
||||||
|
// do nothing
|
||||||
|
} else if (lockFlag && nextPanelInfo.modal === true) {
|
||||||
|
nextPanelInfo = {
|
||||||
|
...nextPanelInfo,
|
||||||
|
modal: false,
|
||||||
|
modalContainerId: undefined,
|
||||||
|
lockModalFalse: true,
|
||||||
|
modalStyle: undefined,
|
||||||
|
modalScale: undefined,
|
||||||
|
shouldShrinkTo1px: false,
|
||||||
|
isHidden: false,
|
||||||
|
};
|
||||||
|
} else if (lockFlag && nextPanelInfo.modal === undefined && hasDetailPanel) {
|
||||||
|
nextPanelInfo = {
|
||||||
|
...nextPanelInfo,
|
||||||
|
modal:
|
||||||
|
existingPanel.panelInfo?.modal === true ? false : existingPanel.panelInfo?.modal,
|
||||||
|
modalContainerId:
|
||||||
|
existingPanel.panelInfo?.modal === true
|
||||||
|
? undefined
|
||||||
|
: existingPanel.panelInfo?.modalContainerId,
|
||||||
|
lockModalFalse: true,
|
||||||
|
modalStyle: existingPanel.panelInfo?.modal === true ? undefined : nextPanelInfo.modalStyle,
|
||||||
|
modalScale: existingPanel.panelInfo?.modal === true ? undefined : nextPanelInfo.modalScale,
|
||||||
|
shouldShrinkTo1px: false,
|
||||||
|
isHidden: false,
|
||||||
|
};
|
||||||
|
} else if (hasDetailPanel && nextPanelInfo.modal === true) {
|
||||||
|
// DetailPanel 존재 시 modal=true 업데이트 차단
|
||||||
|
nextPanelInfo = {
|
||||||
|
...nextPanelInfo,
|
||||||
|
modal: false,
|
||||||
|
modalContainerId: undefined,
|
||||||
|
modalStyle: undefined,
|
||||||
|
modalScale: undefined,
|
||||||
|
shouldShrinkTo1px: false,
|
||||||
|
isHidden: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
// 배열의 끝에서부터 시작하여 조건에 맞는 마지막 인덱스 찾기
|
// 배열의 끝에서부터 시작하여 조건에 맞는 마지막 인덱스 찾기
|
||||||
for (let i = state.panels.length - 1; i >= 0; i--) {
|
for (let i = state.panels.length - 1; i >= 0; i--) {
|
||||||
if (state.panels[i].name === action.payload.name) {
|
if (state.panels[i].name === action.payload.name) {
|
||||||
@@ -143,7 +197,7 @@ export const panelsReducer = (state = initialState, action) => {
|
|||||||
index === lastIndex
|
index === lastIndex
|
||||||
? {
|
? {
|
||||||
...panel,
|
...panel,
|
||||||
panelInfo: { ...panel.panelInfo, ...action.payload.panelInfo },
|
panelInfo: { ...panel.panelInfo, ...nextPanelInfo },
|
||||||
}
|
}
|
||||||
: panel
|
: panel
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
|
|||||||
detailPanelClosedAt: Date.now(), // ✅ 시점 기록
|
detailPanelClosedAt: Date.now(), // ✅ 시점 기록
|
||||||
detailPanelClosedFromSource: sourceMenu, // ✅ 출처
|
detailPanelClosedFromSource: sourceMenu, // ✅ 출처
|
||||||
lastFocusedTargetId: panelInfo?.lastFocusedTargetId, // ✅ 포커스 복원 타겟 전달
|
lastFocusedTargetId: panelInfo?.lastFocusedTargetId, // ✅ 포커스 복원 타겟 전달
|
||||||
|
lockModalFalse: false, // Detail 종료 시 lock 해제
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -1117,6 +1118,24 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
|
|||||||
dispatch(finishVideoPreview());
|
dispatch(finishVideoPreview());
|
||||||
} else if (hasPlayerPanel && launchedFromPlayer) {
|
} else if (hasPlayerPanel && launchedFromPlayer) {
|
||||||
console.log('[DetailPanel] PlayerPanel modal=true detected - launched from Player, skip finishVideoPreview');
|
console.log('[DetailPanel] PlayerPanel modal=true detected - launched from Player, skip finishVideoPreview');
|
||||||
|
|
||||||
|
// Detail 동안 modal=true로 바뀌지 않도록 lockModalFalse 설정
|
||||||
|
const playerPanelEntry = panels.find(
|
||||||
|
(p) => p.name === panel_names.PLAYER_PANEL || p.name === panel_names.PLAYER_PANEL_NEW
|
||||||
|
);
|
||||||
|
if (playerPanelEntry?.panelInfo?.modal === true) {
|
||||||
|
dispatch(
|
||||||
|
updatePanel({
|
||||||
|
name: playerPanelEntry.name,
|
||||||
|
panelInfo: {
|
||||||
|
...playerPanelEntry.panelInfo,
|
||||||
|
modal: false,
|
||||||
|
modalContainerId: undefined,
|
||||||
|
lockModalFalse: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [panels, dispatch, panelInfo?.fromPlayer, panelInfo?.sourcePanel]);
|
}, [panels, dispatch, panelInfo?.fromPlayer, panelInfo?.sourcePanel]);
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export default function HomeBanner({
|
|||||||
const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos);
|
const bannerDataList = useSelector((state) => state.home.bannerData?.bannerInfos);
|
||||||
|
|
||||||
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
|
const popupVisible = useSelector((state) => state.common.popup.popupVisible);
|
||||||
|
const panels = useSelector((state) => state.panels.panels);
|
||||||
// 🔽 useFocusHistory - 경량화된 범용 포커스 히스토리
|
// 🔽 useFocusHistory - 경량화된 범용 포커스 히스토리
|
||||||
const focusHistory = useFocusHistory({
|
const focusHistory = useFocusHistory({
|
||||||
enableLogging: true,
|
enableLogging: true,
|
||||||
@@ -163,7 +164,10 @@ export default function HomeBanner({
|
|||||||
videoData = targetBannerData.bannerDetailInfos?.[0];
|
videoData = targetBannerData.bannerDetailInfos?.[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoData && (videoData.shptmBanrTpNm === 'LIVE' || videoData.shptmBanrTpNm === 'VOD')) {
|
// DetailPanel이 떠 있는 동안에는 배너 자동 재생을 스킵 (PlayerPanel 모달 재설정 방지)
|
||||||
|
const hasDetailPanel = panels.some((p) => p.name === panel_names.DETAIL_PANEL);
|
||||||
|
|
||||||
|
if (!hasDetailPanel && videoData && (videoData.shptmBanrTpNm === 'LIVE' || videoData.shptmBanrTpNm === 'VOD')) {
|
||||||
console.log('[HomeBanner] 초기 비디오 자동 재생:', defaultFocus);
|
console.log('[HomeBanner] 초기 비디오 자동 재생:', defaultFocus);
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
@@ -175,12 +179,13 @@ export default function HomeBanner({
|
|||||||
shptmBanrTpNm: videoData.shptmBanrTpNm,
|
shptmBanrTpNm: videoData.shptmBanrTpNm,
|
||||||
lgCatCd: videoData.lgCatCd,
|
lgCatCd: videoData.lgCatCd,
|
||||||
chanId: videoData.brdcChnlId,
|
chanId: videoData.brdcChnlId,
|
||||||
|
// 기본: 배너는 modal=true로 재생
|
||||||
modal: true,
|
modal: true,
|
||||||
modalContainerId: defaultFocus,
|
modalContainerId: defaultFocus,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [bannerDataList, defaultFocus, dispatch]);
|
}, [bannerDataList, defaultFocus, dispatch, panels]);
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
(index, isHorizontal) => {
|
(index, isHorizontal) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user