feat(prefs): usePref — one per-account+server preference hook (E4 S1)
Fold the hand-rolled server-pref plumbing (savePrefs + local mirror + me-cache merge + adopt-on-login) into a single usePref<T>(serverKey, default, opts) hook, plus useSavePref for dynamic multi-key patches. Migrated (6 savePrefs call sites + 2 duplicated adopt effects -> the hook): - FeedViewProvider: view - App: filterCollapsed, playlistsCollapsed (+ their adopt block removed) - PlayerModal: playerAutoAdvance, playerLoop - plexDetailUi: plexInfoArtBg/Cast/Related (savePref via useSavePref) Left as-is by design: panel layouts (a dynamically-indexed Record, not one key), language (i18n store, no React state), PrefsProvider (debounced multi-field auto-save + baseline echo-suppression - a different model). Behaviour-equivalent (net -84 LOC at the call sites). usePref.dom.test covers the three seed sources, persist path, debounce, adopt, parse, and useSavePref. Frontend gate green: typecheck, knip, eslint (0 err), prettier, 238 vitest.
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
import { useLayoutEffect, useRef, useState, type ReactNode } from "react";
|
||||
import { qk } from "./queryKeys";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { SlidersHorizontal } from "lucide-react";
|
||||
import { useDismiss } from "./useDismiss";
|
||||
import { api } from "./api";
|
||||
import { usePref, useSavePref } from "./usePref";
|
||||
|
||||
// Shared "detail page" UI reused by the movie info page (PlexInfo) and the series show/season pages,
|
||||
// so they look consistent (the standing glassy/HTPC brief): the faint fixed art backdrop, the two
|
||||
@@ -12,42 +10,21 @@ import { api } from "./api";
|
||||
// customize menu that toggles them.
|
||||
|
||||
export function useDetailPrefs() {
|
||||
const qc = useQueryClient();
|
||||
const prefs = (qc.getQueryData<{ preferences?: Record<string, unknown> }>(qk.me())?.preferences ??
|
||||
{}) as {
|
||||
plexInfoArtBg?: boolean;
|
||||
plexInfoCast?: boolean;
|
||||
plexInfoRelated?: boolean;
|
||||
};
|
||||
const [artBg, setArtBg] = useState(prefs.plexInfoArtBg !== false);
|
||||
const [showCast, setShowCast] = useState(prefs.plexInfoCast !== false);
|
||||
const [showRelated, setShowRelated] = useState(prefs.plexInfoRelated !== false);
|
||||
const save = (patch: Record<string, unknown>) => {
|
||||
api.savePrefs(patch).catch(() => {});
|
||||
qc.setQueryData<{ preferences?: Record<string, unknown> } | undefined>(qk.me(), (m) =>
|
||||
m ? { ...m, preferences: { ...(m.preferences || {}), ...patch } } : m,
|
||||
);
|
||||
};
|
||||
// Three per-user detail-page toggles, each a server pref adopted on login (usePref). Default ON:
|
||||
// undefined → true, only an explicit false hides. The detail pages mount after `me` is cached, so
|
||||
// usePref seeds from the cache (no localStorage mirror).
|
||||
const [artBg, setArtBg] = usePref<boolean>("plexInfoArtBg", true);
|
||||
const [showCast, setShowCast] = usePref<boolean>("plexInfoCast", true);
|
||||
const [showRelated, setShowRelated] = usePref<boolean>("plexInfoRelated", true);
|
||||
const savePref = useSavePref();
|
||||
return {
|
||||
artBg,
|
||||
showCast,
|
||||
showRelated,
|
||||
savePref: save, // expose the raw persister for callers with extra per-user prefs (e.g. strip sources)
|
||||
toggleArtBg: () => {
|
||||
const next = !artBg;
|
||||
setArtBg(next);
|
||||
save({ plexInfoArtBg: next });
|
||||
},
|
||||
toggleCast: () => {
|
||||
const next = !showCast;
|
||||
setShowCast(next);
|
||||
save({ plexInfoCast: next });
|
||||
},
|
||||
toggleRelated: () => {
|
||||
const next = !showRelated;
|
||||
setShowRelated(next);
|
||||
save({ plexInfoRelated: next });
|
||||
},
|
||||
savePref, // the raw persister for callers with extra per-user prefs (e.g. strip sources)
|
||||
toggleArtBg: () => setArtBg(!artBg),
|
||||
toggleCast: () => setShowCast(!showCast),
|
||||
toggleRelated: () => setShowRelated(!showRelated),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user