[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:
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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}>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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} />
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user