fix(hotkeys): name the combo another app already owns
Two gaps when Windows refuses a RegisterHotKey: - the toast said "one or both hotkeys" — wrong since there are three autofill combos, and it never said which one lost. - Quick search and New entry failures were only written to the debug panel, which is off in production: the hotkey silently did nothing with no clue why. Delphi now exposes the per-slot registration outcome and the host accumulates the failed combo names across all five hotkeys, emitting one notification for the batch. A combo the user deliberately cleared (vk=0) is never listed. JS names them: "Already used by another app: 2FA code — pick another combo in Settings". Registration stays best-effort per slot: one clash doesn't disarm the others. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -863,6 +863,11 @@ begin
|
||||
// we register both with the supplied combos (replacing any prior).
|
||||
else if ACmd = 'autofill/hotkeys' then
|
||||
begin
|
||||
// Names of the combos Windows refused (already held by another app), so
|
||||
// the toast can say WHICH one is dead instead of leaving the user to
|
||||
// wonder why a hotkey silently does nothing. A combo the user cleared
|
||||
// (vk=0) is skipped on purpose and never listed here.
|
||||
var LFailed := '';
|
||||
// Quick-search combo is set unconditionally (independent of the
|
||||
// autofill enabled flag) so the picker stays armed even when the
|
||||
// autofill hotkeys are turned off.
|
||||
@@ -871,6 +876,7 @@ begin
|
||||
var LQsMods := Word(StrToIntDef(GetParam('qs_mods'), 6));
|
||||
var LQsVk := Word(StrToIntDef(GetParam('qs_vk'), Ord('Q')));
|
||||
var LQsOk := FBridge.SetQuickSearchHotkey(LQsMods, LQsVk);
|
||||
if (not LQsOk) and (LQsVk <> 0) then LFailed := LFailed + 'Quick search, ';
|
||||
LogLine(Format('Quick-search hotkey set — mods:%d vk:%d (ok=%s)',
|
||||
[LQsMods, LQsVk, BoolToStr(LQsOk, True)]));
|
||||
end;
|
||||
@@ -881,6 +887,7 @@ begin
|
||||
var LNeMods := Word(StrToIntDef(GetParam('ne_mods'), 6));
|
||||
var LNeVk := Word(StrToIntDef(GetParam('ne_vk'), Ord('A')));
|
||||
var LNeOk := FBridge.SetNewEntryHotkey(LNeMods, LNeVk);
|
||||
if (not LNeOk) and (LNeVk <> 0) then LFailed := LFailed + 'New entry, ';
|
||||
LogLine(Format('New-entry hotkey set — mods:%d vk:%d (ok=%s)',
|
||||
[LNeMods, LNeVk, BoolToStr(LNeOk, True)]));
|
||||
end;
|
||||
@@ -903,12 +910,19 @@ begin
|
||||
LTotpMods, LTotpVk);
|
||||
LogLine(Format('Autofill hotkeys set — full=mods:%d vk:%d pwd=mods:%d vk:%d totp=mods:%d vk:%d (all_ok=%s)',
|
||||
[LFullMods, LFullVk, LPwdMods, LPwdVk, LTotpMods, LTotpVk, BoolToStr(LAllOk, True)]));
|
||||
// Notify JS of the result so the UI can flag a failed-to-register combo
|
||||
// (typically a clash with another app's global hotkey).
|
||||
WebBrowser.ExecuteJavaScript(
|
||||
'if(window.Bridge&&Bridge.onAutofillHotkeysResult)' +
|
||||
'Bridge.onAutofillHotkeysResult(' + BoolToStr(LAllOk, True).ToLower + ')');
|
||||
if (not FBridge.AutofillFullActive) and (LFullVk <> 0) then
|
||||
LFailed := LFailed + 'Autofill (full), ';
|
||||
if (not FBridge.AutofillPwdActive) and (LPwdVk <> 0) then
|
||||
LFailed := LFailed + 'Password only, ';
|
||||
if (not FBridge.AutofillTotpActive) and (LTotpVk <> 0) then
|
||||
LFailed := LFailed + '2FA code, ';
|
||||
end;
|
||||
// One notification for the whole batch, naming the combos that failed —
|
||||
// empty string = everything registered.
|
||||
LFailed := LFailed.TrimRight([',', ' ']);
|
||||
WebBrowser.ExecuteJavaScript(
|
||||
'if(window.Bridge&&Bridge.onAutofillHotkeysResult)' +
|
||||
'Bridge.onAutofillHotkeysResult("' + LFailed.Replace('"', '') + '")');
|
||||
end
|
||||
|
||||
// execute: JS has matched an entry, decrypted the password, and is
|
||||
|
||||
Reference in New Issue
Block a user