The provider tree mounts above <App>, which pins this tab's account only after /api/me resolves — so on a genuinely fresh tab (empty sessionStorage) the manager's sort, filters, view and layout initialised from an unknown account and stayed at defaults until a second reload. Make the active account reactive (a subscribable store + useActiveAccountId via useSyncExternalStore; setActiveAccount/clearActiveAccount notify) and re-read the stored value when the account transitions null→id, via a shared useAccountRehydrate hook. A markDirty guard (called by each owning setter) prevents clobbering a value the user changed in the brief pre-pin window; the effect is keyed on the account id only, so the user's own writes can't loop it. useSortState, useFilterState and ChannelsProvider (view/layout) all adopt it. Affects sort identically — this was a long-standing caveat, not new to R13.
31 lines
1.2 KiB
TypeScript
31 lines
1.2 KiB
TypeScript
import { useCallback, useState } from "react";
|
|
import { getAccountRaw, setAccountRaw } from "./storage";
|
|
import { useAccountRehydrate } from "./useAccountRehydrate";
|
|
import { hydrateSort, type SortOption, type SortState } from "./columnSort";
|
|
|
|
// The per-account persisted sort state, hydrated + healed against the current options — the plumbing
|
|
// the channel manager and channel discovery each hand-rolled (useState + parseSortState + a persist
|
|
// key). One home so a new sortable surface (Plex, a future table) gets persistence for free.
|
|
export function useSortState(
|
|
storageBase: string,
|
|
options: SortOption[] = [],
|
|
fallback: SortState = null,
|
|
): [SortState, (next: SortState) => void] {
|
|
const [sort, setSort] = useState<SortState>(() =>
|
|
hydrateSort(getAccountRaw(storageBase), options, fallback),
|
|
);
|
|
// When the account is pinned after mount (first load), re-read the stored sort for that account.
|
|
const markDirty = useAccountRehydrate(() =>
|
|
setSort(hydrateSort(getAccountRaw(storageBase), options, fallback)),
|
|
);
|
|
const set = useCallback(
|
|
(next: SortState) => {
|
|
markDirty();
|
|
setSort(next);
|
|
setAccountRaw(storageBase, JSON.stringify(next));
|
|
},
|
|
[storageBase, markDirty],
|
|
);
|
|
return [sort, set];
|
|
}
|