diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index fa75049168..9d9ad48571 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -853,6 +853,7 @@ export type SearchExploreResponseDto = { items: SearchExploreItem[]; }; export type MetadataSearchDto = { + albumIds?: string[]; checksum?: string; city?: string | null; country?: string | null; @@ -929,6 +930,7 @@ export type PlacesResponseDto = { name: string; }; export type RandomSearchDto = { + albumIds?: string[]; city?: string | null; country?: string | null; createdAfter?: string; @@ -962,6 +964,7 @@ export type RandomSearchDto = { withStacked?: boolean; }; export type SmartSearchDto = { + albumIds?: string[]; city?: string | null; country?: string | null; createdAfter?: string; diff --git a/web/src/lib/components/shared-components/combobox.svelte b/web/src/lib/components/shared-components/combobox.svelte index 8d5800e9a8..b0aff6639e 100644 --- a/web/src/lib/components/shared-components/combobox.svelte +++ b/web/src/lib/components/shared-components/combobox.svelte @@ -5,6 +5,7 @@ id?: string; label: string; value: string; + thumbnail?: string; }; export const asComboboxOptions = (values: string[]) => @@ -380,12 +381,34 @@
  • handleSelect(option)} role="option" > - {option.label} + {#if option.thumbnail} +
    + {#if option.thumbnail === 'no-thumbnail'} +
    + {:else} + {option.label} + {/if} + {option.label} +
    + {:else} +
    + {option.label} +
    + {/if}
  • {/each} {/if} diff --git a/web/src/lib/components/shared-components/search-bar/search-albums-section.svelte b/web/src/lib/components/shared-components/search-bar/search-albums-section.svelte new file mode 100644 index 0000000000..a1f53f31e1 --- /dev/null +++ b/web/src/lib/components/shared-components/search-bar/search-albums-section.svelte @@ -0,0 +1,86 @@ + + +{#if $preferences?.tags?.enabled} +
    +
    +
    + ({ + id: album.id, + label: album.albumName, + value: album.id, + thumbnail: album.albumThumbnailAssetId ? getAssetThumbnailUrl(album.albumThumbnailAssetId) : 'no-thumbnail', + }))} + bind:selectedOption + placeholder={$t('search_albums')} + /> +
    +
    + +
    + {#each selectedAlbums as albumId (albumId)} + {@const album = albumMap[albumId]} + {#if album} +
    + +

    + {album.albumName} +

    +
    + + +
    + {/if} + {/each} +
    +
    +{/if} diff --git a/web/src/lib/components/shared-components/search-bar/search-display-section.svelte b/web/src/lib/components/shared-components/search-bar/search-display-section.svelte index afb8054920..17c872440c 100644 --- a/web/src/lib/components/shared-components/search-bar/search-display-section.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-display-section.svelte @@ -10,12 +10,21 @@ import { Checkbox, Label } from '@immich/ui'; import { t } from 'svelte-i18n'; + import type { SvelteSet } from 'svelte/reactivity'; interface Props { filters: SearchDisplayFilters; + selectedAlbums: SvelteSet; } - let { filters = $bindable() }: Props = $props(); + let { filters = $bindable(), selectedAlbums }: Props = $props(); + + //disable the filter if albums get selected + $effect(() => { + if (selectedAlbums?.size > 0) { + filters.isNotInAlbum = false; + } + });
    @@ -23,7 +32,12 @@ {$t('display_options').toUpperCase()}
    - + 0} + id="not-in-album-checkbox" + size="tiny" + bind:checked={filters.isNotInAlbum} + />
    diff --git a/web/src/lib/modals/SearchFilterModal.svelte b/web/src/lib/modals/SearchFilterModal.svelte index 78f80d0ba3..81dd2f06ca 100644 --- a/web/src/lib/modals/SearchFilterModal.svelte +++ b/web/src/lib/modals/SearchFilterModal.svelte @@ -8,6 +8,7 @@ query: string; queryType: 'smart' | 'metadata' | 'description'; personIds: SvelteSet; + albumIds: SvelteSet; tagIds: SvelteSet; location: SearchLocationFilter; camera: SearchCameraFilter; @@ -19,6 +20,7 @@