[251122] fix: Youtube 비디오 반복재생
🕐 커밋 시간: 2025. 11. 22. 05:24:47 📊 변경 통계: • 총 파일: 2개 • 추가: +60줄 • 삭제: -4줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx 🔧 주요 변경 내용: • UI 컴포넌트 아키텍처 개선 • 소규모 기능 개선
This commit is contained in:
@@ -133,6 +133,14 @@ export default function TReactPlayer({
|
|||||||
}
|
}
|
||||||
handle.forward('onLoadStart', { type, ev }, rest);
|
handle.forward('onLoadStart', { type, ev }, rest);
|
||||||
}
|
}
|
||||||
|
if (type === 'onEnded' && rest?.isYoutube && rest?.type === 'VOD') {
|
||||||
|
// YouTube 재생 종료 시 iframe이 포커스를 가져가는 문제를 방지
|
||||||
|
const iframeEl =
|
||||||
|
typeof playerRef.current?.getInternalPlayer === 'function'
|
||||||
|
? playerRef.current.getInternalPlayer('iframe')
|
||||||
|
: null;
|
||||||
|
iframeEl?.blur();
|
||||||
|
}
|
||||||
handle.forward('onUpdate', { type, ev }, rest);
|
handle.forward('onUpdate', { type, ev }, rest);
|
||||||
},
|
},
|
||||||
[videoRef, playing, config] // ✅ 주요 의존성 추가
|
[videoRef, playing, config] // ✅ 주요 의존성 추가
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
});
|
});
|
||||||
|
|
||||||
const videoPlayer = useRef(null);
|
const videoPlayer = useRef(null);
|
||||||
|
const focusReturnRef = useRef(null);
|
||||||
const modalPrevRef = useRef(panelInfo?.modal);
|
const modalPrevRef = useRef(panelInfo?.modal);
|
||||||
const prevIsTopPanelDetailFromPlayerRef = useRef(false);
|
const prevIsTopPanelDetailFromPlayerRef = useRef(false);
|
||||||
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
|
const [playListInfo, setPlayListInfo] = USE_STATE('playListInfo', '');
|
||||||
@@ -1959,7 +1960,45 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onEnded = useCallback((e) => {
|
const focusBackToPanel = useCallback(() => {
|
||||||
|
// 포커스를 PlayerPanel 쪽으로 강제 이동해 YouTube iframe이 포커스를 가져가는 것을 차단
|
||||||
|
if (focusReturnRef.current) {
|
||||||
|
focusReturnRef.current.focus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const focusBackButtonOrFallback = useCallback(() => {
|
||||||
|
// 종료 시 Back 아이콘으로 포커스를 이동시키되 실패하면 센티넬로 폴백
|
||||||
|
if (Spotlight.focus('player-back-button')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return focusBackToPanel();
|
||||||
|
}, [focusBackToPanel]);
|
||||||
|
|
||||||
|
const stopExternalPlayer = useCallback(() => {
|
||||||
|
const playerInstance = videoPlayer.current;
|
||||||
|
const media = playerInstance?.video;
|
||||||
|
|
||||||
|
if (!media) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReactPlayer의 YouTube 인스턴스 대응: 종료 직후 리플레이 오버레이가 뜨지 않도록 정지/초기화 시도
|
||||||
|
if (typeof media.stopVideo === 'function') {
|
||||||
|
media.stopVideo();
|
||||||
|
}
|
||||||
|
if (typeof media.seekTo === 'function') {
|
||||||
|
media.seekTo(0);
|
||||||
|
}
|
||||||
|
if (typeof media.pause === 'function') {
|
||||||
|
media.pause();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onEnded = useCallback(
|
||||||
|
(e) => {
|
||||||
if (panelInfoRef.current.shptmBanrTpNm === 'MEDIA') {
|
if (panelInfoRef.current.shptmBanrTpNm === 'MEDIA') {
|
||||||
dispatch(
|
dispatch(
|
||||||
updatePanel({
|
updatePanel({
|
||||||
@@ -1980,18 +2019,24 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
if (panelInfoRef.current.shptmBanrTpNm === 'VOD') {
|
if (panelInfoRef.current.shptmBanrTpNm === 'VOD') {
|
||||||
Spotlight.pause();
|
Spotlight.pause();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Spotlight.resume();
|
stopExternalPlayer();
|
||||||
if (panelInfoRef.current.modal) {
|
if (panelInfoRef.current.modal) {
|
||||||
videoPlayer.current.play();
|
// 모달 모드에서는 종료 후 화면을 유지하고 Back 아이콘으로 포커스 이동
|
||||||
|
videoPlayer.current?.showControls?.();
|
||||||
} else {
|
} else {
|
||||||
dispatch(PanelActions.popPanel(panel_names.PLAYER_PANEL));
|
// 전체화면 모드에서도 종료 후 즉시 닫지 않고 제어권 회수
|
||||||
|
videoPlayer.current?.showControls?.();
|
||||||
}
|
}
|
||||||
|
Spotlight.resume();
|
||||||
|
focusBackButtonOrFallback();
|
||||||
}, VIDEO_END_ACTION_DELAY);
|
}, VIDEO_END_ACTION_DELAY);
|
||||||
e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
e?.preventDefault();
|
e?.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, []);
|
},
|
||||||
|
[dispatch, focusBackButtonOrFallback, stopExternalPlayer]
|
||||||
|
);
|
||||||
|
|
||||||
const onKeyDown = (ev) => {
|
const onKeyDown = (ev) => {
|
||||||
if (ev.keyCode === 34) {
|
if (ev.keyCode === 34) {
|
||||||
@@ -2512,6 +2557,12 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
// }
|
// }
|
||||||
// }}
|
// }}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
ref={focusReturnRef}
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{ width: 1, height: 1, opacity: 0, position: 'absolute' }}
|
||||||
|
/>
|
||||||
{isReadyToPlay && (
|
{isReadyToPlay && (
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
key={currentPlayingUrl}
|
key={currentPlayingUrl}
|
||||||
|
|||||||
Reference in New Issue
Block a user