* style(web): run prettier over drifted files prettier --check was failing on 19 files at HEAD. The pinned prettier version (3.8.1) has not changed since the initial migration, so the drift came from unformatted commits, not a toolchain bump. Formatting changes only, no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(web): sync stale test harnesses with current components 15 tests across 6 files were failing at HEAD; the components were committed already out of sync with their tests in the initial migration. All fixes are in test files only: - SectionRow / SeriesContent: mock the watch playback controller required by ContinueWatchingCard and MediaItemMenu, mock the new useSimilarItems hook, add useOptionalAuth to the auth mock, and wrap renders in QueryClientProvider for MediaItemMenu query hooks - SeriesContent: read rating from item.user_rating (the useRating hook no longer exists) - ProfilesSettings: add useHouseholdSessions to the profiles mock for the new HouseholdStreamsPanel - ImpersonationBanner: match the redesigned banner ("Viewing as", sticky full-width bar instead of sidebar offset) - EpisodeRow: watched indicator uses the text-success token now - profile-management: use a valid DiceBear preset ref; "adventurer" no longer resolves and round-trips to "" Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { useMemo, useCallback } from "react";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { api } from "@/api/client";
|
|
import { useSetting, useSetSetting } from "@/hooks/queries/settings";
|
|
import { settingsKeys } from "@/hooks/queries/keys";
|
|
import { parseOverlayPrefs, serializeOverlayPrefs, type CardOverlayPrefs } from "@/lib/overlays";
|
|
|
|
const SETTING_KEY = "card_overlays";
|
|
|
|
interface OverlayConfig {
|
|
enabled: boolean;
|
|
defaults?: string;
|
|
}
|
|
|
|
function useOverlayConfig() {
|
|
return useQuery({
|
|
queryKey: [...settingsKeys.all, "overlay-config"] as const,
|
|
queryFn: () => api<OverlayConfig>("/settings/overlay-config"),
|
|
staleTime: 60_000,
|
|
});
|
|
}
|
|
|
|
export function useOverlayPrefs() {
|
|
const { data: raw, isLoading: userLoading } = useSetting(SETTING_KEY);
|
|
const { data: config, isLoading: configLoading } = useOverlayConfig();
|
|
const setSetting = useSetSetting();
|
|
|
|
const prefs = useMemo(() => {
|
|
// User setting takes priority; fall back to admin defaults
|
|
const source = raw ?? config?.defaults ?? null;
|
|
return parseOverlayPrefs(source);
|
|
}, [raw, config?.defaults]);
|
|
|
|
// Admin kill switch: if disabled server-wide, return null prefs
|
|
const enabled = config?.enabled !== false;
|
|
|
|
const setPrefs = useCallback(
|
|
(next: CardOverlayPrefs) => {
|
|
const serialized = serializeOverlayPrefs(next);
|
|
// Avoid a network round-trip and downstream re-render cascade when
|
|
// the user toggles a control to its current value.
|
|
if (raw === serialized) return;
|
|
setSetting.mutate({ key: SETTING_KEY, value: serialized });
|
|
},
|
|
[raw, setSetting],
|
|
);
|
|
|
|
return {
|
|
prefs: enabled ? prefs : null,
|
|
setPrefs,
|
|
isLoading: userLoading || configLoading,
|
|
enabled,
|
|
};
|
|
}
|