fix list filters

This commit is contained in:
jeffvli
2025-12-02 00:11:42 -08:00
parent 4abfbd1973
commit aff7a61bca
26 changed files with 1022 additions and 565 deletions
@@ -1,40 +1,41 @@
import { parseAsString, useQueryState } from 'nuqs';
import { useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-list-filter-persistence';
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { ItemListKey } from '/@/shared/types/types';
export const useMusicFolderIdFilter = (defaultValue: null | string, listKey: ItemListKey) => {
const server = useCurrentServer();
const { getFilter, setFilter } = useListFilterPersistence(server.id, listKey);
const [searchParams, setSearchParams] = useSearchParams();
const persisted = getFilter(FILTER_KEYS.SHARED.MUSIC_FOLDER_ID);
const [musicFolderId, setMusicFolderId] = useQueryState(
FILTER_KEYS.SHARED.MUSIC_FOLDER_ID,
getDefaultMusicFolderId(defaultValue, persisted),
);
const musicFolderId = useMemo(() => {
const value = parseStringParam(searchParams, FILTER_KEYS.SHARED.MUSIC_FOLDER_ID);
return value ?? persisted ?? defaultValue ?? undefined;
}, [searchParams, persisted, defaultValue]);
const handleSetMusicFolderId = (musicFolderId: string) => {
setMusicFolderId(musicFolderId);
setSearchParams(
(prev) => {
const newParams = setSearchParam(
prev,
FILTER_KEYS.SHARED.MUSIC_FOLDER_ID,
musicFolderId,
);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.MUSIC_FOLDER_ID, musicFolderId);
};
return {
[FILTER_KEYS.SHARED.MUSIC_FOLDER_ID]: musicFolderId ?? undefined,
musicFolderId,
setMusicFolderId: handleSetMusicFolderId,
};
};
const getDefaultMusicFolderId = (defaultValue: null | string, persisted: string | undefined) => {
if (persisted) {
return parseAsString.withDefault(persisted);
}
if (defaultValue) {
return parseAsString.withDefault(defaultValue);
}
return parseAsString;
};
@@ -1,22 +1,36 @@
import { parseAsString, useQueryState } from 'nuqs';
import { useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback';
export const useSearchTermFilter = (defaultValue?: string) => {
const [searchTerm, setSearchTerm] = useQueryState(
FILTER_KEYS.SHARED.SEARCH_TERM,
defaultValue ? parseAsString.withDefault(defaultValue) : parseAsString,
);
const [searchParams, setSearchParams] = useSearchParams();
const searchTerm = useMemo(() => {
const value = parseStringParam(searchParams, FILTER_KEYS.SHARED.SEARCH_TERM);
return value ?? defaultValue ?? undefined;
}, [searchParams, defaultValue]);
const handleSetSearchTerm = (value: null | string) => {
setSearchTerm(value === '' ? null : value);
setSearchParams(
(prev) => {
const newParams = setSearchParam(
prev,
FILTER_KEYS.SHARED.SEARCH_TERM,
value === '' ? null : value,
);
return newParams;
},
{ replace: true },
);
};
const debouncedSetSearchTerm = useDebouncedCallback(handleSetSearchTerm, 300);
return {
[FILTER_KEYS.SHARED.SEARCH_TERM]: searchTerm || undefined,
searchTerm: searchTerm || undefined,
setSearchTerm: debouncedSetSearchTerm,
};
};
@@ -1,7 +1,9 @@
import { parseAsString, useQueryState } from 'nuqs';
import { useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-list-filter-persistence';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { ItemListKey } from '/@/shared/types/types';
export const useSelectFilter = (
@@ -11,31 +13,29 @@ export const useSelectFilter = (
) => {
const server = useCurrentServer();
const { getFilter, setFilter } = useListFilterPersistence(server.id, listKey);
const [searchParams, setSearchParams] = useSearchParams();
const persisted = getFilter(filterKey);
const [value, setValue] = useQueryState(filterKey, getDefaultValue(defaultValue, persisted));
const value = useMemo(() => {
const paramValue = parseStringParam(searchParams, filterKey);
return paramValue ?? persisted ?? defaultValue ?? undefined;
}, [searchParams, filterKey, persisted, defaultValue]);
const handleSetValue = (newValue: string) => {
setValue(newValue);
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, filterKey, newValue);
return newParams;
},
{ replace: true },
);
setFilter(filterKey, newValue);
};
return {
[filterKey]: value ?? undefined,
[filterKey]: value,
setValue: handleSetValue,
value: value ?? undefined,
value,
};
};
const getDefaultValue = (defaultValue: null | string, persisted: string | undefined) => {
if (persisted) {
return parseAsString.withDefault(persisted);
}
if (defaultValue) {
return parseAsString.withDefault(defaultValue);
}
return parseAsString;
};
@@ -1,40 +1,37 @@
import { parseAsString, useQueryState } from 'nuqs';
import { useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-list-filter-persistence';
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { ItemListKey } from '/@/shared/types/types';
export const useSortByFilter = <TSortBy>(defaultValue: null | string, listKey: ItemListKey) => {
const server = useCurrentServer();
const { getFilter, setFilter } = useListFilterPersistence(server.id, listKey);
const [searchParams, setSearchParams] = useSearchParams();
const persisted = getFilter(FILTER_KEYS.SHARED.SORT_BY);
const [sortBy, setSortBy] = useQueryState(
FILTER_KEYS.SHARED.SORT_BY,
getDefaultSortBy(defaultValue, persisted),
);
const sortBy = useMemo(() => {
const value = parseStringParam(searchParams, FILTER_KEYS.SHARED.SORT_BY);
return (value ?? persisted ?? defaultValue ?? undefined) as TSortBy;
}, [searchParams, persisted, defaultValue]);
const handleSetSortBy = (sortBy: string) => {
setSortBy(sortBy);
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_BY, sortBy);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_BY, sortBy);
};
return {
[FILTER_KEYS.SHARED.SORT_BY]: sortBy as TSortBy,
setSortBy: handleSetSortBy,
sortBy,
};
};
const getDefaultSortBy = (defaultValue: null | string, persisted: string | undefined) => {
if (persisted) {
return parseAsString.withDefault(persisted);
}
if (defaultValue) {
return parseAsString.withDefault(defaultValue);
}
return parseAsString;
};
@@ -1,41 +1,38 @@
import { parseAsString, useQueryState } from 'nuqs';
import { useMemo } from 'react';
import { useSearchParams } from 'react-router';
import { useListFilterPersistence } from '/@/renderer/features/shared/hooks/use-list-filter-persistence';
import { FILTER_KEYS } from '/@/renderer/features/shared/utils';
import { useCurrentServer } from '/@/renderer/store';
import { parseStringParam, setSearchParam } from '/@/renderer/utils/query-params';
import { SortOrder } from '/@/shared/types/domain-types';
import { ItemListKey } from '/@/shared/types/types';
export const useSortOrderFilter = (defaultValue: null | string, listKey: ItemListKey) => {
const server = useCurrentServer();
const { getFilter, setFilter } = useListFilterPersistence(server.id, listKey);
const [searchParams, setSearchParams] = useSearchParams();
const persisted = getFilter(FILTER_KEYS.SHARED.SORT_ORDER);
const [sortOrder, setSortOrder] = useQueryState(
FILTER_KEYS.SHARED.SORT_ORDER,
getDefaultSortOrder(defaultValue, persisted),
);
const sortOrder = useMemo(() => {
const value = parseStringParam(searchParams, FILTER_KEYS.SHARED.SORT_ORDER);
return (value ?? persisted ?? defaultValue ?? undefined) as SortOrder;
}, [searchParams, persisted, defaultValue]);
const handleSetSortOrder = (sortOrder: SortOrder) => {
setSortOrder(sortOrder);
setSearchParams(
(prev) => {
const newParams = setSearchParam(prev, FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
return newParams;
},
{ replace: true },
);
setFilter(FILTER_KEYS.SHARED.SORT_ORDER, sortOrder);
};
return {
[FILTER_KEYS.SHARED.SORT_ORDER]: sortOrder as SortOrder,
setSortOrder: handleSetSortOrder,
sortOrder,
};
};
const getDefaultSortOrder = (defaultValue: null | string, persisted: string | undefined) => {
if (persisted) {
return parseAsString.withDefault(persisted);
}
if (defaultValue) {
return parseAsString.withDefault(defaultValue);
}
return parseAsString;
};
+7 -2
View File
@@ -44,7 +44,7 @@ enum AlbumFilterKeys {
HAS_RATING = 'hasRating',
MAX_YEAR = 'maxYear',
MIN_YEAR = 'minYear',
RECENTLY_PLAYED = 'recentlyPlayed',
RECENTLY_PLAYED = 'isRecentlyPlayed',
}
enum ArtistFilterKeys {
@@ -63,7 +63,7 @@ enum SongFilterKeys {
ALBUM_IDS = 'albumIds',
ARTIST_IDS = 'artistIds',
FAVORITE = 'favorite',
GENRE_ID = 'genreId',
GENRE_ID = 'genreIds',
MAX_YEAR = 'maxYear',
MIN_YEAR = 'minYear',
}
@@ -73,10 +73,15 @@ const PaginationFilterKeys = {
SCROLL_OFFSET: 'scrollOffset',
};
enum PlaylistFilterKeys {
CUSTOM = '_custom',
}
export const FILTER_KEYS = {
ALBUM: AlbumFilterKeys,
ARTIST: ArtistFilterKeys,
PAGINATION: PaginationFilterKeys,
PLAYLIST: PlaylistFilterKeys,
SHARED: SharedFilterKeys,
SONG: SongFilterKeys,
};