siftlode/frontend/src/lib/modules.ts

51 lines
2.3 KiB
TypeScript
Raw Normal View History

import type { Me } from "./api";
import type { Page } from "./urlState";
// Admin/system modules — rendered in their own section (below a divider) in the nav rail.
export const SYSTEM_PAGES: readonly Page[] = ["scheduler", "config", "users", "audit"];
// The i18n key for each module's SHORT display name — the same label the nav rail shows. Single
// source so the nav rail and the header's ModuleName pill always read identically (the longer,
// descriptive `pageTitleKey` names are kept only for the browser tab title).
export const moduleLabelKey: Record<Page, string> = {
feed: "header.account.feed",
channels: "header.account.channels",
playlists: "header.account.playlists",
plex: "plex.navLabel",
notifications: "inbox.navLabel",
messages: "messages.navLabel",
downloads: "downloads.navLabel",
stats: "header.account.stats",
scheduler: "header.account.scheduler",
config: "header.account.config",
users: "header.account.users",
audit: "header.account.audit",
settings: "header.account.settings",
};
// The ordered list of primary module pages available to THIS user, in nav-rail order. Single
// source of truth for both the nav rail (NavSidebar) and the header's ◀/▶ module stepper, so a
// new module (or a newly-gated one) shows up in both at once — nothing hard-codes the sequence.
// Availability is derived from the account (plex toggle, demo restrictions, admin role), so the
// reachable set changes with the language-independent account state, not the UI.
export function moduleOrder(me: Me): Page[] {
const pages: Page[] = ["feed", "channels", "playlists"];
if (me.plex_enabled) pages.push("plex");
pages.push("notifications");
if (!me.is_demo) pages.push("messages", "downloads");
pages.push("stats");
if (me.role === "admin") pages.push(...SYSTEM_PAGES);
return pages;
}
// Step to the next/previous module cyclically (wraps at both ends). `dir` = +1 forward, -1 back.
// If the current page isn't a primary module (e.g. Settings), forward lands on the first module
// and back on the last.
export function stepModule(me: Me, current: Page, dir: 1 | -1): Page {
const order = moduleOrder(me);
if (order.length === 0) return current;
const i = order.indexOf(current);
if (i === -1) return dir === 1 ? order[0] : order[order.length - 1];
return order[(i + dir + order.length) % order.length];
}