mirror of
https://github.com/immich-app/immich.git
synced 2025-02-04 01:09:14 -05:00
simplify
This commit is contained in:
parent
5f98f12731
commit
565cac16d7
4 changed files with 64 additions and 51 deletions
|
@ -11,7 +11,7 @@
|
||||||
| 'transparent-gray'
|
| 'transparent-gray'
|
||||||
| 'dark-gray'
|
| 'dark-gray'
|
||||||
| 'overlay-primary';
|
| 'overlay-primary';
|
||||||
export type Size = 'tiny' | 'icon' | 'link' | 'sm' | 'base' | 'lg';
|
export type Size = 'tiny' | 'xs' | 'icon' | 'link' | 'sm' | 'base' | 'lg';
|
||||||
export type Rounded = 'lg' | '3xl' | 'full' | false;
|
export type Rounded = 'lg' | '3xl' | 'full' | false;
|
||||||
export type Shadow = 'md' | false;
|
export type Shadow = 'md' | false;
|
||||||
</script>
|
</script>
|
||||||
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
const sizeClasses: Record<Size, string> = {
|
const sizeClasses: Record<Size, string> = {
|
||||||
tiny: 'p-0 ml-2 mr-0 align-top',
|
tiny: 'p-0 ml-2 mr-0 align-top',
|
||||||
|
xs: 'p-2',
|
||||||
icon: 'p-2.5',
|
icon: 'p-2.5',
|
||||||
link: 'p-2 font-medium',
|
link: 'p-2 font-medium',
|
||||||
sm: 'px-4 py-2 text-sm font-medium',
|
sm: 'px-4 py-2 text-sm font-medium',
|
||||||
|
|
|
@ -22,9 +22,19 @@
|
||||||
let searchedPeople: PersonResponseDto[] = [];
|
let searchedPeople: PersonResponseDto[] = [];
|
||||||
let searchedPeopleCopy: PersonResponseDto[] = [];
|
let searchedPeopleCopy: PersonResponseDto[] = [];
|
||||||
let searchWord: string;
|
let searchWord: string;
|
||||||
let searchFaces = false;
|
let isSearchingPerson = false;
|
||||||
let searchName = '';
|
let searchName = '';
|
||||||
|
|
||||||
|
$: {
|
||||||
|
searchedPeople = searchedPeopleCopy.filter(
|
||||||
|
(person) => personWithFace.person && personWithFace.person.id !== person.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (searchName) {
|
||||||
|
searchedPeople = searchNameLocal(searchName, searchedPeople, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const handleBackButton = () => {
|
const handleBackButton = () => {
|
||||||
dispatch('close');
|
dispatch('close');
|
||||||
|
@ -63,10 +73,6 @@
|
||||||
isShowLoadingSearch = false;
|
isShowLoadingSearch = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
$: {
|
|
||||||
searchedPeople = searchNameLocal(searchName, searchedPeopleCopy, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
const initInput = (element: HTMLInputElement) => {
|
const initInput = (element: HTMLInputElement) => {
|
||||||
element.focus();
|
element.focus();
|
||||||
};
|
};
|
||||||
|
@ -77,7 +83,7 @@
|
||||||
class="absolute top-0 z-[2002] h-full w-[360px] overflow-x-hidden p-2 bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
class="absolute top-0 z-[2002] h-full w-[360px] overflow-x-hidden p-2 bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
||||||
>
|
>
|
||||||
<div class="flex place-items-center justify-between gap-2">
|
<div class="flex place-items-center justify-between gap-2">
|
||||||
{#if !searchFaces}
|
{#if !isSearchingPerson}
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
class="flex place-content-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
class="flex place-content-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
|
@ -94,7 +100,7 @@
|
||||||
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
title="Search existing person"
|
title="Search existing person"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
searchFaces = true;
|
isSearchingPerson = true;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
@ -143,7 +149,7 @@
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
class="flex place-content-center place-items-center rounded-full p-3 transition-colors hover:bg-gray-200 dark:text-immich-dark-fg dark:hover:bg-gray-900"
|
||||||
on:click={() => (searchFaces = false)}
|
on:click={() => (isSearchingPerson = false)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Icon path={mdiClose} size="24" />
|
<Icon path={mdiClose} size="24" />
|
||||||
|
@ -182,7 +188,6 @@
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
{#each searchedPeople as person (person.id)}
|
{#each searchedPeople as person (person.id)}
|
||||||
{#if person.id !== personWithFace.person?.id}
|
|
||||||
<div class="w-fit">
|
<div class="w-fit">
|
||||||
<button class="w-[90px]" on:click={() => dispatch('reassign', person)}>
|
<button class="w-[90px]" on:click={() => dispatch('reassign', person)}>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
|
@ -201,7 +206,6 @@
|
||||||
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import { currentAsset, photoViewer } from '$lib/stores/assets.store';
|
import { currentAsset, photoViewer } from '$lib/stores/assets.store';
|
||||||
import UnassignedFacesSidePannel from './unassigned-faces-side-pannel.svelte';
|
import UnassignedFacesSidePannel from './unassigned-faces-side-pannel.svelte';
|
||||||
import type { FaceWithGeneretedThumbnail } from '$lib/utils/people-utils';
|
import type { FaceWithGeneretedThumbnail } from '$lib/utils/people-utils';
|
||||||
|
import Button from '../elements/buttons/button.svelte';
|
||||||
|
|
||||||
// keep track of the changes
|
// keep track of the changes
|
||||||
let idsOfPersonToCreate: string[] = [];
|
let idsOfPersonToCreate: string[] = [];
|
||||||
|
@ -28,7 +29,7 @@
|
||||||
let selectedPersonToAdd: FaceWithGeneretedThumbnail[] = [];
|
let selectedPersonToAdd: FaceWithGeneretedThumbnail[] = [];
|
||||||
let selectedPersonToUnassign: FaceWithGeneretedThumbnail[] = [];
|
let selectedPersonToUnassign: FaceWithGeneretedThumbnail[] = [];
|
||||||
let selectedPersonToRemove: boolean[] = [];
|
let selectedPersonToRemove: boolean[] = [];
|
||||||
let unassignedFaces: (FaceWithGeneretedThumbnail | null)[] = [];
|
let unassignedFaces: FaceWithGeneretedThumbnail[] = [];
|
||||||
let editedPersonIndex: number;
|
let editedPersonIndex: number;
|
||||||
let shouldRefresh: boolean = false;
|
let shouldRefresh: boolean = false;
|
||||||
|
|
||||||
|
@ -83,7 +84,8 @@
|
||||||
selectedPersonToCreate = new Array<string | null>(peopleWithFaces.length);
|
selectedPersonToCreate = new Array<string | null>(peopleWithFaces.length);
|
||||||
selectedPersonToReassign = new Array<PersonResponseDto | null>(peopleWithFaces.length);
|
selectedPersonToReassign = new Array<PersonResponseDto | null>(peopleWithFaces.length);
|
||||||
selectedPersonToRemove = new Array<boolean>(peopleWithFaces.length);
|
selectedPersonToRemove = new Array<boolean>(peopleWithFaces.length);
|
||||||
unassignedFaces = await Promise.all(
|
unassignedFaces = (
|
||||||
|
await Promise.all(
|
||||||
peopleWithFaces.map(async (personWithFace) => {
|
peopleWithFaces.map(async (personWithFace) => {
|
||||||
if (personWithFace.person || $currentAsset === null) {
|
if (personWithFace.person || $currentAsset === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -92,7 +94,8 @@
|
||||||
return image ? { ...personWithFace, customThumbnail: image } : null;
|
return image ? { ...personWithFace, customThumbnail: image } : null;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
)
|
||||||
|
).filter((item): item is FaceWithGeneretedThumbnail => item !== null);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, "Can't get faces");
|
handleError(error, "Can't get faces");
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -149,9 +152,10 @@
|
||||||
|
|
||||||
const handleAddRemovedFace = (indexToRemove: number) => {
|
const handleAddRemovedFace = (indexToRemove: number) => {
|
||||||
$boundingBoxesArray = [];
|
$boundingBoxesArray = [];
|
||||||
unassignedFaces = unassignedFaces.map((obj) =>
|
unassignedFaces = unassignedFaces
|
||||||
obj && obj.id === selectedPersonToUnassign[indexToRemove].id ? null : obj,
|
.map((obj) => (obj && obj.id === selectedPersonToUnassign[indexToRemove].id ? null : obj))
|
||||||
);
|
.filter((item): item is FaceWithGeneretedThumbnail => item !== null) as FaceWithGeneretedThumbnail[];
|
||||||
|
|
||||||
selectedPersonToUnassign = selectedPersonToUnassign.filter((_, index) => index !== indexToRemove);
|
selectedPersonToUnassign = selectedPersonToUnassign.filter((_, index) => index !== indexToRemove);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -343,16 +347,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div>Visible faces</div>
|
<div>Faces visible</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if isSelectingFaces && selectedPersonToRemove && selectedPersonToRemove.filter((value) => value).length > 0}
|
{#if isSelectingFaces && selectedPersonToRemove && selectedPersonToRemove.filter((value) => value).length > 0}
|
||||||
<button
|
<Button
|
||||||
class="justify-self-end rounded-lg p-2 hover:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/50"
|
size="xs"
|
||||||
|
color="red"
|
||||||
|
title="Unassign faces"
|
||||||
|
shadow={false}
|
||||||
|
rounded="full"
|
||||||
on:click={handleUnassignFaces}
|
on:click={handleUnassignFaces}
|
||||||
>
|
>
|
||||||
Unassign faces
|
Unassign Faces
|
||||||
</button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 flex flex-wrap gap-2">
|
<div class="mt-2 flex flex-wrap gap-2">
|
||||||
|
@ -362,7 +370,7 @@
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each peopleWithFaces as face, index}
|
{#each peopleWithFaces as face, index}
|
||||||
{#if face.person && unassignedFaces[index] === null && !selectedPersonToUnassign.some((unassignedFace) => unassignedFace.id === face.id)}
|
{#if face.person && !unassignedFaces.some((unassignedFace) => unassignedFace.id === face.id) && !selectedPersonToUnassign.some((unassignedFace) => unassignedFace.id === face.id)}
|
||||||
<div class="relative z-[20001] h-[115px] w-[95px]">
|
<div class="relative z-[20001] h-[115px] w-[95px]">
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
import type { FaceWithGeneretedThumbnail } from '$lib/utils/people-utils';
|
import type { FaceWithGeneretedThumbnail } from '$lib/utils/people-utils';
|
||||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||||
|
|
||||||
export let unassignedFaces: (FaceWithGeneretedThumbnail | null)[];
|
export let unassignedFaces: FaceWithGeneretedThumbnail[];
|
||||||
export let allPeople: PersonResponseDto[];
|
export let allPeople: PersonResponseDto[];
|
||||||
export let selectedPersonToAdd: FaceWithGeneretedThumbnail[];
|
export let selectedPersonToAdd: FaceWithGeneretedThumbnail[];
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
<div class="px-4 py-4 text-sm">
|
<div class="px-4 py-4 text-sm">
|
||||||
<div class="mt-4 flex flex-wrap gap-2">
|
<div class="mt-4 flex flex-wrap gap-2">
|
||||||
{#each unassignedFaces as face, index}
|
{#each unassignedFaces as face, index}
|
||||||
{#if face && !selectedPersonToAdd.some((faceToAdd) => face && faceToAdd.id === face.id)}
|
{#if !selectedPersonToAdd.some((faceToAdd) => face && faceToAdd.id === face.id)}
|
||||||
<div class="relative z-[20001] h-[115px] w-[95px]">
|
<div class="relative z-[20001] h-[115px] w-[95px]">
|
||||||
<button
|
<button
|
||||||
tabindex={index}
|
tabindex={index}
|
||||||
|
|
Loading…
Add table
Reference in a new issue