refactor: component files export only components; lint fails on a warning

The 43 react-refresh/only-export-components warnings the gate let through meant an edit to a
provider (or AnchoredPopover, Toaster, plexDetailUi, …) could not be hot-swapped: Fast Refresh
reloads a module that also exports hooks or helpers.

- Each provider's contexts, the types its hooks return and the hooks themselves live in a sibling
  context module (navigationContext.ts, channelsContext.ts, …); the provider file keeps the
  component. loadAccountFilters moved next to the feed filters' defaults (feedFiltersInit.ts),
  following navigationInit/playlistsInit.
- Helpers that sat in component files have their own modules: welcomeMode, downloadTitle,
  plexPlayable, channelSync, ui/anchoredPopoverHooks, ui/pageToolbarSlot, ui/pagerContent,
  ui/toastLevels, ui/overlayOrder, ui/tableAlign, lib/plexDetail; the cells of the channel columns
  and the registry's page wrappers are components files of their own (channelCells, modulePages).
- usePersistedTab, an alias of useAccountPersistedState, is gone; its callers use the original.

npm run lint is now eslint --max-warnings 0, so a warning fails the gate like an error does.
This commit is contained in:
2026-09-17 02:59:09 +02:00
parent 569190480d
commit c3d88d9b20
158 changed files with 1600 additions and 1431 deletions
+2 -19
View File
@@ -1,7 +1,5 @@
import {
createContext,
useCallback,
useContext,
useEffect,
useLayoutEffect,
useMemo,
@@ -23,13 +21,14 @@ import { configureNotifications, getNotifSettings, type NotifSettings } from "..
import { hintsEnabled, setHintsEnabled } from "../lib/hints";
import { getAccountRaw, LS, setAccountRaw } from "../lib/storage";
import type { PrefsController } from "./SettingsPanel";
import { PrefsContext } from "./prefsContext";
const PERF_KEY = LS.perfMode;
// The four Settings-page preferences. They apply locally for instant preview and auto-save (debounced)
// to the server — there is no draft or Save button. This provider owns them (lifted out of the App god
// component) plus the last-saved "baseline" (the server values it was seeded with, then each successful
// save) used to suppress saving what the server already holds. Consumers (SettingsPanel, GlassTuner) read the PrefsController via usePrefs().
// save) used to suppress saving what the server already holds. Consumers (SettingsPanel, GlassTuner) read the PrefsController via usePrefs() (prefsContext.ts).
type EditablePrefs = {
theme: ThemePrefs;
performanceMode: boolean;
@@ -37,22 +36,6 @@ type EditablePrefs = {
notifications: NotifSettings;
};
const PrefsContext = createContext<PrefsController>({
theme: DEFAULT_THEME,
setTheme: () => {},
perf: false,
setPerf: () => {},
hints: true,
setHints: () => {},
notif: getNotifSettings(),
setNotif: () => {},
saveState: "idle",
});
export function usePrefs(): PrefsController {
return useContext(PrefsContext);
}
export function PrefsProvider({ children }: { children: ReactNode }) {
const qc = useQueryClient();
// The account's prefs, seeded straight from the `me` cache — BootGate mounts this only once /api/me