[251118] feat: LiveChannelNext done

🕐 커밋 시간: 2025. 11. 18. 20:35:55

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

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx (javascript):
    🔄 Modified: Spottable()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx (javascript):
    🔄 Modified: Spottable()
This commit is contained in:
2025-11-18 20:35:55 +09:00
parent af439249dc
commit 08de7888c7
5 changed files with 48 additions and 13 deletions

View File

@@ -218,7 +218,8 @@ function PlayerOverlayContents({
return ( return (
<> <>
<Container className={css.overlayContainer} onKeyDownCapture={handleOverlayKeyDownCapture}> <Container className={css.overlayContainer} onKeyDownCapture={handleOverlayKeyDownCapture}>
{shouldShowExtendedControls && playListInfo.length > 1 && noLiveContentsVisible && ( {/* 251118 임시로 unvisible */}
{/* {shouldShowExtendedControls && playListInfo.length > 1 && noLiveContentsVisible && (
<> <>
<div className={css.indicatorUpButton}> <div className={css.indicatorUpButton}>
<SpottableBtn <SpottableBtn
@@ -261,7 +262,7 @@ function PlayerOverlayContents({
/> />
</div> </div>
</> </>
)} )} */}
{currentSideButtonStatus && !videoVerticalVisible && ( {currentSideButtonStatus && !videoVerticalVisible && (
<PlayerTabButton <PlayerTabButton

View File

@@ -1464,7 +1464,9 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
panelInfo.modalContainerId && panelInfo.modalContainerId &&
(lastPanelAction === 'previewPush' || lastPanelAction === 'previewUpdate') (lastPanelAction === 'previewPush' || lastPanelAction === 'previewUpdate')
) { ) {
console.log('[PlayerPanel] Condition 1: Calculating modalStyle from DOM', { lastPanelAction }); console.log('[PlayerPanel] Condition 1: Calculating modalStyle from DOM', {
lastPanelAction,
});
const node = document.querySelector(`[data-spotlight-id="${panelInfo.modalContainerId}"]`); const node = document.querySelector(`[data-spotlight-id="${panelInfo.modalContainerId}"]`);
if (node) { if (node) {
const { width, height, top, left } = node.getBoundingClientRect(); const { width, height, top, left } = node.getBoundingClientRect();
@@ -2381,6 +2383,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
tabIndex={tabIndexV2} tabIndex={tabIndexV2}
onShopNowButtonClick={() => setTabIndexV2(0)} onShopNowButtonClick={() => setTabIndexV2(0)}
onLiveChannelButtonClick={() => setTabIndexV2(2)} onLiveChannelButtonClick={() => setTabIndexV2(2)}
onLiveNext={handleIndicatorDownClick}
onTabClose={(newTabIndex) => setTabIndexV2(newTabIndex)} onTabClose={(newTabIndex) => setTabIndexV2(newTabIndex)}
tabVisible={belowContentsVisible} tabVisible={belowContentsVisible}
/> />

View File

@@ -43,10 +43,10 @@ export default function LiveChannelNext({
)} )}
</div> </div>
</div> </div>
<Marquee className={css.channelName} marqueeOn="focus"> <Marquee className={css.channelName} marqueeOn="render">
{channelName} {channelName}
</Marquee> </Marquee>
<Marquee className={css.programName} marqueeOn="focus"> <Marquee className={css.programName} marqueeOn="render">
{programName} {programName}
</Marquee> </Marquee>
{/* <div className={css.iconWrapper}> {/* <div className={css.iconWrapper}>

View File

@@ -78,8 +78,7 @@
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
min-width: 0; min-width: 0;
max-width: 100px; // 최대 너비 제한 max-width: 120px; // 최대 너비 제한 완화
text-overflow: ellipsis;
} }
.programName { .programName {
@@ -92,8 +91,7 @@
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow: hidden; overflow: hidden;
max-width: 150px; // 최대 너비 제한 max-width: 180px; // 최대 너비 제한 완화
text-overflow: ellipsis;
} }

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react'; import React, { useCallback, useEffect, useMemo } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
@@ -38,11 +38,39 @@ export default function TabContainerV2({
tabIndex = 1, // tabIndex prop으로 제어 (0: ShopNow, 1: LiveChannel, 2: ShopNowButton) tabIndex = 1, // tabIndex prop으로 제어 (0: ShopNow, 1: LiveChannel, 2: ShopNowButton)
onShopNowButtonClick, onShopNowButtonClick,
onLiveChannelButtonClick, onLiveChannelButtonClick,
onLiveNext,
onTabClose, // 탭 닫기 콜백 함수 onTabClose, // 탭 닫기 콜백 함수
tabVisible, tabVisible,
}) { }) {
const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos); const youmaylikeInfos = useSelector((state) => state.main.youmaylikeInfos);
// 다음 재생 가능한 쇼 찾기
const findNextPlayableShow = useCallback((currentPlayList, currentIndex) => {
if (!currentPlayList || currentPlayList.length === 0) return null;
let nextIndex = currentIndex === currentPlayList.length - 1 ? 0 : currentIndex + 1;
let initialIndex = nextIndex;
let attempts = 0;
// 유효한 showId를 가진 다음 쇼 찾기
while (!currentPlayList[nextIndex]?.showId && attempts < currentPlayList.length) {
nextIndex = nextIndex === currentPlayList.length - 1 ? 0 : nextIndex + 1;
attempts++;
if (nextIndex === initialIndex) break;
}
if (currentPlayList[nextIndex]?.showId) {
return currentPlayList[nextIndex];
}
return null;
}, []);
// 다음 쇼 정보 계산
const nextShowInfo = useMemo(() => {
return findNextPlayableShow(playListInfo, selectedIndex);
}, [playListInfo, selectedIndex, findNextPlayableShow]);
// ✨ DEBUG: youmaylikeInfos 데이터 로그 // ✨ DEBUG: youmaylikeInfos 데이터 로그
useEffect(() => { useEffect(() => {
console.log('[DEBUG] TabContainerV2 - youmaylikeInfos:', { console.log('[DEBUG] TabContainerV2 - youmaylikeInfos:', {
@@ -242,9 +270,14 @@ export default function TabContainerV2({
{tabVisible && tabIndex === 2 && ( {tabVisible && tabIndex === 2 && (
<> <>
<LiveChannelNext <LiveChannelNext
channelName={playListInfo?.[0]?.showNm || 'ShopLC'} channelLogo={nextShowInfo?.patncLogoPath}
programName={playListInfo?.[0]?.title || 'Live Channel'} channelName={nextShowInfo?.patncNm || 'ShopLC'}
onClick={onLiveChannelButtonClick} programName={nextShowInfo?.showNm || 'Live Channel'}
backgroundColor={
nextShowInfo?.dfltThumbnailImgPath ||
'linear-gradient(180deg, #284998 0%, #06B0EE 100%)'
}
onClick={onLiveNext}
/> />
<ShopNowButton onClick={onShopNowButtonClick} /> <ShopNowButton onClick={onShopNowButtonClick} />
</> </>