[251116] feat: videoPlayIntentRef
🕐 커밋 시간: 2025. 11. 16. 19:59:28 📊 변경 통계: • 총 파일: 4개 • 추가: +149줄 • 삭제: -16줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/actions/playActions.js ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx (javascript): 🔄 Modified: Spottable() 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx (javascript): ✅ Added: SpotlightContainerDecorator() 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선
This commit is contained in:
@@ -161,11 +161,12 @@ export const startVideoPlayerNew =
|
||||
panelWorkingAction = updatePanel;
|
||||
}
|
||||
|
||||
// playerState 업데이트: 기존 playerState와 새 데이터 병합
|
||||
// 중복 실행 방지: 현재 PlayerPanel이 같은 배너를 재생 중이면 skip
|
||||
const currentPlayerState = topPanel?.panelInfo?.playerState || {};
|
||||
|
||||
// ✅ 정확한 비교: 같은 배너 + 같은 modal 상태 + 같은 위치일 때만 skip
|
||||
if (shouldSkipVideoPlayback(topPanel?.panelInfo, modal, modalContainerId, bannerId)) {
|
||||
if (currentPlayerState?.currentBannerId === bannerId) {
|
||||
console.log('[playActions] startVideoPlayerNew: 동일 배너 재생 중이라 중복 실행 SKIP', {
|
||||
bannerId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,13 @@ const SpottableComponent = Spottable('div');
|
||||
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||
const ContainerBasic = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
|
||||
|
||||
export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, handleShelfFocus }) {
|
||||
export default function HomeBanner({
|
||||
firstSpot,
|
||||
spotlightId,
|
||||
handleItemFocus,
|
||||
handleShelfFocus,
|
||||
videoPlayIntentRef,
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(justForYou());
|
||||
@@ -453,6 +459,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
handleItemFocus={_handleItemFocus}
|
||||
randomNumber={data.randomIndex}
|
||||
videoPlayerable={videoPlayerable}
|
||||
videoPlayIntentRef={videoPlayIntentRef}
|
||||
/>
|
||||
) : (
|
||||
<SpottableComponent spotlightId={'banner' + index}>
|
||||
@@ -472,7 +479,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[_handleItemFocus, _handleShelfFocus, bannerDataList]
|
||||
[_handleItemFocus, _handleShelfFocus, bannerDataList, videoPlayIntentRef]
|
||||
);
|
||||
|
||||
// 0번째 배너(영구 재생)를 위한 렌더링 함수
|
||||
|
||||
@@ -50,6 +50,7 @@ export default function RandomUnit({
|
||||
handleItemFocus,
|
||||
randomNumber,
|
||||
videoPlayerable = false,
|
||||
videoPlayIntentRef,
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -83,13 +84,16 @@ export default function RandomUnit({
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [videoError, setVideoError] = useState(false);
|
||||
const [liveIndicies, setLiveIndicies] = useState([]);
|
||||
const [videoIntentVersion, setVideoIntentVersion] = useState(0);
|
||||
const defaultFocus = useSelector((state) => state.home.defaultFocus);
|
||||
const isVideoTransitionLocked = useSelector((state) => state.home.videoTransitionLocked);
|
||||
|
||||
const timerRef = useRef();
|
||||
const hasAutoPlayStartedRef = useRef(false);
|
||||
const hasPlaybackStartedRef = useRef(false);
|
||||
const videoIntentTimerRef = useRef(null);
|
||||
const isDefaultAutoPlayTarget = defaultFocus === spotlightId;
|
||||
const lastProcessedIntentVersionRef = useRef(-1);
|
||||
const bannerDataRef = useRef(bannerData);
|
||||
const randomDataRef = useRef(
|
||||
bannerDetailInfos && randomNumber !== undefined && bannerDetailInfos.length > 0
|
||||
@@ -273,19 +277,45 @@ export default function RandomUnit({
|
||||
lastUpdate: videoPlayState.lastUpdate,
|
||||
});
|
||||
|
||||
console.log('[RandomUnit] onFocus called', {
|
||||
spotlightId,
|
||||
console.log('[RandomUnit] onFocus - 비디오 재생 의도 저장', {
|
||||
bannerId: spotlightId,
|
||||
videoPlayerable,
|
||||
currentIntent: videoPlayIntentRef.current?.bannerId,
|
||||
currentVideoBannerId,
|
||||
randomData: randomData?.showId || 'no-show-id',
|
||||
});
|
||||
|
||||
setIsFocused(true);
|
||||
|
||||
// video가 플레이 가능한 경우: 다른 배너에서 비디오 재생 중이면 종료
|
||||
if (videoPlayerable && currentVideoBannerId && currentVideoBannerId !== spotlightId) {
|
||||
console.log('[RandomUnit] videoPlayerable=true and different banner, finishing video');
|
||||
dispatch(finishVideoPreview());
|
||||
// 🔽 [251116] 수정: 재생 의도만 저장, 즉시 실행 ❌
|
||||
if (videoPlayerable) {
|
||||
videoPlayIntentRef.current = {
|
||||
bannerId: spotlightId,
|
||||
videoProps: {
|
||||
bannerId: spotlightId,
|
||||
showUrl: randomData.showUrl,
|
||||
patnrId: randomData.patnrId,
|
||||
showId: randomData.showId,
|
||||
shptmBanrTpNm: randomData.shptmBanrTpNm,
|
||||
lgCatCd: randomData.lgCatCd,
|
||||
chanId: randomData.brdcChnlId,
|
||||
modal: true,
|
||||
modalContainerId: spotlightId,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
|
||||
console.log('[RandomUnit] 비디오 재생 의도 저장됨', {
|
||||
intentBannerId: spotlightId,
|
||||
videoUrl: randomData.showUrl,
|
||||
});
|
||||
|
||||
setVideoIntentVersion((version) => version + 1);
|
||||
|
||||
// 기존 finishVideoPreview 호출 제거!
|
||||
// if (videoPlayerable && currentVideoBannerId && currentVideoBannerId !== spotlightId) {
|
||||
// dispatch(finishVideoPreview());
|
||||
// }
|
||||
}
|
||||
|
||||
// video가 플레이 불가능한 경우: 재생 중인 비디오를 1px로 축소
|
||||
@@ -618,6 +648,15 @@ export default function RandomUnit({
|
||||
}
|
||||
}, [randomData]);
|
||||
|
||||
// 🔽 [251116] 기존 로직 단순화 - videoPlayIntentRef가 모든 비디오 제어를 담당
|
||||
useEffect(() => {
|
||||
if (!isFocused) {
|
||||
setVideoError(false);
|
||||
}
|
||||
}, [isFocused]);
|
||||
|
||||
// 🔽 [251116] 기존 복잡한 비디오 시작 로직 비활성화
|
||||
/*
|
||||
useEffect(() => {
|
||||
if (isFocused && !videoError && !hasPlaybackStartedRef.current) {
|
||||
if (timerRef.current) {
|
||||
@@ -665,6 +704,89 @@ export default function RandomUnit({
|
||||
spotlightId,
|
||||
handleStartVideo,
|
||||
]);
|
||||
*/
|
||||
|
||||
// 🔽 [251116] 신규: videoPlayIntentRef 기반 비디오 제어
|
||||
useEffect(() => {
|
||||
if (!videoPlayIntentRef.current) {
|
||||
return undefined;
|
||||
}
|
||||
if (lastProcessedIntentVersionRef.current === videoIntentVersion) {
|
||||
return undefined;
|
||||
}
|
||||
lastProcessedIntentVersionRef.current = videoIntentVersion;
|
||||
|
||||
const intent = videoPlayIntentRef.current;
|
||||
const currentVideoId = videoPlayState.videoId;
|
||||
const activeBannerId = currentVideoBannerId;
|
||||
|
||||
console.log('[RandomUnit] videoPlayIntent useEffect', {
|
||||
intentBannerId: intent.bannerId,
|
||||
currentVideoId,
|
||||
activeBannerId,
|
||||
currentPlayback: videoPlayState.playback,
|
||||
currentDisplay: videoPlayState.display,
|
||||
loadingProgress: videoPlayState.loadingProgress,
|
||||
shouldStart: intent.bannerId !== activeBannerId,
|
||||
isVideoTransitionLocked,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
if (intent.bannerId === activeBannerId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (videoIntentTimerRef.current) {
|
||||
clearTimeout(videoIntentTimerRef.current);
|
||||
}
|
||||
|
||||
videoIntentTimerRef.current = setTimeout(() => {
|
||||
if (videoPlayIntentRef.current?.bannerId !== intent.bannerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[RandomUnit] 비디오 변경 실행', {
|
||||
from: currentVideoId,
|
||||
to: intent.bannerId,
|
||||
});
|
||||
|
||||
if (activeBannerId) {
|
||||
dispatch(finishVideoPreview());
|
||||
|
||||
setTimeout(() => {
|
||||
dispatch(setVideoTransitionLock(true));
|
||||
dispatch(startVideoPlayerNew(intent.videoProps));
|
||||
hasPlaybackStartedRef.current = true;
|
||||
|
||||
setTimeout(() => {
|
||||
dispatch(setVideoTransitionLock(false));
|
||||
}, 2000);
|
||||
}, 100);
|
||||
} else {
|
||||
dispatch(setVideoTransitionLock(true));
|
||||
dispatch(startVideoPlayerNew(intent.videoProps));
|
||||
hasPlaybackStartedRef.current = true;
|
||||
|
||||
setTimeout(() => {
|
||||
dispatch(setVideoTransitionLock(false));
|
||||
}, 2000);
|
||||
}
|
||||
}, 300); // 안정화 시간
|
||||
|
||||
return () => {
|
||||
if (videoIntentTimerRef.current) {
|
||||
clearTimeout(videoIntentTimerRef.current);
|
||||
videoIntentTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
videoPlayState.videoId,
|
||||
dispatch,
|
||||
videoPlayIntentRef,
|
||||
videoIntentVersion,
|
||||
isVideoTransitionLocked,
|
||||
currentVideoBannerId,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isFocused && broadcast?.type === 'videoError') {
|
||||
|
||||
@@ -89,6 +89,8 @@ const HomePanel = ({ isOnTop }) => {
|
||||
enableLogging: true,
|
||||
logPrefix: '[HomePanel-VideoPlay]',
|
||||
});
|
||||
// 🔽 비디오 재생 의도 공유 ref
|
||||
const videoPlayIntentRef = useRef(null);
|
||||
|
||||
// 🔽 useVideoMove - 포커스 전환 기반 동영상 제어
|
||||
// [COMMENTED OUT] useVideoMove 미사용 - cleanup() 호출되지 않음
|
||||
@@ -314,6 +316,7 @@ const HomePanel = ({ isOnTop }) => {
|
||||
el.shptmApphmDspyOptNm
|
||||
)}
|
||||
handleItemFocus={handleItemFocus(el.shptmApphmDspyOptCd)}
|
||||
videoPlayIntentRef={videoPlayIntentRef}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user