Merge pull request #2393 from hoobnn/fix/totp-autofill
fix: add autocomplete for TOTP autofill support
This commit is contained in:
commit
6a88e560c2
@ -24,6 +24,18 @@
|
|||||||
|
|
||||||
<!-- Code Input -->
|
<!-- Code Input -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
|
<!-- Hidden input for password manager autofill (autocomplete="one-time-code") -->
|
||||||
|
<input
|
||||||
|
ref="hiddenOtpInputRef"
|
||||||
|
type="text"
|
||||||
|
inputmode="numeric"
|
||||||
|
autocomplete="one-time-code"
|
||||||
|
maxlength="6"
|
||||||
|
class="pointer-events-none absolute left-0 top-0 h-px w-px opacity-0"
|
||||||
|
aria-hidden="true"
|
||||||
|
tabindex="-1"
|
||||||
|
@input="handleHiddenOtpInput"
|
||||||
|
/>
|
||||||
<div class="flex justify-center gap-2">
|
<div class="flex justify-center gap-2">
|
||||||
<input
|
<input
|
||||||
v-for="(_, index) in 6"
|
v-for="(_, index) in 6"
|
||||||
@ -33,6 +45,7 @@
|
|||||||
maxlength="1"
|
maxlength="1"
|
||||||
inputmode="numeric"
|
inputmode="numeric"
|
||||||
pattern="[0-9]"
|
pattern="[0-9]"
|
||||||
|
autocomplete="off"
|
||||||
class="h-12 w-10 rounded-lg border border-gray-300 text-center text-lg font-semibold focus:border-primary-500 focus:ring-primary-500 dark:border-dark-600 dark:bg-dark-700"
|
class="h-12 w-10 rounded-lg border border-gray-300 text-center text-lg font-semibold focus:border-primary-500 focus:ring-primary-500 dark:border-dark-600 dark:bg-dark-700"
|
||||||
:disabled="verifying"
|
:disabled="verifying"
|
||||||
@input="handleCodeInput($event, index)"
|
@input="handleCodeInput($event, index)"
|
||||||
@ -82,6 +95,7 @@ const appStore = useAppStore()
|
|||||||
const verifying = ref(false)
|
const verifying = ref(false)
|
||||||
const code = ref<string[]>(['', '', '', '', '', ''])
|
const code = ref<string[]>(['', '', '', '', '', ''])
|
||||||
const inputRefs = ref<(HTMLInputElement | null)[]>([])
|
const inputRefs = ref<(HTMLInputElement | null)[]>([])
|
||||||
|
const hiddenOtpInputRef = ref<HTMLInputElement | null>(null)
|
||||||
|
|
||||||
// Watch for code changes and auto-submit when 6 digits are entered
|
// Watch for code changes and auto-submit when 6 digits are entered
|
||||||
watch(
|
watch(
|
||||||
@ -104,6 +118,10 @@ defineExpose({
|
|||||||
inputRefs.value.forEach(input => {
|
inputRefs.value.forEach(input => {
|
||||||
if (input) input.value = ''
|
if (input) input.value = ''
|
||||||
})
|
})
|
||||||
|
// Clear hidden autofill input
|
||||||
|
if (hiddenOtpInputRef.value) {
|
||||||
|
hiddenOtpInputRef.value.value = ''
|
||||||
|
}
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
inputRefs.value[0]?.focus()
|
inputRefs.value[0]?.focus()
|
||||||
})
|
})
|
||||||
@ -126,6 +144,26 @@ const handleCodeInput = (event: Event, index: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle autofill from password managers via the hidden autocomplete="one-time-code" input
|
||||||
|
const handleHiddenOtpInput = (event: Event) => {
|
||||||
|
const input = event.target as HTMLInputElement
|
||||||
|
const digits = input.value.replace(/[^0-9]/g, '').slice(0, 6).split('')
|
||||||
|
|
||||||
|
digits.forEach((digit, i) => {
|
||||||
|
code.value[i] = digit
|
||||||
|
if (inputRefs.value[i]) {
|
||||||
|
inputRefs.value[i]!.value = digit
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let i = digits.length; i < 6; i++) {
|
||||||
|
code.value[i] = ''
|
||||||
|
if (inputRefs.value[i]) {
|
||||||
|
inputRefs.value[i]!.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleKeydown = (event: KeyboardEvent, index: number) => {
|
const handleKeydown = (event: KeyboardEvent, index: number) => {
|
||||||
if (event.key === 'Backspace') {
|
if (event.key === 'Backspace') {
|
||||||
const input = event.target as HTMLInputElement
|
const input = event.target as HTMLInputElement
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user