fix(sort): address R13 S1 review findings
- PlexSidebar activeCount now compares the HEALED sort, so an out-of-scope key (movie "duration" after switching to shows) no longer inflates the active-filter badge while the control + grid show the default. - PlexProvider strips the legacy `sortDir` from the filters blob, so it stops leaking into the facets query key and being re-persisted on every change. - PlexProvider sort migration guards the fall-through: valid JSON that isn't a SortState now falls back instead of using the raw JSON string as the key. - New shared healPlexSort(sort, scope) is the single heal both PlexBrowse and PlexSidebar use (removes the noop-label plexSortOptions call + the duplication). - Tests: useSortState.dom.test.ts (hydrate/persist/heal round-trip via renderHook) and SortControl.dom.test.tsx (options, pick, direction toggle, directionless, trailing). vitest 94 -> 105. Gate green: tsc/eslint(0 err)/prettier/knip clean, vitest 105.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { type SortOption, type SortState } from "./columnSort";
|
||||
import { healSort, type SortOption, type SortState } from "./columnSort";
|
||||
|
||||
// Plex's sort vocabulary, source-agnostic like the feed's — a `SortOption[]` fed to the shared
|
||||
// SortControl. Direction lives in the SortState (no more sibling `sortDir` on PlexFilters); the wire
|
||||
@@ -16,9 +16,20 @@ function plexSortKeys(scope: string): string[] {
|
||||
export const PLEX_SORT_FALLBACK: SortState = { key: "title", dir: "asc" };
|
||||
|
||||
/** Labelled, alpha-ordered options for the SortControl. `label` resolves each key (i18n
|
||||
* `plex.sort.<key>`); pass a no-op label when only the key set matters (healing). */
|
||||
* `plex.sort.<key>`). */
|
||||
export function plexSortOptions(scope: string, label: (key: string) => string): SortOption[] {
|
||||
return plexSortKeys(scope)
|
||||
.map((key) => ({ key, label: label(key) }))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
/** Heal a stored sort against a scope's available keys, collapsing an out-of-scope key to the default.
|
||||
* The single heal both the sidebar control and the browse query use, so they never diverge. Always
|
||||
* non-null (the fallback is), so callers can read `.key` without a guard. */
|
||||
export function healPlexSort(sort: SortState, scope: string): NonNullable<SortState> {
|
||||
return healSort(
|
||||
sort,
|
||||
plexSortKeys(scope).map((key) => ({ key, label: key })),
|
||||
PLEX_SORT_FALLBACK,
|
||||
)!;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user