refactor(feed): lift the sort vocabulary out of Feed into lib/feedSort
The active-filter chips need to label a sort, and parseSort/SORT_MAP were module-private in Feed. Pure move, no behaviour change.
This commit is contained in:
@@ -6,6 +6,14 @@ import { api, HttpError, type FeedFilters, type Video } from "../lib/api";
|
||||
import i18n from "../i18n";
|
||||
import { notify, resolveVideo } from "../lib/notifications";
|
||||
import { useDebounced } from "../lib/useDebounced";
|
||||
import {
|
||||
buildSort,
|
||||
DIRECTIONLESS,
|
||||
parseSort,
|
||||
SORT_DEFAULT_DIR,
|
||||
SORT_KEYS,
|
||||
type SortKey,
|
||||
} from "../lib/feedSort";
|
||||
import VirtualFeed from "./VirtualFeed";
|
||||
// Lazy: the in-app YouTube player (IFrame API) loads only when a video is first opened.
|
||||
const PlayerModal = lazy(() => import("./PlayerModal"));
|
||||
@@ -25,32 +33,6 @@ const rollSeed = () => Math.floor(Math.random() * 1_000_000_000);
|
||||
// Ordering = a key + direction (like the Playlists page), mapped to the backend sort strings
|
||||
// (which encode both). One entry per concept; a single arrow flips the direction.
|
||||
// "relevance" (full-text search ranking) and "shuffle" are directionless single-string sorts.
|
||||
type SortKey = "date" | "popular" | "duration" | "title" | "subscribers" | "priority" | "shuffle" | "relevance";
|
||||
const SORT_KEYS: SortKey[] = ["date", "popular", "duration", "title", "subscribers", "priority", "shuffle"];
|
||||
const DIRECTIONLESS: SortKey[] = ["shuffle", "relevance"];
|
||||
const SORT_MAP: Record<Exclude<SortKey, "shuffle" | "relevance">, { asc: string; desc: string }> = {
|
||||
date: { desc: "newest", asc: "oldest" },
|
||||
popular: { desc: "views", asc: "views_asc" },
|
||||
duration: { desc: "duration_desc", asc: "duration_asc" },
|
||||
title: { asc: "title", desc: "title_desc" },
|
||||
subscribers: { desc: "subscribers", asc: "subscribers_asc" },
|
||||
priority: { desc: "priority", asc: "priority_asc" },
|
||||
};
|
||||
const SORT_DEFAULT_DIR: Record<Exclude<SortKey, "shuffle" | "relevance">, "asc" | "desc"> = {
|
||||
date: "desc", popular: "desc", duration: "desc", title: "asc", subscribers: "desc", priority: "desc",
|
||||
};
|
||||
function parseSort(s: string): { key: SortKey; dir: "asc" | "desc" } {
|
||||
if (s === "shuffle" || s === "relevance") return { key: s, dir: "desc" };
|
||||
for (const k of Object.keys(SORT_MAP) as (keyof typeof SORT_MAP)[]) {
|
||||
if (SORT_MAP[k].asc === s) return { key: k, dir: "asc" };
|
||||
if (SORT_MAP[k].desc === s) return { key: k, dir: "desc" };
|
||||
}
|
||||
return { key: "date", dir: "desc" };
|
||||
}
|
||||
function buildSort(key: SortKey, dir: "asc" | "desc"): string {
|
||||
if (key === "shuffle" || key === "relevance") return key;
|
||||
return SORT_MAP[key][dir];
|
||||
}
|
||||
|
||||
function matchesView(status: string, show: string): boolean {
|
||||
switch (show) {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// The feed's sort vocabulary. `FeedFilters.sort` is a single wire string ("newest", "views_asc",
|
||||
// …); the UI thinks in a key + direction. Kept here rather than inside Feed so the active-filter
|
||||
// chips can label a sort without re-deriving the mapping.
|
||||
|
||||
export type SortKey =
|
||||
| "date"
|
||||
| "popular"
|
||||
| "duration"
|
||||
| "title"
|
||||
| "subscribers"
|
||||
| "priority"
|
||||
| "shuffle"
|
||||
| "relevance";
|
||||
|
||||
export const SORT_KEYS: SortKey[] = [
|
||||
"date",
|
||||
"popular",
|
||||
"duration",
|
||||
"title",
|
||||
"subscribers",
|
||||
"priority",
|
||||
"shuffle",
|
||||
];
|
||||
|
||||
/** Sorts with no meaningful asc/desc flip. */
|
||||
export const DIRECTIONLESS: SortKey[] = ["shuffle", "relevance"];
|
||||
|
||||
const SORT_MAP: Record<Exclude<SortKey, "shuffle" | "relevance">, { asc: string; desc: string }> = {
|
||||
date: { desc: "newest", asc: "oldest" },
|
||||
popular: { desc: "views", asc: "views_asc" },
|
||||
duration: { desc: "duration_desc", asc: "duration_asc" },
|
||||
title: { asc: "title", desc: "title_desc" },
|
||||
subscribers: { desc: "subscribers", asc: "subscribers_asc" },
|
||||
priority: { desc: "priority", asc: "priority_asc" },
|
||||
};
|
||||
|
||||
export const SORT_DEFAULT_DIR: Record<
|
||||
Exclude<SortKey, "shuffle" | "relevance">,
|
||||
"asc" | "desc"
|
||||
> = {
|
||||
date: "desc",
|
||||
popular: "desc",
|
||||
duration: "desc",
|
||||
title: "asc",
|
||||
subscribers: "desc",
|
||||
priority: "desc",
|
||||
};
|
||||
|
||||
export function parseSort(s: string): { key: SortKey; dir: "asc" | "desc" } {
|
||||
if (s === "shuffle" || s === "relevance") return { key: s, dir: "desc" };
|
||||
for (const k of Object.keys(SORT_MAP) as (keyof typeof SORT_MAP)[]) {
|
||||
if (SORT_MAP[k].asc === s) return { key: k, dir: "asc" };
|
||||
if (SORT_MAP[k].desc === s) return { key: k, dir: "desc" };
|
||||
}
|
||||
return { key: "date", dir: "desc" };
|
||||
}
|
||||
|
||||
export function buildSort(key: SortKey, dir: "asc" | "desc"): string {
|
||||
if (key === "shuffle" || key === "relevance") return key;
|
||||
return SORT_MAP[key][dir];
|
||||
}
|
||||
Reference in New Issue
Block a user