S4's reachability half. Home already led the nav order; what was missing was every way IN other than the rail. - Settings → Appearance → Startup: "Start on Home", the documented escape hatch for the landing override. Deliberately still localStorage and not a server pref — `loadInitialPage` answers before /api/me lands, and a landing module decided after the first paint is a visible jump. Its two stored values are now ONE exported constant, so the writer and the boot-time reader cannot drift on a magic string. - The command palette gets "Meglepetés" / "Surprise me": it navigates to Home and rerolls the hero on arrival. No second "Mit nézzek?" row beside it — the Home module row already matches that phrase through its descriptive title. - A global Shift+W jumps to Home. A chord, not a bare `w`: the Plex player binds bare letters and `w` sits on `s`, so a blind reach for the subtitle key would have thrown a viewer out of the film. The palette's request crosses a lazy module boundary, so it is a token that waits (lib/homeIntent) rather than an event fired into an empty room. Browser-measured: taken with a compare-and-clear, because StrictMode's double-invoked mount effect otherwise rerolled twice and landed on the page two picks deep. HU/EN parity kept; UAT on localdev in both languages, including the empty shelf.
31 lines
1.7 KiB
TypeScript
31 lines
1.7 KiB
TypeScript
import { createStore } from "./store";
|
|
|
|
// A one-shot "…and surprise me straight away" request for the Home surface (E24), handed over by
|
|
// callers that cannot reach its state — today the command palette's "Meglepetés".
|
|
//
|
|
// A TOKEN that waits, not an event that fires: Home is a lazy module and is normally NOT mounted
|
|
// when the request is made (the palette navigates to it in the same click), so an event would be
|
|
// shouted into an empty room. Home takes the token on arrival, which clears it, so walking back to
|
|
// Home an hour later does not replay the press — a stale reroll would look like the page deciding
|
|
// on its own that the answer you came back for was wrong.
|
|
const surprise = createStore(0);
|
|
|
|
/** Ask Home to reroll its hero as soon as it is on screen. Pair it with a `setPage("home")`. */
|
|
export const requestSurprise = (): void => surprise.set((n) => n + 1);
|
|
|
|
/** The pending token (0 = nothing pending) — the render subscription that wakes Home up. Home only. */
|
|
export const useSurpriseRequest = (): number => surprise.use();
|
|
|
|
/** Take the pending request, clearing it; false when there was nothing to take.
|
|
*
|
|
* Compare-and-clear rather than a plain read + `consume()`, because a reroll is NOT idempotent — it
|
|
* spends a `/discover/pick` and steps the tier rotation — and React 18's StrictMode invokes a mount
|
|
* effect twice with the same render snapshot. Measured in the browser (2026-09-07): the palette's
|
|
* "Meglepetés" from another module arrived at Home as `start=2`, two picks deep, before the page had
|
|
* painted once. Checking the LIVE store is what makes the second pass a no-op. */
|
|
export const takeSurprise = (): boolean => {
|
|
if (!surprise.get()) return false;
|
|
surprise.set(0);
|
|
return true;
|
|
};
|