properly handle disableArtistFilter and disableGenreFilter props for all list filters

This commit is contained in:
jeffvli
2026-01-18 14:07:52 -08:00
parent dad3d10a83
commit c3d4f6cacd
7 changed files with 91 additions and 67 deletions
@@ -3,7 +3,6 @@ import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters'; import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { genresQueries } from '/@/renderer/features/genres/api/genres-api'; import { genresQueries } from '/@/renderer/features/genres/api/genres-api';
@@ -32,16 +31,16 @@ import {
interface JellyfinAlbumFiltersProps { interface JellyfinAlbumFiltersProps {
disableArtistFilter?: boolean; disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
} }
export const JellyfinAlbumFilters = ({ disableArtistFilter }: JellyfinAlbumFiltersProps) => { export const JellyfinAlbumFilters = ({
disableArtistFilter,
disableGenreFilter,
}: JellyfinAlbumFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const serverId = useCurrentServerId(); const serverId = useCurrentServerId();
const { customFilters } = useListContext();
const isGenrePage = customFilters?.genreIds !== undefined;
const { const {
query, query,
setAlbumArtist, setAlbumArtist,
@@ -298,7 +297,7 @@ export const JellyfinAlbumFilters = ({ disableArtistFilter }: JellyfinAlbumFilte
/> />
</> </>
)} )}
{!isGenrePage && ( {!disableGenreFilter && (
<> <>
<Divider my="md" /> <Divider my="md" />
<VirtualMultiSelect <VirtualMultiSelect
@@ -3,7 +3,6 @@ import { ChangeEvent, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters'; import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
@@ -27,20 +26,21 @@ import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/dom
interface NavidromeAlbumFiltersProps { interface NavidromeAlbumFiltersProps {
disableArtistFilter?: boolean; disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
} }
export const NavidromeAlbumFilters = ({ disableArtistFilter }: NavidromeAlbumFiltersProps) => { export const NavidromeAlbumFilters = ({
disableArtistFilter,
disableGenreFilter,
}: NavidromeAlbumFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const server = useCurrentServer(); const server = useCurrentServer();
const serverId = server.id; const serverId = server.id;
const { customFilters } = useListContext();
const artistSelectMode = useAppStore((state) => state.artistSelectMode); const artistSelectMode = useAppStore((state) => state.artistSelectMode);
const genreSelectMode = useAppStore((state) => state.genreSelectMode); const genreSelectMode = useAppStore((state) => state.genreSelectMode);
const { setArtistSelectMode, setGenreSelectMode } = useAppStoreActions(); const { setArtistSelectMode, setGenreSelectMode } = useAppStoreActions();
const isGenrePage = customFilters?.genreIds !== undefined;
const { const {
query, query,
setAlbumArtist, setAlbumArtist,
@@ -327,7 +327,7 @@ export const NavidromeAlbumFilters = ({ disableArtistFilter }: NavidromeAlbumFil
/> />
</> </>
)} )}
{!isGenrePage && ( {!disableGenreFilter && (
<> <>
<Divider my="md" /> <Divider my="md" />
<VirtualMultiSelect <VirtualMultiSelect
@@ -3,7 +3,6 @@ import { ChangeEvent, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters'; import { useAlbumListFilters } from '/@/renderer/features/albums/hooks/use-album-list-filters';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
@@ -26,17 +25,17 @@ import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/dom
interface SubsonicAlbumFiltersProps { interface SubsonicAlbumFiltersProps {
disableArtistFilter?: boolean; disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
} }
export const SubsonicAlbumFilters = ({ disableArtistFilter }: SubsonicAlbumFiltersProps) => { export const SubsonicAlbumFilters = ({
disableArtistFilter,
disableGenreFilter,
}: SubsonicAlbumFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const serverId = useCurrentServerId(); const serverId = useCurrentServerId();
const { customFilters } = useListContext();
const isGenrePage = customFilters?.genreIds !== undefined;
const { query, setAlbumArtist, setFavorite, setGenreId, setMaxYear, setMinYear } = const { query, setAlbumArtist, setFavorite, setGenreId, setMaxYear, setMinYear } =
useAlbumListFilters(); useAlbumListFilters();
@@ -262,7 +261,7 @@ export const SubsonicAlbumFilters = ({ disableArtistFilter }: SubsonicAlbumFilte
/> />
</> </>
)} )}
{!isGenrePage && ( {!disableGenreFilter && (
<> <>
<Divider my="md" /> <Divider my="md" />
<VirtualMultiSelect <VirtualMultiSelect
@@ -39,7 +39,7 @@ export const isFilterValueSet = (value: unknown): boolean => {
export const ListFiltersModal = ({ isActive, itemType }: ListFiltersProps) => { export const ListFiltersModal = ({ isActive, itemType }: ListFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const server = useCurrentServer(); const server = useCurrentServer();
const { isSidebarOpen, setIsSidebarOpen } = useListContext(); const { isSidebarOpen, pageKey, setIsSidebarOpen } = useListContext();
const serverType = server.type; const serverType = server.type;
@@ -53,6 +53,9 @@ export const ListFiltersModal = ({ isActive, itemType }: ListFiltersProps) => {
const canPin = Boolean(setIsSidebarOpen); const canPin = Boolean(setIsSidebarOpen);
const disableArtistFilter = pageKey === ItemListKey.ALBUM_ARTIST_ALBUM;
const disableGenreFilter = pageKey === ItemListKey.GENRE_ALBUM;
return ( return (
<> <>
<FilterButton isActive={isActive} onClick={handlers.toggle} /> <FilterButton isActive={isActive} onClick={handlers.toggle} />
@@ -81,7 +84,10 @@ export const ListFiltersModal = ({ isActive, itemType }: ListFiltersProps) => {
</Group> </Group>
} }
> >
<FilterComponent /> <FilterComponent
disableArtistFilter={disableArtistFilter}
disableGenreFilter={disableGenreFilter}
/>
</Modal> </Modal>
</> </>
); );
@@ -91,11 +97,18 @@ export const ListFilters = ({ itemType }: ListFiltersProps) => {
const server = useCurrentServer(); const server = useCurrentServer();
const serverType = server.type; const serverType = server.type;
const FilterComponent = FILTERS[serverType][itemType]; const FilterComponent = FILTERS[serverType][itemType];
const { pageKey } = useListContext();
const disableArtistFilter = pageKey === ItemListKey.ALBUM_ARTIST_ALBUM;
const disableGenreFilter = pageKey === ItemListKey.GENRE_ALBUM;
return ( return (
<ComponentErrorBoundary> <ComponentErrorBoundary>
<Suspense fallback={<Spinner container />}> <Suspense fallback={<Spinner container />}>
<FilterComponent /> <FilterComponent
disableArtistFilter={disableArtistFilter}
disableGenreFilter={disableGenreFilter}
/>
</Suspense> </Suspense>
</ComponentErrorBoundary> </ComponentErrorBoundary>
); );
@@ -3,7 +3,6 @@ import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
import { import {
@@ -27,19 +26,19 @@ import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/dom
interface JellyfinSongFiltersProps { interface JellyfinSongFiltersProps {
disableArtistFilter?: boolean; disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
} }
export const JellyfinSongFilters = ({ disableArtistFilter }: JellyfinSongFiltersProps) => { export const JellyfinSongFilters = ({
disableArtistFilter,
disableGenreFilter,
}: JellyfinSongFiltersProps) => {
const server = useCurrentServer(); const server = useCurrentServer();
const serverId = server.id; const serverId = server.id;
const { t } = useTranslation(); const { t } = useTranslation();
const { query, setArtistIds, setCustom, setFavorite, setMaxYear, setMinYear } = const { query, setArtistIds, setCustom, setFavorite, setMaxYear, setMinYear } =
useSongListFilters(); useSongListFilters();
const { customFilters } = useListContext();
const isGenrePage = customFilters?.genreIds !== undefined;
// Despite the fact that getTags returns genres, it only returns genre names. // Despite the fact that getTags returns genres, it only returns genre names.
// We prefer using IDs, hence the double query // We prefer using IDs, hence the double query
const genreListQuery = useGenreList(); const genreListQuery = useGenreList();
@@ -280,7 +279,7 @@ export const JellyfinSongFilters = ({ disableArtistFilter }: JellyfinSongFilters
/> />
</> </>
)} )}
{!isGenrePage && ( {!disableGenreFilter && (
<> <>
<Divider my="md" /> <Divider my="md" />
<VirtualMultiSelect <VirtualMultiSelect
@@ -3,7 +3,6 @@ import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
import { import {
@@ -24,17 +23,21 @@ import { Text } from '/@/shared/components/text/text';
import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback'; import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback';
import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/domain-types'; import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/domain-types';
export const NavidromeSongFilters = () => { interface NavidromeSongFiltersProps {
disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
}
export const NavidromeSongFilters = ({
disableArtistFilter,
disableGenreFilter,
}: NavidromeSongFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const server = useCurrentServer(); const server = useCurrentServer();
const serverId = server.id; const serverId = server.id;
const { query, setArtistIds, setCustom, setFavorite, setGenreId, setMaxYear, setMinYear } = const { query, setArtistIds, setCustom, setFavorite, setGenreId, setMaxYear, setMinYear } =
useSongListFilters(); useSongListFilters();
const { customFilters } = useListContext();
const isGenrePage = customFilters?.genreIds !== undefined;
const genreListQuery = useGenreList(); const genreListQuery = useGenreList();
const genreList = useMemo(() => { const genreList = useMemo(() => {
@@ -257,18 +260,22 @@ export const NavidromeSongFilters = () => {
w="100%" w="100%"
/> />
</Stack> </Stack>
<Divider my="md" /> {!disableArtistFilter && (
<VirtualMultiSelect <>
displayCountType="song" <Divider my="md" />
height={300} <VirtualMultiSelect
label={artistFilterLabel} displayCountType="song"
onChange={handleArtistChange} height={300}
options={selectableAlbumArtists} label={artistFilterLabel}
RowComponent={ArtistMultiSelectRow} onChange={handleArtistChange}
singleSelect={artistSelectMode === 'single'} options={selectableAlbumArtists}
value={selectedArtistIds} RowComponent={ArtistMultiSelectRow}
/> singleSelect={artistSelectMode === 'single'}
{!isGenrePage && ( value={selectedArtistIds}
/>
</>
)}
{!disableGenreFilter && (
<VirtualMultiSelect <VirtualMultiSelect
displayCountType="song" displayCountType="song"
height={220} height={220}
@@ -3,7 +3,6 @@ import { ChangeEvent, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { useListContext } from '/@/renderer/context/list-context';
import { artistsQueries } from '/@/renderer/features/artists/api/artists-api'; import { artistsQueries } from '/@/renderer/features/artists/api/artists-api';
import { useGenreList } from '/@/renderer/features/genres/api/genres-api'; import { useGenreList } from '/@/renderer/features/genres/api/genres-api';
import { import {
@@ -20,15 +19,19 @@ import { Switch } from '/@/shared/components/switch/switch';
import { Text } from '/@/shared/components/text/text'; import { Text } from '/@/shared/components/text/text';
import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/domain-types'; import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/shared/types/domain-types';
export const SubsonicSongFilters = () => { interface SubsonicSongFiltersProps {
disableArtistFilter?: boolean;
disableGenreFilter?: boolean;
}
export const SubsonicSongFilters = ({
disableArtistFilter,
disableGenreFilter,
}: SubsonicSongFiltersProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const serverId = useCurrentServerId(); const serverId = useCurrentServerId();
const { query, setArtistIds, setFavorite, setGenreId } = useSongListFilters(); const { query, setArtistIds, setFavorite, setGenreId } = useSongListFilters();
const { customFilters } = useListContext();
const isGenrePage = customFilters?.genreIds !== undefined;
const genreListQuery = useGenreList(); const genreListQuery = useGenreList();
const genreList = useMemo(() => { const genreList = useMemo(() => {
@@ -149,19 +152,23 @@ export const SubsonicSongFilters = () => {
/> />
</Group> </Group>
))} ))}
<Divider my="md" /> {!disableArtistFilter && (
<VirtualMultiSelect <>
disabled={isArtistDisabled} <Divider my="md" />
displayCountType="song" <VirtualMultiSelect
height={300} disabled={isArtistDisabled}
label={artistFilterLabel} displayCountType="song"
onChange={handleArtistFilter} height={300}
options={selectableAlbumArtists} label={artistFilterLabel}
RowComponent={ArtistMultiSelectRow} onChange={handleArtistFilter}
singleSelect={true} options={selectableAlbumArtists}
value={selectedArtistIds} RowComponent={ArtistMultiSelectRow}
/> singleSelect={true}
{!isGenrePage && ( value={selectedArtistIds}
/>
</>
)}
{!disableGenreFilter && (
<> <>
<Divider my="md" /> <Divider my="md" />
<VirtualMultiSelect <VirtualMultiSelect