From 0e13d775b0f63f1c4879ee90494253a96cd65e4b Mon Sep 17 00:00:00 2001 From: "junghoon86.park" Date: Mon, 13 Oct 2025 18:39:57 +0900 Subject: [PATCH] =?UTF-8?q?[live]=20=EC=98=81=EC=83=81=EC=AA=BD=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=ED=94=BC=EA=B7=B8=EB=A7=88=20?= =?UTF-8?q?=EB=8F=99=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 영상쪽 스타일 피그마와 동기화작업. - 스타일 변경및 spotlightId변경. --- .../PlayerOverlay/PlayerOverlayContents.jsx | 159 ++++++++++-------- .../TabContents/ShopNowContents.jsx | 65 ++++--- .../PlayerTabContents/v2/TabContainer.v2.jsx | 84 ++++++--- .../v2/TabContainer.v2.module.less | 38 ++++- 4 files changed, 231 insertions(+), 115 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 670eb27f..bd88a835 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx @@ -1,14 +1,24 @@ -import React, { useCallback, useEffect, useMemo, useRef } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, +} from 'react'; import classNames from 'classnames'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; import Marquee from '@enact/ui/Marquee'; -import defaultLogoImg from '../../../../assets/images/ic-tab-partners-default@3x.png'; +import defaultLogoImg + from '../../../../assets/images/ic-tab-partners-default@3x.png'; import { setShowPopup } from '../../../actions/commonActions'; import CustomImage from '../../../components/CustomImage/CustomImage'; import { ACTIVE_POPUP } from '../../../utils/Config'; @@ -16,9 +26,12 @@ import { SpotlightIds } from '../../../utils/SpotlightIds'; import PlayerTabButton from '../PlayerTabContents/TabButton/PlayerTabButton'; import css from './PlayerOverlayContents.module.less'; -const SpottableBtn = Spottable('button'); +const SpottableBtn = Spottable("button"); -const Container = SpotlightContainerDecorator({ enterTo: 'default-element' }, 'div'); +const Container = SpotlightContainerDecorator( + { enterTo: "default-element" }, + "div" +); export default function PlayerOverlayContents({ type, @@ -55,7 +68,7 @@ export default function PlayerOverlayContents({ const backBtnRef = useRef(null); useEffect(() => { - if (type === 'MEDIA' && !panelInfo.modal && backBtnRef.current) { + if (type === "MEDIA" && !panelInfo.modal && backBtnRef.current) { Spotlight.focus(SpotlightIds.PLAYER_BACK_BUTTON); } }, [panelInfo?.shptmBanrTpNm, panelInfo.modal, backBtnRef.current]); @@ -70,7 +83,7 @@ export default function PlayerOverlayContents({ const patncLogoPath = useMemo(() => { let logo = playListInfo[selectedIndex]?.patncLogoPath; - if (type === 'MEDIA') { + if (type === "MEDIA") { logo = panelInfo?.patncLogoPath; } @@ -79,7 +92,7 @@ export default function PlayerOverlayContents({ const partnerName = useMemo(() => { let name = playListInfo[selectedIndex]?.patncNm; - if (type === 'MEDIA') { + if (type === "MEDIA") { name = panelInfo?.patncNm; } @@ -88,11 +101,11 @@ export default function PlayerOverlayContents({ const showName = useMemo(() => { let name = playListInfo[selectedIndex]?.showNm; - if (type === 'MEDIA') { + if (type === "MEDIA") { name = panelInfo?.showNm; } - return name ? name.replace(//gi, ' ') : ''; + return name ? name.replace(//gi, " ") : ""; }, [playListInfo, selectedIndex, panelInfo]); const onSpotlightMoveTabButton = (e) => { @@ -103,15 +116,15 @@ export default function PlayerOverlayContents({ const onSpotlightMoveMediaButton = (e) => { e.stopPropagation(); - if (type === 'LIVE') { - return Spotlight.focus('videoIndicator-down-button'); + if (type === "LIVE") { + return Spotlight.focus("videoIndicator-down-button"); } - Spotlight.focus('videoPlayer_mediaControls'); + Spotlight.focus("videoPlayer_mediaControls"); }; const onSpotlightMoveSlider = useCallback( (e) => { - if (type === 'VOD') { + if (type === "VOD") { e.stopPropagation(); Spotlight.focus(SpotlightIds.PLAYER_SLIDER); @@ -123,7 +136,7 @@ export default function PlayerOverlayContents({ const onSpotlightMoveSideTab = (e) => { e.stopPropagation(); e.preventDefault(); - Spotlight.focus('tab-0'); + Spotlight.focus("tab-0"); }; const onSpotlightMoveBelowTab = (e) => { @@ -133,13 +146,14 @@ export default function PlayerOverlayContents({ // tabIndexV2에 따라 다른 버튼으로 포커스 이동 if (tabIndexV2 === 0) { // ShopNow 탭: Close 버튼으로 - Spotlight.focus('below-tab-close-button'); + // Spotlight.focus('below-tab-close-button'); + Spotlight.focus("shownow_close_button"); } else if (tabIndexV2 === 1) { // LIVE CHANNEL 탭: LIVE CHANNEL 버튼으로 - Spotlight.focus('below-tab-live-channel-button'); + Spotlight.focus("below-tab-live-channel-button"); } else if (tabIndexV2 === 2) { // ShopNowButton: ShopNowButton으로 - Spotlight.focus('below-tab-shop-now-button'); + Spotlight.focus("below-tab-shop-now-button"); } }; @@ -149,7 +163,7 @@ export default function PlayerOverlayContents({ const currentSideButtonStatus = useMemo(() => { if ( - type !== 'MEDIA' && + type !== "MEDIA" && !panelInfo?.modal && !sideContentsVisible && tabContainerVersion === 1 @@ -175,63 +189,67 @@ export default function PlayerOverlayContents({ return ( <> - {type !== 'MEDIA' && playListInfo.length > 1 && noLiveContentsVisible && ( - <> -
- 1 && + noLiveContentsVisible && ( + <> +
+ +
+
+ -
-
- -
- - )} + } + aria-label="Next channel" + /> +
+ + )} {currentSideButtonStatus && !videoVerticalVisible && ( )} - {cntry_cd === 'US' && ( + {cntry_cd === "US" && (
{partnerName && ( @@ -276,14 +294,17 @@ export default function PlayerOverlayContents({

{partnerName}

{showName}
- {type === 'VOD' && disclaimer && ( + {type === "VOD" && disclaimer && (

{disclaimer}

diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx index cae74c05..6803ca1c 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx @@ -1,37 +1,61 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { + useDispatch, + useSelector, +} from 'react-redux'; import { Job } from '@enact/core/util'; import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; -import { getContainerNode, setContainerLastFocusedElement } from '@enact/spotlight/src/container'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; +import { + getContainerNode, + setContainerLastFocusedElement, +} from '@enact/spotlight/src/container'; import { sendLogTotalRecommend } from '../../../../actions/logActions'; import { pushPanel } from '../../../../actions/panelActions'; import { hidePlayerOverlays } from '../../../../actions/videoPlayActions'; import TItemCard, { TYPES } from '../../../../components/TItemCard/TItemCard'; -import TVirtualGridList from '../../../../components/TVirtualGridList/TVirtualGridList'; +import TVirtualGridList + from '../../../../components/TVirtualGridList/TVirtualGridList'; import useScrollTo from '../../../../hooks/useScrollTo'; -import { LOG_CONTEXT_NAME, LOG_MENU, LOG_MESSAGE_ID, panel_names } from '../../../../utils/Config'; +import { + LOG_CONTEXT_NAME, + LOG_MENU, + LOG_MESSAGE_ID, + panel_names, +} from '../../../../utils/Config'; import { scaleH } from '../../../../utils/helperMethods'; -import ListEmptyContents from '../TabContents/ListEmptyContents/ListEmptyContents'; +import ListEmptyContents + from '../TabContents/ListEmptyContents/ListEmptyContents'; import css1 from './ShopNowContents.module.less'; import cssV2 from './ShopNowContents.v2.module.less'; const extractPriceInfo = (priceInfo) => { - if (!priceInfo) return { originalPrice: '', discountedPrice: '', discountRate: '' }; + if (!priceInfo) + return { originalPrice: "", discountedPrice: "", discountRate: "" }; - const parts = priceInfo.split('|').map((part) => part.trim()); + const parts = priceInfo.split("|").map((part) => part.trim()); return { - originalPrice: parts[0] || '', - discountedPrice: parts[1] || '', - discountRate: parts[4] || '', + originalPrice: parts[0] || "", + discountedPrice: parts[1] || "", + discountRate: parts[4] || "", }; }; -const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); +const Container = SpotlightContainerDecorator( + { enterTo: "last-focused" }, + "div" +); export default function ShopNowContents({ shopNowInfo, videoVerticalVisible, @@ -41,7 +65,7 @@ export default function ShopNowContents({ panelInfo, tabTitle, version = 1, - direction = 'vertical', + direction = "vertical", }) { const css = version === 2 ? cssV2 : css1; const { getScrollTo, scrollTop } = useScrollTo(); @@ -66,7 +90,7 @@ export default function ShopNowContents({ useEffect(() => { return () => { - const gridListId = 'playVideoShopNowBox'; + const gridListId = "playVideoShopNowBox"; const girdList = getContainerNode(gridListId); if (girdList) setContainerLastFocusedElement(null, [gridListId]); @@ -119,7 +143,8 @@ export default function ShopNowContents({ } = shopNowInfo[index]; // 미리 계산된 가격 정보를 사용 - const { originalPrice, discountedPrice, discountRate } = priceInfoMap[index] || {}; + const { originalPrice, discountedPrice, discountRate } = + priceInfoMap[index] || {}; const handleItemClick = () => { const params = { @@ -148,7 +173,7 @@ export default function ShopNowContents({ showId: playListInfo?.showId, liveFlag: playListInfo?.liveFlag, thumbnailUrl: playListInfo?.thumbnailUrl, - liveReqFlag: panelInfo?.shptmBanrTpNm === 'LIVE' && 'Y', + liveReqFlag: panelInfo?.shptmBanrTpNm === "LIVE" && "Y", patnrId, prdtId, launchedFromPlayer: true, @@ -177,7 +202,7 @@ export default function ShopNowContents({ // v2에서 첫 번째 아이템일 때 위로 가면 Close 버튼으로 e.stopPropagation(); e.preventDefault(); - Spotlight.focus('below-tab-close-button'); + Spotlight.focus("shownow_close_button"); } : undefined } @@ -212,7 +237,9 @@ export default function ShopNowContents({ itemWidth={version === 2 ? 310 : videoVerticalVisible ? 540 : 600} itemHeight={version === 2 ? 445 : 236} spacing={version === 2 ? 30 : 12} - className={videoVerticalVisible ? css.verticalItemList : css.itemList} + className={ + videoVerticalVisible ? css.verticalItemList : css.itemList + } noScrollByWheel={false} spotlightId="playVideoShopNowBox" /> 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 e2592682..339b2c16 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,13 +1,20 @@ -import React, { useCallback, useEffect } from 'react'; +import React, { + useCallback, + useEffect, +} from 'react'; import classNames from 'classnames'; import Spotlight from '@enact/spotlight'; -import SpotlightContainerDecorator from '@enact/spotlight/SpotlightContainerDecorator'; +import SpotlightContainerDecorator + from '@enact/spotlight/SpotlightContainerDecorator'; import Spottable from '@enact/spotlight/Spottable'; -import icon_arrow_dwon from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png'; -import icon_shop_now from '../../../../../assets/images/player/icon_tabcontainer_shopnow.png'; +// import icon_arrow_right from '../../../../../assets/images/icons'; +import icon_arrow_dwon + from '../../../../../assets/images/player/icon_tabcontainer_arrow_down.png'; +import icon_shop_now + from '../../../../../assets/images/player/icon_tabcontainer_shopnow.png'; import { LOG_MENU } from '../../../../utils/Config'; import { $L } from '../../../../utils/helperMethods'; import { SpotlightIds } from '../../../../utils/SpotlightIds'; @@ -17,9 +24,12 @@ import YouMayLikeContents from '../TabContents/YouMayLikeContents'; import ShopNowButton from './ShopNowButton'; import css from './TabContainer.v2.module.less'; -const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'); +const Container = SpotlightContainerDecorator( + { enterTo: "last-focused" }, + "div" +); -const SpottableDiv = Spottable('div'); +const SpottableDiv = Spottable("div"); export default function TabContainerV2({ panelInfo, @@ -40,8 +50,10 @@ export default function TabContainerV2({ tabVisible, }) { const tabList = [ - $L('SHOP NOW'), - panelInfo?.shptmBanrTpNm === 'LIVE' ? $L('LIVE CHANNEL') : $L('FEATURED SHOWS'), + $L("SHOP NOW"), + panelInfo?.shptmBanrTpNm === "LIVE" + ? $L("LIVE CHANNEL") + : $L("FEATURED SHOWS"), ]; useEffect(() => { @@ -52,8 +64,10 @@ export default function TabContainerV2({ } if (tabIndex === 1) { - const isLive = panelInfo?.shptmBanrTpNm === 'LIVE'; - nowMenu = isLive ? LOG_MENU.FULL_LIVE_CHANNELS : LOG_MENU.FULL_FEATURED_SHOWS; + const isLive = panelInfo?.shptmBanrTpNm === "LIVE"; + nowMenu = isLive + ? LOG_MENU.FULL_LIVE_CHANNELS + : LOG_MENU.FULL_FEATURED_SHOWS; } if (nowMenu) { @@ -75,7 +89,7 @@ export default function TabContainerV2({ if (videoVerticalVisible) { e.stopPropagation(); e.preventDefault(); - Spotlight.focus('spotlightId-video-contaienr'); + Spotlight.focus("spotlightId-video-contaienr"); } }, [videoVerticalVisible] @@ -106,7 +120,7 @@ export default function TabContainerV2({ useEffect(() => { if (tabIndex === 2) { setTimeout(() => { - Spotlight.focus('below-tab-shop-now-button'); + Spotlight.focus("below-tab-shop-now-button"); }, 100); } }, [tabIndex]); @@ -123,26 +137,44 @@ export default function TabContainerV2({ {tabVisible && tabIndex === 0 && ( <>
-
-
- shop now icon -
-
SHOP NOW
-
{ // 첫 번째 ShopNow 아이템으로 포커스 이동 e.stopPropagation(); e.preventDefault(); - Spotlight.focus('shop-now-item-0'); + Spotlight.focus("shop-now-item-0"); + }} + > +
+ shop now icon +
+
SHOP NOW
+
+ arrow down +
+
+ {/* { + // 첫 번째 ShopNow 아이템으로 포커스 이동 + e.stopPropagation(); + e.preventDefault(); + Spotlight.focus("shop-now-item-0"); }} > × - + */}
{ // 첫 번째 PlayerItem으로 포커스 이동 - Spotlight.focus('tabChannel-video-0'); + Spotlight.focus("tabChannel-video-0"); }} > LIVE CHANNEL @@ -185,7 +217,7 @@ export default function TabContainerV2({
- {panelInfo?.shptmBanrTpNm === 'LIVE' && playListInfo && ( + {panelInfo?.shptmBanrTpNm === "LIVE" && playListInfo && ( )} - {tabVisible && tabIndex === 2 && } + {tabVisible && tabIndex === 2 && ( + + )} ); } diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.module.less b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.module.less index 06956c4f..382248b5 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.module.less +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.module.less @@ -113,8 +113,16 @@ } .shopNowHeaderLeft { - .flex(@display: flex, @justifyCenter: flex-start, @alignCenter: center); - + .size(@w: 300px, @h: 70px); + padding: 20px 30px; + border-radius: 100px; + border: 1px solid rgba(234, 234, 234, 0.5); + overflow: hidden; + .flex(@display: flex, @justifyCenter: space-between, @alignCenter: center); + background: rgba(0, 0, 0, 0.3); + backdrop-filter: blur(5px); + cursor: pointer; + transition: all 0.3s ease; > * { margin-right: 15px; @@ -122,6 +130,32 @@ margin-right: 0; } } + .arrowIcon { + .size(@w: 26.25px, @h: 15.63px); + img { + width: 100%; + height: 100%; + object-fit: contain; + transform: rotate(270deg); + } + } + &:hover { + background: rgba(0, 0, 0, 0.5); + border-color: rgba(234, 234, 234, 0.7); + } + + &:focus { + background: @PRIMARY_COLOR_RED; + border-color: @PRIMARY_COLOR_RED; + + .buttonText { + color: white; + } + + &::after { + .focused(@boxShadow: 22px, @borderRadius: 100px); + } + } } .shopNowHeaderText {