refactor: use immich/ui PasswordInput (#22099)

refactor: password-input
This commit is contained in:
Jason Rasmussen
2025-09-16 16:09:09 -04:00
committed by GitHub
parent 7fe2f19258
commit 6ffd8e679e
7 changed files with 28 additions and 73 deletions

View File

@@ -182,7 +182,7 @@
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
inputType={SettingInputFieldType.NUMBER}
label={$t('admin.oauth_timeout')}
description={$t('admin.oauth_timeout_description')}
required={true}

View File

@@ -1,13 +1,13 @@
<script lang="ts">
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
import { SettingInputFieldType } from '$lib/constants';
import { getJobName } from '$lib/utils';
import { JobName, type SystemConfigDto, type SystemConfigJobDto } from '@immich/sdk';
import { isEqual } from 'lodash-es';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings';
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
import { t } from 'svelte-i18n';
import { SettingInputFieldType } from '$lib/constants';
interface Props {
savedConfig: SystemConfigDto;
@@ -63,7 +63,7 @@
inputType={SettingInputFieldType.NUMBER}
label={$t('admin.job_concurrency', { values: { job: $getJobName(jobName) } })}
description=""
value="1"
value={1}
disabled={true}
title={$t('admin.job_not_concurrency_safe')}
/>

View File

@@ -3,7 +3,6 @@
import IndividualSharedViewer from '$lib/components/share-page/individual-shared-viewer.svelte';
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
import ImmichLogoSmallLink from '$lib/components/shared-components/immich-logo-small-link.svelte';
import PasswordField from '$lib/components/shared-components/password-field.svelte';
import ThemeButton from '$lib/components/shared-components/theme-button.svelte';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { user } from '$lib/stores/user.store';
@@ -11,7 +10,7 @@
import { handleError } from '$lib/utils/handle-error';
import { navigate } from '$lib/utils/navigation';
import { getMySharedLink, SharedLinkType, type AssetResponseDto, type SharedLinkResponseDto } from '@immich/sdk';
import { Button } from '@immich/ui';
import { Button, PasswordInput } from '@immich/ui';
import { tick } from 'svelte';
import { t } from 'svelte-i18n';
@@ -79,7 +78,7 @@
</div>
<div class="mt-4">
<form class="flex gap-x-2" novalidate {onsubmit}>
<PasswordField autocomplete="off" bind:password placeholder="Password" />
<PasswordInput autocomplete="off" bind:value={password} placeholder="Password" />
<Button type="submit">{$t('submit')}</Button>
</form>
</div>

View File

@@ -1,49 +0,0 @@
<script lang="ts">
import { Icon } from '@immich/ui';
import { mdiEyeOffOutline, mdiEyeOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import type { HTMLInputAttributes } from 'svelte/elements';
interface Props extends HTMLInputAttributes {
password: string;
autocomplete: AutoFill;
required?: boolean;
onInput?: (value: string) => void;
}
let { password = $bindable(), required = true, onInput = undefined, ...rest }: Props = $props();
let showPassword = $state(false);
</script>
<div class="relative w-full">
<input
{...rest}
class="immich-form-input w-full pe-12!"
type={showPassword ? 'text' : 'password'}
{required}
value={password}
oninput={(e) => {
password = e.currentTarget.value;
onInput?.(password);
}}
/>
{#if password.length > 0}
<button
type="button"
tabindex="-1"
class="absolute inset-y-0 end-0 px-4 text-gray-700 dark:text-gray-200"
onclick={() => (showPassword = !showPassword)}
title={showPassword ? $t('hide_password') : $t('show_password')}
>
<Icon icon={showPassword ? mdiEyeOffOutline : mdiEyeOutline} size="1.25em" />
</button>
{/if}
</div>
<style>
input::-ms-reveal {
display: none;
}
</style>

View File

@@ -1,15 +1,13 @@
<script lang="ts">
import { SettingInputFieldType } from '$lib/constants';
import { PasswordInput } from '@immich/ui';
import { onMount, tick, type Snippet } from 'svelte';
import { t } from 'svelte-i18n';
import { quintOut } from 'svelte/easing';
import type { FormEventHandler } from 'svelte/elements';
import { fly } from 'svelte/transition';
import PasswordField from '../password-field.svelte';
interface Props {
inputType: SettingInputFieldType;
value: string | number | undefined | null;
type Props = {
min?: number;
max?: number;
step?: string;
@@ -23,7 +21,14 @@
passwordAutocomplete?: AutoFill;
descriptionSnippet?: Snippet;
trailingSnippet?: Snippet;
}
} & (
| { inputType: SettingInputFieldType.PASSWORD; value: string }
| { inputType: SettingInputFieldType.NUMBER; value: number | null | undefined }
| {
inputType: SettingInputFieldType.TEXT | SettingInputFieldType.COLOR | SettingInputFieldType.EMAIL;
value: string | null | undefined;
}
);
let {
inputType,
@@ -145,15 +150,15 @@
{@render trailingSnippet?.()}
</div>
{:else}
<PasswordField
<PasswordInput
aria-describedby={description ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
size="small"
id={label}
name={label}
autocomplete={passwordAutocomplete}
{required}
password={(value || '').toString()}
onInput={(passwordValue) => (value = passwordValue)}
bind:value={value as string}
{disabled}
{title}
/>