From 65309f034c858be0be51c65d812b38cbb5596c64 Mon Sep 17 00:00:00 2001 From: optrader Date: Tue, 18 Nov 2025 19:50:02 +0900 Subject: [PATCH 1/3] [251118] feat: LiveChannelButton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ• 컀밋 μ‹œκ°„: 2025. 11. 18. 19:50:01 πŸ“Š λ³€κ²½ 톡계: β€’ 총 파일: 4개 β€’ μΆ”κ°€: +11쀄 β€’ μ‚­μ œ: -1쀄 πŸ“ μΆ”κ°€λœ 파일: + com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.figma.jsx + com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx + com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less πŸ“ μˆ˜μ •λœ 파일: ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx πŸ”§ ν•¨μˆ˜ λ³€κ²½ λ‚΄μš©: πŸ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx (javascript): πŸ”„ Modified: Spottable() πŸ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx (javascript): βœ… Added: handleSpotlightUp() πŸ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less (unknown): βœ… Added: translateX(), focused(), gradient() --- .../v2/LiveChannelButton.figma.jsx | 92 ++++++++++++++ .../v2/LiveChannelButton.jsx | 61 ++++++++++ .../v2/LiveChannelButton.module.less | 114 ++++++++++++++++++ .../PlayerTabContents/v2/TabContainer.v2.jsx | 12 +- 4 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.figma.jsx create mode 100644 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx create mode 100644 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.figma.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.figma.jsx new file mode 100644 index 00000000..653c4aa6 --- /dev/null +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.figma.jsx @@ -0,0 +1,92 @@ +
+
+
+
+
+
+ ShopLC +
+
+ Sandal Black... +
+
+
+
+
+
+
; diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx new file mode 100644 index 00000000..f79d48d8 --- /dev/null +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.jsx @@ -0,0 +1,61 @@ +import React from 'react'; + +import Spotlight from '@enact/spotlight'; +import Spottable from '@enact/spotlight/Spottable'; +import { Marquee, MarqueeController } from '@enact/ui/Marquee'; +import { compose } from 'ramda/src/compose'; + +import icon_arrow_dwon from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png'; +import CustomImage from '../../../../components/CustomImage/CustomImage'; +import { SpotlightIds } from '../../../../utils/SpotlightIds'; +import css from './LiveChannelButton.module.less'; + +const SpottableDiv = Spottable('div'); + +export default function LiveChannelButton({ + channelLogo, + channelName = 'ShopLC', + programName = 'Sandal Black...', + backgroundColor = 'linear-gradient(180deg, #284998 0%, #06B0EE 100%)', + onClick, + spotlightId = 'live-channel-button', +}) { + const handleSpotlightUp = (e) => { + e.stopPropagation(); + e.preventDefault(); + Spotlight.focus(SpotlightIds.PLAYER_BACK_BUTTON); + }; + + return ( +
+ +
+
+ {channelLogo ? ( + + ) : ( +
+ )} +
+
+ + {channelName} + + + {programName} + + {/*
+
+
*/} +
+ arrow down +
+ +
+ ); +} diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less new file mode 100644 index 00000000..15e953a9 --- /dev/null +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelButton.module.less @@ -0,0 +1,114 @@ +@import "../../../../style/CommonStyle.module.less"; +@import "../../../../style/utils.module.less"; + +.container { + position: fixed; + bottom: 40px; + left: 50%; + transform: translateX(-50%); + z-index: 5; +} + +.liveChannelButton { + width: 100%; + max-width: 455px; + height: 92px; + padding: 10px 10px 10px 10px; + background: rgba(0, 0, 0, 0.3); + border: 1px solid rgba(234, 234, 234, 0.3); + border-radius: 100px; + display: inline-flex; + justify-content: flex-start; + align-items: center; + gap: 15px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(0, 0, 0, 0.5); + border-color: rgba(234, 234, 234, 0.5); + } + + &:focus { + background: @PRIMARY_COLOR_RED; + border-color: @PRIMARY_COLOR_RED; + + &::after { + .focused(@boxShadow: 22px, @borderRadius: 100px); + } + } +} + +.logoWrapper { + width: 72px; + height: 72px; + position: relative; + flex-shrink: 0; +} + +.logoBackground { + width: 100%; + height: 100%; + border-radius: 50%; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(180deg, #284998 0%, #06B0EE 100%); +} + +.logoImage { + width: 100%; + height: 100%; + object-fit: cover; +} + +.logoPlaceholder { + width: 57.35px; + height: 19.86px; + background: white; +} + +.channelName { + color: #fcfcfc; + font-size: 25px; + font-family: "LG Smart UI"; + font-weight: 700; + line-height: 35px; + white-space: nowrap; + overflow: hidden; + min-width: 0; + max-width: 100px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ + text-overflow: ellipsis; +} + +.programName { + color: rgba(234, 234, 234, 0.7); + font-size: 25px; + font-family: "LG Smart UI"; + font-weight: 600; + line-height: 35px; + white-space: nowrap; + flex: 1; + min-width: 0; + overflow: hidden; + max-width: 150px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ + text-overflow: ellipsis; +} + + +.arrowIcon { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 26.25px; + height: 15.63px; + margin-right: 10px; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } +} diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx index 8316920d..454a579a 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx @@ -16,6 +16,7 @@ import { SpotlightIds } from '../../../../utils/SpotlightIds'; import LiveChannelContents from '../TabContents/LiveChannelContents'; import ShopNowContents from '../TabContents/ShopNowContents'; import ShopNowButton from './ShopNowButton'; +import LiveChannelButton from './LiveChannelButton'; import css from './TabContainer.v2.module.less'; const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); @@ -238,7 +239,16 @@ export default function TabContainerV2({ )} - {tabVisible && tabIndex === 2 && } + {tabVisible && tabIndex === 2 && ( + <> + + + + )} ); } From af439249dc4a217ef1756f4d56f390d36303859d Mon Sep 17 00:00:00 2001 From: optrader Date: Tue, 18 Nov 2025 20:09:02 +0900 Subject: [PATCH 2/3] [251118] feat: LiveChannelNext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ• 컀밋 μ‹œκ°„: 2025. 11. 18. 20:09:01 πŸ“Š λ³€κ²½ 톡계: β€’ 총 파일: 3개 β€’ μΆ”κ°€: +2쀄 β€’ μ‚­μ œ: -2쀄 πŸ“ μΆ”κ°€λœ 파일: + 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/PlayerTabContents/v2/TabContainer.v2.jsx (javascript): πŸ”„ Modified: Spottable() πŸ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx (javascript): βœ… Added: handleSpotlightUp() πŸ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less (unknown): βœ… Added: translateX(), focused(), gradient() --- .../PlayerTabContents/v2/LiveChannelNext.jsx | 61 ++++++++++ .../v2/LiveChannelNext.module.less | 114 ++++++++++++++++++ .../PlayerTabContents/v2/TabContainer.v2.jsx | 4 +- 3 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx create mode 100644 com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx new file mode 100644 index 00000000..2beaf527 --- /dev/null +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx @@ -0,0 +1,61 @@ +import React from 'react'; + +import Spotlight from '@enact/spotlight'; +import Spottable from '@enact/spotlight/Spottable'; +import { Marquee, MarqueeController } from '@enact/ui/Marquee'; +import { compose } from 'ramda/src/compose'; + +import icon_arrow_dwon from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png'; +import CustomImage from '../../../../components/CustomImage/CustomImage'; +import { SpotlightIds } from '../../../../utils/SpotlightIds'; +import css from './LiveChannelNext.module.less'; + +const SpottableDiv = Spottable('div'); + +export default function LiveChannelNext({ + channelLogo, + channelName = 'ShopLC', + programName = 'Sandal Black...', + backgroundColor = 'linear-gradient(180deg, #284998 0%, #06B0EE 100%)', + onClick, + spotlightId = 'live-channel-button', +}) { + const handleSpotlightUp = (e) => { + e.stopPropagation(); + e.preventDefault(); + Spotlight.focus(SpotlightIds.PLAYER_BACK_BUTTON); + }; + + return ( +
+ +
+
+ {channelLogo ? ( + + ) : ( +
+ )} +
+
+ + {channelName} + + + {programName} + + {/*
+
+
*/} +
+ arrow down +
+ +
+ ); +} diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less new file mode 100644 index 00000000..15e953a9 --- /dev/null +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less @@ -0,0 +1,114 @@ +@import "../../../../style/CommonStyle.module.less"; +@import "../../../../style/utils.module.less"; + +.container { + position: fixed; + bottom: 40px; + left: 50%; + transform: translateX(-50%); + z-index: 5; +} + +.liveChannelButton { + width: 100%; + max-width: 455px; + height: 92px; + padding: 10px 10px 10px 10px; + background: rgba(0, 0, 0, 0.3); + border: 1px solid rgba(234, 234, 234, 0.3); + border-radius: 100px; + display: inline-flex; + justify-content: flex-start; + align-items: center; + gap: 15px; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + background: rgba(0, 0, 0, 0.5); + border-color: rgba(234, 234, 234, 0.5); + } + + &:focus { + background: @PRIMARY_COLOR_RED; + border-color: @PRIMARY_COLOR_RED; + + &::after { + .focused(@boxShadow: 22px, @borderRadius: 100px); + } + } +} + +.logoWrapper { + width: 72px; + height: 72px; + position: relative; + flex-shrink: 0; +} + +.logoBackground { + width: 100%; + height: 100%; + border-radius: 50%; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + background: linear-gradient(180deg, #284998 0%, #06B0EE 100%); +} + +.logoImage { + width: 100%; + height: 100%; + object-fit: cover; +} + +.logoPlaceholder { + width: 57.35px; + height: 19.86px; + background: white; +} + +.channelName { + color: #fcfcfc; + font-size: 25px; + font-family: "LG Smart UI"; + font-weight: 700; + line-height: 35px; + white-space: nowrap; + overflow: hidden; + min-width: 0; + max-width: 100px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ + text-overflow: ellipsis; +} + +.programName { + color: rgba(234, 234, 234, 0.7); + font-size: 25px; + font-family: "LG Smart UI"; + font-weight: 600; + line-height: 35px; + white-space: nowrap; + flex: 1; + min-width: 0; + overflow: hidden; + max-width: 150px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ + text-overflow: ellipsis; +} + + +.arrowIcon { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + width: 26.25px; + height: 15.63px; + margin-right: 10px; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } +} diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx index 454a579a..2c5f0f5d 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx @@ -16,7 +16,7 @@ import { SpotlightIds } from '../../../../utils/SpotlightIds'; import LiveChannelContents from '../TabContents/LiveChannelContents'; import ShopNowContents from '../TabContents/ShopNowContents'; import ShopNowButton from './ShopNowButton'; -import LiveChannelButton from './LiveChannelButton'; +import LiveChannelNext from './LiveChannelNext'; import css from './TabContainer.v2.module.less'; const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); @@ -241,7 +241,7 @@ export default function TabContainerV2({ {tabVisible && tabIndex === 2 && ( <> - Date: Tue, 18 Nov 2025 20:35:55 +0900 Subject: [PATCH 3/3] [251118] feat: LiveChannelNext done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ• 컀밋 μ‹œκ°„: 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() --- .../PlayerOverlay/PlayerOverlayContents.jsx | 5 ++- .../src/views/PlayerPanel/PlayerPanel.jsx | 5 ++- .../PlayerTabContents/v2/LiveChannelNext.jsx | 4 +- .../v2/LiveChannelNext.module.less | 6 +-- .../PlayerTabContents/v2/TabContainer.v2.jsx | 41 +++++++++++++++++-- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx index a333f5e3..d3ea63e5 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx @@ -218,7 +218,8 @@ function PlayerOverlayContents({ return ( <> - {shouldShowExtendedControls && playListInfo.length > 1 && noLiveContentsVisible && ( + {/* 251118 μž„μ‹œλ‘œ unvisible */} + {/* {shouldShowExtendedControls && playListInfo.length > 1 && noLiveContentsVisible && ( <>
- )} + )} */} {currentSideButtonStatus && !videoVerticalVisible && ( setTabIndexV2(0)} onLiveChannelButtonClick={() => setTabIndexV2(2)} + onLiveNext={handleIndicatorDownClick} onTabClose={(newTabIndex) => setTabIndexV2(newTabIndex)} tabVisible={belowContentsVisible} /> diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx index 2beaf527..a309a304 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.jsx @@ -43,10 +43,10 @@ export default function LiveChannelNext({ )}
- + {channelName} - + {programName} {/*
diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less index 15e953a9..bb107a75 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less @@ -78,8 +78,7 @@ white-space: nowrap; overflow: hidden; min-width: 0; - max-width: 100px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ - text-overflow: ellipsis; + max-width: 120px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ μ™„ν™” } .programName { @@ -92,8 +91,7 @@ flex: 1; min-width: 0; overflow: hidden; - max-width: 150px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ - text-overflow: ellipsis; + max-width: 180px; // μ΅œλŒ€ λ„ˆλΉ„ μ œν•œ μ™„ν™” } diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx index 2c5f0f5d..0c8bdfb0 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect } from 'react'; +import React, { useCallback, useEffect, useMemo } from 'react'; import classNames from 'classnames'; import { useSelector } from 'react-redux'; @@ -38,11 +38,39 @@ export default function TabContainerV2({ 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(() => { console.log('[DEBUG] TabContainerV2 - youmaylikeInfos:', { @@ -242,9 +270,14 @@ export default function TabContainerV2({ {tabVisible && tabIndex === 2 && ( <>