Improve Jellyfin/Navidrome Album/Song filter, Navidrome artist recent release

- Use `compilation=false` for Navidrome recent releases with artist credit
- Add `YesNoSelect` (yes, no, undefined) for `favorite` for Navidrome/Jellyfin `album`/`track`, and Navidrome `compilation`
- Fix folderButton translation
This commit is contained in:
Kendall Garner 2025-06-29 22:14:06 -07:00
parent b5bdea1845
commit 5456c2c2b8
No known key found for this signature in database
GPG key ID: 9355F387FE765C94
10 changed files with 119 additions and 62 deletions

View file

@ -1,5 +1,5 @@
import debounce from 'lodash/debounce';
import { ChangeEvent, useMemo } from 'react';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { MultiSelectWithInvalidData } from '/@/renderer/components/select-with-invalid-data';
@ -10,8 +10,8 @@ import { Divider } from '/@/shared/components/divider/divider';
import { Group } from '/@/shared/components/group/group';
import { NumberInput } from '/@/shared/components/number-input/number-input';
import { Stack } from '/@/shared/components/stack/stack';
import { Switch } from '/@/shared/components/switch/switch';
import { Text } from '/@/shared/components/text/text';
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
import { GenreListSort, LibraryItem, SongListQuery, SortOrder } from '/@/shared/types/domain-types';
interface JellyfinSongFiltersProps {
@ -69,10 +69,10 @@ export const JellyfinSongFilters = ({
return filter?._custom?.jellyfin?.Tags?.split('|');
}, [filter?._custom?.jellyfin?.Tags]);
const toggleFilters = [
const yesNoFilters = [
{
label: t('filter.isFavorited', { postProcess: 'sentenceCase' }),
onChange: (e: ChangeEvent<HTMLInputElement>) => {
onChange: (favorite?: boolean) => {
const updatedFilters = setFilter({
customFilters,
data: {
@ -83,7 +83,7 @@ export const JellyfinSongFilters = ({
IncludeItemTypes: 'Audio',
},
},
favorite: e.currentTarget.checked ? true : undefined,
favorite,
},
itemType: LibraryItem.SONG,
key: pageKey,
@ -174,15 +174,16 @@ export const JellyfinSongFilters = ({
return (
<Stack p="0.8rem">
{toggleFilters.map((filter) => (
{yesNoFilters.map((filter) => (
<Group
justify="space-between"
key={`nd-filter-${filter.label}`}
>
<Text>{filter.label}</Text>
<Switch
checked={filter?.value || false}
<YesNoSelect
onChange={filter.onChange}
size="xs"
value={filter.value}
/>
</Group>
))}
@ -218,7 +219,7 @@ export const JellyfinSongFilters = ({
/>
</Group>
)}
{tagsQuery.data?.boolTags?.length && (
{tagsQuery.data?.boolTags && tagsQuery.data.boolTags.length > 0 && (
<Group grow>
<MultiSelectWithInvalidData
clearable

View file

@ -1,5 +1,5 @@
import debounce from 'lodash/debounce';
import { ChangeEvent, useMemo } from 'react';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { SelectWithInvalidData } from '/@/renderer/components/select-with-invalid-data';
@ -10,8 +10,8 @@ import { Divider } from '/@/shared/components/divider/divider';
import { Group } from '/@/shared/components/group/group';
import { NumberInput } from '/@/shared/components/number-input/number-input';
import { Stack } from '/@/shared/components/stack/stack';
import { Switch } from '/@/shared/components/switch/switch';
import { Text } from '/@/shared/components/text/text';
import { YesNoSelect } from '/@/shared/components/yes-no-select/yes-no-select';
import { GenreListSort, LibraryItem, SongListQuery, SortOrder } from '/@/shared/types/domain-types';
interface NavidromeSongFiltersProps {
@ -93,12 +93,12 @@ export const NavidromeSongFilters = ({
const toggleFilters = [
{
label: t('filter.isFavorited', { postProcess: 'sentenceCase' }),
onChange: (e: ChangeEvent<HTMLInputElement>) => {
onChange: (favorite: boolean | undefined) => {
const updatedFilters = setFilter({
customFilters,
data: {
_custom: filter._custom,
favorite: e.currentTarget.checked ? true : undefined,
favorite,
},
itemType: LibraryItem.SONG,
key: pageKey,
@ -137,10 +137,10 @@ export const NavidromeSongFilters = ({
key={`nd-filter-${filter.label}`}
>
<Text>{filter.label}</Text>
<Switch
checked={filter?.value || false}
<YesNoSelect
onChange={filter.onChange}
size="xs"
value={filter.value}
/>
</Group>
))}

View file

@ -467,7 +467,7 @@ export const SongListHeaderFilters = ({
.filter((value) => value !== 'Audio') // Don't account for includeItemTypes: Audio
.some((value) => value !== undefined);
const isGenericFilterApplied = filter?.favorite || filter?.genreIds?.length;
const isGenericFilterApplied = filter?.favorite !== undefined || filter?.genreIds?.length;
return isNavidromeFilterApplied || isJellyfinFilterApplied || isGenericFilterApplied;
}, [

View file

@ -69,7 +69,7 @@ export const SubsonicSongFilters = ({
const updatedFilters = setFilter({
customFilters,
data: {
favorite: e.target.checked,
favorite: e.target.checked ? true : undefined,
},
itemType: LibraryItem.SONG,
key: pageKey,