fix(feed): reliably switch to relevance sort when a search starts
The relevance auto-select ran in a Feed effect that raced per-keystroke query updates, so fast typing left the sort on the default. Move the switch into the header input's onChange so it's set atomically with the query (only overriding the default newest sort); the Feed effect now only reverts to newest when the term is cleared. 'Back to feed' also sets relevance explicitly.
This commit is contained in:
parent
2e5919399c
commit
20bcdf5ecb
2 changed files with 15 additions and 12 deletions
|
|
@ -137,19 +137,15 @@ export default function Feed({
|
||||||
retry: false,
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// When a search term first appears, rank the local feed by relevance (YouTube-like); when
|
// Switching to the relevance sort when a search starts happens atomically in the header's
|
||||||
// it's cleared, fall back to the default newest sort. Only fires on the empty↔non-empty
|
// input onChange (race-free with the query update). Here we only handle the reverse: when
|
||||||
// transition, so it never overrides a sort the user picks while a query stays active.
|
// the term is cleared, fall back to the default sort — relevance has no dropdown option and
|
||||||
|
// doesn't rank without a query.
|
||||||
const qEmpty = !filters.q.trim();
|
const qEmpty = !filters.q.trim();
|
||||||
const prevQEmptyRef = useRef(qEmpty);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sortKeyNow = parseSort(filters.sort).key;
|
if (qEmpty && parseSort(filters.sort).key === "relevance") {
|
||||||
if (prevQEmptyRef.current && !qEmpty && sortKeyNow !== "relevance") {
|
|
||||||
setFilters({ ...filters, sort: "relevance" });
|
|
||||||
} else if (!prevQEmptyRef.current && qEmpty && sortKeyNow === "relevance") {
|
|
||||||
setFilters({ ...filters, sort: buildSort("date", "desc") });
|
setFilters({ ...filters, sort: buildSort("date", "desc") });
|
||||||
}
|
}
|
||||||
prevQEmptyRef.current = qEmpty;
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [qEmpty]);
|
}, [qEmpty]);
|
||||||
|
|
||||||
|
|
@ -316,8 +312,8 @@ export default function Feed({
|
||||||
// disabled and still holds its pre-search cache) is stale. Drop those caches so
|
// disabled and still holds its pre-search cache) is stale. Drop those caches so
|
||||||
// it re-fetches fresh on return instead of showing the old (often empty) result.
|
// it re-fetches fresh on return instead of showing the old (often empty) result.
|
||||||
// Surface the just-searched videos in the feed you return to: switch the Source
|
// Surface the just-searched videos in the feed you return to: switch the Source
|
||||||
// filter to "search" so your own search finds show (filtered by the kept term).
|
// filter to "search" (your own search finds) and rank them by relevance.
|
||||||
setFilters({ ...filters, librarySource: "search" });
|
setFilters({ ...filters, librarySource: "search", sort: "relevance" });
|
||||||
onExitYtSearch();
|
onExitYtSearch();
|
||||||
qc.removeQueries({ queryKey: ["feed"] });
|
qc.removeQueries({ queryKey: ["feed"] });
|
||||||
qc.removeQueries({ queryKey: ["feed-count"] });
|
qc.removeQueries({ queryKey: ["feed-count"] });
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,14 @@ export default function Header({
|
||||||
<Search className="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted" />
|
<Search className="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted" />
|
||||||
<input
|
<input
|
||||||
value={filters.q}
|
value={filters.q}
|
||||||
onChange={(e) => setFilters({ ...filters, q: e.target.value })}
|
onChange={(e) => {
|
||||||
|
const q = e.target.value;
|
||||||
|
// When a search first appears, rank the feed by relevance — set atomically with
|
||||||
|
// the query (race-free vs. per-keystroke updates). Only overrides the default
|
||||||
|
// "newest" sort; a custom sort the user chose is left alone. Cleared in Feed.
|
||||||
|
const startSearch = !filters.q.trim() && !!q.trim() && filters.sort === "newest";
|
||||||
|
setFilters({ ...filters, q, ...(startSearch ? { sort: "relevance" } : {}) });
|
||||||
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
// Enter runs a live YouTube search for the typed term (the box itself filters
|
// Enter runs a live YouTube search for the typed term (the box itself filters
|
||||||
// the local catalog as you type; Enter escalates to the YouTube API).
|
// the local catalog as you type; Enter escalates to the YouTube API).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue