[251026] feat: HomeBaner Video-1

🕐 커밋 시간: 2025. 10. 26. 20:17:22

📊 변경 통계:
  • 총 파일: 3개
  • 추가: +139줄
  • 삭제: -70줄

📝 수정된 파일:
  ~ 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

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • 중간 규모 기능 개선
  • 코드 정리 및 최적화
This commit is contained in:
2025-10-26 20:17:23 +09:00
parent efbe4c866c
commit a7e9f4f0a0
3 changed files with 137 additions and 68 deletions

View File

@@ -59,6 +59,56 @@ export const startVideoPlayer =
}
};
export const startVideoPlayerNew =
({ modal, modalContainerId, modalClassName, spotlightDisable, useNewPlayer, bannerId, ...rest }) =>
(dispatch, getState) => {
const panels = getState().panels.panels;
const topPanel = panels[panels.length - 1];
let panelWorkingAction = pushPanel;
// const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL;
const panelName = panel_names.PLAYER_PANEL;
if (topPanel && topPanel.name === panelName) {
panelWorkingAction = updatePanel;
}
// playerState 업데이트: 기존 playerState와 새 데이터 병합
const currentPlayerState = topPanel?.panelInfo?.playerState || {};
// 같은 배너에서 이미 비디오가 재생 중이면 return (중복 재생 방지)
if (currentPlayerState.currentBannerId === bannerId) {
return;
}
const newPlayerState = {
...currentPlayerState,
currentBannerId: bannerId,
};
dispatch(
panelWorkingAction(
{
name: panelName,
panelInfo: {
modal,
modalContainerId,
modalClassName,
playerState: newPlayerState,
...rest,
},
},
true
)
);
if (modal && modalContainerId && !spotlightDisable) {
Spotlight.setPointerMode(false);
startVideoFocusTimer = setTimeout(() => {
Spotlight.focus(modalContainerId);
}, 0);
}
};
export const finishVideoPreview = () => (dispatch, getState) => {
const panels = getState().panels.panels;
const topPanel = panels[panels.length - 1];

View File

@@ -59,7 +59,7 @@ import css from './HomeBanner.module.less';
import PersistentVideoUnit from './PersistentVideoUnit';
import JustForSwitchBanner from './RandomBannerType/JustForYouBanner';
import Random from './RandomUnit';
import RandomUnitNew from './RandomUnit';
// import RandomUnitNew from './RandomUnit';
import Rolling from './RollingUnit';
import SimpleVideoContainer from './SimpleVideoContainer';
@@ -407,8 +407,18 @@ export default function HomeBanner({
]);
const renderItem = useCallback(
(index, isHorizontal, videoPlayerable = false) => {
(index, isHorizontal) => {
const data = bannerDataList?.[index] ?? {};
// videoPlayable을 동적으로 계산
// Random이나 Rolling 배너에서 LIVE 또는 VOD 타입의 비디오가 있는지 확인
const videoPlayerable =
(data.shptmDspyTpNm === "Random" || data.shptmDspyTpNm === "Rolling") &&
data.bannerDetailInfos?.some(item =>
item.shptmBanrTpNm === "LIVE" ||
item.shptmBanrTpNm === "VOD"
);
return (
<div className={!isHorizontal ? css.imgBox : undefined}>
{data.shptmDspyTpNm === "Rolling" ? (
@@ -456,56 +466,56 @@ export default function HomeBanner({
);
// 1번째 배너(포커스 재생) 및 기타 배너를 위한 렌더링 함수
const renderItemNew = useCallback(
(index, isHorizontal) => {
const data = bannerDataList?.[index] ?? {};
// const renderItemNew = useCallback(
// (index, isHorizontal) => {
// const data = bannerDataList?.[index] ?? {};
// DSP00201 레이아웃의 두 번째 배너는 새로운 RandomUnitNew를 사용
if (selectTemplate === "DSP00201" && index === 1) {
return (
<div className={!isHorizontal ? css.imgBox : undefined}>
<RandomUnitNew
bannerData={data}
isHorizontal={isHorizontal}
key={"banner" + index}
spotlightId={"banner" + index}
handleShelfFocus={_handleShelfFocus}
handleItemFocus={_handleItemFocus}
randomNumber={data.randomIndex}
/>
</div>
);
}
// // DSP00201 레이아웃의 두 번째 배너는 새로운 RandomUnitNew를 사용
// if (selectTemplate === "DSP00201" && index === 1) {
// return (
// <div className={!isHorizontal ? css.imgBox : undefined}>
// <RandomUnitNew
// bannerData={data}
// isHorizontal={isHorizontal}
// key={"banner" + index}
// spotlightId={"banner" + index}
// handleShelfFocus={_handleShelfFocus}
// handleItemFocus={_handleItemFocus}
// randomNumber={data.randomIndex}
// />
// </div>
// );
// }
// 다른 타입의 유닛 렌더링 (예: RollingUnit)
if (data.shptmDspyTpNm === "Rolling") {
return (
<div className={!isHorizontal ? css.imgBox : undefined}>
<RollingUnit
bannerData={data}
isHorizontal={isHorizontal}
key={"banner" + index}
spotlightId={"banner" + index}
handleShelfFocus={_handleShelfFocus}
handleItemFocus={_handleItemFocus}
/>
</div>
);
}
// 기본 이미지만 있는 배너 등 다른 케이스 처리
return (
<div
className={!isHorizontal ? css.imgBox : undefined}
key={"banner" + index}
>
<SpottableComponent spotlightId={"banner" + index}>
{/* ... 정적 이미지 렌더링 로직 ... */}
</SpottableComponent>
</div>
);
},
[_handleItemFocus, _handleShelfFocus, bannerDataList, selectTemplate]
);
// // 다른 타입의 유닛 렌더링 (예: RollingUnit)
// if (data.shptmDspyTpNm === "Rolling") {
// return (
// <div className={!isHorizontal ? css.imgBox : undefined}>
// <RollingUnit
// bannerData={data}
// isHorizontal={isHorizontal}
// key={"banner" + index}
// spotlightId={"banner" + index}
// handleShelfFocus={_handleShelfFocus}
// handleItemFocus={_handleItemFocus}
// />
// </div>
// );
// }
// // 기본 이미지만 있는 배너 등 다른 케이스 처리
// return (
// <div
// className={!isHorizontal ? css.imgBox : undefined}
// key={"banner" + index}
// >
// <SpottableComponent spotlightId={"banner" + index}>
// {/* ... 정적 이미지 렌더링 로직 ... */}
// </SpottableComponent>
// </div>
// );
// },
// [_handleItemFocus, _handleShelfFocus, bannerDataList, selectTemplate]
// );
// 0번째 배너(영구 재생)를 위한 렌더링 함수
const renderItemPersistentVideo = useCallback(
@@ -544,34 +554,34 @@ export default function HomeBanner({
return (
<>
<ContainerBasic className={css.smallBox}>
{renderItem(0, true, true)}
{renderItem(1, true, true)}
{renderItem(0, true)}
{renderItem(1, true)}
</ContainerBasic>
{renderItem(2, false, false)}
{renderItem(3, false, false)}
{renderItem(2, false)}
{renderItem(3, false)}
</>
);
}
case "DSP00202": {
return (
<>
{renderItem(0, false, false)}
{renderItem(0, false)}
<ContainerBasic className={css.smallBox}>
{renderItem(1, true, true)}
{renderItem(2, true, true)}
{renderItem(1, true)}
{renderItem(2, true)}
</ContainerBasic>
{renderItem(3, false, false)}
{renderItem(3, false)}
</>
);
}
case "DSP00203": {
return (
<>
{renderItem(0, false, false)}
{renderItem(1, false, false)}
{renderItem(0, false)}
{renderItem(1, false)}
<ContainerBasic className={css.smallBox}>
{renderItem(2, true, true)}
{renderItem(3, true, true)}
{renderItem(2, true)}
{renderItem(3, true)}
</ContainerBasic>
</>
);

View File

@@ -18,7 +18,7 @@ import { changeAppStatus } from '../../../actions/commonActions';
import { updateHomeInfo } from '../../../actions/homeActions';
import { sendLogTopContents, sendLogTotalRecommend } from '../../../actions/logActions';
import { pushPanel } from '../../../actions/panelActions';
import { finishVideoPreview, startVideoPlayer } from '../../../actions/playActions';
import { finishVideoPreview, startVideoPlayer, startVideoPlayerNew } from '../../../actions/playActions';
import CustomImage from '../../../components/CustomImage/CustomImage';
import usePriceInfo from '../../../hooks/usePriceInfo';
import {
@@ -57,6 +57,13 @@ export default function RandomUnit({
const homeCategory = useSelector((state) => state.home.menuData?.data?.homeCategory);
const countryCode = useSelector((state) => state.common.httpHeader.cntry_cd);
// 현재 재생 중인 비디오 배너 ID 가져오기
const currentVideoBannerId = useSelector((state) => {
const panels = state.panels?.panels || [];
const playerPanel = panels.find((p) => p.name === panel_names.PLAYER_PANEL);
return playerPanel?.panelInfo?.playerState?.currentBannerId;
});
// 정상적으로 로딩되면 빈객체로 넘어가고 , 에러가 나면 객체안에 타입이 담겨옵니다.
const broadcast = useSelector((state) => state.common.broadcast);
const { curationId, curationTitle } = useSelector((state) => state.home);
@@ -198,15 +205,15 @@ export default function RandomUnit({
const onFocus = useCallback(() => {
setIsFocused(true);
// video가 플레이 가능한 경우 기존 비디오 즉시 종료
if (videoPlayerable) {
// video가 플레이 가능한 경우: 다른 배너에서 비디오 재생 중이면 종료
if (videoPlayerable && currentVideoBannerId && currentVideoBannerId !== spotlightId) {
dispatch(finishVideoPreview());
}
if (handleItemFocus) {
handleItemFocus();
}
}, [handleItemFocus]);
}, [handleItemFocus, videoPlayerable, spotlightId, currentVideoBannerId]);
const shelfFocus = useCallback(() => {
if (handleShelfFocus) {
@@ -417,7 +424,8 @@ export default function RandomUnit({
}
dispatch(
startVideoPlayer({
startVideoPlayerNew({
bannerId: spotlightId,
showUrl: randomData.showUrl,
patnrId: randomData.patnrId,
showId: randomData.showId,
@@ -491,7 +499,8 @@ export default function RandomUnit({
timerRef.current = setTimeout(
() =>
dispatch(
startVideoPlayer({
startVideoPlayerNew({
bannerId: spotlightId,
showUrl: randomData.showUrl,
patnrId: randomData.patnrId,
showId: randomData.showId,