import React, { useCallback, useEffect, useMemo } from 'react'; import classNames from 'classnames'; import { useSelector } from 'react-redux'; import Spotlight from '@enact/spotlight'; import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; // import icon_arrow_right from '../../../../../assets/images/icons'; import icon_arrow_dwon from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png'; import usePrevious from '../../../../hooks/usePrevious'; import { LOG_MENU } from '../../../../utils/Config'; import { createDebugHelpers } from '../../../../utils/debug'; import { $L } from '../../../../utils/helperMethods'; import { SpotlightIds } from '../../../../utils/SpotlightIds'; import FeaturedShowContents from '../TabContents/FeaturedShowContents'; import LiveChannelContents from '../TabContents/LiveChannelContents'; import ShopNowContents from '../TabContents/ShopNowContents'; import LiveChannelNext from './LiveChannelNext'; import ShopNowButton from './ShopNowButton'; import css from './TabContainer.v2.module.less'; // 디버그 헬퍼 설정 const DEBUG_MODE = false; const { dlog, dwarn, derror } = createDebugHelpers(DEBUG_MODE); const Container = SpotlightContainerDecorator( { enterTo: 'last-focused' }, 'div' ); const SpottableDiv = Spottable('div'); export default function TabContainerV2({ panelInfo, playListInfo, shopNowInfo, selectedIndex, setSelectedIndex, liveChannelInfos, videoVerticalVisible, handleItemFocus, prevChannelIndex, currentTime, spotlightId, tabIndex = 1, // tabIndex prop으로 제어 (0: ShopNow, 1: LiveChannel, 2: ShopNowButton) onShopNowButtonClick, onLiveChannelButtonClick, onLiveNext, onTabClose, // 탭 닫기 콜백 함수 tabVisible, }) { 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 데이터 로그 useEffect(() => { dlog('[DEBUG] TabContainerV2 - youmaylikeInfos:', { exists: !!youmaylikeInfos, length: youmaylikeInfos?.length, data: youmaylikeInfos, shopNowInfo_length: shopNowInfo?.length, shouldShowYouMayAlso: shopNowInfo && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0, }); }, [youmaylikeInfos, shopNowInfo]); const tabList = [ $L('SHOP NOW'), panelInfo?.shptmBanrTpNm === 'LIVE' ? $L('LIVE CHANNEL') : $L('FEATURED SHOWS'), ]; useEffect(() => { let nowMenu; if (tabIndex === 0) { nowMenu = LOG_MENU.FULL_SHOP_NOW; } if (tabIndex === 1) { const isLive = panelInfo?.shptmBanrTpNm === 'LIVE'; nowMenu = isLive ? LOG_MENU.FULL_LIVE_CHANNELS : LOG_MENU.FULL_FEATURED_SHOWS; } if (nowMenu) { handleItemFocus(nowMenu); } }, [handleItemFocus, panelInfo?.shptmBanrTpNm, tabIndex]); const _handleItemFocus = useCallback( (nowMenu) => { if (handleItemFocus) { handleItemFocus(nowMenu); } }, [handleItemFocus] ); const onSpotlightIndicatorUpButton = useCallback( (e) => { if (videoVerticalVisible) { e.stopPropagation(); e.preventDefault(); Spotlight.focus('spotlightId-video-contaienr'); } }, [videoVerticalVisible] ); const handleCloseButtonClick = useCallback( (e) => { e.stopPropagation(); e.preventDefault(); if (onTabClose) { onTabClose(2); // tabIndex를 2로 설정 } }, [onTabClose] ); // 위 방향 포커스 이동 시 백 버튼으로 이동 const handleSpotlightUpToBackButton = useCallback((e) => { e.stopPropagation(); e.preventDefault(); // VideoPlayer가 belowContentsVisible prop을 감지해서 이미 controls를 표시했으므로 // 바로 포커스 이동 Spotlight.focus(SpotlightIds.PLAYER_BACK_BUTTON); }, []); // 이전 tabIndex 값 추적 const prevTabIndexRef = usePrevious(tabIndex); const prevTabIndex = prevTabIndexRef.current; // 하나의 함수에서 모든 tabIndex 변화 처리 const handleTabIndexChange = useCallback((newTabIndex, oldTabIndex) => { console.log( `[TabIndexChange] Tab changed from ${oldTabIndex} to ${newTabIndex}` ); if (newTabIndex === 0) { // tabIndex = 0 (ShopNow) const timeoutId = setTimeout(() => { Spotlight.focus('shownow_close_button'); }, 100); return () => clearTimeout(timeoutId); } if (newTabIndex === 1) { // tabIndex = 1 (LiveChannel) const timeoutId = setTimeout(() => { Spotlight.focus('below-tab-live-channel-button'); }, 100); return () => clearTimeout(timeoutId); } if (newTabIndex === 2) { // tabIndex = 2 (ShopNowButton) const timeoutId = setTimeout(() => { Spotlight.focus('below-tab-shop-now-button'); }, 10); return () => clearTimeout(timeoutId); } }, []); // tabIndex 변화 감지 및 처리 useEffect(() => { // 초기 렌더링이 아닐 때만 실행 (prevTabIndex가 정의되었을 때) if (prevTabIndex !== undefined && prevTabIndex !== tabIndex) { handleTabIndexChange(tabIndex, prevTabIndex); } }, [tabIndex, prevTabIndex, handleTabIndexChange]); return ( {tabVisible && tabIndex === 0 && ( <>
{ // 첫 번째 ShopNow 아이템으로 포커스 이동 e.stopPropagation(); e.preventDefault(); Spotlight.focus('shop-now-item-0'); }} >
shop now icon
SHOP NOW
arrow down
{/* { // 첫 번째 ShopNow 아이템으로 포커스 이동 e.stopPropagation(); e.preventDefault(); Spotlight.focus("shop-now-item-0"); }} > × */}
{/* YouMayAlso Like 헤더 (ShopNow 아이템 < 3 && YouMayLike 데이터 존재) */} {shopNowInfo && shopNowInfo.length < 3 && youmaylikeInfos && youmaylikeInfos.length > 0 && (
You may also like
)}
)} {tabVisible && tabIndex === 1 && ( <> { // 첫 번째 PlayerItem으로 포커스 이동 Spotlight.focus('tabChannel-video-0'); }} onSpotlightFocus={() => { console.log('[TabContainerV2] below-tab button focused'); }} > {tabList[1]}
arrow down
{panelInfo?.shptmBanrTpNm === 'LIVE' && playListInfo && ( )} {panelInfo?.shptmBanrTpNm === 'VOD' && playListInfo && ( )} )} {tabVisible && tabIndex === 2 && ( <> )}
); }