Merge: keep scrape-sourced YouTube search results across a reload
This commit is contained in:
commit
2277f9157f
2 changed files with 33 additions and 8 deletions
|
|
@ -130,10 +130,18 @@ export default function App() {
|
|||
// popstate handler below derives ytSearch from it, so Back steps player → search → feed in
|
||||
// that order (a player opened over the results pops first, then the search, then the feed) —
|
||||
// instead of the search vanishing because it had no history entry of its own.
|
||||
const [ytSearch, setYtSearch] = useState<string | null>(null);
|
||||
const [ytSearch, setYtSearch] = useState<string | null>(() => {
|
||||
// Restore a live search across a reload ONLY when it was served by the zero-quota scrape
|
||||
// source (re-fetching is free) — an api-source search would re-spend ~100 units, so it's
|
||||
// dropped to the normal feed as before. The scrape flag rides in history.state (survives F5).
|
||||
const st = window.history.state;
|
||||
return st?._yt && st?._ytScrape ? (st._yt as string) : null;
|
||||
});
|
||||
const enterYtSearch = useCallback((q: string) => {
|
||||
setYtSearch(q);
|
||||
const st = window.history.state || {};
|
||||
// Drop any prior _ytScrape marker — the new search's source isn't known yet; Feed re-stamps
|
||||
// it once the results resolve, so a reload only restores a confirmed scrape-sourced search.
|
||||
const { _ytScrape: _drop, ...st } = window.history.state || {};
|
||||
if (st._yt) window.history.replaceState({ ...st, _yt: q }, ""); // refine current search
|
||||
else window.history.pushState({ ...st, sfPage: "feed", _yt: q }, ""); // new sub-view entry
|
||||
}, []);
|
||||
|
|
@ -271,12 +279,17 @@ export default function App() {
|
|||
// from history.state on popstate. (stripUrlParams preserves history.state, so this stamp
|
||||
// survives a later query-string strip.)
|
||||
useEffect(() => {
|
||||
// Drop any stale _yt from a prior session (a reload starts on the normal feed; ytSearch
|
||||
// begins null), so the first Back doesn't resurrect a search we're no longer showing.
|
||||
// Drop a stale _yt (a reload starts on the normal feed; a search would re-spend quota), but
|
||||
// KEEP _chan/_chanName so the open channel page survives F5 (channelView restores from it above).
|
||||
const { _yt: _staleYt, ...rest } = window.history.state || {};
|
||||
// A reload returns to the normal feed by dropping a stale _yt — EXCEPT when the search was
|
||||
// scrape-sourced (zero quota): then we keep _yt + _ytScrape so it restores and re-fetches for
|
||||
// free (ytSearch above already initialised from it). An api-source search is still dropped (it
|
||||
// would re-spend ~100 units). _chan/_chanName are always kept so a channel page survives F5.
|
||||
const st = window.history.state || {};
|
||||
if (st._yt && st._ytScrape) {
|
||||
window.history.replaceState({ ...st, sfPage: page }, "");
|
||||
} else {
|
||||
const { _yt: _staleYt, _ytScrape: _staleScrape, ...rest } = st;
|
||||
window.history.replaceState({ ...rest, sfPage: page }, "");
|
||||
}
|
||||
function onPop(e: PopStateEvent) {
|
||||
const p = (e.state?.sfPage as Page) ?? "feed";
|
||||
// Guard a Back step that leaves Settings with unsaved changes: re-assert the Settings
|
||||
|
|
|
|||
|
|
@ -151,6 +151,18 @@ export default function Feed({
|
|||
retry: false,
|
||||
});
|
||||
|
||||
// Remember (in history.state) that this live search was served by the zero-quota scrape source,
|
||||
// so a reload restores the results instead of dropping to the feed — re-fetching scrape pages
|
||||
// costs no quota. An api-source search is left unmarked (a reload would re-spend ~100 units).
|
||||
useEffect(() => {
|
||||
if (!ytActive) return;
|
||||
const st = window.history.state;
|
||||
if (!st || st._yt !== ytSearch) return; // only mark our own sub-view entry
|
||||
if (ytQuery.data?.pages?.[0]?.source === "scrape" && !st._ytScrape) {
|
||||
window.history.replaceState({ ...st, _ytScrape: true }, "");
|
||||
}
|
||||
}, [ytActive, ytSearch, ytQuery.data]);
|
||||
|
||||
// Switching to the relevance sort when a search starts happens atomically in the header's
|
||||
// input onChange (race-free with the query update). Here we only handle the reverse: when
|
||||
// the term is cleared, fall back to the default sort — relevance has no dropdown option and
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue