[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:
2025-11-24 10:45:28 +09:00
parent e2a50b62ab
commit d2c149c914
9 changed files with 700 additions and 259 deletions

View File

@@ -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} />