From 16e00a0f9f982dbfcf31afc3c8c10e9a0eace4a5 Mon Sep 17 00:00:00 2001 From: Bram Johnson <89540826+bramjohnson@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:44:58 -0400 Subject: [PATCH] feat(playlists): add `isMissing` and `isPresent` operators to Navidrome smart playlist form (#2149) --- src/i18n/locales/en.json | 2 ++ .../query-builder/query-builder-option.tsx | 33 ++++++++++++------- src/shared/api/navidrome/navidrome-types.ts | 15 +++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 4e96df9ac..a14a1780d 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -314,6 +314,8 @@ "inTheRangeDate": "Is in the range (date)", "is": "Is", "isNot": "Is not", + "isMissing": "Is missing", + "isPresent": "Is present", "isGreaterThan": "Is greater than", "isLessThan": "Is less than", "matchesRegex": "Matches regex", diff --git a/src/renderer/components/query-builder/query-builder-option.tsx b/src/renderer/components/query-builder/query-builder-option.tsx index 5865b2192..56896f811 100644 --- a/src/renderer/components/query-builder/query-builder-option.tsx +++ b/src/renderer/components/query-builder/query-builder-option.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Filters } from '/@/renderer/components/query-builder'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; @@ -102,19 +102,28 @@ const QueryValueInput = ({ const isDatePickerOperator = operator === 'beforeDate' || operator === 'afterDate' || operator === 'inTheRangeDate'; + const BooleanSelectComponent = useMemo( + () => ( + - ); + return BooleanSelectComponent; case 'date': if (isDatePickerOperator && operator !== 'inTheRangeDate') { const dateValue = value ? parseDateValue(value) : null; diff --git a/src/shared/api/navidrome/navidrome-types.ts b/src/shared/api/navidrome/navidrome-types.ts index 2ae2084ad..bde37acbd 100644 --- a/src/shared/api/navidrome/navidrome-types.ts +++ b/src/shared/api/navidrome/navidrome-types.ts @@ -216,6 +216,17 @@ export const NDSongQueryPlaylistOperators = [ }, ]; +const NDPresenceOperators = [ + { + label: i18n.t('filterOperator.isMissing'), + value: 'isMissing', + }, + { + label: i18n.t('filterOperator.isPresent'), + value: 'isPresent', + }, +]; + export const NDSongQueryDateOperators = [ { label: i18n.t('filterOperator.is'), @@ -225,6 +236,7 @@ export const NDSongQueryDateOperators = [ label: i18n.t('filterOperator.isNot'), value: 'isNot', }, + ...NDPresenceOperators, { label: i18n.t('filterOperator.before'), value: 'before', @@ -268,6 +280,7 @@ export const NDSongQueryStringOperators = [ label: i18n.t('filterOperator.isNot'), value: 'isNot', }, + ...NDPresenceOperators, { label: i18n.t('filterOperator.contains'), value: 'contains', @@ -295,6 +308,7 @@ export const NDSongQueryBooleanOperators = [ label: i18n.t('filterOperator.isNot'), value: 'isNot', }, + ...NDPresenceOperators, ]; export const NDSongQueryNumberOperators = [ @@ -306,6 +320,7 @@ export const NDSongQueryNumberOperators = [ label: i18n.t('filterOperator.isNot'), value: 'isNot', }, + ...NDPresenceOperators, { label: i18n.t('filterOperator.contains'), value: 'contains',