fix(channel): the channel page's address names the channel and its own view, not the page under it
Opening a channel kept every key of the page under it (`?q=music&sort=oldest&chan=…`, a sort the channel did not show), and the channel's own tab, sort and content types lived in its state alone, so a reload or a bookmark lost them. Now the channel's address is `channelUrl`: the shell's keys and `chan`, shared by `openChannel` and the channel link's href. The page writes its view (`chtab`, `chsort`, `chtypes`, lib/channelPageUrlState) and reopens it; these are shell keys, cleared by a page switch and by closing it in place. While a channel stands over a page, no module store writes its keys (`urlPage`); Back finds them on the page's own entry. A link written by an older build opens without the page's keys.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
// retired. Only non-default values are emitted so URLs stay clean. NOTE: the browser TAB title stays
|
||||
// the short module/channel name (NavigationProvider owns document.title) — the query never leaks into it.
|
||||
import { TAG_CATEGORIES, type FeedFilters } from "./api";
|
||||
import { CHANNEL_PAGE_KEYS } from "./channelPageUrlState";
|
||||
|
||||
export const FEED_KEYS = [
|
||||
"q",
|
||||
@@ -31,12 +32,13 @@ export const FEED_KEYS = [
|
||||
] as const;
|
||||
const KEYS = FEED_KEYS;
|
||||
|
||||
// The keys the shell itself reads, whatever page is on screen: the page, the channel page (it opens
|
||||
// over any page), the welcome card's mode and the one-time entry links. No module may declare one of
|
||||
// The keys the shell itself reads, whatever page is on screen: the page, the channel page and its view
|
||||
// (it opens over any page, lib/channelPageUrlState), the welcome card's mode and the one-time entry links. No module may declare one of
|
||||
// these (moduleUrl.contract.test), and a page switch never clears them.
|
||||
export const SHELL_KEYS = [
|
||||
"page",
|
||||
"chan",
|
||||
...CHANNEL_PAGE_KEYS,
|
||||
"m",
|
||||
"link",
|
||||
"oauth",
|
||||
@@ -228,6 +230,21 @@ export function urlWithParams(updates: Record<string, string | null>): string {
|
||||
return hrefHere(params);
|
||||
}
|
||||
|
||||
/** The channel page's address, opened over the page on screen: the shell's own keys (the page, an
|
||||
* entry link not yet read) and the channel — none of the page's keys, and none of another channel's
|
||||
* view (the channel page writes its own, lib/channelPageUrlState). What `openChannel` pushes, and what a
|
||||
* channel link points at, so a new tab opens the same view. */
|
||||
export function channelUrl(id: string): string {
|
||||
const here = new URLSearchParams(window.location.search);
|
||||
const viewKeys: readonly string[] = CHANNEL_PAGE_KEYS;
|
||||
const params = new URLSearchParams();
|
||||
for (const k of SHELL_KEYS) {
|
||||
const v = k === "chan" ? id : here.get(k);
|
||||
if (v != null && !viewKeys.includes(k)) params.set(k, v);
|
||||
}
|
||||
return hrefHere(params);
|
||||
}
|
||||
|
||||
/** This page's address with its query replaced by `query` and its fragment by `hash` — what every
|
||||
* address-bar writer hands to `history`. Built on the URL itself, never by gluing `pathname` in front:
|
||||
* a path opened as `//evil.com/x` would read as a link to ANOTHER host, `history.replaceState` refuses
|
||||
|
||||
Reference in New Issue
Block a user