search panel focus
This commit is contained in:
@@ -213,12 +213,6 @@ const TVerticalPagenator = forwardRef(
|
||||
focus: focus || !currentSpot,
|
||||
align: "top",
|
||||
});
|
||||
// [2024.06.04] 베너 탑인 경우에는, LIVE,VOD 로 포커스 가도록 수정
|
||||
if (node.getAttribute("data-spotlight-id") !== "DSP00101") {
|
||||
if (focus || !currentSpot) {
|
||||
Spotlight.focus(node);
|
||||
}
|
||||
}
|
||||
if (onFocusedContainerIdRef.current) {
|
||||
if (!node.getAttribute("data-spotlight-id")) {
|
||||
console.warn("TVerticalPagenator should have spotlight id");
|
||||
|
||||
@@ -16,8 +16,10 @@ import {
|
||||
} from '../../utils/helperMethods';
|
||||
import AutoScrollArea, { POSITION } from '../AutoScrollArea/AutoScrollArea';
|
||||
import css from './TVirtualGridList.module.less';
|
||||
import Spotlight from '@enact/spotlight';
|
||||
|
||||
export default function TVirtualGridList({
|
||||
defaultSpotlightId,
|
||||
dataSize,
|
||||
direction = "vertical",
|
||||
className,
|
||||
@@ -43,6 +45,7 @@ export default function TVirtualGridList({
|
||||
const scrollPosition = useRef("top");
|
||||
|
||||
const scrollToRef = useRef(null);
|
||||
const defaultFocusTargetRef = useRef(null);
|
||||
const scrollHorizontalPos = useRef(0);
|
||||
const scrollVerticalPos = useRef(0);
|
||||
const visibleIndexRef = useRef({firstVisibleIndex:0, lastVisibleIndex:0});
|
||||
@@ -58,6 +61,13 @@ export default function TVirtualGridList({
|
||||
|
||||
useEffect(() => {
|
||||
const listRef = gridlistParentRef.current.childNodes[0];
|
||||
if(spotlightId &&defaultSpotlightId && defaultSpotlightId.indexOf(spotlightId) === 0){
|
||||
let matched = defaultSpotlightId.match(/\d+$/); //find index
|
||||
if(matched){
|
||||
defaultFocusTargetRef.current = {spotlightId: defaultSpotlightId, index: matched[0]};
|
||||
scrollToRef.current({index: matched[0], animate: false, focus: true});
|
||||
}
|
||||
}
|
||||
if(direction === 'vertical'){
|
||||
listRef.addEventListener("wheel", handleWheel, true);
|
||||
}
|
||||
@@ -86,9 +96,14 @@ export default function TVirtualGridList({
|
||||
if (onScrollStop) {
|
||||
onScrollStop(e);
|
||||
}
|
||||
|
||||
isScrolling.current = false;
|
||||
|
||||
if(defaultFocusTargetRef.current){
|
||||
if(defaultFocusTargetRef.current.index >= e.moreInfo.firstVisibleIndex
|
||||
&& defaultFocusTargetRef.current.index <= e.moreInfo.lastVisibleIndex){
|
||||
Spotlight.focus(defaultFocusTargetRef.current.spotlightId);
|
||||
defaultFocusTargetRef.current = null;
|
||||
}
|
||||
}
|
||||
if (e.reachedEdgeInfo) {
|
||||
if (e.reachedEdgeInfo.top) {
|
||||
scrollPosition.current = "top";
|
||||
|
||||
@@ -21,6 +21,12 @@ export const SpotlightIds = {
|
||||
LIST_PLAYER: "list_player",
|
||||
LIST_PLAYER2: "list_player2",
|
||||
|
||||
// SearchPanel
|
||||
SEARCH_THEME: "search_theme",
|
||||
SEARCH_SHOW: "search_show",
|
||||
SEARCH_ITEM: "search_item",
|
||||
SEARCH_BESTSELLER: "search_bestseller",
|
||||
|
||||
//pin Code Popup
|
||||
PINCODE_CONTAINER: "pincodeContainer",
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function HomeBanner({
|
||||
}
|
||||
return "banner" + targetIndex;
|
||||
}
|
||||
return "banner0";
|
||||
return null;
|
||||
}, [bannerDataList]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -87,7 +87,7 @@ export default function HomeBanner({
|
||||
(index, isHorizontal) => {
|
||||
const data = bannerDataList?.[index] ?? {};
|
||||
return (
|
||||
<div className={!isHorizontal && css.imgBox}>
|
||||
<div className={!isHorizontal ? css.imgBox: undefined}>
|
||||
{data.shptmDspyTpNm === "Rolling" ? (
|
||||
<Rolling
|
||||
bannerData={data}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { LOG_MENU, panel_names } from "../../../utils/Config";
|
||||
import { $L } from "../../../utils/helperMethods";
|
||||
import css from "./NoSearchResults.module.less";
|
||||
import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDecorator";
|
||||
import { SpotlightIds } from "../../../utils/SpotlightIds";
|
||||
const ContainerBasic = SpotlightContainerDecorator(
|
||||
{ enterTo: null },
|
||||
"div"
|
||||
@@ -84,7 +85,7 @@ export default function NoSearchResults({ handleItemFocus }) {
|
||||
</div>
|
||||
<p>{$L("SORRY, NO RESULTS MATCHING YOUR SEARCH")}</p>
|
||||
</div>
|
||||
<ContainerBasic className={css.bestSellerWrap} data-wheel-point={true}>
|
||||
<ContainerBasic className={css.bestSellerWrap} data-wheel-point={true} spotlightId={SpotlightIds.SEARCH_BESTSELLER}>
|
||||
<SectionTitle title={$L("BEST SELLER")} />
|
||||
<TGrid>
|
||||
{bestSellerDatas &&
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
@@ -9,7 +9,6 @@ import SpotlightContainerDecorator from "@enact/spotlight/SpotlightContainerDeco
|
||||
import { popPanel, updatePanel } from "../../actions/panelActions";
|
||||
import { getSearch, resetSearch } from "../../actions/searchActions";
|
||||
import TBody from "../../components/TBody/TBody";
|
||||
import TButton from "../../components/TButton/TButton";
|
||||
import TInput, { ICONS, KINDS } from "../../components/TInput/TInput";
|
||||
import TPanel from "../../components/TPanel/TPanel";
|
||||
import TVerticalPagenator from "../../components/TVerticalPagenator/TVerticalPagenator";
|
||||
@@ -20,6 +19,8 @@ import NoSearchResults from "./NoSearchResults/NoSearchResults";
|
||||
import RecommendedKeywords from "./RecommendedKeywords/RecommendedKeywords";
|
||||
import css from "./SearchPanel.module.less";
|
||||
import SearchResults from "./SearchResults/SearchResults";
|
||||
import { setContainerLastFocusedElement } from "@enact/spotlight/src/container";
|
||||
import { SpotlightIds } from "../../utils/SpotlightIds";
|
||||
|
||||
const ContainerBasic = SpotlightContainerDecorator(
|
||||
{ enterTo: "last-focused" },
|
||||
@@ -30,7 +31,7 @@ const ITEMS_PER_PAGE = 9;
|
||||
export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
const { sendLogGNB } = useLogService();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const [firstSpot, setFirstSpot] = useState(false);
|
||||
const recommandedKeywords = useSelector(
|
||||
(state) => state.myPage.recommandedKeywordData.data?.keywords
|
||||
);
|
||||
@@ -96,10 +97,17 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const clearAllContainerHistory = useCallback(()=>{
|
||||
setContainerLastFocusedElement(null, [SpotlightIds.SEARCH_THEME]);
|
||||
setContainerLastFocusedElement(null, [SpotlightIds.SEARCH_SHOW]);
|
||||
setContainerLastFocusedElement(null, [SpotlightIds.SEARCH_ITEM]);
|
||||
setContainerLastFocusedElement(null, [SpotlightIds.SEARCH_BESTSELLER]);
|
||||
},[]);
|
||||
|
||||
const handleSearchSubmit = useCallback(
|
||||
(query) => {
|
||||
clearAllContainerHistory();
|
||||
if (!searchPerformed && !query) return;
|
||||
|
||||
if (query.trim()) {
|
||||
dispatch(
|
||||
getSearch({
|
||||
@@ -137,14 +145,9 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
currentPage * ITEMS_PER_PAGE < recommandedKeywords?.length;
|
||||
|
||||
useEffect(() => {
|
||||
const focusJobValue = focusJob.current;
|
||||
|
||||
if (panelInfo && isOnTop) {
|
||||
if (panelInfo.currentSpot) {
|
||||
console.log("chw", panelInfo.currentSpot);
|
||||
Spotlight.focus(panelInfo.currentSpot);
|
||||
focusJobValue.start(() => Spotlight.focus(panelInfo.currentSpot));
|
||||
const currentFocusedItem = Spotlight.getCurrent();
|
||||
if (panelInfo.currentSpot && firstSpot) {
|
||||
Spotlight.focus(panel_names.SEARCH_PANEL);
|
||||
}
|
||||
}
|
||||
}, [panelInfo, isOnTop]);
|
||||
@@ -194,7 +197,25 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
);
|
||||
const onFocusedContainerId = useCallback((containerId) => {
|
||||
setFocusedContainerId(containerId);
|
||||
}, []);
|
||||
if (!firstSpot) {
|
||||
setTimeout(() => {
|
||||
Spotlight.resume();
|
||||
setFirstSpot(true);
|
||||
if (panelInfo.currentSpot) {
|
||||
Spotlight.focus(panelInfo.currentSpot);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}, [panelInfo, firstSpot]);
|
||||
|
||||
const panelInfoFall = useMemo(()=>{
|
||||
const newPanelInfo = {...panelInfo};
|
||||
if(firstSpot){
|
||||
newPanelInfo.currentSpot = null;
|
||||
}
|
||||
return newPanelInfo;
|
||||
},[panelInfo, firstSpot]);
|
||||
|
||||
return (
|
||||
<TPanel
|
||||
className={css.container}
|
||||
@@ -206,6 +227,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
scrollable={false}
|
||||
spotlightDisabled={!isOnTop}
|
||||
>
|
||||
<ContainerBasic>
|
||||
<TVerticalPagenator
|
||||
className={css.tVerticalPagenator}
|
||||
spotlightId={"search_verticalPagenator"}
|
||||
@@ -219,6 +241,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
<ContainerBasic
|
||||
className={css.inputContainer}
|
||||
data-wheel-point={true}
|
||||
spotlightId={'search-input-layer'}
|
||||
>
|
||||
<TInput
|
||||
className={css.inputBox}
|
||||
@@ -236,7 +259,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
{searchPerformed && searchQuery !== null ? (
|
||||
Object.keys(searchDatas).length > 0 ? (
|
||||
<SearchResults
|
||||
panelInfo={panelInfo}
|
||||
panelInfo={panelInfoFall}
|
||||
searchQueryRef={searchQueryRef}
|
||||
isRecommendedSearchRef={isRecommendedSearchRef}
|
||||
/>
|
||||
@@ -257,6 +280,7 @@ export default function SearchPanel({ panelInfo, isOnTop, spotlightId }) {
|
||||
</ContainerBasic>
|
||||
)}
|
||||
</TVerticalPagenator>
|
||||
</ContainerBasic>
|
||||
</TBody>
|
||||
</TPanel>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
.tBody {
|
||||
height: 100%;
|
||||
>div{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.focusedContainerId{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import useLogService from "../../../hooks/useLogService";
|
||||
import { $L } from "../../../utils/helperMethods";
|
||||
import css from "./SearchResults.module.less";
|
||||
import SearchResultsType from "./SearchResultsType";
|
||||
import { SpotlightIds } from "../../../utils/SpotlightIds";
|
||||
|
||||
const Container = SpotlightContainerDecorator(
|
||||
{ enterTo: "last-focused" },
|
||||
@@ -55,11 +56,11 @@ export default memo(function SearchResults({
|
||||
spotJobValue.start(() => {
|
||||
if (searchDatas) {
|
||||
if (searchDatas?.theme?.length > 0) {
|
||||
Spotlight.focus("searchThemeItem0");
|
||||
Spotlight.focus(SpotlightIds.SEARCH_THEME);
|
||||
} else if (searchDatas?.show?.length > 0) {
|
||||
Spotlight.focus("searchShowItem0");
|
||||
Spotlight.focus(SpotlightIds.SEARCH_SHOW);
|
||||
} else {
|
||||
Spotlight.focus("searchItem0");
|
||||
Spotlight.focus(SpotlightIds.SEARCH_ITEM);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -99,7 +100,7 @@ export default memo(function SearchResults({
|
||||
count={count}
|
||||
data={data}
|
||||
idx={index}
|
||||
key={title + index}
|
||||
key={category + "searchResult"}
|
||||
panelInfo={panelInfo}
|
||||
searchQueryRef={searchQueryRef}
|
||||
sectionTitle={title}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
||||
|
||||
import classNames from "classnames";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
@@ -16,6 +16,7 @@ import SearchItemCard from "./SearchCard/SearchItemCard";
|
||||
import SearchShowCard from "./SearchCard/SearchShowCard";
|
||||
import SearchThemeCard from "./SearchCard/SearchThemeCard";
|
||||
import css from "./SearchResultsType.module.less";
|
||||
import { SpotlightIds } from "../../../utils/SpotlightIds";
|
||||
|
||||
const Container = SpotlightContainerDecorator(
|
||||
{ leaveFor: { right: "" }, enterTo: "last-focused" },
|
||||
@@ -59,10 +60,10 @@ export default function SearchResultsType({
|
||||
const dataRef = usePrevious(data);
|
||||
|
||||
useEffect(() => {
|
||||
if (initPerformed) {
|
||||
if(data && !panelInfo.currentSpot){
|
||||
scrollLeft();
|
||||
}
|
||||
}, [initPerformed]);
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
const scrollLeftJobValue = scrollLeftJob.current;
|
||||
@@ -83,7 +84,7 @@ export default function SearchResultsType({
|
||||
const onScroll = useCallback(
|
||||
(ev) => {
|
||||
const { lastVisibleIndex } = ev.moreInfo;
|
||||
if (dataRef.current.length >= SEARCH_DATA_MAX_RESULTS_LIMIT) {
|
||||
if (dataRef.current && dataRef.current.length >= SEARCH_DATA_MAX_RESULTS_LIMIT) {
|
||||
const nextSearchIndex =
|
||||
(Math.floor(lastVisibleIndex / SEARCH_DATA_MAX_RESULTS_LIMIT) + 1) *
|
||||
SEARCH_DATA_MAX_RESULTS_LIMIT +
|
||||
@@ -117,11 +118,11 @@ export default function SearchResultsType({
|
||||
<SearchThemeCard
|
||||
contentId={contentId}
|
||||
idx={idx}
|
||||
key={"theme" + index}
|
||||
key={category + index}
|
||||
keyword={keyword}
|
||||
patncNm={partnerName}
|
||||
searchQueryRef={searchQueryRef}
|
||||
spotlightId={"searchThemeItem" + index}
|
||||
spotlightId={SpotlightIds.SEARCH_THEME+ index}
|
||||
title={title}
|
||||
type={"theme"}
|
||||
{...rest}
|
||||
@@ -146,11 +147,11 @@ export default function SearchResultsType({
|
||||
<SearchShowCard
|
||||
contentId={contentId}
|
||||
idx={idx}
|
||||
key={"show" + index}
|
||||
key={category + index}
|
||||
liveFlag={liveFlag}
|
||||
patncNm={partnerName}
|
||||
searchQueryRef={searchQueryRef}
|
||||
spotlightId={"searchShowItem" + index}
|
||||
spotlightId={SpotlightIds.SEARCH_SHOW+ index}
|
||||
thumbnail={thumbnail}
|
||||
title={title}
|
||||
{...rest}
|
||||
@@ -176,11 +177,11 @@ export default function SearchResultsType({
|
||||
contentId={contentId}
|
||||
dcPrice={dcPrice}
|
||||
idx={idx}
|
||||
key={"item" + index}
|
||||
key={category + index}
|
||||
patncNm={partnerName}
|
||||
price={price}
|
||||
searchQueryRef={searchQueryRef}
|
||||
spotlightId={"searchItem" + index}
|
||||
spotlightId={SpotlightIds.SEARCH_ITEM+ index}
|
||||
thumbnail={thumbnail}
|
||||
title={title}
|
||||
length={dataSize}
|
||||
@@ -196,23 +197,33 @@ export default function SearchResultsType({
|
||||
[category, data, idx, searchQueryRef]
|
||||
);
|
||||
|
||||
const gridListId = useMemo(()=>{
|
||||
switch(category){
|
||||
case 'theme':
|
||||
return SpotlightIds.SEARCH_THEME;
|
||||
case 'show':
|
||||
return SpotlightIds.SEARCH_SHOW;
|
||||
case 'item':
|
||||
return SpotlightIds.SEARCH_ITEM;
|
||||
}
|
||||
},[category]);
|
||||
|
||||
const { itemWidth, itemHeight, spacing } = ITEM_SIZE[category] || {};
|
||||
|
||||
return (
|
||||
<Container data-wheel-point={true}>
|
||||
<Container data-wheel-point={true} spotlightId={'searchresult_section_'+category}>
|
||||
<SectionTitle
|
||||
className={css.sectionTitle}
|
||||
title={sectionTitle}
|
||||
itemCount={count ? count : null}
|
||||
label={sectionTitle + ", Heading 2"}
|
||||
/>
|
||||
<Container
|
||||
className={classNames(css.container, category && css[category])}
|
||||
>
|
||||
<TVirtualGridList
|
||||
defaultSpotlightId={panelInfo.currentSpot}
|
||||
key={sectionTitle}
|
||||
spotlightId={gridListId}
|
||||
cbScrollTo={getScrollTo}
|
||||
className={css.grid}
|
||||
className={classNames(css.container, category && css[category], css.grid)}
|
||||
dataSize={count ? count : 0}
|
||||
renderItem={renderItem}
|
||||
direction="horizontal"
|
||||
@@ -223,6 +234,5 @@ export default function SearchResultsType({
|
||||
onScroll={onScroll}
|
||||
/>
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,16 @@
|
||||
padding-left: 60px;
|
||||
}
|
||||
.container {
|
||||
> div {
|
||||
.flex();
|
||||
margin: 30px 0 50px;
|
||||
width: 100%;
|
||||
}
|
||||
.grid {
|
||||
&.grid {
|
||||
padding-right: 60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
&.theme {
|
||||
.grid {
|
||||
&.grid {
|
||||
> div {
|
||||
height: 141px;
|
||||
}
|
||||
@@ -24,7 +22,7 @@
|
||||
}
|
||||
|
||||
&.show {
|
||||
.grid {
|
||||
&.grid {
|
||||
> div {
|
||||
height: 240px;
|
||||
}
|
||||
@@ -32,7 +30,7 @@
|
||||
}
|
||||
|
||||
&.item {
|
||||
.grid {
|
||||
&.grid {
|
||||
> div {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user