feat(autofill): Ctrl+Shift+T types the 2FA code
Same workflow as the password-only hotkey: click the 2FA field, press the combo, the current 6-digit code is typed in. Reuses the whole autofill pipeline — no new native typing path. The code is sent in the password slot with an empty username, so Delphi's existing password-only branch types just the code. - Bridge: akTotp kind, hotkey id 47, registered/torn down alongside the other two autofill combos; an unconfigured combo (vk=0) doesn't count as a registration failure. - Matching filters on totp_secret BEFORE scoring, so the multi-match picker never offers an entry that has no code. - Configurable + synced like the others (autofillHotkeyTotp), collision-checked against the other four slots, covered by Reset to defaults and the cheatsheet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -205,9 +205,14 @@ const Bridge = (() => {
|
||||
const n = autofillComboToWin32(combos.newEntry);
|
||||
ne = '&ne_mods=' + n.mods + '&ne_vk=' + n.vk;
|
||||
}
|
||||
let tp = '';
|
||||
if (combos.totp) {
|
||||
const t = autofillComboToWin32(combos.totp);
|
||||
tp = '&totp_mods=' + t.mods + '&totp_vk=' + t.vk;
|
||||
}
|
||||
cmd('cmd://autofill/hotkeys?enabled=' + (enabled ? '1' : '0') +
|
||||
'&full_mods=' + f.mods + '&full_vk=' + f.vk +
|
||||
'&pwd_mods=' + p.mods + '&pwd_vk=' + p.vk + qs + ne);
|
||||
'&pwd_mods=' + p.mods + '&pwd_vk=' + p.vk + qs + ne + tp);
|
||||
},
|
||||
|
||||
// Called by Delphi after a setAutofillHotkeys request, with true if
|
||||
@@ -673,6 +678,8 @@ const state = {
|
||||
'{"ctrl":true,"shift":true,"alt":false,"win":false,"key":"L"}'),
|
||||
autofillHotkeyPwd: JSON.parse(localStorage.getItem('autofillHotkeyPwd') ||
|
||||
'{"ctrl":true,"shift":true,"alt":false,"win":false,"key":"P"}'),
|
||||
autofillHotkeyTotp: JSON.parse(localStorage.getItem('autofillHotkeyTotp') ||
|
||||
'{"ctrl":true,"shift":true,"alt":false,"win":false,"key":"T"}'),
|
||||
quickSearchHotkey: JSON.parse(localStorage.getItem('quickSearchHotkey') ||
|
||||
'{"ctrl":true,"shift":true,"alt":false,"win":false,"key":"Q"}'),
|
||||
newEntryHotkey: JSON.parse(localStorage.getItem('newEntryHotkey') ||
|
||||
@@ -6302,6 +6309,7 @@ function openSettings() {
|
||||
// Hotkey capture buttons — labels reflect current combos.
|
||||
$('#settingAutofillFullCombo').textContent = autofillComboLabel(state.autofillHotkeyFull);
|
||||
$('#settingAutofillPwdCombo').textContent = autofillComboLabel(state.autofillHotkeyPwd);
|
||||
$('#settingAutofillTotpCombo').textContent = autofillComboLabel(state.autofillHotkeyTotp);
|
||||
$('#settingQuickSearchCombo').textContent = autofillComboLabel(state.quickSearchHotkey);
|
||||
$('#settingNewEntryCombo').textContent = autofillComboLabel(state.newEntryHotkey);
|
||||
$('#settingAutofillHotkeysRow').style.display = Bridge.active ? '' : 'none';
|
||||
@@ -6690,7 +6698,8 @@ const SYNCED_SETTING_KEYS = [
|
||||
// Hotkey combos are user preferences — values are portable. The
|
||||
// registration itself is Windows-only, so non-Windows clients just
|
||||
// ignore them.
|
||||
'autofillHotkeyFull', 'autofillHotkeyPwd', 'quickSearchHotkey', 'newEntryHotkey',
|
||||
'autofillHotkeyFull', 'autofillHotkeyPwd', 'autofillHotkeyTotp',
|
||||
'quickSearchHotkey', 'newEntryHotkey',
|
||||
// Sidebar section collapsed state. Object of { folders, tags, tools }
|
||||
// booleans. Synced so the user gets the same fold state across devices.
|
||||
'sidebarCollapsed',
|
||||
@@ -6764,6 +6773,7 @@ async function loadServerSettings() {
|
||||
case 'pageSize': localStorage.setItem('pageSize', String(v)); break;
|
||||
case 'autofillHotkeyFull':
|
||||
case 'autofillHotkeyPwd':
|
||||
case 'autofillHotkeyTotp':
|
||||
case 'quickSearchHotkey':
|
||||
case 'newEntryHotkey':
|
||||
case 'sidebarCollapsed':
|
||||
@@ -7702,6 +7712,7 @@ async function init() {
|
||||
const others = [
|
||||
kind !== 'full' ? state.autofillHotkeyFull : null,
|
||||
kind !== 'password' ? state.autofillHotkeyPwd : null,
|
||||
kind !== 'totp' ? state.autofillHotkeyTotp : null,
|
||||
kind !== 'quickSearch' ? state.quickSearchHotkey : null,
|
||||
kind !== 'newEntry' ? state.newEntryHotkey : null,
|
||||
].filter(Boolean);
|
||||
@@ -7714,6 +7725,7 @@ async function init() {
|
||||
// Commit.
|
||||
if (kind === 'full') state.autofillHotkeyFull = captured;
|
||||
else if (kind === 'password') state.autofillHotkeyPwd = captured;
|
||||
else if (kind === 'totp') state.autofillHotkeyTotp = captured;
|
||||
else if (kind === 'quickSearch') state.quickSearchHotkey = captured;
|
||||
else /* newEntry */ state.newEntryHotkey = captured;
|
||||
btn.textContent = autofillComboLabel(captured);
|
||||
@@ -7726,16 +7738,19 @@ async function init() {
|
||||
}
|
||||
bindHotkeyCapture('#settingAutofillFullCombo', 'full');
|
||||
bindHotkeyCapture('#settingAutofillPwdCombo', 'password');
|
||||
bindHotkeyCapture('#settingAutofillTotpCombo', 'totp');
|
||||
bindHotkeyCapture('#settingQuickSearchCombo', 'quickSearch');
|
||||
bindHotkeyCapture('#settingNewEntryCombo', 'newEntry');
|
||||
|
||||
$('#settingAutofillResetHotkeys').addEventListener('click', () => {
|
||||
state.autofillHotkeyFull = { ctrl: true, shift: true, alt: false, win: false, key: 'L' };
|
||||
state.autofillHotkeyPwd = { ctrl: true, shift: true, alt: false, win: false, key: 'P' };
|
||||
state.autofillHotkeyTotp = { ctrl: true, shift: true, alt: false, win: false, key: 'T' };
|
||||
state.quickSearchHotkey = { ctrl: true, shift: true, alt: false, win: false, key: 'Q' };
|
||||
state.newEntryHotkey = { ctrl: true, shift: true, alt: false, win: false, key: 'A' };
|
||||
$('#settingAutofillFullCombo').textContent = autofillComboLabel(state.autofillHotkeyFull);
|
||||
$('#settingAutofillPwdCombo').textContent = autofillComboLabel(state.autofillHotkeyPwd);
|
||||
$('#settingAutofillTotpCombo').textContent = autofillComboLabel(state.autofillHotkeyTotp);
|
||||
$('#settingQuickSearchCombo').textContent = autofillComboLabel(state.quickSearchHotkey);
|
||||
$('#settingNewEntryCombo').textContent = autofillComboLabel(state.newEntryHotkey);
|
||||
autofillPushHotkeys();
|
||||
|
||||
Reference in New Issue
Block a user