[251122] fix: MediaPanel in VOD

🕐 커밋 시간: 2025. 11. 22. 05:46:17

📊 변경 통계:
  • 총 파일: 2개
  • 추가: +85줄
  • 삭제: -42줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.js
  ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx (javascript):
    🔄 Modified: normalizeModalStyle()

🔧 주요 변경 내용:
  • UI 컴포넌트 아키텍처 개선
This commit is contained in:
2025-11-22 05:46:17 +09:00
parent eaa0201469
commit 5278151102
2 changed files with 83 additions and 38 deletions

View File

@@ -561,7 +561,7 @@ const VideoPlayerBase = class extends React.Component {
/** /**
* Disables seek function. * Disables seek function.
* *
* Note that jump by arrow keys will also be disabled when `true`. * Note that jump by arrow keys will also be disabled when `true`.
* *
* @type {Boolean} * @type {Boolean}
* @public * @public
@@ -2314,6 +2314,10 @@ const VideoPlayerBase = class extends React.Component {
mediaProps.height = height; mediaProps.height = height;
mediaProps.videoRef = this.setVideoRef; mediaProps.videoRef = this.setVideoRef;
mediaProps.config = reactPlayerConfig; mediaProps.config = reactPlayerConfig;
// 웹/TV 전체화면에서 ReactPlayer(YouTube) iframe이 자체 컨트롤을 활성화하지 않도록 포인터 이벤트 차단
if (!panelInfo.modal) {
mediaProps.style = { ...(mediaProps.style || {}), pointerEvents: 'none' };
}
delete mediaProps.mediaComponent; delete mediaProps.mediaComponent;
delete mediaProps.ref; delete mediaProps.ref;
// mediaProps.isYoutube = isYoutube; // mediaProps.isYoutube = isYoutube;

View File

@@ -211,6 +211,7 @@ const MediaPanel = React.forwardRef(
}); });
const videoPlayer = useRef(null); const videoPlayer = useRef(null);
const focusReturnRef = useRef(null);
const isTransitioningToFullscreen = useRef(false); const isTransitioningToFullscreen = useRef(false);
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', ''); const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
const [shopNowInfo, setShopNowInfo] = USE_STATE('shopNowInfo'); const [shopNowInfo, setShopNowInfo] = USE_STATE('shopNowInfo');
@@ -2004,42 +2005,79 @@ const MediaPanel = React.forwardRef(
}; };
}, []); }, []);
const onEnded = useCallback((e) => { const focusBackToPanel = useCallback(() => {
if (panelInfoRef.current.shptmBanrTpNm === 'MEDIA') { if (focusReturnRef.current) {
// ⚠️ 배경 설정 복원 취소 - DetailPanel 업데이트 없이 바로 패널 제거 focusReturnRef.current.focus();
// dispatch( return true;
// updatePanel({ }
// name: panel_names.DETAIL_PANEL, return false;
// panelInfo: { }, []);
// launchedFromPlayer: true,
// isPlayerFinished: true, const focusBackButtonOrFallback = useCallback(() => {
// }, if (Spotlight.focus('player-back-button')) {
// }) return true;
// ); }
console.log('[MediaPanel] 🚫 Skipping background restoration for ended media'); return focusBackToPanel();
Spotlight.pause(); }, [focusBackToPanel]);
setTimeout(() => {
Spotlight.resume(); const stopExternalPlayer = useCallback(() => {
dispatch(PanelActions.popPanel()); const playerInstance = videoPlayer.current;
}, VIDEO_END_ACTION_DELAY); const media = playerInstance?.video;
if (!media) {
return; return;
} }
if (panelInfoRef.current.shptmBanrTpNm === 'VOD') {
Spotlight.pause(); if (typeof media.stopVideo === 'function') {
setTimeout(() => { media.stopVideo();
Spotlight.resume(); }
if (panelInfoRef.current.modal) { if (typeof media.seekTo === 'function') {
videoPlayer.current.play(); media.seekTo(0);
} else { }
dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL)); if (typeof media.pause === 'function') {
} media.pause();
}, VIDEO_END_ACTION_DELAY);
e?.stopPropagation();
e?.preventDefault();
return;
} }
}, []); }, []);
const onEnded = useCallback(
(e) => {
const currentInfo = panelInfoRef.current;
// MEDIA: 기존 동작 유지 (배경 복원 없이 즉시 pop)
if (currentInfo.shptmBanrTpNm === 'MEDIA') {
console.log('[MediaPanel] 🚫 Skipping background restoration for ended media');
Spotlight.pause();
setTimeout(() => {
Spotlight.resume();
dispatch(PanelActions.popPanel());
}, VIDEO_END_ACTION_DELAY);
return;
}
// VOD: modal 여부에 따라 동작 분리
if (currentInfo.shptmBanrTpNm === 'VOD') {
Spotlight.pause();
setTimeout(() => {
stopExternalPlayer();
if (currentInfo.modal) {
// 모달: 화면 유지 + Back 포커스 회수
videoPlayer.current?.showControls?.();
Spotlight.resume();
focusBackButtonOrFallback();
} else {
// 전체화면: 바로 종료(pop)하여 포커스가 VOD 컨트롤로 남지 않게 함
Spotlight.resume();
dispatch(PanelActions.popPanel(panel_names.MEDIA_PANEL));
}
}, VIDEO_END_ACTION_DELAY);
e?.stopPropagation();
e?.preventDefault();
return;
}
},
[dispatch, focusBackButtonOrFallback, stopExternalPlayer]
);
const onKeyDown = (ev) => { const onKeyDown = (ev) => {
if (ev.keyCode === 34) { if (ev.keyCode === 34) {
handleIndicatorDownClick(); handleIndicatorDownClick();
@@ -2263,14 +2301,17 @@ const MediaPanel = React.forwardRef(
> >
<Container <Container
spotlightRestrict={panelInfo?.modal ? 'self-only' : undefined} spotlightRestrict={panelInfo?.modal ? 'self-only' : undefined}
spotlightId="spotlightId-video-contaienr" spotlightId={
panelInfo?.modal ? 'spotlightId-video-contaienr' : 'fullscreen-video-container'
}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
// onClick={() => {
// if (!panelInfo?.modal && isOnTop && panelInfo?.shptmBanrTpNm !== 'MEDIA') {
// setBelowContentsVisible((prev) => !prev);
// }
// }}
> >
<div
ref={focusReturnRef}
tabIndex={-1}
aria-hidden="true"
style={{ width: 1, height: 1, opacity: 0, position: 'absolute' }}
/>
{(() => { {(() => {
if (isReadyToPlay) { if (isReadyToPlay) {
// console.log('[MediaPanel]-LoadingVideo 🎬 VideoPlayer 렌더링:', { // console.log('[MediaPanel]-LoadingVideo 🎬 VideoPlayer 렌더링:', {