diff --git a/i18n/en.json b/i18n/en.json index a15666aed4..6cf5bbeaee 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1893,6 +1893,7 @@ "remove_assets_title": "Remove assets?", "remove_custom_date_range": "Remove custom date range", "remove_deleted_assets": "Remove Deleted Assets", + "remove_filter": "Remove filter", "remove_from_album": "Remove from album", "remove_from_album_action_prompt": "{count} removed from the album", "remove_from_favorites": "Remove from favorites", diff --git a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte index f32b74efa2..2f79b1143f 100644 --- a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -42,7 +42,7 @@ type SmartSearchDto, } from '@immich/sdk'; import { ActionButton, CommandPaletteDefaultProvider, Icon, IconButton, LoadingSpinner } from '@immich/ui'; - import { mdiArrowLeft, mdiDotsVertical, mdiImageOffOutline, mdiSelectAll } from '@mdi/js'; + import { mdiArrowLeft, mdiClose, mdiDotsVertical, mdiImageOffOutline, mdiSelectAll } from '@mdi/js'; import { tick, untrack } from 'svelte'; import { t } from 'svelte-i18n'; @@ -65,6 +65,7 @@ let searchQuery = $derived(page.url.searchParams.get(QueryParameter.QUERY)); let smartSearchEnabled = $derived(featureFlagsManager.value.smartSearch); let terms = $derived(searchQuery ? JSON.parse(searchQuery) : {}); + let searchTermKeys = $derived(getObjectKeys(terms)); $effect(() => { // we want this to *only* be reactive on `terms` @@ -235,50 +236,65 @@ function getObjectKeys(obj: T): (keyof T)[] { return Object.keys(obj) as (keyof T)[]; } + + function removeFilter(key: keyof SearchTerms) { + delete terms[key]; + void goto(Route.search(terms)); + } -{#if terms} -
- {#each getObjectKeys(terms) as searchKey (searchKey)} - {@const value = terms[searchKey]} -
+{#if searchTermKeys.length > 0} +
+
+ {#each searchTermKeys as searchKey (searchKey)} + {@const value = terms[searchKey]}
- {getHumanReadableSearchKey(searchKey as keyof SearchTerms)} -
+ + {getHumanReadableSearchKey(searchKey as keyof SearchTerms)} + - {#if value !== true} -
- {#if (searchKey === 'takenAfter' || searchKey === 'takenBefore') && typeof value === 'string'} - {getHumanReadableDate(value)} - {:else if searchKey === 'personIds' && Array.isArray(value)} - {#await getPersonName(value) then personName} - {personName} - {/await} - {:else if searchKey === 'tagIds' && (Array.isArray(value) || value === null)} - {#await getTagNames(value) then tagNames} - {tagNames} - {/await} - {:else if searchKey === 'rating'} - {$t('rating_count', { values: { count: value ?? 0 } })} - {:else if value === null || value === ''} - {$t('unknown')} - {:else} - {value} - {/if} -
- {/if} -
- {/each} + {#if value !== true} + + {#if (searchKey === 'takenAfter' || searchKey === 'takenBefore') && typeof value === 'string'} + {getHumanReadableDate(value)} + {:else if searchKey === 'personIds' && Array.isArray(value)} + {#await getPersonName(value) then personName} + {personName} + {/await} + {:else if searchKey === 'tagIds' && (Array.isArray(value) || value === null)} + {#await getTagNames(value) then tagNames} + {tagNames} + {/await} + {:else if searchKey === 'rating'} + {$t('rating_count', { values: { count: value ?? 0 } })} + {:else if value === null || value === ''} + {$t('unknown')} + {:else} + {value} + {/if} + + {/if} + + +
+ {/each} +
{/if}