add has_rating filter for Navidrome song list

This commit is contained in:
jeffvli
2026-03-06 18:03:10 -08:00
parent d4c2b1e914
commit 9e08157517
6 changed files with 72 additions and 3 deletions
@@ -13,6 +13,7 @@ import { TagFilters } from '/@/renderer/features/shared/components/tag-filter';
import { useSongListFilters } from '/@/renderer/features/songs/hooks/use-song-list-filters';
import { useCurrentServer } from '/@/renderer/store';
import { useAppStore, useAppStoreActions } from '/@/renderer/store/app.store';
import { hasFeature } from '/@/shared/api/utils';
import { Divider } from '/@/shared/components/divider/divider';
import { Group } from '/@/shared/components/group/group';
import { VirtualMultiSelect } from '/@/shared/components/multi-select/virtual-multi-select';
@@ -27,6 +28,7 @@ import {
LibraryItem,
SortOrder,
} from '/@/shared/types/domain-types';
import { ServerFeature } from '/@/shared/types/features-types';
interface NavidromeSongFiltersProps {
disableArtistFilter?: boolean;
@@ -40,8 +42,18 @@ export const NavidromeSongFilters = ({
const { t } = useTranslation();
const server = useCurrentServer();
const serverId = server.id;
const { query, setArtistIds, setCustom, setFavorite, setGenreId, setMaxYear, setMinYear } =
useSongListFilters();
const {
query,
setArtistIds,
setCustom,
setFavorite,
setGenreId,
setHasRating,
setMaxYear,
setMinYear,
} = useSongListFilters();
const showRatingFilter = hasFeature(server, ServerFeature.TRACK_YES_NO_RATING_FILTER);
const genreListQuery = useQuery(
genresQueries.list({
@@ -278,6 +290,25 @@ export const NavidromeSongFilters = ({
w="100%"
/>
</Stack>
{showRatingFilter && (
<>
<Divider my="md" />
<Stack gap="xs">
<Text size="sm" weight={500}>
{t('filter.isRated', { postProcess: 'sentenceCase' })}
</Text>
<SegmentedControl
data={segmentedControlData}
onChange={(value) => {
setHasRating(segmentValueToBoolean(value));
}}
size="sm"
value={booleanToSegmentValue(query.hasRating)}
w="100%"
/>
</Stack>
</>
)}
{!disableArtistFilter && (
<>
<Divider my="md" />
@@ -53,6 +53,11 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
[searchParams],
);
const hasRating = useMemo(
() => parseBooleanParam(searchParams, FILTER_KEYS.SONG.HAS_RATING),
[searchParams],
);
const custom = useMemo(
() => parseCustomFiltersParam(searchParams, FILTER_KEYS.SONG._CUSTOM),
[searchParams],
@@ -103,6 +108,15 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
[setSearchParams],
);
const setHasRating = useCallback(
(value: boolean | null) => {
setSearchParams((prev) => setSearchParam(prev, FILTER_KEYS.SONG.HAS_RATING, value), {
replace: true,
});
},
[setSearchParams],
);
const setCustom = useCallback(
(
value:
@@ -142,6 +156,7 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
[FILTER_KEYS.SONG.ARTIST_IDS]: null,
[FILTER_KEYS.SONG.FAVORITE]: null,
[FILTER_KEYS.SONG.GENRE_ID]: null,
[FILTER_KEYS.SONG.HAS_RATING]: null,
[FILTER_KEYS.SONG.MAX_YEAR]: null,
[FILTER_KEYS.SONG.MIN_YEAR]: null,
},
@@ -160,10 +175,22 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
[FILTER_KEYS.SONG.ARTIST_IDS]: artistIds ?? undefined,
[FILTER_KEYS.SONG.FAVORITE]: favorite ?? undefined,
[FILTER_KEYS.SONG.GENRE_ID]: genreId ?? undefined,
[FILTER_KEYS.SONG.HAS_RATING]: hasRating ?? undefined,
[FILTER_KEYS.SONG.MAX_YEAR]: maxYear ?? undefined,
[FILTER_KEYS.SONG.MIN_YEAR]: minYear ?? undefined,
}),
[searchTerm, sortBy, sortOrder, custom, artistIds, favorite, genreId, maxYear, minYear],
[
searchTerm,
sortBy,
sortOrder,
custom,
artistIds,
favorite,
genreId,
hasRating,
maxYear,
minYear,
],
);
return {
@@ -173,6 +200,7 @@ export const useSongListFilters = (listKey?: ItemListKey) => {
setCustom,
setFavorite,
setGenreId,
setHasRating,
setMaxYear,
setMinYear,
setSearchTerm,