fix: HomeBanner 동영상기능 원복

This commit is contained in:
djaco
2025-06-23 09:49:13 +09:00
parent 556a0e8456
commit 2f1cfc7baa
5 changed files with 2356 additions and 2199 deletions

View File

@@ -201,9 +201,13 @@ export const types = {
*
* SET_PLAYER_CONTROL: 특정 컴포넌트에게 비디오 재생 제어권을 부여합니다.
* CLEAR_PLAYER_CONTROL: 컴포넌트로부터 비디오 재생 제어권을 회수합니다.
* PAUSE_PLAYER_CONTROL: 현재 제어권을 가진 비디오를 '일시정지' 상태로 변경합니다.
* RESUME_PLAYER_CONTROL: '일시정지' 상태의 비디오를 다시 재생합니다.
*/
SET_PLAYER_CONTROL: "SET_PLAYER_CONTROL",
CLEAR_PLAYER_CONTROL: "CLEAR_PLAYER_CONTROL",
PAUSE_PLAYER_CONTROL: "PAUSE_PLAYER_CONTROL",
RESUME_PLAYER_CONTROL: "RESUME_PLAYER_CONTROL",
// reset action
RESET_REDUX_STATE: "RESET_REDUX_STATE",

View File

@@ -133,13 +133,25 @@ export const requestPlayControl =
(ownerId, videoInfo) => (dispatch, getState) => {
const { playerControl } = getState().home;
const currentOwnerId = playerControl.ownerId;
const isPersistentOwner = currentOwnerId === 'banner0_persistent';
// 이미 다른 컴포넌트가 제어권을 가지고 있다면, 먼저 해제한다. (선점)
if (currentOwnerId && currentOwnerId !== ownerId) {
dispatch(releasePlayControl(currentOwnerId, true)); // fromPreemption = true
// 이미 같은 컴포넌트가 제어권을 가지고 있다면 아무것도 하지 않음
if (currentOwnerId === ownerId) {
return;
}
// 새로운 제어권을 설정하고 비디오를 재생한다.
// 다른 컴포넌트가 제어권을 가지고 있을 때의 처리 (선점 로직)
if (currentOwnerId && currentOwnerId !== ownerId) {
// 만약 현재 재생중인 비디오가 영구 재생 비디오라면, 종료하는 대신 '일시정지'
if (isPersistentOwner) {
dispatch(pausePlayerControl(currentOwnerId));
} else {
// 그 외의 경우는 기존처럼 완전히 종료
dispatch(releasePlayControl(currentOwnerId, true)); // fromPreemption = true
}
}
// 새로운 제어권을 설정하고 비디오를 재생
dispatch({
type: types.SET_PLAYER_CONTROL,
payload: { ownerId },
@@ -158,6 +170,7 @@ export const requestPlayControl =
*/
export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch, getState) => {
const { playerControl } = getState().home;
const isPersistentOwner = playerControl.ownerId === 'banner0_persistent';
// 제어권을 가진 컴포넌트가 자신일 경우에만 해제
// 단, 선점 로직에 의해 호출된 경우는 소유권 확인 없이 즉시 실행
@@ -166,5 +179,43 @@ export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch
type: types.CLEAR_PLAYER_CONTROL,
});
dispatch(finishVideoPreview());
// 제어권 해제 후, 만약 이전에 일시정지된 영구 비디오가 있었다면 다시 재생
if (isPersistentOwner && playerControl.isPaused) {
dispatch(resumePlayerControl('banner0_persistent'));
}
}
};
/**
* 현재 재생 중인 비디오를 '일시정지' 상태로 변경하는 액션.
* 이 함수는 플레이어 패널을 닫지 않고, 단순히 비디오 재생을 멈추는 신호를 보냅니다.
*
* @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID.
*/
export const pausePlayerControl = (ownerId) => (dispatch, getState) => {
const { playerControl } = getState().home;
// 제어권을 가진 컴포넌트가 자신일 경우에만 일시정지
if (playerControl.ownerId === ownerId) {
dispatch({
type: types.PAUSE_PLAYER_CONTROL,
});
}
};
/**
* '일시정지' 상태의 비디오를 다시 재생하는 액션.
*
* @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID.
*/
export const resumePlayerControl = (ownerId) => (dispatch, getState) => {
const { playerControl } = getState().home;
// 제어권을 가진 컴포넌트가 자신이고, 일시정지 상태일 때만 재개
if (playerControl.ownerId === ownerId && playerControl.isPaused) {
dispatch({
type: types.RESUME_PLAYER_CONTROL,
});
}
};

View File

@@ -23,6 +23,7 @@ const initialState = {
curationTitle: "",
playerControl: {
ownerId: null,
isPaused: false,
},
};
@@ -198,6 +199,7 @@ export const homeReducer = (state = initialState, action) => {
playerControl: {
...state.playerControl,
ownerId: action.payload.ownerId,
isPaused: false,
},
};
}
@@ -208,6 +210,27 @@ export const homeReducer = (state = initialState, action) => {
playerControl: {
...state.playerControl,
ownerId: null,
isPaused: false,
},
};
}
case types.PAUSE_PLAYER_CONTROL: {
return {
...state,
playerControl: {
...state.playerControl,
isPaused: true,
},
};
}
case types.RESUME_PLAYER_CONTROL: {
return {
...state,
playerControl: {
...state.playerControl,
isPaused: false,
},
};
}

View File

@@ -266,27 +266,80 @@ export default function HomeBanner({
}
}, [shouldShowOptionalTermsPopup, termsLoading]);
// const renderItem = useCallback(
// (index, isHorizontal) => {
// const data = bannerDataList?.[index] ?? {};
// if (index === 1) {
// return (
// <div className={!isHorizontal ? css.imgBox : undefined}>
// <RandomUnitNew
// bannerData={data}
// isHorizontal={isHorizontal}
// key={"banner" + index}
// spotlightId={"banner" + index}
// handleShelfFocus={_handleShelfFocus}
// onFocus={handleSecondBannerFocus}
// onBlur={handleSecondBannerBlur}
// randomNumber={data.randomIndex}
// />
// </div>
// );
// }
// return (
// <div className={!isHorizontal ? css.imgBox : undefined}>
// {data.shptmDspyTpNm === "Rolling" ? (
// <Rolling
// bannerData={data}
// isHorizontal={isHorizontal}
// key={"banner" + index}
// spotlightId={"banner" + index}
// handleShelfFocus={_handleShelfFocus}
// handleItemFocus={_handleItemFocus}
// />
// ) : data.shptmDspyTpNm === "Random" ? (
// <Random
// bannerData={data}
// isHorizontal={isHorizontal}
// key={"banner" + index}
// spotlightId={"banner" + index}
// handleShelfFocus={_handleShelfFocus}
// handleItemFocus={_handleItemFocus}
// randomNumber={data.randomIndex}
// />
// ) : (
// <SpottableComponent spotlightId={"banner" + index}>
// <CustomImage
// delay={0}
// src={
// isHorizontal
// ? homeTopDisplayInfo.wdthtpImgPath1
// : homeTopDisplayInfo.vtctpImgPath1
// }
// aria-label={
// isHorizontal
// ? homeTopDisplayInfo.wdthtpImgNm1
// : homeTopDisplayInfo.vtctpImgNm1
// }
// />
// </SpottableComponent>
// )}
// </div>
// );
// },
// [
// bannerDataList,
// _handleItemFocus,
// _handleShelfFocus,
// handleSecondBannerFocus,
// handleSecondBannerBlur,
// ],
// );
const renderItem = useCallback(
(index, isHorizontal) => {
const data = bannerDataList?.[index] ?? {};
if (index === 1) {
return (
<div className={!isHorizontal ? css.imgBox : undefined}>
<RandomUnitNew
bannerData={data}
isHorizontal={isHorizontal}
key={"banner" + index}
spotlightId={"banner" + index}
handleShelfFocus={_handleShelfFocus}
onFocus={handleSecondBannerFocus}
onBlur={handleSecondBannerBlur}
randomNumber={data.randomIndex}
/>
</div>
);
}
return (
<div className={!isHorizontal ? css.imgBox : undefined}>
{data.shptmDspyTpNm === "Rolling" ? (
@@ -328,13 +381,7 @@ export default function HomeBanner({
</div>
);
},
[
bannerDataList,
_handleItemFocus,
_handleShelfFocus,
handleSecondBannerFocus,
handleSecondBannerBlur,
],
[_handleItemFocus, _handleShelfFocus, bannerDataList]
);
const renderItemPersistentVideo = useCallback(

File diff suppressed because it is too large Load Diff