diff --git a/web/src/routes/(user)/user-settings/UserSettingsList.svelte b/web/src/routes/(user)/user-settings/UserSettingsList.svelte
index 06637b7e4..5e5868b93 100644
--- a/web/src/routes/(user)/user-settings/UserSettingsList.svelte
+++ b/web/src/routes/(user)/user-settings/UserSettingsList.svelte
@@ -8,7 +8,6 @@
import UserUsageStatistic from './UserUsageStatistic.svelte';
import { OpenQueryParam, QueryParameter } from '$lib/constants';
import { oauth } from '$lib/utils';
- import { type ApiKeyResponseDto, type PasskeyResponseDto, type SessionResponseDto } from '@immich/sdk';
import {
mdiAccountGroupOutline,
mdiAccountOutline,
@@ -42,20 +41,6 @@
const query = createPreloadedQuery(getUserConfigQuery);
const config = $derived(query.data);
- interface Props {
- keys?: ApiKeyResponseDto[];
- sessions?: SessionResponseDto[];
- passkeys?: PasskeyResponseDto[];
- passkeyEnabled?: boolean;
- }
-
- let {
- keys = $bindable([]),
- sessions = $bindable([]),
- passkeys = $bindable([]),
- passkeyEnabled = false,
- }: Props = $props();
-
let oauthOpen =
oauth.isCallback(location) || $page.url.searchParams.get(QueryParameter.OPEN_SETTING) === OpenQueryParam.OAUTH;
@@ -92,7 +77,7 @@
-
+
-
+
{/if}
-{#if passkeyEnabled}
+{#if config.passkey.enabled}
-
+
{/if}
diff --git a/web/src/routes/auth/login/+page.svelte b/web/src/routes/auth/login/+page.svelte
index 9adfd1f27..30a696949 100644
--- a/web/src/routes/auth/login/+page.svelte
+++ b/web/src/routes/auth/login/+page.svelte
@@ -2,11 +2,13 @@
import { goto } from '$app/navigation';
import AuthPageLayout from '$lib/components/layouts/AuthPageLayout.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
- import { createPreloadedQuery } from '$lib/queries/client';
+ import { createPreloadedQuery, MutationCancelledError } from '$lib/queries/client';
import { getPublicConfigQuery } from '$lib/queries/config-public.query';
+ import { loginWithPasskeyMutation } from '$lib/queries/passkey.query';
import { getServerConfigQuery } from '$lib/queries/server.query';
import { Route } from '$lib/route';
- import { handleLoginWithPasskey, isPasskeyCancelled, isPasskeySupported } from '$lib/services/passkey.service';
+ import { browserSupportsWebAuthn } from '@simplewebauthn/browser';
+ import { createMutation } from '@tanstack/svelte-query';
import { oauth } from '$lib/utils';
import { getServerErrorMessage, handleError } from '$lib/utils/handle-error';
import { login, type LoginResponseDto } from '@immich/sdk';
@@ -26,10 +28,8 @@
let email = $state('');
let password = $state('');
let oauthError = $state('');
- let passkeyError = $state('');
let loading = $state(false);
let oauthLoading = $state(true);
- let passkeyLoading = $state(false);
const queries = {
publicConfig: createPreloadedQuery(getPublicConfigQuery),
@@ -39,9 +39,17 @@
const publicConfig = $derived(queries.publicConfig.data);
const serverConfig = $derived(queries.serverConfig.data);
- const passkeySupported = isPasskeySupported();
+ const passkeySupported = browserSupportsWebAuthn();
const passkeyEnabled = $derived(publicConfig.passkey.enabled && passkeySupported);
+ const passkeyLogin = createMutation(() => ({ ...loginWithPasskeyMutation(), onSuccess: (user) => onLogin(user) }));
+ const passkeyLoading = $derived(passkeyLogin.isPending || passkeyLogin.isSuccess);
+ const passkeyError = $derived(
+ passkeyLogin.error && !(passkeyLogin.error instanceof MutationCancelledError)
+ ? getServerErrorMessage(passkeyLogin.error) || $t('errors.something_went_wrong')
+ : '',
+ );
+
const onSuccess = async (user: LoginResponseDto) => {
await goto(data.continueUrl, { invalidateAll: true });
eventManager.emit('AuthLogin', user);
@@ -125,20 +133,6 @@
}
};
- const handlePasskeyLogin = async () => {
- try {
- passkeyError = '';
- passkeyLoading = true;
- const user = await handleLoginWithPasskey();
- await onLogin(user);
- } catch (error) {
- if (!isPasskeyCancelled(error)) {
- passkeyError = getServerErrorMessage(error) || $t('errors.something_went_wrong');
- }
- passkeyLoading = false;
- }
- };
-
const handleOAuthLogin = async () => {
oauthLoading = true;
oauthError = '';
@@ -208,7 +202,7 @@
size="large"
fullWidth
color={publicConfig.passwordLogin.enabled ? 'secondary' : 'primary'}
- onclick={handlePasskeyLogin}
+ onclick={() => passkeyLogin.mutate()}
>
{$t('login_with_passkey')}