[251115] fix: DetailPanel FullScreen Focus Move

🕐 커밋 시간: 2025. 11. 15. 22:03:44

📊 변경 통계:
  • 총 파일: 17개
  • 추가: +573줄
  • 삭제: -87줄

📁 추가된 파일:
  + com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/panelActions.js
  ~ com.twin.app.shoptime/src/components/MediaPlayer/MediaControls.js
  ~ com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.module.less
  ~ com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.v2.jsx
  ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.js
  ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less
  ~ com.twin.app.shoptime/src/utils/SpotlightIds.js
  ~ com.twin.app.shoptime/src/views/HomePanel/BestSeller/BestSeller.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/EventPopUpBanner/EventPopUpBanner.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/PickedForYou/PickedForYou.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx
  ~ com.twin.app.shoptime/src/views/MainView/MainView.jsx
  ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResultsNew/ItemCard.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/actions/panelActions.js (javascript):
     Added: updatePanel()
  📄 com.twin.app.shoptime/src/components/MediaPlayer/MediaControls.js (javascript):
     Added: onSpotlightRight(), onSpotlightUp(), MediaControlsDecoratorHOC(), handleCancel()
     Deleted: onSpotlightRight(), onSpotlightUp(), MediaControlsDecoratorHOC(), handleCancel()
  📄 com.twin.app.shoptime/src/components/VideoPlayer/MediaPlayer.v2.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less (unknown):
     Added: position()
     Deleted: position()
  📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/src/views/HomePanel/SubCategory/SubCategory.jsx (javascript):
    🔄 Modified: getExpsOrdByLgCatCd()
  📄 com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx (javascript):
    🔄 Modified: normalizeModalStyle()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator(), PlayerOverlayContents()
  📄 com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/MediaOverlayContents.jsx (javascript):
     Added: MediaOverlayContents()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • UI 컴포넌트 아키텍처 개선
  • 공통 유틸리티 함수 최적화
This commit is contained in:
2025-11-15 22:03:44 +09:00
parent 70381438ac
commit a503bf923a
17 changed files with 1878 additions and 1492 deletions

View File

@@ -1,28 +1,13 @@
import React, {
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
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 {
pushPanel,
updatePanel,
} from '../../../actions/panelActions';
import {
navigateToDetailFromHome,
} from '../../../actions/panelNavigationActions';
import { pushPanel, updatePanel, navigateFromBestSeller } from '../../../actions/panelActions';
import { navigateToDetailFromHome } from '../../../actions/panelNavigationActions';
import SectionTitle from '../../../components/SectionTitle/SectionTitle';
import Tag from '../../../components/TItemCard/Tag';
import TItemCard from '../../../components/TItemCard/TItemCard';
@@ -30,23 +15,13 @@ import TItemCardNew from '../../../components/TItemCard/TItemCard.new';
import TScroller from '../../../components/TScroller/TScroller';
import useScrollReset from '../../../hooks/useScrollReset';
import useScrollTo from '../../../hooks/useScrollTo';
import {
LOG_CONTEXT_NAME,
LOG_MESSAGE_ID,
panel_names,
} from '../../../utils/Config';
import {
$L,
scaleW,
} from '../../../utils/helperMethods';
import { LOG_CONTEXT_NAME, LOG_MESSAGE_ID, panel_names } from '../../../utils/Config';
import { $L, scaleW } from '../../../utils/helperMethods';
import { SpotlightIds } from '../../../utils/SpotlightIds';
import css from './BestSeller.module.less';
const SpottableComponent = Spottable("div");
const Container = SpotlightContainerDecorator(
{ enterTo: "last-focused" },
"div"
);
const SpottableComponent = Spottable('div');
const Container = SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div');
const BestSeller = ({
order,
@@ -58,25 +33,15 @@ const BestSeller = ({
shelfTitle,
}) => {
const { getScrollTo, scrollLeft } = useScrollTo();
const { handleScrollReset, handleStopScrolling } = useScrollReset(
scrollLeft,
true
);
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollLeft, true);
const dispatch = useDispatch();
const { cursorVisible } = useSelector((state) => state.common.appStatus);
const bestSellerDatas = useSelector(
(state) => state.product.bestSellerData?.bestSeller
);
const bestSellerNewDatas = useSelector(
(state) =>
state.foryou?.recommendInfo?.recommendProduct
);
const bestSellerDatas = useSelector((state) => state.product.bestSellerData?.bestSeller);
const bestSellerNewDatas = useSelector((state) => state.foryou?.recommendInfo?.recommendProduct);
const [drawChk, setDrawChk] = useState(false);
const [firstChk, setFirstChk] = useState(0);
@@ -84,59 +49,57 @@ const BestSeller = ({
const [bestInfos, setBestInfos] = useState(null);
const [bestItemNewData, setBestItemNewData] = useState([]);
useEffect(()=>{
useEffect(() => {
setBestInfos(
bestSellerNewDatas?.filter(
(item) => item.recommendTpCd === "BESTSELLER"
) || [] // 기본값으로 빈 배열 설정
)
},[bestSellerNewDatas])
bestSellerNewDatas?.filter((item) => item.recommendTpCd === 'BESTSELLER') || [] // 기본값으로 빈 배열 설정
);
}, [bestSellerNewDatas]);
useEffect(() => {
if (!bestInfos || bestInfos.length === 0) {
const baseData = bestSellerDatas?.map((item) => ({
...item,
foryou: false,
})) || [];
const baseData =
bestSellerDatas?.map((item) => ({
...item,
foryou: false,
})) || [];
setBestItemNewData(baseData);
return;
}
const recommendedData = bestInfos[0].productInfos?.map((item) => ({
...item,
foryou: true,
})) || [];
const recommendedPrdtIds = new Set(recommendedData.map(item => item.prdtId));
const baseData = bestSellerDatas?.map((item) => ({
...item,
foryou: recommendedPrdtIds.has(item.prdtId),
})) || [];
const recommendedData =
bestInfos[0].productInfos?.map((item) => ({
...item,
foryou: true,
})) || [];
const recommendedPrdtIds = new Set(recommendedData.map((item) => item.prdtId));
const baseData =
bestSellerDatas?.map((item) => ({
...item,
foryou: recommendedPrdtIds.has(item.prdtId),
})) || [];
setBestItemNewData(baseData);
}, [bestSellerDatas, bestInfos]);
const orderStyle = useMemo(() => ({ order: order }), [order]);
useEffect(() => {
useEffect(() => {
setDrawChk(true);
}, [bestSellerNewDatas]);
const handleCardClick = useCallback(
(patnrId, prdtId) => () => {
dispatch(
pushPanel({
name: panel_names.DETAIL_PANEL,
panelInfo: {
patnrId: patnrId,
prdtId: prdtId,
nowShelf: spotlightId,
},
navigateFromBestSeller({
patnrId,
prdtId,
spotlightId,
})
);
},
[dispatch]
[dispatch, spotlightId]
);
const handleMoreCardClick = useCallback(() => {
@@ -144,7 +107,7 @@ const BestSeller = ({
pushPanel({
name: panel_names.TRENDING_NOW_PANEL,
panelInfo: {
pageName: "BS",
pageName: 'BS',
focusedContainerId: SpotlightIds.TRENDING_NOW_BEST_SELLER,
},
})
@@ -171,21 +134,18 @@ const BestSeller = ({
if (firstChk === 0 && itemIndex === 0) {
const c = Spotlight.getCurrent();
if (c) {
let cAriaLabel = c.getAttribute("aria-label");
cAriaLabel = "Best Seller, Heading 1," + cAriaLabel;
c.setAttribute("aria-label", cAriaLabel);
let cAriaLabel = c.getAttribute('aria-label');
cAriaLabel = 'Best Seller, Heading 1,' + cAriaLabel;
c.setAttribute('aria-label', cAriaLabel);
}
setFirstChk(1);
} else if (firstChk === 1 && itemIndex === 0) {
const c = Spotlight.getCurrent();
if (c) {
let cAriaLabel = c.getAttribute("aria-label");
let cAriaLabel = c.getAttribute('aria-label');
if (cAriaLabel) {
const newcAriaLabel = cAriaLabel.replace(
"Best Seller, Heading 1,",
""
);
c.setAttribute("aria-label", newcAriaLabel);
const newcAriaLabel = cAriaLabel.replace('Best Seller, Heading 1,', '');
c.setAttribute('aria-label', newcAriaLabel);
}
}
} else {
@@ -219,7 +179,6 @@ const BestSeller = ({
handleShelfFocus();
}
}, [handleShelfFocus]);
return (
<Container
@@ -230,7 +189,7 @@ const BestSeller = ({
onFocus={_handleShelfFocus}
>
<SectionTitle
title={$L("BEST SELLER")}
title={$L('BEST SELLER')}
data-title-index="homeBestSellerTitle"
label="BEST SELLER"
/>
@@ -262,15 +221,15 @@ const BestSeller = ({
) => {
const rankText =
rankOrd === 1
? rankOrd + "st"
? rankOrd + 'st'
: rankOrd === 2
? rankOrd + "nd"
? rankOrd + 'nd'
: rankOrd === 3
? rankOrd + "rd"
: rankOrd + "th";
? rankOrd + 'rd'
: rankOrd + 'th';
return (
<TItemCardNew
key={"subItem" + itemIndex}
key={'subItem' + itemIndex}
contextName={LOG_CONTEXT_NAME.HOME}
messageId={LOG_MESSAGE_ID.SHELF_CLICK}
order={itemIndex + 1}
@@ -291,13 +250,13 @@ const BestSeller = ({
onBlur={handleBlur(itemIndex)}
onClick={handleCardClick(patnrId, prdtId)}
offerInfo={offerInfo}
spotlightId={"bestsellerItem" + itemIndex}
spotlightId={'bestsellerItem' + itemIndex}
firstLabel={rankText}
label={itemIndex * 1 + 1 + " of " + bestItemNewData.length}
label={itemIndex * 1 + 1 + ' of ' + bestItemNewData.length}
lastLabel=" go to detail, button"
euEnrgLblInfos={euEnrgLblInfos}
>
{foryou === true && <Tag text={"For You"} />}
{foryou === true && <Tag text={'For You'} />}
</TItemCardNew>
);
}
@@ -308,7 +267,7 @@ const BestSeller = ({
<SpottableComponent
className={css.displayBox}
onClick={handleMoreCardClick}
spotlightId={"bestseller-item-more-btn"}
spotlightId={'bestseller-item-more-btn'}
aria-label="See more button"
></SpottableComponent>
</div>
@@ -318,4 +277,4 @@ const BestSeller = ({
);
};
export default BestSeller;
export default BestSeller;