chore(web): migration svelte 5 syntax (#13883)

This commit is contained in:
Alex
2024-11-14 08:43:25 -06:00
committed by GitHub
parent 9203a61709
commit 0b3742cf13
310 changed files with 6435 additions and 4176 deletions
+64 -49
View File
@@ -38,34 +38,35 @@
import { fly } from 'svelte/transition';
import type { PageData } from './$types';
export let data: PageData;
interface Props {
data: PageData;
}
$: people = data.people.people;
$: visiblePeople = people.filter((people) => !people.isHidden);
$: countVisiblePeople = searchName ? searchedPeopleLocal.length : data.people.total - data.people.hidden;
$: showPeople = searchName ? searchedPeopleLocal : visiblePeople;
let selectHidden = false;
let searchName = '';
let showChangeNameModal = false;
let showSetBirthDateModal = false;
let showMergeModal = false;
let personName = '';
let nextPage = data.people.hasNextPage ? 2 : null;
let personMerge1: PersonResponseDto;
let personMerge2: PersonResponseDto;
let potentialMergePeople: PersonResponseDto[] = [];
let edittingPerson: PersonResponseDto | null = null;
let searchedPeopleLocal: PersonResponseDto[] = [];
let handleSearchPeople: (force?: boolean, name?: string) => Promise<void>;
let changeNameInputEl: HTMLInputElement | null;
let innerHeight: number;
let { data }: Props = $props();
let selectHidden = $state(false);
let searchName = $state('');
let showChangeNameModal = $state(false);
let showSetBirthDateModal = $state(false);
let showMergeModal = $state(false);
let personName = $state('');
let nextPage = $state(data.people.hasNextPage ? 2 : null);
let personMerge1 = $state<PersonResponseDto>();
let personMerge2 = $state<PersonResponseDto>();
let potentialMergePeople: PersonResponseDto[] = $state([]);
let edittingPerson: PersonResponseDto | null = $state(null);
let searchedPeopleLocal: PersonResponseDto[] = $state([]);
// let handleSearchPeople: (force?: boolean, name?: string) => Promise<void> = $state();
let changeNameInputEl = $state<HTMLInputElement>();
let innerHeight = $state(0);
let searchPeopleElement = $state<ReturnType<typeof SearchPeople>>();
onMount(() => {
const getSearchedPeople = $page.url.searchParams.get(QueryParameter.SEARCHED_PEOPLE);
if (getSearchedPeople) {
searchName = getSearchedPeople;
handlePromiseError(handleSearchPeople(true, searchName));
if (searchPeopleElement) {
handlePromiseError(searchPeopleElement.searchPeople(true, searchName));
}
}
return websocketEvents.on('on_person_thumbnail', (personId: string) => {
for (const person of people) {
@@ -198,7 +199,9 @@
);
};
const submitNameChange = async () => {
const submitNameChange = async (event: Event) => {
event.preventDefault();
potentialMergePeople = [];
showChangeNameModal = false;
if (!edittingPerson || personName === edittingPerson.name) {
@@ -225,9 +228,9 @@
potentialMergePeople = people
.filter(
(person: PersonResponseDto) =>
personMerge2.name.toLowerCase() === person.name.toLowerCase() &&
personMerge2?.name.toLowerCase() === person.name.toLowerCase() &&
person.id !== personMerge2.id &&
person.id !== personMerge1.id &&
person.id !== personMerge1?.id &&
!person.isHidden,
)
.slice(0, 3);
@@ -293,11 +296,26 @@
const onResetSearchBar = async () => {
await clearQueryParam(QueryParameter.SEARCHED_PEOPLE, $page.url);
};
let people = $state(data.people.people);
$effect(() => {
people = data.people.people;
});
let visiblePeople = $derived(people.filter((people) => !people.isHidden));
let countVisiblePeople = $derived(searchName ? searchedPeopleLocal.length : data.people.total - data.people.hidden);
let showPeople = $derived(searchName ? searchedPeopleLocal : visiblePeople);
// const submitNameChange = (event: Event) => {
// event.preventDefault();
// if (searchPeopleElement) {
// handlePromiseError(searchPeopleElement.searchPeople(true, searchName));
// }
// };
</script>
<svelte:window bind:innerHeight />
{#if showMergeModal}
{#if showMergeModal && personMerge1 && personMerge2}
<MergeSuggestionModal
{personMerge1}
{personMerge2}
@@ -312,23 +330,23 @@
title={$t('people')}
description={countVisiblePeople === 0 && !searchName ? undefined : `(${countVisiblePeople.toLocaleString($locale)})`}
>
<svelte:fragment slot="buttons">
{#snippet buttons()}
{#if people.length > 0}
<div class="flex gap-2 items-center justify-center">
<div class="hidden sm:block">
<div class="w-40 lg:w-80 h-10">
<SearchPeople
bind:this={searchPeopleElement}
type="searchBar"
placeholder={$t('search_people')}
onReset={onResetSearchBar}
onSearch={handleSearch}
bind:searchName
bind:searchedPeopleLocal
bind:handleSearch={handleSearchPeople}
/>
</div>
</div>
<LinkButton on:click={() => (selectHidden = !selectHidden)}>
<LinkButton onclick={() => (selectHidden = !selectHidden)}>
<div class="flex flex-wrap place-items-center justify-center gap-x-1 text-sm">
<Icon path={mdiEyeOutline} size="18" />
<p class="ml-2">{$t('show_and_hide_people')}</p>
@@ -336,24 +354,20 @@
</LinkButton>
</div>
{/if}
</svelte:fragment>
{/snippet}
{#if countVisiblePeople > 0 && (!searchName || searchedPeopleLocal.length > 0)}
<PeopleInfiniteScroll
people={showPeople}
hasNextPage={!!nextPage && !searchName}
{loadNextPage}
let:person
let:index
>
<PeopleCard
{person}
preload={index < 20}
onChangeName={() => handleChangeName(person)}
onSetBirthDate={() => handleSetBirthDate(person)}
onMergePeople={() => handleMergePeople(person)}
onHidePerson={() => handleHidePerson(person)}
/>
<PeopleInfiniteScroll people={showPeople} hasNextPage={!!nextPage && !searchName} {loadNextPage}>
{#snippet children({ person, index })}
<PeopleCard
{person}
preload={index < 20}
onChangeName={() => handleChangeName(person)}
onSetBirthDate={() => handleSetBirthDate(person)}
onMergePeople={() => handleMergePeople(person)}
onHidePerson={() => handleHidePerson(person)}
/>
{/snippet}
</PeopleInfiniteScroll>
{:else}
<div class="flex min-h-[calc(66vh_-_11rem)] w-full place-content-center items-center dark:text-white">
@@ -368,7 +382,7 @@
{#if showChangeNameModal}
<FullScreenModal title={$t('change_name')} onClose={() => (showChangeNameModal = false)}>
<form on:submit|preventDefault={submitNameChange} autocomplete="off" id="change-name-form">
<form onsubmit={submitNameChange} autocomplete="off" id="change-name-form">
<div class="flex flex-col gap-2">
<label class="immich-form-label" for="name">{$t('name')}</label>
<input
@@ -381,16 +395,17 @@
/>
</div>
</form>
<svelte:fragment slot="sticky-bottom">
{#snippet stickyBottom()}
<Button
color="gray"
fullwidth
on:click={() => {
onclick={() => {
showChangeNameModal = false;
}}>{$t('cancel')}</Button
>
<Button type="submit" fullwidth form="change-name-form">{$t('ok')}</Button>
</svelte:fragment>
{/snippet}
</FullScreenModal>
{/if}
@@ -25,7 +25,7 @@
NotificationType,
notificationController,
} from '$lib/components/shared-components/notification/notification';
import { AppRoute, QueryParameter } from '$lib/constants';
import { AppRoute, PersonPageViewMode, QueryParameter } from '$lib/constants';
import { createAssetInteractionStore } from '$lib/stores/asset-interaction.store';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { AssetStore } from '$lib/stores/assets.store';
@@ -58,47 +58,33 @@
import { t } from 'svelte-i18n';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
export let data: PageData;
let numberOfAssets = data.statistics.assets;
let { isViewing: showAssetViewer } = assetViewingStore;
enum ViewMode {
VIEW_ASSETS = 'view-assets',
SELECT_PERSON = 'select-person',
MERGE_PEOPLE = 'merge-people',
SUGGEST_MERGE = 'suggest-merge',
BIRTH_DATE = 'birth-date',
UNASSIGN_ASSETS = 'unassign-faces',
interface Props {
data: PageData;
}
let { data = $bindable() }: Props = $props();
let numberOfAssets = $state(data.statistics.assets);
let { isViewing: showAssetViewer } = assetViewingStore;
let assetStore = new AssetStore({
isArchived: false,
personId: data.person.id,
});
$: person = data.person;
$: thumbnailData = getPeopleThumbnailUrl(person);
$: if (person) {
handlePromiseError(updateAssetCount());
handlePromiseError(assetStore.updateOptions({ personId: person.id }));
}
const assetInteractionStore = createAssetInteractionStore();
const { selectedAssets, isMultiSelectState } = assetInteractionStore;
let viewMode: ViewMode = ViewMode.VIEW_ASSETS;
let isEditingName = false;
let previousRoute: string = AppRoute.EXPLORE;
let viewMode: PersonPageViewMode = $state(PersonPageViewMode.VIEW_ASSETS);
let isEditingName = $state(false);
let previousRoute: string = $state(AppRoute.EXPLORE);
let people: PersonResponseDto[] = [];
let personMerge1: PersonResponseDto;
let personMerge2: PersonResponseDto;
let potentialMergePeople: PersonResponseDto[] = [];
let refreshAssetGrid = false;
let personMerge1: PersonResponseDto | undefined = $state();
let personMerge2: PersonResponseDto | undefined = $state();
let potentialMergePeople: PersonResponseDto[] = $state([]);
let personName = '';
let suggestedPeople: PersonResponseDto[] = [];
let suggestedPeople: PersonResponseDto[] = $state([]);
/**
* Save the word used to search people name: for example,
@@ -107,11 +93,8 @@
* However, it needs to make a new api request if searching 'r' returns 20 names (arbitrary value, the limit sent back by the server).
* or if the new search word starts with another word / letter
**/
let isSearchingPeople = false;
let suggestionContainer: HTMLDivElement;
$: isAllArchive = [...$selectedAssets].every((asset) => asset.isArchived);
$: isAllFavorite = [...$selectedAssets].every((asset) => asset.isFavorite);
let isSearchingPeople = $state(false);
let suggestionContainer: HTMLElement | undefined = $state();
onMount(() => {
const action = $page.url.searchParams.get(QueryParameter.ACTION);
@@ -120,7 +103,7 @@
previousRoute = getPreviousRoute;
}
if (action == 'merge') {
viewMode = ViewMode.MERGE_PEOPLE;
viewMode = PersonPageViewMode.MERGE_PEOPLE;
}
return websocketEvents.on('on_person_thumbnail', (personId: string) => {
@@ -131,7 +114,7 @@
});
const handleEscape = async () => {
if ($showAssetViewer || viewMode === ViewMode.SUGGEST_MERGE) {
if ($showAssetViewer || viewMode === PersonPageViewMode.SUGGEST_MERGE) {
return;
}
if ($isMultiSelectState) {
@@ -162,11 +145,11 @@
const handleUnmerge = () => {
$assetStore.removeAssets([...$selectedAssets].map((a) => a.id));
assetInteractionStore.clearMultiselect();
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
};
const handleReassignAssets = () => {
viewMode = ViewMode.UNASSIGN_ASSETS;
viewMode = PersonPageViewMode.UNASSIGN_ASSETS;
};
const toggleHidePerson = async () => {
@@ -191,13 +174,11 @@
await updateAssetCount();
await handleGoBack();
data.person = person;
refreshAssetGrid = !refreshAssetGrid;
data = { ...data, person };
};
const handleSelectFeaturePhoto = async (asset: AssetResponseDto) => {
if (viewMode !== ViewMode.SELECT_PERSON) {
if (viewMode !== PersonPageViewMode.SELECT_PERSON) {
return;
}
try {
@@ -209,12 +190,12 @@
assetInteractionStore.clearMultiselect();
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
};
const handleMergeSamePerson = async (response: [PersonResponseDto, PersonResponseDto]) => {
const [personToMerge, personToBeMergedIn] = response;
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
isEditingName = false;
try {
await mergePerson({
@@ -228,7 +209,6 @@
people = people.filter((person: PersonResponseDto) => person.id !== personToMerge.id);
if (personToBeMergedIn.name != personName && person.id === personToBeMergedIn.id) {
await updateAssetCount();
refreshAssetGrid = !refreshAssetGrid;
return;
}
await goto(`${AppRoute.PEOPLE}/${personToBeMergedIn.id}`, { replaceState: true });
@@ -243,11 +223,11 @@
personName = person.name;
personMerge1 = person;
personMerge2 = person2;
viewMode = ViewMode.SUGGEST_MERGE;
viewMode = PersonPageViewMode.SUGGEST_MERGE;
};
const changeName = async () => {
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
person.name = personName;
try {
isEditingName = false;
@@ -264,7 +244,7 @@
};
const handleCancelEditName = () => {
if (viewMode === ViewMode.SUGGEST_MERGE) {
if (viewMode === PersonPageViewMode.SUGGEST_MERGE) {
return;
}
isSearchingPeople = false;
@@ -295,13 +275,13 @@
potentialMergePeople = result
.filter(
(person: PersonResponseDto) =>
personMerge2.name.toLowerCase() === person.name.toLowerCase() &&
personMerge2?.name.toLowerCase() === person.name.toLowerCase() &&
person.id !== personMerge2.id &&
person.id !== personMerge1.id &&
person.id !== personMerge1?.id &&
!person.isHidden,
)
.slice(0, 3);
viewMode = ViewMode.SUGGEST_MERGE;
viewMode = PersonPageViewMode.SUGGEST_MERGE;
return;
}
await changeName();
@@ -309,7 +289,7 @@
const handleSetBirthDate = async (birthDate: string) => {
try {
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
person.birthDate = birthDate;
const updatedPerson = await updatePerson({
@@ -331,7 +311,7 @@
};
const handleGoBack = async () => {
viewMode = ViewMode.VIEW_ASSETS;
viewMode = PersonPageViewMode.VIEW_ASSETS;
if ($page.url.searchParams.has(QueryParameter.ACTION)) {
$page.url.searchParams.delete(QueryParameter.ACTION);
await goto($page.url);
@@ -341,37 +321,50 @@
onDestroy(() => {
assetStore.destroy();
});
let person = $derived(data.person);
let thumbnailData = $derived(getPeopleThumbnailUrl(person));
$effect(() => {
if (person) {
handlePromiseError(updateAssetCount());
handlePromiseError(assetStore.updateOptions({ personId: person.id }));
}
});
let isAllArchive = $derived([...$selectedAssets].every((asset) => asset.isArchived));
let isAllFavorite = $derived([...$selectedAssets].every((asset) => asset.isFavorite));
</script>
{#if viewMode === ViewMode.UNASSIGN_ASSETS}
{#if viewMode === PersonPageViewMode.UNASSIGN_ASSETS}
<UnMergeFaceSelector
assetIds={[...$selectedAssets].map((a) => a.id)}
personAssets={person}
onClose={() => (viewMode = ViewMode.VIEW_ASSETS)}
onClose={() => (viewMode = PersonPageViewMode.VIEW_ASSETS)}
onConfirm={handleUnmerge}
/>
{/if}
{#if viewMode === ViewMode.SUGGEST_MERGE}
{#if viewMode === PersonPageViewMode.SUGGEST_MERGE && personMerge1 && personMerge2}
<MergeSuggestionModal
{personMerge1}
{personMerge2}
{potentialMergePeople}
onClose={() => (viewMode = ViewMode.VIEW_ASSETS)}
onClose={() => (viewMode = PersonPageViewMode.VIEW_ASSETS)}
onReject={changeName}
onConfirm={handleMergeSamePerson}
/>
{/if}
{#if viewMode === ViewMode.BIRTH_DATE}
{#if viewMode === PersonPageViewMode.BIRTH_DATE}
<SetBirthDateModal
birthDate={person.birthDate ?? ''}
onClose={() => (viewMode = ViewMode.VIEW_ASSETS)}
onClose={() => (viewMode = PersonPageViewMode.VIEW_ASSETS)}
onUpdate={handleSetBirthDate}
/>
{/if}
{#if viewMode === ViewMode.MERGE_PEOPLE}
{#if viewMode === PersonPageViewMode.MERGE_PEOPLE}
<MergeFaceSelector {person} onBack={handleGoBack} onMerge={handleMerge} />
{/if}
@@ -399,14 +392,14 @@
</ButtonContextMenu>
</AssetSelectControlBar>
{:else}
{#if viewMode === ViewMode.VIEW_ASSETS || viewMode === ViewMode.SUGGEST_MERGE || viewMode === ViewMode.BIRTH_DATE}
{#if viewMode === PersonPageViewMode.VIEW_ASSETS || viewMode === PersonPageViewMode.SUGGEST_MERGE || viewMode === PersonPageViewMode.BIRTH_DATE}
<ControlAppBar showBackButton backIcon={mdiArrowLeft} onClose={() => goto(previousRoute)}>
<svelte:fragment slot="trailing">
{#snippet trailing()}
<ButtonContextMenu icon={mdiDotsVertical} title={$t('menu')}>
<MenuOption
text={$t('select_featured_photo')}
icon={mdiAccountBoxOutline}
onClick={() => (viewMode = ViewMode.SELECT_PERSON)}
onClick={() => (viewMode = PersonPageViewMode.SELECT_PERSON)}
/>
<MenuOption
text={person.isHidden ? $t('unhide_person') : $t('hide_person')}
@@ -416,21 +409,23 @@
<MenuOption
text={$t('set_date_of_birth')}
icon={mdiCalendarEditOutline}
onClick={() => (viewMode = ViewMode.BIRTH_DATE)}
onClick={() => (viewMode = PersonPageViewMode.BIRTH_DATE)}
/>
<MenuOption
text={$t('merge_people')}
icon={mdiAccountMultipleCheckOutline}
onClick={() => (viewMode = ViewMode.MERGE_PEOPLE)}
onClick={() => (viewMode = PersonPageViewMode.MERGE_PEOPLE)}
/>
</ButtonContextMenu>
</svelte:fragment>
{/snippet}
</ControlAppBar>
{/if}
{#if viewMode === ViewMode.SELECT_PERSON}
<ControlAppBar onClose={() => (viewMode = ViewMode.VIEW_ASSETS)}>
<svelte:fragment slot="leading">{$t('select_featured_photo')}</svelte:fragment>
{#if viewMode === PersonPageViewMode.SELECT_PERSON}
<ControlAppBar onClose={() => (viewMode = PersonPageViewMode.VIEW_ASSETS)}>
{#snippet leading()}
{$t('select_featured_photo')}
{/snippet}
</ControlAppBar>
{/if}
{/if}
@@ -442,12 +437,12 @@
enableRouting={true}
{assetStore}
{assetInteractionStore}
isSelectionMode={viewMode === ViewMode.SELECT_PERSON}
singleSelect={viewMode === ViewMode.SELECT_PERSON}
isSelectionMode={viewMode === PersonPageViewMode.SELECT_PERSON}
singleSelect={viewMode === PersonPageViewMode.SELECT_PERSON}
onSelect={handleSelectFeaturePhoto}
onEscape={handleEscape}
>
{#if viewMode === ViewMode.VIEW_ASSETS || viewMode === ViewMode.SUGGEST_MERGE || viewMode === ViewMode.BIRTH_DATE}
{#if viewMode === PersonPageViewMode.VIEW_ASSETS || viewMode === PersonPageViewMode.SUGGEST_MERGE || viewMode === PersonPageViewMode.BIRTH_DATE}
<!-- Person information block -->
<div
class="relative w-fit p-4 sm:px-6"
@@ -473,7 +468,7 @@
type="button"
class="flex items-center justify-center"
title={$t('edit_name')}
on:click={() => (isEditingName = true)}
onclick={() => (isEditingName = true)}
>
<ImageThumbnail
circle
@@ -510,11 +505,11 @@
{#each suggestedPeople as person, index (person.id)}
<button
type="button"
class="flex w-full border-t border-gray-400 dark:border-immich-dark-gray h-14 place-items-center bg-gray-200 p-2 dark:bg-gray-700 hover:bg-gray-300 hover:dark:bg-[#232932] focus:bg-gray-300 focus:dark:bg-[#232932] {index ===
class="flex w-full border border-gray-200 dark:border-immich-dark-gray h-14 place-items-center bg-gray-100 p-2 dark:bg-gray-700 hover:bg-gray-300 hover:dark:bg-[#232932] focus:bg-gray-300 focus:dark:bg-[#232932] {index ===
suggestedPeople.length - 1
? 'rounded-b-lg border-b'
: ''}"
on:click={() => handleSuggestPeople(person)}
onclick={() => handleSuggestPeople(person)}
>
<ImageThumbnail
circle