add isEnabled property for playback filters

This commit is contained in:
jeffvli
2025-12-27 18:12:14 -08:00
parent 38b2508de6
commit f904aafd4a
3 changed files with 41 additions and 1 deletions
+1
View File
@@ -407,6 +407,7 @@ export const filterSongsByPlayerFilters = (songs: Song[], filters: PlayerFilter[
// Filter out invalid filters (missing field, operator, or value) // Filter out invalid filters (missing field, operator, or value)
const validFilters = filters.filter( const validFilters = filters.filter(
(filter) => (filter) =>
Boolean(filter.isEnabled) &&
filter.field && filter.field &&
filter.operator && filter.operator &&
filter.value !== undefined && filter.value !== undefined &&
@@ -21,6 +21,7 @@ import {
} from '/@/shared/api/navidrome/navidrome-types'; } from '/@/shared/api/navidrome/navidrome-types';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Button } from '/@/shared/components/button/button'; import { Button } from '/@/shared/components/button/button';
import { Checkbox } from '/@/shared/components/checkbox/checkbox';
import { DateInput } from '/@/shared/components/date-picker/date-picker'; import { DateInput } from '/@/shared/components/date-picker/date-picker';
import { Group } from '/@/shared/components/group/group'; import { Group } from '/@/shared/components/group/group';
import { NumberInput } from '/@/shared/components/number-input/number-input'; import { NumberInput } from '/@/shared/components/number-input/number-input';
@@ -165,12 +166,14 @@ const getOperatorsForFieldType = (
}; };
const FilterValueInput = ({ const FilterValueInput = ({
disabled,
field, field,
filterFields, filterFields,
onChange, onChange,
operator, operator,
value, value,
}: { }: {
disabled?: boolean;
field: PlayerFilterField; field: PlayerFilterField;
filterFields: FilterFieldConfig[]; filterFields: FilterFieldConfig[];
onChange: (value: (number | string)[] | boolean | number | string) => void; onChange: (value: (number | string)[] | boolean | number | string) => void;
@@ -203,6 +206,7 @@ const FilterValueInput = ({
{ label: 'true', value: 'true' }, { label: 'true', value: 'true' },
{ label: 'false', value: 'false' }, { label: 'false', value: 'false' },
]} ]}
disabled={disabled}
onChange={(e) => onChange(e === 'true')} onChange={(e) => onChange(e === 'true')}
value={value?.toString() || 'false'} value={value?.toString() || 'false'}
width="30%" width="30%"
@@ -215,6 +219,7 @@ const FilterValueInput = ({
<DateInput <DateInput
clearable clearable
defaultLevel="year" defaultLevel="year"
disabled={disabled}
maxWidth={170} maxWidth={170}
onChange={(date) => onChange(date || '')} onChange={(date) => onChange(date || '')}
size="sm" size="sm"
@@ -226,6 +231,7 @@ const FilterValueInput = ({
} }
return ( return (
<TextInput <TextInput
disabled={disabled}
onChange={(e) => onChange(e.currentTarget.value)} onChange={(e) => onChange(e.currentTarget.value)}
size="sm" size="sm"
value={(value as string) || ''} value={(value as string) || ''}
@@ -235,6 +241,7 @@ const FilterValueInput = ({
case 'number': case 'number':
return ( return (
<NumberInput <NumberInput
disabled={disabled}
onChange={(e) => onChange(Number(e) || 0)} onChange={(e) => onChange(Number(e) || 0)}
size="sm" size="sm"
value={value !== undefined && value !== null ? Number(value) : undefined} value={value !== undefined && value !== null ? Number(value) : undefined}
@@ -245,6 +252,7 @@ const FilterValueInput = ({
default: default:
return ( return (
<TextInput <TextInput
disabled={disabled}
onChange={(e) => onChange(e.currentTarget.value)} onChange={(e) => onChange(e.currentTarget.value)}
size="sm" size="sm"
value={(value as string) || ''} value={(value as string) || ''}
@@ -265,6 +273,7 @@ export const PlayerFilterSettings = () => {
const newFilter: PlayerFilter = { const newFilter: PlayerFilter = {
field: 'name', field: 'name',
id: nanoid(), id: nanoid(),
isEnabled: true,
operator: 'is', operator: 'is',
value: '', value: '',
}; };
@@ -322,6 +331,13 @@ export const PlayerFilterSettings = () => {
[filters, setPlaybackFilters], [filters, setPlaybackFilters],
); );
const handleToggleEnabled = useCallback(
(id: string, isEnabled: boolean) => {
setPlaybackFilters(filters.map((f) => (f.id === id ? { ...f, isEnabled } : f)));
},
[filters, setPlaybackFilters],
);
const fieldOptions = useMemo( const fieldOptions = useMemo(
() => filterFields.map((f) => ({ label: f.label, value: f.value })), () => filterFields.map((f) => ({ label: f.label, value: f.value })),
[filterFields], [filterFields],
@@ -344,8 +360,18 @@ export const PlayerFilterSettings = () => {
return ( return (
<Group gap="sm" key={filter.id}> <Group gap="sm" key={filter.id}>
<Checkbox
checked={filter.isEnabled ?? true}
onChange={(e) =>
handleToggleEnabled(
filter.id,
e.currentTarget.checked,
)
}
/>
<Select <Select
data={fieldOptions} data={fieldOptions}
disabled={!filter.isEnabled}
onChange={(e) => onChange={(e) =>
handleFieldChange(filter.id, e as PlayerFilterField) handleFieldChange(filter.id, e as PlayerFilterField)
} }
@@ -354,6 +380,7 @@ export const PlayerFilterSettings = () => {
/> />
<Select <Select
data={operators} data={operators}
disabled={!filter.isEnabled}
onChange={(e) => onChange={(e) =>
handleOperatorChange( handleOperatorChange(
filter.id, filter.id,
@@ -364,6 +391,7 @@ export const PlayerFilterSettings = () => {
width="25%" width="25%"
/> />
<FilterValueInput <FilterValueInput
disabled={!filter.isEnabled}
field={filter.field} field={filter.field}
filterFields={filterFields} filterFields={filterFields}
onChange={(value) => onChange={(value) =>
+12 -1
View File
@@ -476,6 +476,7 @@ const PlayerFilterOperatorSchema = z.enum([
const PlayerFilterSchema = z.object({ const PlayerFilterSchema = z.object({
field: PlayerFilterFieldSchema, field: PlayerFilterFieldSchema,
id: z.string(), id: z.string(),
isEnabled: z.boolean().optional(),
operator: PlayerFilterOperatorSchema, operator: PlayerFilterOperatorSchema,
value: z.union([ value: z.union([
z.string(), z.string(),
@@ -1792,10 +1793,20 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
} }
} }
if (version <= 18) {
// Add isEnabled property to all existing player filters
if (state.playback?.filters && Array.isArray(state.playback.filters)) {
state.playback.filters = state.playback.filters.map((filter) => ({
...filter,
isEnabled: true,
}));
}
}
return persistedState; return persistedState;
}, },
name: 'store_settings', name: 'store_settings',
version: 18, version: 19,
}, },
), ),
); );