From ac6938a629206a6b8e7cb949d0c13e37579276c0 Mon Sep 17 00:00:00 2001 From: Preslav Penchev <55917783+pressslav@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:38:06 +0000 Subject: [PATCH] fix(web): allow pasting PIN code from clipboard or password manager (#26944) * fix(web): allow pasting PIN code from clipboard or password manager The keydown handler was blocking Ctrl+V/Cmd+V since it called preventDefault() on all non-numeric keys. Also adds an onpaste handler to distribute pasted digits across the individual inputs. * refactor: handle paste in handleInput, remove maxlength * cleanup + fix digit focus --------- Co-authored-by: Preslav Penchev Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> --- .../user-settings-page/PinCodeInput.svelte | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/web/src/lib/components/user-settings-page/PinCodeInput.svelte b/web/src/lib/components/user-settings-page/PinCodeInput.svelte index c438d8f0b1..2ab48c0afe 100644 --- a/web/src/lib/components/user-settings-page/PinCodeInput.svelte +++ b/web/src/lib/components/user-settings-page/PinCodeInput.svelte @@ -49,25 +49,22 @@ const handleInput = (event: Event, index: number) => { const target = event.target as HTMLInputElement; - let currentPinValue = target.value; + const digits = target.value.replaceAll(/\D/g, '').slice(0, pinLength - index); - if (target.value.length > 1) { - currentPinValue = value.slice(0, 1); - } - - if (Number.isNaN(Number(value))) { + if (digits.length === 0) { pinValues[index] = ''; - target.value = ''; + value = pinValues.join('').trim(); return; } - pinValues[index] = currentPinValue; + for (let i = 0; i < digits.length; i++) { + pinValues[index + i] = digits[i]; + } value = pinValues.join('').trim(); - if (value && index < pinLength - 1) { - focusNext(index); - } + const lastFilledIndex = Math.min(index + digits.length, pinLength - 1); + pinCodeInputElements[lastFilledIndex]?.focus(); if (value.length === pinLength) { onFilled?.(value); @@ -104,12 +101,6 @@ } return; } - default: { - if (Number.isNaN(Number(event.key))) { - event.preventDefault(); - } - break; - } } } @@ -125,7 +116,6 @@ {type} inputmode="numeric" pattern="[0-9]*" - maxlength="1" bind:this={pinCodeInputElements[index]} id="pin-code-{index}" class="h-12 w-10 rounded-xl border-2 border-suble dark:border-gray-700 text-center text-lg font-medium focus:border-immich-primary focus:ring-primary dark:focus:border-primary font-mono bg-white dark:bg-light"