refactor(channels): share useSortState across the manager + discovery (R13 S1)

ChannelsProvider and ChannelDiscovery each hand-rolled the same sort plumbing
(useState<SortState> + parseSortState + a persist key). Both now use the shared
useSortState hook. hydrateSort gains an empty-options rule: with no vocabulary
passed it parses without healing (these owners heal for display via
ColumnSortControl against the live columns), so the un-healed provider store is
preserved. plexSortKeys made module-private (knip).

Closes R13 S1: feed, Plex, and the two channel tables all sort through one
SortControl + one SortState model. Gate green: tsc/eslint(0 err)/prettier/knip
clean, vitest 94.
This commit is contained in:
2026-08-13 23:41:12 +02:00
parent e4bdc5ea6a
commit 45bd588af7
6 changed files with 30 additions and 25 deletions
+10
View File
@@ -169,4 +169,14 @@ describe("hydrateSort", () => {
dir: "desc",
});
});
it("parses without healing when no options are supplied (caller heals for display)", () => {
// A table/provider that owns no vocabulary keeps whatever was stored, even an unknown key.
expect(hydrateSort(JSON.stringify({ key: "anything", dir: "desc" }), [])).toEqual({
key: "anything",
dir: "desc",
});
// A malformed stored value still coerces to the fallback.
expect(hydrateSort(JSON.stringify({ key: 3, dir: "up" }), [], null)).toBeNull();
});
});