feat(player): the YouTube player and the file viewer are named in the address
The player names what it plays in its own history entry (watch, wrel, wtab): a reload or a
bookmark reopens it on the page that hosts it, with that page's list as the queue, or alone
from the catalog (GET /api/videos/{id}/row); a page that hosts none gets the shell's. Back
lands on the page's address without it (useBackToClose's url; ui/Modal passes it on). The
Files viewer and player do the same (fview, fplay). The Plex and channel-manager views are
always written in full, as their fallback is remembered state.
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
// from the address bar so a manager view is bookmarkable/shareable — the analogue of the feed's
|
||||
// urlState and Plex's plexUrlState. Keys are NAMESPACED (`ctab`/`csort`/`cf`) so they're
|
||||
// channels-unique (like `?v=`/`?pl`/`pscope`): no other provider ever reads or clears them, and the
|
||||
// feed's URL-stripping can't delete them out from under the manager. Only non-default values are
|
||||
// emitted, so URLs stay clean. The name search (`cq`) is part of the view like the rest: a bookmark of a
|
||||
// searched list opens searched.
|
||||
import { decodeSortParam, encodeSortParam, type SortState } from "./columnSort";
|
||||
// feed's URL-stripping can't delete them out from under the manager. The tab, sort and filters are
|
||||
// always written, their defaults too: a page opened without them takes this browser's remembered view,
|
||||
// which may not be the one bookmarked. The name search (`cq`) is part of the view like the rest (a
|
||||
// bookmark of a searched list opens searched), but nothing remembers it, so only a term is written.
|
||||
import { decodeSortParamOrNone, encodeSortParamOrNone, type SortState } from "./columnSort";
|
||||
import { type FilterMap } from "./tableColumns";
|
||||
import { decodeFilterMap, encodeFilterMap } from "./filterMapParam";
|
||||
|
||||
@@ -23,12 +24,11 @@ export const CHANNELS_KEYS = ["ctab", "csort", "cf", "cq"] as const;
|
||||
const KEYS = CHANNELS_KEYS;
|
||||
const VIEWS = ["subscribed", "discovery", "hidden", "blocked"];
|
||||
|
||||
// Sort ⇄ `key:dir` (e.g. `subscribers:desc`) via the shared codec in columnSort. There is no default
|
||||
// sort here (fallback null), so any sort emits — no default short-circuit needed. The filter map rides
|
||||
// as one JSON value (lib/filterMapParam).
|
||||
// Sort ⇄ `key:dir` (e.g. `subscribers:desc`, `none` unsorted) via the shared codec in columnSort. The
|
||||
// filter map rides as one JSON value (lib/filterMapParam), an empty one as `cf=`.
|
||||
|
||||
/** The address-bar delta for the manager content state: each namespaced key mapped to its emitted
|
||||
* value, or null to delete it (so a control back at its default clears the key). Pass `null` to clear
|
||||
* value, or null to delete it (only the search's, when cleared). Pass `null` to clear
|
||||
* ALL manager keys — used when the app is off the Channels page (localStorage still holds the state; it
|
||||
* re-mirrors on return). Feed the result into urlWithParams(). */
|
||||
export function channelsParamUpdates(
|
||||
@@ -36,9 +36,9 @@ export function channelsParamUpdates(
|
||||
): Record<string, string | null> {
|
||||
if (!state) return { ctab: null, csort: null, cf: null, cq: null };
|
||||
return {
|
||||
ctab: state.view && state.view !== "subscribed" ? state.view : null,
|
||||
csort: encodeSortParam(state.sort),
|
||||
cf: encodeFilterMap(state.filters),
|
||||
ctab: state.view || "subscribed",
|
||||
csort: encodeSortParamOrNone(state.sort),
|
||||
cf: encodeFilterMap(state.filters) ?? "",
|
||||
cq: state.search.trim() || null,
|
||||
};
|
||||
}
|
||||
@@ -55,10 +55,10 @@ export function channelsParamsToState(
|
||||
base: ChannelsUrlState,
|
||||
): ChannelsUrlState {
|
||||
const tab = params.get("ctab");
|
||||
const csort = params.get("csort");
|
||||
const linkedSort = decodeSortParamOrNone(params.get("csort"));
|
||||
return {
|
||||
view: tab && VIEWS.includes(tab) ? tab : base.view,
|
||||
sort: csort != null ? (decodeSortParam(csort) ?? base.sort) : base.sort,
|
||||
sort: linkedSort === undefined ? base.sort : linkedSort,
|
||||
filters: params.has("cf") ? decodeFilterMap(params.get("cf") ?? "") : base.filters,
|
||||
search: params.get("cq") ?? base.search,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user