fix: browse takes the pill like the other sections

This commit is contained in:
MyLuxy committed 2026-10-17 05:13:20 +02:00
1 parent cc392a0b10
commit 9f02a1a9a9
2 files changed
+33 -13

No files matched your search

+24 -12
View File
@@ -4,7 +4,7 @@
import '../assets/Inter-Regular.ttf';
import { jsx, jsxs } from 'react/jsx-runtime';
import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { focusEnd, useLocale, useT } from '../i18n/index.js';
import { NO_FILTERS, activeCount, genreLabel, genres, getGame } from '../state/catalog.js';
import { useIsImmersive, useNavActions, useNavState } from '../state/nav.jsx';
@@ -26,12 +26,20 @@ import { FocusScope, Text, View } from '@ps5-react/core';
function Header({ children }) {
const t2 = useT();
const { rtl } = useLocale();
const { section, filters, on, step, keyOf, browseFocus } = useSections();
const { section, shown, filters, on, step, keyOf, browseFocus, leaveBrowse } = useSections();
const wishlist = useWishlist();
const favorites = wishlist.filter((id) => getGame(id)).length;
const nav = useNavActions();
const { top } = useNavState();
const [browsing, setBrowsing] = (0, useState)(false);
const browsingNow = (0, useRef)(false);
browsingNow.current = browsing;
// A closed menu returns focus a frame later: only then can it tell whether focus left Browse.
(0, useEffect)(() => {
if (browsing) return void 0;
const id = setTimeout(leaveBrowse, 50);
return () => clearTimeout(id);
}, [browsing]);
const [choosingLanguage, setChoosingLanguage] = (0, useState)(false);
const immersive = useIsImmersive();
const [layouts, track] = useNavLayouts();
@@ -61,7 +69,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
/* @__PURE__ */ (0, jsx)(DownloadToast, { actionRef: toastAction }),
choosingLanguage ? /* @__PURE__ */ (0, jsx)(LanguageSheet, { onClose: () => setChoosingLanguage(false) }) : null,
/* @__PURE__ */ (0, jsx)(View, { style: immersive ? { position: "absolute", left: 0, right: 0, top: 0, zIndex: 40, display: "none" } : { position: "absolute", left: 0, right: 0, top: 0, zIndex: 40 }, children: /* @__PURE__ */ (0, jsx)(FocusScope, { focusKey: "header", inert: immersive, children: /* @__PURE__ */ (0, jsxs)(View, { onLayout: track("header"), style: { height: 96, flexDirection: "row", alignItems: "center", justifyContent: "space-between", backgroundColor: "#000000", paddingHorizontal: 48 }, children: [
/* @__PURE__ */ (0, jsx)(NavPill, { section, layouts }),
/* @__PURE__ */ (0, jsx)(NavPill, { section: shown, layouts }),
/* @__PURE__ */ (0, jsxs)(View, { style: { flex: 1, flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 24 }, children: [
/* @__PURE__ */ (0, jsx)(View, { style: rtl ? { marginRight: -24 } : { marginLeft: -24 }, children: /* @__PURE__ */ (0, jsx)(
NavItem,
@@ -69,7 +77,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
focusKey: keyOf("search"),
icon: "search",
label: t2("nav.search"),
current: section === "search",
current: shown === "search",
onPress: on.search,
onLayout: track("search"),
nextFocusDown: down
@@ -82,7 +90,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
{
focusKey: keyOf("discover"),
label: t2("nav.discover"),
current: section === "discover",
current: shown === "discover",
onPress: on.discover,
onLayout: track("discover"),
nextFocusDown: down
@@ -95,11 +103,15 @@ import { FocusScope, Text, View } from '@ps5-react/core';
focusKey: keyOf("catalog"),
label: t2("nav.browse"),
trailing: browsing ? "chevronUp" : "chevronDown",
current: section === "catalog",
current: shown === "catalog",
onPress: () => setBrowsing((open) => !open),
onLayout: track("catalog"),
nextFocusDown: down,
...browseFocus
onFocus: browseFocus.onFocus,
onBlur: () => {
browseFocus.onBlur();
if (!browsingNow.current) leaveBrowse();
}
}
),
/* @__PURE__ */ (0, jsxs)(Menu, { open: browsing, onClose: () => setBrowsing(false), rows: genres.length + 2, children: [
@@ -140,7 +152,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
{
focusKey: keyOf("top"),
label: t2("nav.top"),
current: section === "top",
current: shown === "top",
onPress: on.top,
onLayout: track("top"),
nextFocusDown: down
@@ -151,7 +163,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
{
focusKey: keyOf("new"),
label: t2("nav.new"),
current: section === "new",
current: shown === "new",
onPress: on.new,
onLayout: track("new"),
nextFocusDown: down
@@ -165,7 +177,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
focusKey: keyOf("favorites"),
icon: "heart",
label: favorites ? String(favorites) : null,
current: section === "favorites",
current: shown === "favorites",
onPress: on.favorites,
onLayout: track("favorites"),
nextFocusDown: down,
@@ -177,7 +189,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
{
focusKey: keyOf("downloads"),
icon: "download",
current: section === "downloads",
current: shown === "downloads",
onPress: on.downloads,
onLayout: track("downloads"),
nextFocusDown: down,
@@ -189,7 +201,7 @@ import { FocusScope, Text, View } from '@ps5-react/core';
{
focusKey: keyOf("files"),
icon: "folder",
current: section === "files",
current: shown === "files",
onPress: on.files,
onLayout: track("files"),
nextFocusDown: down
+9 -1
View File
@@ -55,6 +55,9 @@ import { useQueryActive, useStoreActions, useStoreState } from '../state/store.j
const section = top.name === "search" ? "search" : top.name === "game" ? null : underneath;
const topName = (0, useRef)(top.name);
topName.current = top.name;
// L1/R1 stopped on Browse: the pill and the item show it as the current section, like any other
// tab, while the page stays where it was until ✕ opens the menu and a choice there shows the library.
const [stopped, setStopped] = (0, useState)(false);
const [on] = (0, useState)(() => ({
show,
search: () => topName.current !== "search" && nav.push({ name: "search" }, "nav:search"),
@@ -70,9 +73,11 @@ import { useQueryActive, useStoreActions, useStoreState } from '../state/store.j
const next = TABS[TABS.indexOf(current) + (forward ? 1 : -1)];
if (!next) return;
if (next === "catalog") {
setStopped(true);
nav.focusLater(next === section ? "nav:current" : KEYS2.catalog);
return;
}
setStopped(false);
if (next === "downloads" || next === "files") {
store.setQuery("");
nav.home();
@@ -87,7 +92,10 @@ import { useQueryActive, useStoreActions, useStoreState } from '../state/store.j
// The page's top elements go up to `nav:current`, the current section's item, like a PS5 tab
// row; the scope's own memory would be stale after L1/R1 or a closed menu.
keyOf: (name) => name === section ? "nav:current" : KEYS2[name],
browseFocus: { onFocus: () => onBrowse = true, onBlur: () => onBrowse = false }
shown: stopped ? "catalog" : section,
browseFocus: { onFocus: () => onBrowse = true, onBlur: () => onBrowse = false },
// The stop ends once focus is off Browse and its menu is closed.
leaveBrowse: () => onBrowse || setStopped(false)
};
}