mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore(web): refactor search ui
This commit is contained in:
parent
b5adec7290
commit
993c757f33
8 changed files with 51 additions and 60 deletions
|
|
@ -9,9 +9,7 @@
|
|||
let filters = $derived(searchManager.filter.date);
|
||||
let invalid = $derived(filters.takenAfter && filters.takenBefore && filters.takenAfter > filters.takenBefore);
|
||||
|
||||
let currentPreset: SearchDatePreset | undefined = $derived(
|
||||
getSearchDatePreset(filters.takenAfter, filters.takenBefore),
|
||||
);
|
||||
let currentPreset = $derived(getSearchDatePreset(filters.takenAfter, filters.takenBefore));
|
||||
|
||||
const setPreset = (preset: SearchDatePreset) => {
|
||||
if (currentPreset === preset) {
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@
|
|||
import {
|
||||
getPeople,
|
||||
getSearchDatePreset,
|
||||
searchDateTitle,
|
||||
searchMediaTitle,
|
||||
searchPeopleTitle,
|
||||
searchPlacesTitle,
|
||||
searchTagsTitle,
|
||||
searchTypeTitle,
|
||||
getSearchDateTitle,
|
||||
getSearchMediaTitle,
|
||||
getSearchPeopleTitle,
|
||||
getSearchPlacesTitle,
|
||||
getSearchTagsTitle,
|
||||
getSearchTypeTitle,
|
||||
} from './search-bar-utils';
|
||||
import { onMount } from 'svelte';
|
||||
import { searchManager } from '$lib/managers/search-manager.svelte';
|
||||
|
|
@ -61,30 +61,30 @@
|
|||
|
||||
let searchHistory = $state<SearchHistorySection>();
|
||||
|
||||
let activeFilter: string = $state('type');
|
||||
let peoplePromise: Promise<PersonResponseDto[]> | undefined = $state(undefined);
|
||||
let people: PersonResponseDto[] | undefined = $state(undefined);
|
||||
let tagsPromise: Promise<TagResponseDto[]> | undefined = $state(undefined);
|
||||
let tags: TagResponseDto[] | undefined = $state(undefined);
|
||||
let activeFilter = $state('type');
|
||||
let peoplePromise = $state<Promise<PersonResponseDto[]>>();
|
||||
let people = $state<PersonResponseDto[]>();
|
||||
let tagsPromise = $state<Promise<TagResponseDto[]>>();
|
||||
let tags = $state<TagResponseDto[]>();
|
||||
|
||||
let typeTitle: string | undefined = $derived(searchTypeTitle(searchManager.filter.queryType));
|
||||
let peopleTitle: string | undefined = $state(undefined);
|
||||
let dateTitle: string | undefined = $derived(
|
||||
searchDateTitle(
|
||||
let typeTitle = $derived(getSearchTypeTitle(searchManager.filter.queryType));
|
||||
let peopleTitle = $state<string>();
|
||||
let dateTitle = $derived(
|
||||
getSearchDateTitle(
|
||||
getSearchDatePreset(searchManager.filter.date.takenAfter, searchManager.filter.date.takenBefore),
|
||||
searchManager.filter.date.takenAfter,
|
||||
searchManager.filter.date.takenBefore,
|
||||
),
|
||||
);
|
||||
let placesTitle: string | undefined = $derived(
|
||||
searchPlacesTitle(
|
||||
let placesTitle = $derived(
|
||||
getSearchPlacesTitle(
|
||||
searchManager.filter.location.city,
|
||||
searchManager.filter.location.state,
|
||||
searchManager.filter.location.country,
|
||||
),
|
||||
);
|
||||
let tagsTitle: string | undefined = $state(undefined);
|
||||
let mediaTitle: string | undefined = $derived(searchMediaTitle(searchManager.filter.mediaType));
|
||||
let tagsTitle = $state<string>();
|
||||
let mediaTitle = $derived(getSearchMediaTitle(searchManager.filter.mediaType));
|
||||
|
||||
let filters = [
|
||||
{
|
||||
|
|
@ -155,13 +155,13 @@
|
|||
|
||||
$effect(() => {
|
||||
if (people) {
|
||||
peopleTitle = searchPeopleTitle(people, searchManager.filter.personIds);
|
||||
peopleTitle = getSearchPeopleTitle(people, searchManager.filter.personIds);
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (tags) {
|
||||
tagsTitle = searchTagsTitle(tags, searchManager.filter.tagIds!);
|
||||
tagsTitle = getSearchTagsTitle(tags, searchManager.filter.tagIds!);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
let selectedIndex: number | undefined = $state(undefined);
|
||||
let element = $state<HTMLDivElement>();
|
||||
|
||||
const rootId = $props.id();
|
||||
|
||||
export function moveSelection(increment: 1 | -1) {
|
||||
if (!isSearchSuggestions) {
|
||||
return;
|
||||
|
|
@ -73,7 +75,7 @@
|
|||
if (index === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return `history-section-${index}`;
|
||||
return `${rootId}-entry-${index}`;
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@
|
|||
$effect(() => handlePromiseError(updateStates(countryFilter)));
|
||||
$effect(() => handlePromiseError(updateCities(countryFilter, stateFilter)));
|
||||
|
||||
onMount(() => {
|
||||
void updateCountries();
|
||||
});
|
||||
onMount(() => updateCountries());
|
||||
</script>
|
||||
|
||||
<div id="location-selection">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import ImageThumbnail from '$lib/components/assets/thumbnail/ImageThumbnail.svelte';
|
||||
import { getPeople, searchPeopleTitle } from './search-bar-utils';
|
||||
import { getPeople, getSearchPeopleTitle } from './search-bar-utils';
|
||||
import SingleGridRow from '$lib/components/shared-components/SingleGridRow.svelte';
|
||||
import SearchBar from '$lib/elements/SearchBar.svelte';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
selectedPeople.add(id);
|
||||
}
|
||||
|
||||
title = searchPeopleTitle(people, selectedPeople);
|
||||
title = getSearchPeopleTitle(people, selectedPeople);
|
||||
}
|
||||
|
||||
const filterPeople = (list: PersonResponseDto[], name: string) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import { onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import { mdiClose } from '@mdi/js';
|
||||
import { searchTagsTitle } from './search-bar-utils';
|
||||
import { getSearchTagsTitle } from './search-bar-utils';
|
||||
import { searchManager } from '$lib/managers/search-manager.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
selectedTags.add(option.value);
|
||||
selectedOption = undefined;
|
||||
title = searchTagsTitle(allTags, selectedTags);
|
||||
title = getSearchTagsTitle(allTags, selectedTags);
|
||||
};
|
||||
|
||||
const handleRemove = (tag: string) => {
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
}
|
||||
|
||||
selectedTags.delete(tag);
|
||||
title = searchTagsTitle(allTags, selectedTags);
|
||||
title = getSearchTagsTitle(allTags, selectedTags);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { searchTypeTitle } from './search-bar-utils';
|
||||
import { getSearchTypeTitle } from './search-bar-utils';
|
||||
import SearchButton from './SearchButton.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { searchManager } from '$lib/managers/search-manager.svelte';
|
||||
|
|
@ -23,17 +23,17 @@
|
|||
</SearchButton>
|
||||
{/if}
|
||||
<SearchButton checked active={queryType === 'metadata'} onclick={() => setType('metadata')}>
|
||||
{searchTypeTitle('metadata')}
|
||||
{getSearchTypeTitle('metadata')}
|
||||
</SearchButton>
|
||||
<SearchButton checked active={queryType === 'description'} onclick={() => setType('description')}>
|
||||
{searchTypeTitle('description')}
|
||||
{getSearchTypeTitle('description')}
|
||||
</SearchButton>
|
||||
<SearchButton checked active={queryType === 'fullPath'} onclick={() => setType('fullPath')}>
|
||||
{searchTypeTitle('fullPath')}
|
||||
{getSearchTypeTitle('fullPath')}
|
||||
</SearchButton>
|
||||
{#if featureFlagsManager.value.ocr}
|
||||
<SearchButton checked active={queryType === 'ocr'} onclick={() => setType('ocr')}>
|
||||
{searchTypeTitle('ocr')}
|
||||
{getSearchTypeTitle('ocr')}
|
||||
</SearchButton>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export enum SearchDatePreset {
|
|||
|
||||
export const getSearchDatePreset = (after: DateTime | undefined, before: DateTime | undefined) => {
|
||||
if (!after && !before) {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const start = after?.toMillis();
|
||||
|
|
@ -46,7 +46,7 @@ export const getSearchDateRange = (after: DateTime | undefined, before: DateTime
|
|||
return start && end ? $t('search_filter_date_interval', { values: { start, end } }) : (start ?? end);
|
||||
};
|
||||
|
||||
export const searchDateTitle = (
|
||||
export const getSearchDateTitle = (
|
||||
preset: SearchDatePreset | undefined,
|
||||
before: DateTime | undefined,
|
||||
after: DateTime | undefined,
|
||||
|
|
@ -66,12 +66,12 @@ export const searchDateTitle = (
|
|||
return getSearchDateRange(before, after);
|
||||
}
|
||||
default: {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const searchTypeTitle = (type: string) => {
|
||||
export const getSearchTypeTitle = (type: string) => {
|
||||
const $t = get(t);
|
||||
switch (type) {
|
||||
case 'metadata': {
|
||||
|
|
@ -87,23 +87,15 @@ export const searchTypeTitle = (type: string) => {
|
|||
return $t('ocr');
|
||||
}
|
||||
default: {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const searchPlacesTitle = (city?: string, state?: string, country?: string) => {
|
||||
let title = city;
|
||||
if (state) {
|
||||
title = title ? `${title}, ${state}` : state;
|
||||
}
|
||||
if (country) {
|
||||
title = title ? `${title}, ${country}` : country;
|
||||
}
|
||||
return title;
|
||||
};
|
||||
export const getSearchPlacesTitle = (city?: string, state?: string, country?: string) =>
|
||||
[city, state, country].filter(Boolean).join(', ') || undefined;
|
||||
|
||||
export const searchMediaTitle = (mediaType: MediaType) => {
|
||||
export const getSearchMediaTitle = (mediaType: MediaType) => {
|
||||
const $t = get(t);
|
||||
switch (mediaType) {
|
||||
case MediaType.Image: {
|
||||
|
|
@ -113,7 +105,7 @@ export const searchMediaTitle = (mediaType: MediaType) => {
|
|||
return $t('video');
|
||||
}
|
||||
default: {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -122,21 +114,22 @@ export const getPeople = async (selected: SvelteSet<string>): Promise<PersonResp
|
|||
const $t = get(t);
|
||||
try {
|
||||
const res = await getAllPeople({ withHidden: false });
|
||||
return [...res.people.filter((p) => selected.has(p.id)), ...res.people.filter((p) => !selected.has(p.id))];
|
||||
res.people.sort((a, b) => (selected.has(a.id) ? -1 : selected.has(b.id) ? 1 : 0));
|
||||
return res.people;
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.failed_to_get_people'));
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
export const searchPeopleTitle = (people: PersonResponseDto[], selected: SvelteSet<string>) => {
|
||||
export const getSearchPeopleTitle = (people: PersonResponseDto[], selected: SvelteSet<string>) => {
|
||||
if (selected.size === 0) {
|
||||
return undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const $t = get(t);
|
||||
|
||||
const name = people.filter((p) => p.name).find((p) => selected.has(p.id))?.name;
|
||||
const name = people.find(({ id, name }) => name && selected.has(id))?.name;
|
||||
if (name) {
|
||||
return selected.size === 1 ? name : $t('name_plus_more_people', { values: { name, count: selected.size - 1 } });
|
||||
}
|
||||
|
|
@ -144,7 +137,7 @@ export const searchPeopleTitle = (people: PersonResponseDto[], selected: SvelteS
|
|||
return $t('people_count', { values: { count: selected.size } });
|
||||
};
|
||||
|
||||
export const searchTagsTitle = (tags: TagResponseDto[], selected: SvelteSet<string>) => {
|
||||
export const getSearchTagsTitle = (tags: TagResponseDto[], selected: SvelteSet<string>) => {
|
||||
const $t = get(t);
|
||||
|
||||
const id = selected.values().next().value;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue