[251124] fix: PlayerPanel videoState updated
🕐 커밋 시간: 2025. 11. 24. 10:45:28 📊 변경 통계: • 총 파일: 9개 • 추가: +509줄 • 삭제: -66줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/actions/mainActions.js ~ com.twin.app.shoptime/src/actions/playActions.js ~ com.twin.app.shoptime/src/api/TAxios.js ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.js ~ com.twin.app.shoptime/src/reducers/playReducer.js ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/actions/mainActions.js (javascript): ❌ Deleted: onSuccess(), onFail() 📄 com.twin.app.shoptime/src/actions/playActions.js (javascript): 🔄 Modified: clearAllVideoTimers(), pauseModalVideo(), hideModalVideo() ❌ Deleted: CLEAR_PLAYER_INFO() 📄 com.twin.app.shoptime/src/api/TAxios.js (javascript): 🔄 Modified: setTokenRefreshing(), createSafeApiThunk() 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx (javascript): 🔄 Modified: SpotlightContainerDecorator() 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx (javascript): 🔄 Modified: createPanelInfo() 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선 • API 서비스 레이어 개선 • UI 컴포넌트 아키텍처 개선
This commit is contained in:
@@ -39,6 +39,7 @@ import {
|
||||
pauseModalVideo,
|
||||
resumeModalVideo,
|
||||
resumeFullscreenVideo,
|
||||
updateVideoPlayState,
|
||||
} from '../../actions/playActions';
|
||||
import { resetPlayerOverlays } from '../../actions/videoPlayActions';
|
||||
import { convertUtcToLocal } from '../../components/MediaPlayer/util';
|
||||
@@ -436,17 +437,153 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
||||
}
|
||||
}, [isOnTop, panelInfo]);
|
||||
|
||||
// 새로운 useEffect 추가 (라인 328 이후)
|
||||
// 이전 상태 저장을 위한 ref
|
||||
const previousVideoPlayState = useRef(null);
|
||||
const previousPanelInfo = useRef(null);
|
||||
const previousVideoSource = useRef(null);
|
||||
const previousIsOnTop = useRef(null);
|
||||
|
||||
// Redux 상태 변화 모니터링 useEffect (중요 변화만)
|
||||
useEffect(() => {
|
||||
// modal 여부와 관계없이 videoPlayer가 있고 isPaused 값이 명시적일 때 제어
|
||||
if (videoPlayer.current && panelInfo?.isPaused !== undefined) {
|
||||
if (panelInfo.isPaused === true) {
|
||||
videoPlayer.current.pause();
|
||||
} else if (panelInfo.isPaused === false) {
|
||||
videoPlayer.current.play();
|
||||
// HomePanel이 최상위이고 videoPlayState가 실제로 변경되었을 때만 로그
|
||||
const isOnTop = panel_names.HOME_PANEL === topPanel?.name;
|
||||
const hasSignificantChange =
|
||||
previousVideoPlayState.current?.isPlaying !== videoPlayState?.isPlaying ||
|
||||
previousVideoPlayState.current?.isPaused !== videoPlayState?.isPaused ||
|
||||
Math.abs(
|
||||
(previousVideoPlayState.current?.currentTime || 0) - (videoPlayState?.currentTime || 0)
|
||||
) > 1;
|
||||
|
||||
// 🔍 DetailPanel으로 인한 일시정지 상태 변화도 모니터링
|
||||
const isDetailPanelOnTop = panel_names.DETAIL_PANEL === topPanel?.name;
|
||||
const isPlayingChanged =
|
||||
previousVideoPlayState.current?.isPlaying !== videoPlayState?.isPlaying;
|
||||
const isPausedChanged = previousVideoPlayState.current?.isPaused !== videoPlayState?.isPaused;
|
||||
|
||||
if (
|
||||
(isOnTop && videoPlayState && hasSignificantChange) ||
|
||||
(isDetailPanelOnTop && (isPlayingChanged || isPausedChanged))
|
||||
) {
|
||||
console.log('📊 [PlayerPanel] Significant videoPlayState change', {
|
||||
previousState: previousVideoPlayState.current,
|
||||
currentState: videoPlayState,
|
||||
topPanelName: topPanel?.name,
|
||||
isOnTop,
|
||||
isDetailPanelOnTop,
|
||||
videoPlayerExists: !!videoPlayer.current,
|
||||
currentPlayingUrl,
|
||||
changeReason: isDetailPanelOnTop ? 'DetailPanel transition' : 'HomePanel state change',
|
||||
// 🔍 Redux paused 상태 특별 확인
|
||||
reduxIsPaused: videoPlayState?.isPaused,
|
||||
reduxIsPlaying: videoPlayState?.isPlaying,
|
||||
panelInfoIsPaused: panelInfo?.isPaused,
|
||||
timestamp: new Date().toISOString(),
|
||||
source: 'useEffect videoPlayState',
|
||||
});
|
||||
}
|
||||
|
||||
previousVideoPlayState.current = videoPlayState;
|
||||
}, [videoPlayState, topPanel?.name, panelInfo?.isPaused]);
|
||||
|
||||
// PanelInfo 상태 변화 모니터링 useEffect (isPaused가 실제로 변경될 때만)
|
||||
useEffect(() => {
|
||||
const isOnTop = panel_names.HOME_PANEL === topPanel?.name;
|
||||
const isPausedChanged = previousPanelInfo.current?.isPaused !== panelInfo?.isPaused;
|
||||
|
||||
if (isOnTop && panelInfo?.isPaused !== undefined && isPausedChanged) {
|
||||
// 상태 변경 시에만 디버깅 로그 출력
|
||||
console.log('🔍 [PlayerPanel] PanelInfo isPaused changed', {
|
||||
previousIsPaused: previousPanelInfo.current?.isPaused,
|
||||
currentIsPaused: panelInfo.isPaused,
|
||||
isOnTop,
|
||||
videoPlayerExists: !!videoPlayer.current,
|
||||
currentPlayingUrl,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
console.log('🎮 [PlayerPanel] PanelInfo isPaused changed', {
|
||||
previousIsPaused: previousPanelInfo.current?.isPaused,
|
||||
currentIsPaused: panelInfo.isPaused,
|
||||
videoPlayerExists: !!videoPlayer.current,
|
||||
currentPlayingUrl,
|
||||
shptmBanrTpNm: panelInfo?.shptmBanrTpNm,
|
||||
showId: panelInfo?.showId,
|
||||
timestamp: new Date().toISOString(),
|
||||
source: 'useEffect panelInfo.isPaused',
|
||||
});
|
||||
|
||||
if (videoPlayer.current) {
|
||||
if (panelInfo.isPaused === true) {
|
||||
console.log('🔴 [PlayerPanel] Calling VideoPlayer.pause() due to PanelInfo change');
|
||||
videoPlayer.current.pause();
|
||||
} else if (panelInfo.isPaused === false) {
|
||||
console.log('🟢 [PlayerPanel] Calling VideoPlayer.play() due to PanelInfo change');
|
||||
videoPlayer.current.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [panelInfo?.isPaused]);
|
||||
|
||||
previousPanelInfo.current = panelInfo;
|
||||
}, [panelInfo?.isPaused, topPanel?.name, currentPlayingUrl]);
|
||||
|
||||
// VideoPlayer 인스턴스 및 소스 변경 모니터링 (중요 변화만)
|
||||
useEffect(() => {
|
||||
const isOnTop = panel_names.HOME_PANEL === topPanel?.name;
|
||||
const isDetailPanelOnTop = panel_names.DETAIL_PANEL === topPanel?.name;
|
||||
const isVideoSourceChanged = previousVideoSource.current !== currentPlayingUrl;
|
||||
const isOnTopChanged = previousIsOnTop.current !== isOnTop;
|
||||
const isDetailPanelOnTopChanged =
|
||||
previousIsOnTop.current === false && isDetailPanelOnTop === true;
|
||||
const videoPlayerJustCreated = previousVideoSource.current === null && videoPlayer.current;
|
||||
|
||||
if (
|
||||
(isVideoSourceChanged ||
|
||||
isOnTopChanged ||
|
||||
isDetailPanelOnTopChanged ||
|
||||
videoPlayerJustCreated) &&
|
||||
videoPlayer.current
|
||||
) {
|
||||
const changeReason = isDetailPanelOnTopChanged
|
||||
? 'DetailPanel opened'
|
||||
: isVideoSourceChanged
|
||||
? 'Video source changed'
|
||||
: isOnTopChanged
|
||||
? 'Top panel changed'
|
||||
: 'VideoPlayer created';
|
||||
|
||||
console.log('🎬 [PlayerPanel] VideoPlayer state change', {
|
||||
hasVideoPlayer: !!videoPlayer.current,
|
||||
currentPlayingUrl,
|
||||
previousVideoSource: previousVideoSource.current,
|
||||
topPanelName: topPanel?.name,
|
||||
isOnTop,
|
||||
isDetailPanelOnTop,
|
||||
isVideoSourceChanged,
|
||||
isOnTopChanged,
|
||||
isDetailPanelOnTopChanged,
|
||||
videoPlayerJustCreated,
|
||||
changeReason,
|
||||
timestamp: new Date().toISOString(),
|
||||
source: 'useEffect videoPlayer.current',
|
||||
});
|
||||
|
||||
// VideoPlayer 상태 확인 (소스 변경이나 PlayerPanel 생성 시에만)
|
||||
if (isVideoSourceChanged || videoPlayerJustCreated || isDetailPanelOnTopChanged) {
|
||||
const mediaState = videoPlayer.current.getMediaState?.();
|
||||
if (mediaState) {
|
||||
console.log('📊 [PlayerPanel] VideoPlayer current state', {
|
||||
mediaState,
|
||||
videoPlayState,
|
||||
changeReason,
|
||||
timestamp: new Date().toISOString(),
|
||||
source: 'useEffect getMediaState',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousVideoSource.current = currentPlayingUrl;
|
||||
previousIsOnTop.current = isOnTop || isDetailPanelOnTop; // 현재 최상위 패널 상태 저장
|
||||
}, [videoPlayer.current, currentPlayingUrl, topPanel?.name]);
|
||||
|
||||
// Modal 상태 변화 감지 (true → false, false → true)
|
||||
useEffect(() => {
|
||||
@@ -1130,11 +1267,63 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
||||
|
||||
// 최상단 패널이 DetailPanel이고 PlayerPanel에서 진입했는지 확인
|
||||
const isTopPanelDetailFromPlayer = useMemo(() => {
|
||||
return (
|
||||
const result =
|
||||
topPanel?.name === panel_names.DETAIL_PANEL &&
|
||||
topPanel?.panelInfo?.launchedFromPlayer === true
|
||||
);
|
||||
}, [topPanel]);
|
||||
topPanel?.panelInfo?.launchedFromPlayer === true;
|
||||
|
||||
// 🔍 DetailPanel 상태 변화 로깅
|
||||
if (result) {
|
||||
console.log('🎬 [PlayerPanel] DetailPanel is now on top (from Player)', {
|
||||
topPanelName: topPanel?.name,
|
||||
launchedFromPlayer: topPanel?.panelInfo?.launchedFromPlayer,
|
||||
modalPlayerPanelExists: panels.some(
|
||||
(p) => p.name === panel_names.PLAYER_PANEL && p.panelInfo?.modal
|
||||
),
|
||||
currentVideoState: {
|
||||
isPlaying: videoPlayState?.isPlaying,
|
||||
isPaused: videoPlayState?.isPaused,
|
||||
currentTime: videoPlayState?.currentTime,
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [topPanel, panels, videoPlayState]);
|
||||
|
||||
// 🔍 PlayerPanel이 밑에 깔렸을 때 자신의 상태를 업데이트하는 useEffect
|
||||
useEffect(() => {
|
||||
const isDetailPanelOnTop = topPanel?.name === panel_names.DETAIL_PANEL;
|
||||
const isModalPlayerPanel = panelInfo?.modal === true;
|
||||
const isCurrentPanelOnTop = topPanel?.name === panel_names.PLAYER_PANEL;
|
||||
|
||||
// PlayerPanel이 modal이고 밑에 깔렸을 때
|
||||
if (isModalPlayerPanel && !isCurrentPanelOnTop && isDetailPanelOnTop) {
|
||||
console.log('🔴 [PlayerPanel] Self-pausing due to DetailPanel on top', {
|
||||
isDetailPanelOnTop,
|
||||
isModalPlayerPanel,
|
||||
isCurrentPanelOnTop,
|
||||
currentReduxState: videoPlayState,
|
||||
needsPause: videoPlayState?.isPlaying === true || videoPlayState?.isPaused === false,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// PlayerPanel 자신의 상태를 일시정지로 업데이트
|
||||
if (videoPlayState?.isPlaying === true || videoPlayState?.isPaused === false) {
|
||||
console.log('🔄 [PlayerPanel] Dispatching self-pause to Redux');
|
||||
dispatch(
|
||||
updateVideoPlayState({
|
||||
isPlaying: false,
|
||||
isPaused: true,
|
||||
currentTime: videoPlayState?.currentTime || 0,
|
||||
duration: videoPlayState?.duration || 0,
|
||||
playbackRate: videoPlayState?.playbackRate || 1,
|
||||
source: 'PlayerPanel-self-pause',
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [topPanel?.name, panelInfo?.modal, videoPlayState, dispatch]);
|
||||
|
||||
const cannotPlay = useMemo(() => {
|
||||
return !isOnTop && topPanel?.name === panel_names.PLAYER_PANEL;
|
||||
@@ -2624,6 +2813,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
||||
tabContainerVersion={tabContainerVersion}
|
||||
tabIndexV2={tabIndexV2}
|
||||
dispatch={dispatch}
|
||||
videoPlayState={videoPlayState}
|
||||
>
|
||||
{typeof window === 'object' && window.PalmSystem && (
|
||||
<source src={currentPlayingUrl} type={videoType} />
|
||||
|
||||
Reference in New Issue
Block a user